前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CPU快表

CPU快表

作者头像
虚拟化云计算
发布2023-03-28 08:55:54
4970
发布2023-03-28 08:55:54
举报
文章被收录于专栏:虚拟化云计算虚拟化云计算

我是cloud3

前几天看到字节跳动技术团队的一篇文章,关于TLB导致的虚拟化场景下“性能抖动"

https://blog.csdn.net/ByteDanceTech/article/details/104765810

今天借着这个话题和大家分享一下CPU内的TLB。

为什么需要TLB

Intel的16位处理器8086共有20根地址线,能访问1MB的内存,是直接通过物理地址来访问内存。CPU发到地址总线上的信号就叫做物理地址。

这样应用程序直接访问物理内存是不安全的,后来从80386开始CPU内引入MMU不仅解决了安全问题,而且使得物理内存按需申请,提升了物理内存的利用率 。

但是使用MMU有个问题:

因为页表是放在内存里的,假如采用4级页表,一次访存仅仅是虚拟地址到物理地址的转换就要去内存查4次页表,再算上真正的内存访问,最坏情况下需要5次内存IO才能获取一个内存数据。

为了提高内存IO时地址转换的效率,现在CPU都引入了TLB。

TLB在哪里

在配备MMU的处理器中,TLB存储在片上RAM中,TLB被组织为一个n路组关联的缓存。每个CPU核心私有TLB,对于SMT架构甚至每个超线程都有自己的TLB。Intel从80386开始引入TLB。

TLB的作用

TLB是Translation Lookaside Buffer的简称,可翻译为“地址转换后援缓冲器”,也可简称为“快表”。

硬件存在TLB后,虚拟地址到物理地址的转换过程发生了变化。MMU接收到虚拟地址后,首先在TLB中查找,如果找到该VA对应的PTE就直接转换,找不到再去内存页表查找,并将虚拟地址和物理地址的映射关系缓存到TLB中。

之前我们提到的高速缓存其实指的是数据cache,数据cache缓存的是内存数据,提高了CPU读取内存数据的速度。而TLB是页表的Cache,缓存的是虚拟地址和其映射的物理地址,调高了MMU的工作效率。

TLB Flush

我们知道进程切换的时候,操作系统会把要运行进程的页目录表物理内存基地址等信息存放到CR3寄存器中,也就是说MMU要查另外的表了,这个时候TLB中缓存的还是上一个进程的页表条目PTE,所以我们需要主动flush掉TLB,这个Flush动作是操作系统加载CR3时触发CPU做的。

当然直接Flush掉整个TLB肯定是没有问题的,但是会有性能问题。

全局和局部Flush

从PTI引入之前,每个进程都有一个属于自己的页表,这个页表中包含两部分内容:用户态地址空间和内核态地址空间。也就是说在用户态和内核态之间进行切换时,是不用切换页表的。

那么TLB中也就会同时缓存内核态和用户态地址(这也是Meltdown漏洞攻击的主要原理)。同时所有进程页表中内核态地址是相同的。

所以,内核态地址映射就可以添加一个Global标识,在进程切换时不被Flush掉。

Intel-64和IA-32 architectures允许使用global pages,是通过CR4.PGE(bit 7)控制的。当global page被使能时,如果PTE中的G flag(bit 8)设置,则相应的TLB entry被视作为global的。

global TLB entry在没有PCID时,进行mov to CR3操作(也就是进程切换时),不会被flush掉。在引入PTI特性之前,所有的内核地址空间对应的映射都被设置为global,如果可以避免在进程切换时flush掉内核态地址空间对应的TLB entry,可以很大程度提升性功能。

用PCID/ASID来区分进程的PTE

Intel在Westmere架构引入进程上下文标识符,即PCID,对应ARM上的ASID。PCID就用于区分TLB中不同进程对应的页表条目PTE。

在Intel的手册中提到:PCID是一个12位的标识符,位于CR3寄存器的最低12位。通过CR4寄存器中的PCIDE Flag来控制是否enable PCID。

在没有PCID的CPU中,当进程切换时,则必须flush掉所有TLB项,有了PCID后每一条PTE中包含PCID信息,新的加载CR3的过程变成了:如果CR4的PCID=1,加载CR3就不需要Flush TLB。

Linux在4.14中版开始引入PCID,4.15版中全面使用了PCID。

TLB shootdown

假如一个进程有多个线程同时运行在不同的CPU上,其中一个线程要释放一部分内存而修改PTE,那这个CPU上的TLB项要修改,同时要通知其他CPU上的TLB要Flush对应的项了,通知的方式是使用IPI (Inter-Processor Interrupt)

这一过程叫做TLB shootdown。

发送IPI的这个过程,在x86上的体现就是需要CPU执行wrmsr指令,对应的操作是触发ICR。wrmsr这条指令在虚拟化上会引发vmexit,需要Hypervisor处理。

做过虚拟化的朋友可能看到vmexit就比较头疼,改造那么多virtio就是为了减少vmexit的,在CPU这块居然还没避免。

如何优化TLB,可以看看文章开头的链接。

我是cloud3,一起聊聊CPU、操作系统、云计算

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-03-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 虚机 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档