维基百科在文章MTRR 中说:
较新的(主要是 64 位)x86 CPU 支持一种称为页面属性表的更高级技术,该技术允许按表设置这些模式,而不是使用有限数量的低粒度寄存器
因此,对于较新的 x86/x86_64 CPU,可以说 MTRR 可以作为 PAT(页面属性表)的附加技术来实现。 PAT 存储在内存中的位置是页表(页表条目或 PTE 中的一些位),在 CPU 中它们存储(缓存)在 TLB 表中(它是 MMU 的一部分)。 TLB(和MMU)已经是每次内存访问都会访问的地方。我认为,它可能是控制内存类型的好地方,即使使用 MTRR(?)
但是如果我停止猜测并打开 RTFM 书会怎样?关于 x86 世界有一本非常好的书:The Unabridged Pentium 4: IA32 Processor Genealogy (ISBN-13: 978-0321246561)。第 7 部分,第 24 章“Pentium Pro 软件增强”,“MTRR 添加”部分。
在第 582-584 页,每种 mtrr 内存类型都有很长的规则,但所有 5 种类型的规则(Uncacheable=UC,Write-Combining=WC,Write-Through=WT,Write-Protect=WP,Write-Back =WB) 以:“执行缓存查找”开头。
在第 9 部分“Pentium III”第 32 章“Pentium III Xeon”中,该书明确表示:
当它必须执行内存访问时,处理器会同时查询 MTRR 和选定的 PTE 或 PDE 以确定内存类型(以及因此要遵循的行为规则)。
但从另一边... WRMSR 到 MTRR regs 将使 TLB 无效(根据 intel 说明手册“instruct32.chm”):
当使用 WRMSR 指令写入 MTRR 时,TLB 无效,包括全局条目(参见 IA-32 Intel(R) 架构软件开发人员手册第 3 章中的“Translation Lookaside Buffers (TLB)” ,第 3 卷)。
并且在“Intel 64 and IA-32 Architectures Software developer manual, vol 3a”,“10.11.9 大页面注意事项”一节中还有一个更直接的提示:
MTRR 为有限数量的区域提供内存类型,这些区域具有 4 KB 粒度(与 4 KB 页面的粒度相同)。 给定页面的内存类型缓存在处理器的 TLB 中。
你问:
在每次内存访问时,硬件都会检查物理地址是否在给定范围内
没有。每个内存访问都不会与所有 MTRR 进行比较。当 PTE 加载到 TLB 时,所有 MTRR 范围都与内存的 PTE 位预先组合。那么检查内存类型的唯一地方将是 TLB 行。 TLB IS 检查每个内存访问。
是查找缓存还是查找写组合缓冲区还是直接发送到内存控制器
不,有些事情我们不清楚。缓存会查找每个访问,即使是 UC(例如,如果区域刚刚更改为 UC,则可以缓存应该被驱逐的副本)。
从第 24 章开始(关于 Pentium 4):
从可缓存内存加载
允许处理器缓存的内存类型是 WP、WT 和 WB 内存(由 MTRR 和 PTE 或 PDE 定义)。
当核心调度加载拖把时,拖把被放置在分配器阶段为它保留的加载缓冲区中。然后将内存数据读取请求发送到 L1 Data Cache 以实现:
- 如果缓存中有包含所请求读取数据的行的副本,则将读取的数据放置在加载缓冲区中。
- 如果缓存查找未命中,则请求将向上转发到 L2 缓存。
- 如果 L2 缓存具有包含所请求读取数据的扇区副本,则读取的数据会立即放入加载缓冲区,并将扇区复制到 L1 数据缓存中。
- 如果缓存查找未命中,则请求将向上转发到 L3 缓存(如果有)或 FSB 接口单元。
- 如果 L3 Cache 具有包含所请求读取数据的扇区副本,则读取的数据会立即放入 Load Buffer,并将扇区复制到 L2 Cache 和 L1 数据缓存中。
- 如果在顶级缓存中的查找导致未命中,则将请求转发到 FSB 接口单元。
- 当扇区从内存中返回时,读取的数据立即放入加载缓冲区,并将扇区复制到 L3 缓存(如果有)、L2 缓存和 L1 数据缓存。
允许处理器内核推测性地执行从 WC、WP、WT 或 WB 内存空间读取数据的加载
从不可缓存的内存中加载
不可缓存的内存类型是 UC 和 WC(由 MTRR 和 PTE 或 PDE 定义)。
当核心调度加载拖把时,读取请求被放置在分配器阶段为它保留的加载缓冲区中。内存数据读取请求也会提交给处理器的缓存。在缓存命中的情况下,缓存行被从缓存中逐出。该请求被发送到 FSB 接口单元。在 FSB 上执行存储器数据读取事务以仅从存储器中获取请求的字节。当数据从内存返回时,读取的数据立即放入Load Buffer中。
不允许处理器内核推测性地执行从 UC 内存空间读取数据的加载
存储到 UC 内存
UC是两种不可缓存的内存类型之一(另一种是WC内存类型)。当执行到 UC 内存的存储时,它会发布到分配器阶段为它保留的存储缓冲区中。存储到 UC 内存也提交到 L1 数据缓存、L2 缓存或 L3 缓存(如果有的话)。如果缓存命中,则从缓存中逐出该行。
当包含存储到 UC 内存的存储缓冲区被转发到 FSB 接口单元时,在 FSB 上执行内存数据写入事务...
存储到 WC 内存
WC 内存类型非常适合具有以下特性的内存区域(例如,视频帧缓冲区):
- 处理器不缓存 WC 内存。
- 允许从 WC 内存推测执行加载。
- 对 WC 内存的存储存储在处理器的写入组合缓冲区 (WCB) 中。
- 每个 WCB 可以容纳一行(64 字节数据)。
- 当对一行 WC 内存空间执行存储时,字节会累积在分配用于记录对该内存空间行的写入的 WCB 中。
- 对 WCB 中某个位置的后续存储可能会覆盖由先前存储到该位置的先前存储在该位置中的字节。换句话说,对同一位置的多次写入会被折叠,以便该位置反映写入该位置的最后一个数据字节。
- 当 WCB 最终通过 FSB 转储到外部存储器时,数据不一定按照执行早期程序存储的顺序写入内存。被写入的设备必须容忍这种类型的行为(即,它必须正常运行)。有关详细信息,请参阅第 1080 页的“WCB FSB 交易”。
存储到 WT 内存
当存储到可缓存时,会执行直写内存。存储被发布在存储缓冲区中,该缓冲区保留供分配器阶段使用。此外,存储被提交到 L1 数据缓存进行查找。有几种可能性:
* 如果存储命中Data Cache,则更新缓存中的行,但仍保持S状态(表示该行有效)。
* 如果存储错过了Data Cache,则转发到L2 Cache并进行查找:
* - 如果命中 L2 Cache 中的一行,则更新该行,但仍处于 S 状态(这意味着该行有效)。
* - 如果 L2 Cache 未命中且没有 L3 Cache,则不采取进一步措施。