2. x86提供了一条INVLPG指令,该指令是特权指令。操作系统可以通过该指令对TLB中的单独的某一entry进行更新。关于这条指令的详细信息,可以参考一下 intel 64 and IA32 Architecture Software Developer's Manual. Linux kernel中使用到该指令的例子有: void set_pte_vaddr(unsigned long vaddr, pte_t pteval) { ... /* * It's enough to flush this one mapping. * (PGE mappings get flushed as well) */ __flush_tlb_one(vaddr); }
set_pte_vaddr函数在内核中被用来直接操作页目录表项,里面涉及到x86线性地址映射物理地址的原理,函数在最后调用__flush_tlb_one来刷新TLB中对应的项: static inline void __flush_tlb_one(unsigned long addr) { if (cpu_has_invlpg) __flush_tlb_single(addr); else __flush_tlb(); } 从函数的实现可以看到,如果CPU支持INVLPG指令,那么就调用__flush_tlb_single函数来刷新TLB中的项(具体哪一项由虚拟线性地址addr来指定),__flush_tlb_single的实现是: