x86 / x86_64架构的每个现代高性能CPU都有一些数据缓存层次结构:L1,L2,有时是L3(在极少数情况下是L4),从/到主RAM加载的数据缓存在某些他们
有时程序员可能希望某些数据不会缓存在某些或所有缓存级别中(例如,当想要memset 16 GB的RAM并保留一些数据仍在缓存中时):有一些非时间(NT) )像MOVNTDQA(https://stackoverflow.com/a/37092 http://lwn.net/Articles/255364/)
这样的说明但是有一种编程方式(对于某些AMD或Intel CPU系列,如P3,P4,Core,Core i *,......)完全(但暂时)关闭部分或全部级别的缓存,以进行更改每个内存访问指令(全局或某些应用程序/ RAM区域)如何使用内存层次结构?例如:关闭L1,关闭L1和L2?或者将每个内存访问类型更改为“未缓存”UC(CR0的CD + NW位??? SDM vol3a页423 424,425和“三级缓存禁用标志,IA32_MISC_ENABLE MSR的第6位(仅在基于英特尔NetBurst微体系结构的处理器中可用) - 允许禁用和启用L3缓存,独立于L1和L2缓存。“)。
我认为这样的行动将有助于保护数据免受缓存侧通道攻击/泄漏,如窃取AES密钥,隐蔽缓存通道,Meltdown / Spectre。虽然这种禁用会产生巨大的性能损失。
PS:我记得很多年前在一些技术新闻网站上发布的这样一个程序,但现在找不到它。将一些神奇的值写入MSR只是一个Windows exe,并使每个Windows程序运行得很慢。缓存关闭直到重新启动或直到使用“撤消”选项启动程序。答案 0 :(得分:10)
The Intel's manual 3A,第11.5.3节,提供了全局禁用缓存的算法:
11.5.3防止缓存
要在启用并收到缓存填充后禁用L1,L2和L3缓存,请执行以下步骤:
- 进入无填充缓存模式。 (将控制寄存器CR0中的CD标志设置为1,将NW标志设置为0。
- 使用WBINVD指令刷新所有缓存。
- 禁用MTRR并将默认内存类型设置为未缓存或为未缓存的内存设置所有MTRR type(参见第11.11.2.1节中对TYPE字段和E标志的讨论的讨论, “IA32_MTRR_DEF_TYPE MSR”)。
醇>在设置CD标志以确保系统内存一致性后,必须刷新缓存(步骤2)。如果缓存是 如果没有刷新,则仍会发生缓存命中读取,并且将从有效的缓存行中读取数据。
上面列出的三个独立步骤的目的是满足三个不同的要求:(i)停止新数据 替换高速缓存中的现有数据(ii)确保已经在高速缓存中的数据被驱逐到存储器,(iii)确保后续存储器引用观察UC存储器类型语义。不同的处理器实现缓存 控制硬件可以允许这三个要求的软件实现的一些变化。见下面的注释。
备注强> 在控制寄存器CR0中设置CD标志会修改处理器的缓存行为,如图所示 在表11-5中,但仅在所有处理器系列中设置CD标志可能不够 强制所有物理内存的有效内存类型为UC,也不强制严格的内存 由于不同处理器系列的硬件实现变化,排序。强迫 对所有物理内存的UC内存类型和严格的内存排序,它们都足够了 将所有物理内存的MTRR编程为UC内存类型或禁用所有MTRR。
对于Pentium 4和Intel Xeon处理器,按照上面给出的步骤顺序完成后 执行时,缓存行包含WBINVD指令结束和之间的代码 在MTRRS实际被禁用之前,可以保留在缓存层次结构中。这里,要完全从缓存中删除代码,必须在执行后执行第二条WBINVD指令 MTRR已被禁用。
这是一个很长的引用,但归结为此代码
;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's manual 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
还可以在以下位置选择性地禁用缓存:
IA32_PAT
并使用PAT,PCD,PWT位作为3位索引,可以选择六种缓存类型中的一种(UC-,UC,WC,WT,WP) ,WB)。 在这些选项中,只有页面属性可以暴露给用户模式程序(例如参见this)。