Mctrain's Blog

What I learned in IT, as well as thought about life

TLB的那些事儿

| Comments

这两天因为某些原因,好好地研究了一下Intel的手册,比较系统地学习了一下和TLB相关的知识。以下内容主要来自Intel手册第三卷的第4章,第11章和第28章。

我们知道,现在内存寻址基本采用的是页表翻译机制,即给定一个虚拟地址,经过2~4层页表,得到一个物理地址。虽然该过程一般由硬件(MMU)完成,但是也会有一定的延迟。因此,为了加速页表翻译的过程,一般的处理器都会有一个翻译信息的缓存机制,在Intel中,有两个相关的机制:TLBpaging-structure cache

TLB,cache的关系如下图所示:

i7

当处理器在获取指令或者读取数据的时候,每当遇到一个虚拟地址,会首先通过TLB等地址翻译缓存机制查找该虚拟地址对应的物理地址,如果没有找到对应的条目,则通过内存翻译硬件机制MMU通过走页表的方式查找相应的物理地址,当得到确切的物理地址之后,则会通过cache找到物理地址对应的内存数据,如果cache中没有相应的数据,再去内存中读取。

PCID

在介绍TLBpaging-structure cache之前,有必要先提一下PCID。PCID的全称是Process-Context Identifiers,如果没有PCID,那么运行在处理器上的软件每次切换CR3,都会造成整个处理器的地址翻译缓存信息(包括TLBpaging-structure cache)被刷掉。而PCID则是优化了这一过程。可以这么说,每个进程有自己的一个PCID,这使得进程间的切换不用刷掉处理器中对应的地址翻译缓存信息。

每个进程的PCID由CR3的0:11共12个bits组成,只有在CR4.PCIDE = 1的情况下才有PCID一说,否则当前的PCID只能是000H

当logical processor在TLBpaging-structure cache里面创建条目的时候,它会将该条目和当前的PCID挂钩,当翻译地址需要使用这些条目的时候,它也只会查找那些和当前PCID匹配的条目。

注:logical processor的数目一般和processor是一样的,不过当processor支持超线程(hyper-threading)的时候,每个processor上一般会有两个logical processor。

