CR3寄存器目前博客主要能查找到的内容都比较简单,例如
《控制寄存器 cr0,cr2,cr3》等博客,只对CR3寄存器进行了简单的介绍:
状态和控制寄存器组除了EFLAGS、EIP ,还有四个32位的控制寄存器,它们是CR0,CR1,CR2和CR3。
CR3含有存放页目录表页面的物理地址,因此CR3也被称为PDBR。因为页目录表页面是页对齐的,所以该寄存器只有高20位是有效的。而低12位保留供更高级处理器使用,因此在往CR3中加载一个新值时低12位必须设置为0。
使用MOV指令加载CR3时具有让页高速缓冲无效的副作用。为了减少地址转换所要求的总线周期数量,最近访问的页目录和页表会被存放在处理器的页高速缓冲器件中,该缓冲器件被称为转换查找缓冲区(Translation Lookaside Buffer,TLB)。只有当TLB中不包含要求的页表项时才会使用额外的总线周期从内存中读取页表项。
即使CR0中的PG位处于复位状态(PG=0),我们也能先加载CR3。以允许对分页机制进行初始化。当切换任务时,CR3的内容也会随之改变。但是如果新任务的CR3值与原任务的一样,处理器就无需刷新页高速缓冲。这样共享页表的任务可以执行得更快。
本文深入挖掘一下CR3寄存器的相关信息,了解MMU、TLB、操作系统与CR3寄存器的交互。
一、CR3寄存器
对于64位机,CR3寄存器也从32位变成了64位,它的主要功能还是用来存放页目录表物理内存基地址,每当进程切换时,Linux就会把下一个将要运行进程的页目录表物理内存基地址等信息存放到CR3寄存器中。
图片来源(http://ilinuxkernel.com/?p=606)
二、CR3寄存器与TLB
关于CR3寄存器与TLB找到了两个大佬的博文,对于TLB里面的信息描述得很清楚,可以直接移步~
1、《TLB原理》
地址:https://zhuanlan.zhihu.com/p/108425561?utm_source=wechat_timeline
这个文章对于TLB的原理描述地很清晰,TLB只能使用虚拟地址来做tag,那么是否会出现TLB别名问题以及TLB歧义问题都进行了分析。文中指出了TLB不存在别名问题,但是存在TLB歧义,解决TLB歧义最简单的方法就是进程切换之后使整个TLB无效,这会导致性能损失,所以文中提出了尽可能避免TLB flush的方法,例如在TLB中添加一项ASID(Address Space ID)的匹配之类的。这篇文章很有参考价值,内容也比较新~
2、《进程切换分析(2):TLB处理》
地址:http://www.wowotech.net/process_management/context-switch-tlb.html
这个文章也提出了《TLB原理》这个文章中的一些问题,但是没有上一篇文章那么细致,它重点关注了进程切换的时候,TLB的一些处理。
在《深入理解LINUX内核》一书中指出,Intel微处理器只提供了两种使TLB无效的技术:
- 在向CR3寄存器写入值时所有Pentium处理器自动刷新相对于非全局页的TLB表项;
- 在Pentium Pro及之后的处理器中,invlpg汇编语言指令使映射指定虚拟地址的单个TLB表项无效。
深入理解LINUX内核基于2.6版本内核,本文将基于4.15版本内核对相关内容进行探究,所以上面的说法可能有些已经过时,需要我们自己看内核代码来分析。对于本节给出的文章2《进程切换分析(2):TLB处理》ÿ