nullplan wrote:
You should INVLPG every time you reduce access or change the address. So if Present changes from 1 to 0, RW changes from 1 to 0, Super changes from 0 to 1, or the address changes at all. Otherwise INVLPG is not necessary. Be aware that a stale TLB entry may cause a spurious page fault, or at least Linux has code for detecting and handling those. That is, you may get a page fault even though the access was permitted. In that case, just return. According to the manual it shouldn't happen, but I cannot imagine the Linux guys writing that special case just for fun.
Which to prefer depends. INVLPG is more targeted, MOV to CR3 is more of a shotgun approach. Normally you want to use INVLPG when just changing single mappings, but MOV to CR3 can be the better option if you don't know precisely how much you are changing. For example, my kernel is booting with PML4[0] == PML4[256], and PML4[256] maps all physical memory. So I need to remove all TLBs that came from PML4[0], but I really don't feel like using INVLPG on every 2MB page in physical memory. And at that time, the Global bit is not in use. So MOV to CR3 is just the easiest way to flush all possible TLBs from the identity mapping.
I understood, thanks