硬件enforce了以下两个关于PCID的规则:

  • 如果IA32_EFER.LMA = 0或者CR3[11:0] != 000H,则将CR4.PCIDE从0改为1会造成general-protection exception (#GP)
  • 如果CR4.PCIDE = 1,则将CR0.PG改为0会造成general-protection exception

TLB

TLBs的全称是translation lookaside buffers,它存储了page number(由虚拟地址的高位组成)到page frame(由虚拟地址的高位组成)的映射。另外,page numberpage offset(由虚拟地址的地位组成)的界线由page size决定:

  • 32-bit paging
    • 如果是大页(4M),则page number由虚拟地址的31:22位决定;
    • 如果是普通页(4K),则page number由虚拟地址的31:12位决定。
  • PAE paging
    • 如果是大页(2M),则page number由虚拟地址的31:21位决定;
    • 如果是普通页(4K),则page number由虚拟地址的31:12位决定。
  • IA-32e paging
    • 如果是超大页(1G),则page number由虚拟地址的47:30位决定;
    • 如果是大页(2M),则page number由虚拟地址的47:21位决定;
    • 如果是普通页(4K),则page number由虚拟地址的47:12位决定。

TLB中的每个条目存储了以下信息:

  • page number所对应的page frame
  • 在页表寻址过程中得到的访问权限:
    • The logical-AND of the R/W flags.
    • The logical-AND of the U/S flags.
    • The logical-OR of the XD flags (necessary only if IA32_EFER.NXE = 1).
  • 在页表寻址过程中得到的其它属性:
    • The dirty flag
    • The memory type

Paging-Structure Caches

除了TLB缓存虚拟地址到物理地址的映射之外,还有一个被称为paging-structure cache的机制,即用于缓存虚拟地址到某一个页表项地址的映射,包括:

  • PML4 cache (IA-32e paging only):缓存虚拟地址的47:39位到PML4E物理地址的映射;
  • PDPTE cache (IA-32e paging only):缓存虚拟地址的47:30位到PDPTE物理地址的映射;
  • PDE cache:
    • For 32-bit paging,缓存虚拟地址的31:22位到PDE物理地址的映射;
    • For PAE paging,缓存虚拟地址的31:21位到PDE物理地址的映射;
    • For IA-32e paging,缓存虚拟地址的47:21位到PDE物理地址的映射;

Global Pages

除了可以用PCID标记特定的进程的地址翻译缓存信息之外,也可以通过global page的机制标记相应的地址翻译缓存信息。

首先,这需要CR4.PGE设置成1,之后,如果PTE(或者大页的最有一级页表项)中的G bit(即第8个bit)是1的话,则该TLB条目就被标记成global。需要注意的一点是, global page这个标记对paging-structure caches不适用,它只能标记TLB中的条目。

logical processor可以通过被标记成global的TLB条目来翻译一个和当前PCID项不同的虚拟地址。

翻译虚拟地址的步骤

* 如果在TLB中找到对应虚拟地址到物理地址的映射,则直接使用;
* 否则,在PDE cache中查找,如果有match,则获得相应的PTE的物理地址;
* 否则,在PDPTE cache中查找,如果有match,则获得相应的PDE的物理地址;
* 否则,在PML4 cache中查找,如果有match,则获得相应的PDPTE的物理地址;
* 否则,就直接从CR3中获得PML4的物理地址。

其它需要注意的事项

在寻址过程中,只有当四级页表中(对于IA32-e来说)每一个条目的P flag都是1,且所有的reserved bits都是0的情况下才会填上相应虚拟地址的TLB条目。paging-structure cache也类似。另外,在缓存该翻译信息之前,会先把accessed flag设置为1。

而且,对于prefetch和speculative execution造成的地址翻译也有可能被缓存下来。

另外一点很重要的是,如果软件修改了某一个相应的paging-structure条目,TLB和paging-structure cache里面的条目都可能还存在,这就需要开发者意思到这点,并且能够手动的调用相应的invalidate的指令。

另外还有一个有趣的问题是:Multiple Cached Entries for a Single Paging-Structure Entry,即同一个页表项可能会存在不同的地址翻译缓存,文中给出了两种可能造成该情况的场景:

  • 假设两个PML4E指向了同一个PDPT,因此对于这个PDPT中的任意一个PDPTE,都有可能会有两个paging-structure cache中的条目引用它,因为它们的虚拟地址项是不同的。
  • 假设某个PML4E指向了PML4本身,这样,所有47:39位为0,或者47:30为0,或者47:21为0,以及47:12为0的这些虚拟地址都是指向PML4的物理地址,因此,PML4的物理地址就可能会有很多的TLBpaging-structure cache引用它。

TLBs and Paging-Structure Caches的invalidate机制

以下操作会invalidate TLB和paging-structure cache相关的条目:

  • INVLPG:一个参数:线性地址。该操作会invalidate所有和该线性地址和当前PCID相关的TLB和paging-structure cache条目,以及global TLB条目;
  • INVPCID:两个参数:INVPCID type 和 INVPCID descriptor。四种type:
    • Individual-address,即只invalidate一个特定的虚拟地址翻译;
    • Single-context,即只invalidate某个PCID相关的所有的虚拟地址翻译;
    • All-context, including globals,即可以invalidate掉所有PCID对应的虚拟地址翻译,包括global page标记的TLB条目;
    • All-context,同上,但是不能invalidate掉global page标记的TLB条目;
  • MOV to CR0:如果将CR0.PG从1变成0,将会invalidate所有PCID的TLBpaging-structure cache的条目,包括global;
  • MOV to CR3:
    • 如果CR4.PCIDE为0,会invalidatePCID为000H的TLBpaging-structure cache的条目,不包含global;
    • If CR4.PCIDE为1,且源地址的第63位为0,将源地址的第11:0位作为PCID,invalidate掉相应PCID的TLBpaging-structure cache条目;
    • If CR4.PCIDE为1,且源地址的第63位为1,则不会invalidate任何条目;
  • MOV to CR4:
    • 如果它修改了CR4.PGE的值,或者将CR4.PCID的值从1改成0,则invalidate所有TLBpaging-structure cache的条目,包含global;
    • 如果它修改了CR4.PAE的值,或者将CR4.SMEP的值从0改为1,则invalidate当前PCID的TLBpaging-structure cache的条目。
  • Task switch:如果task switch修改了CR3的值,则将PCID为000H的TLBpaging-structure cache的条目进行invalidate。
  • page fault exception会invalidate和造成page fault相关的虚拟地址所对应的TLBpaging-structure cache的条目。

多核相关

在多核环境中,当某个核修改了相应的地址翻译信息需要进行invalidation的时候,也需要考虑其它核的TLBpaging-structure cache的缓存了相关的条目。这种地址翻译修改的传递被称为TLB shootdown,该过程一般是通过memory-based semaphores或者interprocessor interrupts (IPI)。文中给了一个低效的实现方案:

* 除了当前的logical processor之外,暂停其它所有的logical processor;
* 让当前的logical processor修改相应的地址翻译信息;
* 让所有的logical processor invalidate相应的`TLB`和`paging-structure cache`条目;
* 恢复所有logical processor的执行。

当然可能会有一些优化的方案,但是需要考虑很多情况,这里就不详细介绍了。

虚拟化相关

虚拟化环境增加了一层额外的地址翻译,EPT。同时由于在CPU中多了一个root和non-root模式,因此增加了一个virtual processor的概念,相应的,在地址翻译缓存这块也就多增加了一个virtual-processor identifiers(VPID)的机制进行优化。

在一般情况下,如果发生VMX transition(即vmexit或者vmenter),则会invalidate相应logical processor的TLB,加入了VPID的特性,每个logical processor就可以同时管理多个线性地址空间的TLB,而不需要每次发生VMX transition的时候都invalidate。

VPID在以下三种情况下为000H:

* Outside VMX operation.
* In VMX root operation.
* In VMX non-root operation when the “enable VPID” VM-execution control is 0.

当VMCS的VM-execution controlenable VPID被设为1的时候,VMX non-root模式下VPID由当前logical processor中VMCS的VM-execution control的VPID域来决定。

另外,VPID和PCID是可以同时被使用的。

在EPT被开启的情况下,TLBpaging-structure cache中可能会缓存以下信息:

  • Guest-physical mappings,包括了guest-physical page numberphysical page frame的映射(存储在TLB中),以及guest-physiaddress的高位到EPT页表页的物理地址的映射(存储在paging-structure cache中);
  • Combined mappings,包括了linear page numberphysical page frame的映射(存储在TLB中),以及linear page number到相应页表页的物理地址的映射(存储在paging-structure cache中)。

除此之外还有一个叫做linear mapping,在EPT开启的情况下不会被缓存,它主要映射了线性地址的映射,和非硬件虚拟化的TLB机制类似。

在地址翻译缓存条目的创建和使用过程中,可能会涉及到PCID,VPID和EP4TA(即EPT-PML4-table,表示当前EPTP第51:12位的值)。

在和虚拟化相关的TLB invalidation中,相关的操作如下所示:

  • 和VMX不相关的invalidation指令(如INVLPG和INVPCID),会invalidate当前VPID的linear mappingscombined mappings
  • EPT violation会invalidate当前EP4TA相关的guest-physical mappings,以及和该guest-physical address相应的linear address的combined mappings
  • 如果enable VPID位为0,VM entries和VM exits会invalidate掉VPID为0000H的所有linear mappingscombined mappings
  • INVVPID指令,会invalidate掉linear mappingscombined mappings。带两个参数:INVVPID type 和 INVVPID descriptor。四种type:
    • Individual-address,即只invalidate一个特定的虚拟地址翻译;
    • Single-context,即只invalidate某个VPID相关的所有的虚拟地址翻译;
    • All-context,即可以invalidate掉所有VPID(除了000H)对应的虚拟地址翻译;
    • Single-context-retaining-globals,同single-context,但是不能invalidate掉global page标记的TLB条目;
  • INVEPT指令,会invalidate掉guest-physical mappingscombined mappings。带两个参数:INVEPT type 和 INVEPT descriptor。两种type:
    • Single-context,即只invalidate某个EP4TA相关的所有的虚拟地址翻译;
      • All-context,即可以invalidate所有EP4TA相关的所有的虚拟地址翻译;

Comments