英特尔手册 3A的第 11.5.3 节提供了一种全局禁用缓存的算法:
11.5.3 防止缓存
要在启用并收到缓存填充后禁用 L1、L2 和 L3 缓存,请执行以下步骤:
- 进入无填充缓存模式。(将控制寄存器 CR0 中的 CD 标志设置为 1,将 NW 标志设置为 0。
- 使用 WBINVD 指令刷新所有缓存。
- 禁用 MTRR 并将默认内存类型设置为未缓存或将所有 MTRR 设置为未缓存内存类型(参见第 11.11.2.1 节“IA32_MTRR_DEF_TYPE MSR”中关于 TYPE 字段和 E 标志的讨论)。
设置 CD 标志后,必须刷新缓存(步骤 2)以确保系统内存一致性。如果没有刷新缓存,读取时仍会发生缓存命中,并且将从有效的缓存行中读取数据。
上面列出的三个单独步骤的意图解决了三个不同的要求:(i) 停止使用新数据替换缓存中的现有数据 (ii) 确保将缓存中的数据逐出到内存中,(iii) 确保后续内存引用观察 UC 内存类型语义。缓存控制硬件的不同处理器实现可能允许这三个要求的软件实现有一些变化。请参阅下面的注释。
注意
在控制寄存器 CR0 中设置 CD 标志会修改处理器的缓存行为,如表 11-5 所示,但单独设置 CD 标志可能不足以在所有处理器系列中强制所有物理内存的有效内存类型为 UC 或由于不同处理器系列的硬件实现变化,它是否强制执行严格的内存排序。要在所有物理内存上强制 UC 内存类型和严格的内存排序,将所有物理内存的 MTRR 编程为 UC 内存类型或禁用所有 MTRR 就足够了。
对于 Pentium 4 和 Intel Xeon 处理器,在执行上述步骤序列之后,包含 WBINVD 指令末尾和 MTRRS 实际禁用之前的代码的缓存行可能会保留在缓存层次结构中。这里,要从缓存中完全删除代码,必须在禁用 MTRR 后执行第二条 WBINVD 指令。
这是一个很长的报价,但归结为这段代码
;Step 1 - Enter no-fill mode
mov eax, cr0
or eax, 1<<30 ; Set bit CD
and eax, ~(1<<29) ; Clear bit NW
mov cr0, eax
;Step 2 - Invalidate all the caches
wbinvd
;All memory accesses happen from/to memory now, but UC memory ordering may not be enforced still.
;For Atom processors, we are done, UC semantic is automatically enforced.
xor eax, eax
xor edx, edx
mov ecx, IA32_MTRR_DEF_TYPE ;MSR number is 2FFH
wrmsr
;P4 only, remove this code from the L1I
wbinvd
其中大部分不能从用户模式执行。
AMD 的手册 2在第 7.6.2 节中提供了类似的算法
7.6.2 高速缓存控制机制
AMD64 架构提供了许多控制内存高速缓存能力的机制。这些将在以下部分中进行描述。
缓存禁用。CR0 寄存器的第 30 位是高速缓存禁用位 CR0.CD。当 CR0.CD 清为 0 时启用缓存,当 CR0.CD 设置为 1 时禁用缓存。禁用缓存时,读写访问主内存。
软件可以在缓存仍然保存有效数据(或指令)时禁用缓存。如果在 CR0.CD=1 时读取或写入命中 L1 数据缓存或 L2 缓存,处理器将执行以下操作:
- 如果缓存线处于修改或拥有状态,则将其写回。
- 使高速缓存行无效。
- 执行不可缓存的主内存访问以读取或写入数据。
如果在 CR0.CD=1 时指令提取命中 L1 指令高速缓存,则某些处理器型号可能会读取高速缓存的指令,而不是访问主存储器。当 CR0.CD=1 时,L2 和 L3 缓存的确切行为取决于模型,并且可能因不同类型的内存访问而异。
当 CR0.CD=1 时,处理器也会响应缓存探测。命中缓存的探测会导致处理器执行步骤 1。仅当代表内存写入或独占读取执行探测时,才会执行步骤 2(缓存行无效)。
直写禁用。CR0 寄存器的第 29 位是非直写禁用位 CR0.NW。在早期的 x86 处理器中,CR0.NW 用于控制缓存的透写行为,CR0.NW 和 CR0.CD 的组合决定了缓存的运行模式。
[...]
在 AMD64 架构的实现中,CR0.NW 不用于限定由 CR0.CD 建立的缓存操作模式。
这转化为这段代码(非常类似于英特尔的代码):
;Step 1 - Disable the caches
mov eax, cr0
or eax, 1<<30
mov cr0, eax
;For some models we need to invalidated the L1I
wbinvd
;Step 2 - Disable speculative accesses
xor eax, eax
xor edx, edx
mov ecx, MTRRdefType ;MSR number is 2FFH
wrmsr
缓存也可以在以下位置选择性地禁用:
- 页级,属性位 PCD(Page Cache Disable)[仅适用于 Pentium Pro 和 Pentium II]。
当两者都明确时,使用相关的 MTTR,如果 PCD 设置为疼痛
- 页面级别,具有PAT(Page Attribute Table)机制。
通过填充IA32_PAT
缓存类型并使用位 PAT、PCD、PWT 作为 3 位索引,可以选择六种缓存类型(UC-、UC、WC、WT、WP、WB)中的一种。
- 使用 MTTR(固定或可变)。通过将特定物理区域
的缓存类型设置为 UC 或 UC- 。
在这些选项中,只有页面属性可以暴露给用户模式程序(例如,参见this)。