What it does is create a branch in code that is never actually followed, but is executed speculatively by the CPU, which then discards the result. The problem is that even though the result is discarded, computation of the result causes a measurable side effect (specifically, it populates caches accessible to the code).
In short, the speculatively executed branch retrieves a value from a kernel page (that the code shouldn't have access to) - Intel CPUs allow this, but AMD CPUs do not. It then &s the value with 0x01, and then uses the result to calculate and access an address in a page that it DOES have access to.
This results in that address being stored in the TLB (i.e. a cache that stores mapping from virtual to physical memory).
The result of the computation is then discarded, but the address that it calculated is still in TLB. Since there are two possible addresses that could have been cached based on the value of the data in the kernel page, all the code has to do is time the access to each address, and it can discern the value of the bit in the kernel page based on the relative timings.
Do we know this for sure ? I see now that the meltdown paper has a suggestion in chapter 7.1 that the CPU should perform the permission check on the page table before data is fetched to the cache,
But dismisses that suggestion on the grounds it will haves very high performance impact.
Are you saying AMD does the check first anyway, and either takes the performance hit or has found a way to not take a performance hit ?
My understanding isn't especially deep, but I believe AMD prevents access to unloaded pages that the code doesn't have permission to access, even for speculative access. Their specific quote is:
"AMD processors are not subject to the types of attacks that the kernel page table isolation feature protects against. The AMD microarchitecture does not allow memory references, including speculative references, that access higher privileged data when running in a lesser privileged mode when that access would result in a page fault."
In short, the speculatively executed branch retrieves a value from a kernel page (that the code shouldn't have access to) - Intel CPUs allow this, but AMD CPUs do not. It then &s the value with 0x01, and then uses the result to calculate and access an address in a page that it DOES have access to.
This results in that address being stored in the TLB (i.e. a cache that stores mapping from virtual to physical memory).
The result of the computation is then discarded, but the address that it calculated is still in TLB. Since there are two possible addresses that could have been cached based on the value of the data in the kernel page, all the code has to do is time the access to each address, and it can discern the value of the bit in the kernel page based on the relative timings.