For Meltdown, you need to just never load data from L1$ when permissions checks fail. Since address translation is already on the L1$, doing permissions checks there as well is not a big burden. This is quite natural to do, and also why Meltdown specifically affected Intel, and not everybody.
For Spectre 2, you need to add some bits to the branch target buffer to tag entries by the privilege level and ideally PCID (to protect user level processes from each other). And then you just don't use BTB entries with the wrong tag.
It'd still be interesting to know the details, e.g. what exactly they changed for Spectre 2.