首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在现代x86/amd64 64芯片上关闭L1、L2、L3 CPU缓存?

如何在现代x86/amd64 64芯片上关闭L1、L2、L3 CPU缓存?
EN

Stack Overflow用户
提问于 2018-01-20 19:26:42
回答 1查看 11.6K关注 0票数 15

x86/x86_64体系结构中的每一个现代高性能CPU都有一些数据缓存的层次结构: L1、L2,有时还有L3 (在非常罕见的情况下还有L4 ),其中一些缓存从主内存加载到主内存中的数据。

有时,程序员可能希望某些数据不被缓存在一些或所有缓存级别中(例如,当需要memset 16 GB内存并将一些数据保存在缓存中时):有一些非时态(NT)指令用于这类操作,如MOVNTDQA (https://stackoverflow.com/a/37092 http://lwn.net/Articles/255364/)。

但是是否有一种编程方式(对于一些AMD或Intel家族,如P3、P4、Core、Core *、.)若要完全(但暂时)关闭部分或所有级别的缓存,则要更改每个内存访问指令(全局或某些应用程序/RAM区域)如何使用内存层次结构?例如:关闭L1,关闭L1和L2?或者将每个内存访问类型更改为"uncached“UC (CD+NW位CR0?)SDM vol3a pages 423 424425和“第三级缓存禁用标志,IA32_MISC_ENABLE MSR的第6位(仅在基于Intel NetBurst微体系结构的处理器中可用)允许L3缓存被禁用和启用,而不依赖于L1和L2缓存。”

我认为这样做将有助于保护数据免受高速缓存端通道的攻击/泄漏,如窃取AES密钥、秘密缓存通道、熔毁/幽灵。虽然这种禁用会带来巨大的性能成本。

PS:我记得很多年前在一些技术新闻网站上发布了这样一个程序,但现在找不到了。它只是一个Windows,将一些神奇的值写入到MSR中,并使每个Windows程序在它之后运行得非常慢。缓存被关闭,直到重新启动,或直到使用“撤销”选项启动程序。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-20 22:02:40

英特尔的3A手册第11.5.3节提供了一种全局禁用缓存的算法:

11.5.3防止缓存 若要在启用L1、L2和L3缓存并接收缓存填充后禁用它们,请执行以下步骤:

  1. 输入无填充缓存模式。(将控制寄存器CR0中的CD标志设置为1,NW标志设置为0。
  2. 使用WBINVD指令刷新所有缓存。
  3. 禁用MTRRs并将默认内存类型设置为未缓存内存类型或设置未缓存内存类型的所有MTRR(请参阅11.11.2.1节“IA32_MTRR_DEF_TYPE MSR”中关于类型字段和E标志的讨论)。

必须在设置CD标志后刷新缓存(步骤2),以确保系统内存的一致性。如果没有刷新缓存,那么读取时仍然会发生缓存命中,数据将从有效的缓存行中读取。

上面列出的三个单独步骤的意图解决了三个不同的要求:(一)停止替换缓存中现有数据的新数据;(二)确保缓存中已经存在的数据被逐出到内存中;(三)确保后续内存引用遵守UC内存类型语义。不同的处理器实现缓存控制硬件可能允许这三个需求的软件实现的一些变化。见下文注。

注意到,在控制寄存器中设置CD标志的修改了表11-5中所示的处理器的缓存行为,但是在所有处理器家族中单独设置CD标志可能不足以强制所有物理内存类型为UC,也不强制严格的内存排序,因为不同处理器系列的硬件实现不同。要强制UC内存类型和对所有物理内存进行严格的内存排序,只需将所有物理内存的MTRR编程为UC内存类型或禁用所有MTRR即可。

对于奔腾4和Intel Xeon处理器,在执行上述步骤之后,包含WBINVD指令结束和MTRRS实际禁用之前的代码的缓存行可以保留在缓存层次结构中。在这里,要从缓存中完全删除代码,必须在MTRRs被禁用后执行第二条WBINVD指令。

这是一个很长的引号,但归根结底是这个代码

代码语言:javascript
运行
复制
;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时,缓存被禁用。当缓存被禁用时,读取和写入访问主存。软件可以在缓存仍然保存有效数据(或指令)时禁用缓存。如果读或写在L1数据缓存或L2缓存( CR0.CD=1 )时命中,则处理器执行以下操作:

  1. 如果缓存行处于已修改或拥有状态,则将其写回。
  2. 使缓存行无效。
  3. 执行不可缓存的主内存访问以读取或写入数据.

如果当一个L1指令缓存被CR0.CD=1访问时,一些处理器模型可能会读取缓存的指令,而不是访问主存。当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建立的缓存操作模式。

这将转换为以下代码(非常类似于Intel的代码):

代码语言:javascript
运行
复制
;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

还可以在以下位置选择性地禁用缓存:

  • 页面级别,只有Pentium Pro和Pentium II的属性位PCD (Page禁用)。 当两者都清楚时,使用相关的MTTR,如果PCD被设置为
  • 页面级别,具有PAT (Page属性表)机制。 通过使用缓存类型填充IA32_PAT并使用bits、PCD、PWT作为3位索引,可以选择六种缓存类型之一( UC -、UC、WC、WT、WP、WB)。
  • 使用MTTRs (固定或可变)。 将缓存类型设置为UC或UC-用于特定的物理区域。

在这些选项中,只有页面属性可以公开给用户模式程序(例如,请参见 )。

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48360238

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档