相关指令
在ARMv8-A中,TLB flush/invalidate(通常ARM/x86处理器手册中称为invalidate,linux系统中称为flush,以下的讨论统称为flush)的指令为:
TLBI <type><level>{IS} {, <Xt>}
其中"level"为1到3,对应ARMv8的三个exception level,即EL1,EL2,EL3,通常EL1运行linux等操作系统,EL2在虚拟化模式下运行hypervisor。
"type"相当于一个filter,指按照什么规则去选择被flush的item,包括VA(Virtual Address),IPA(Intermediate Physical Address),ASID(Adress Space Identifier),VMID(Virtual Mechine Identifier)。在虚拟化模式下,IPA即EL1层的物理地址,它需要经过EL2层的转化才能成为最终的物理地址。ASID是区别有相同虚拟地址的不同进程的,VMID是区别有相同虚拟地址的不同虚拟机的。
"Xt"是可选参数,表示通用寄存器X0到X30。
例如 “TLBI VAE1, X0”,表示将flush虚拟地址(type为VA)等于X0寄存器值的这个TLB entry。
当然也可以使用“TLBI ALLELn”将TLB中的所有entries全部flush。
"IS"(Inner Shareable)也是可选参数。Inner和Outer是描述cache属性的,通常一个CPU独有的(比如L1 cache)和一个cluster下的CPU共享的(比如L2 cache)被定义为inner,不同cluster的CPU共享的(比如L3 cache)被定义为outer。TLB也是一种cache,但不管是L1 data/instuction TLB,还是L2 LTB,都是每个CPU单独一份,所以都是inner的。Shareable是描述内存属性的,表示该内存区域是否可被多核共享。对于多核共享的内存,当其中的某个核,比如,对共享内存中的某个page做了访问限制,它需要通过发出IPI(Inter Processor Interrupt)的方式,来通知其他核flush各自的TLB,这种方式被称为TLB击落(shootdown),在ARM指令上的体现就是TLBI IS。

和ARM使用一条指令配合不同参数来处理不同的TLB flush操作有所不同,作为CISC(复杂指令集)的典型代表,x86采用的是提供多条指令的方式:
INVLPG m - flush地址m所在的page对应的TLB entry,相当于ARM中的VA。
INVPCID - PCID相当于ARM中的ASID。
INVIPID - VPID相当于ARM中的VMID。
INVEPT - EPT是x86虚拟化中hypervisor(运行于ring0 - root级别)使用的页表,相当于ARM中的IPA。
操作系统支持
基于处理器提供的这些指令,操作系统根据软件应用的需要,封装了一系列的API供软件开发者使用。以Linux为例,
flush_tlb_all() , flush整个TLB,其调用的指令是TLBI VMALLE1IS
dsb(ishst); // ensure write has completed
__tlbi(vmalle1is); // invalidate all TLB entries
dsb(ish); // ensure completion of TLB invalidation
isb(); // synchronize context and ensure that no instructions are
// fetched using the old translation
flush_tlb_mm(struct mm_struct *mm),flush属于某个进程/address space的TLB,其调用的指令是TLBI ASIDE1IS
unsigned long asid = __TLBI_VADDR(0, ASID(mm));
dsb(ishst);
__tlbi(aside1is, asid);
__tlbi_user(aside1is, asid);
dsb(ish);
参考:《ARM Cortex-A Series Programmer's Guide for ARMv8-A》




