0
点赞
收藏
分享

微信扫一扫

29-TLB


基本上到了这里,保护模式已接近尾声。不过,仍然有一些边角和细节需要你去掌握和理解。前面的文章里,尚有一些遗留的问题,比如页属性,并未介绍完,什么是 G 位,什么是 PWT,什么是 PCD?

在解释这些东西之前,TLB(Translation Lookaside Buffer) 这个东西不讲,对不起这个博客,对不起阅读保护模式的读者。

TLB 由来

中译名为快表

经过前面大量的学习和实践,你已对 10-10-12 分页和 PAE 分页了如指掌。倘若在 10-10-12 分页模式下,CPU 需要访问一个 int 类型的变量,所做的操作将会是这样:

  1. 读取 4 字节的PDE
  2. 读取 4 字节的 PTE
  3. 读取 4 字节(int 占用4字节)的物理内存

如果在 PAE 分页模式下,是这样:

  1. 读取 8 字节 PDPTE
  2. 读取 8 字节 PDE
  3. 读取 8 字节 PTE
  4. 读取 4 字节的物理内存

在 10-10-12 分页模式下,CPU 每次要访问额外的访问 8 字节内存数据才能读取到数据,而在 PAE 分页模式下,需要额外的访问 24 字节内存数据才能读取到数据。

对于 CPU 而言,如此频繁的进行内存访问,这是极其奢侈且不能容忍的事情!—— TLB 由此诞生。

CPU 的设计者基于这样一种设想,倘若可以不经由页目录表和页表,直接就能把线性地址映射成物理地址,这样就不需要额外的去访问内存中的 PDE 和 PTE了。

TLB 结构

为了避免过多不必要的内存访问,CPU 设计者在 CPU 中安排了一个寄存器 TLB. 这个寄存器实际上就是一个大数组,在 CPU 中的数组,它的结构像下面这样。

线性地址

物理地址

页属性

LRU统计信息

0x00401020

0x50702020

可读可写

103

……

……

……

……

倘若 CPU 要访问的线性地址就是 0x00401020,CPU就可以立即在 TLB 中查到它对应的物理地址就是 0x50702020。

如果找不到,CPU 就只能老老实实的,去内存中访问 PDE 和 PTE 吧,同时把这个线性地址再写到 TLB 中去保存。如果 TLB 满了怎么办?这时候 LRU 统计信息就起作用了,它会把不经常使用的那一条抹掉,把新值写上。要知道,TLB 的大小是非常小的,因为 CPU 中开辟大空间容量等价是极其昂贵的。

思考一下,如果使用上的表查询线性地址 0x00401234 这个地址,快表能起作用吗?先不看后面的答案,给一下自己的思考。

当然能起作用,因为 0x00401020 和 0x00401234 本就在同一个物理页。实际上在快表中,真正起作用的就只是线性地址的前20位,后面的12位偏移没啥用。

TLB 相关细节

  1. TLB 中的属性,是 PDPTE(倘若有的话)/PDE/PTE 三者属性AND操作的结果。
  2. 不同的 CPU,TLB 大小是不一样的。
  3. 如果 CR3 被重写,TLB 中的内容立刻失效!

!!! 第 3 条尤其注意!!!

我们都知道,32 位系统中一个进程拥有 4GB 的线性地址空间。在低 2GB 中,不同进程对应的物理页是不同的。而在 高 2GB 中,不同进程对应的物理页**几乎**是相同的。

而进程的切换,意味着 CR3 的切换,CR3 的切换导致 TLB 条目失效,对于几乎完全共享的高 2GB 地址空间来说,这种失效将造成浪费,重建 TLB 的工作将变得的重复而乏味。如果能指定某些条目不失效,要怎么办?

页属性 G 位

相信你对 G 位已经不陌生了,如果你还记得《不提权读取高2G内存》,当时在修改页属性的时候,留了一个小小的细节,如果属性 G 位不清 0 的话,很有可能导致实验失败。

而 G 位的作用,就是让 TLB 中含 G = 1 的条目不被刷新。

在那个实验里,如果你 G 位不更改,就算你更改了 U/S 属性位也没什么效果,因为 TLB 中的条目的 U/S 属性没有被改变,你的实验仍然会失败。

指令 invlpg

CPU 提供了​​invplg​​指令供我们强制刷新 TLB 某个具体的条目,而且可以无视 G 属性位。这个指令的格式如下:

invlpg [线性地址]

比如你可以执行 ​​invlpg [0x00401020]​​强制刷新该线性地址对应的条目。

TLB 种类

在 CPU 中,缓存指令的地址和数据的地址使用的 TLB 也是不同的。对于大页和小页,也使用不同的 TLB。这部分了解即可。

第一组:缓存一般页表(4K字节页面)的指令页表缓存(Instruction-TLB);
第二组:缓存一般页表(4K字节页面)的数据页表缓存(Data-TLB);
第三组:缓存大尺寸页表(2M/4M字节页面)的指令页表缓存(Instruction-TLB);
第四组:缓存大尺寸页表(2M/4M字节页面)的数据页表缓存(Data-TLB)

总结

本篇需要你掌握的 TLB 的由来,为什么需要它。同时结合实验《不提权读取高2G内存》,理解 G 位的含义。动手能力强的同学,可以想想,如何去证明 TLB 这个东西的存在呢?


举报

相关推荐

Linux: TLB 查询流程

2023/11/29

29、html介绍

2022/01/29

【架构-29】RPC

2021-03-29

0 条评论