So there are 2 other options: impose a hard limit by protocol rules or change the rules to alter financial incentives somehow so it's not profitable for miners to generate big blocks.
FWIW, there is already a financial incentive that makes it unprofitable for miners to generate big blocks.
Bigger blocks have a longer relay time, hence a higher chance of becoming orphaned blocks. If someone else's block reaches more nodes than yours in a race, it costs you the fees and the block subsidy.
I'm not entirely sure that we still need a block size limit. Getting a 'spam block' these days would seem to require someone, or some combination, to have invested adequate resources in hashing to get a block, but still not value the fees or block subsidy. That's a very plausible scenario during bootstrap (or for an altcoin), but the hashing resources required to get Bitcoin blocks are huge, and I don't think trolls will invest that much money just for lulz.