显然,x86 INVD
使高速缓存层次结构无效,而不将内容写回内存.
我很好奇,这样的教学有什么用?鉴于人们对各种缓存级别的数据控制得很少,甚至对异步刷新的内容控制得更少,这似乎只是一种确保你不知道什么数据的方法.再也不在记忆中了.
好问题!
这种钝性指令的一个用例,如invd
专用或非常早期的自举代码,例如当RAM的存在或不存在尚未被验证时.由于我们可能不知道RAM是否存在,其大小,或者即使其特定部分正常运行,或者我们可能不想依赖它,因此CPU有时可以将其自身缓存的一部分编程为RAM操作并使用它.这称为Cache-as-RAM(CAR).在设置CAR期间,在使用CAR时,以及在拆卸CAR模式期间,内核必须确保没有任何内容从该缓存写入内存.
要设置CAR,必须将CPU设置为No-Fill Cache Mode,并且必须将用作CAR的内存范围指定为Write-Back.这可以通过以下步骤完成:
设置MTRR(存储器类型范围寄存器)以将一块存储器指定为WB(回写).
invd
整个缓存,防止任何缓存的写入被写出并导致混乱.
将缓存模式设置为正常缓存模式(cr0.CD=0
).
在正常缓存模式下,通过读取"触摸"内存跨度的所有缓存行以用作CAR,从而用它填充缓存.填充高速缓存行只能在正常高速缓存模式下完成.
将缓存模式设置为No-Fill Cache Mode(cr0.CD=1
).
设置CAR的动机是,一旦设置,CAR区域内的所有访问(读/写)将达到缓存而不会达到RAM,但缓存的内容将是可寻址的,并且就像RAM一样.因此,不是编写只使用寄存器的汇编程序代码,现在可以使用普通的C代码,只要它访问的堆栈和本地/全局变量被限制在CAR区域内.
当退出CAR时,在这个"伪RAM"中发生的所有内存写入突然从缓存中射出并丢弃RAM中同一地址的任何实际内容将是一件坏事.因此,当退出CAR时,再次invd
用于完全删除CAR区域的内容,然后设置正常缓存模式.
英特尔提到了i486微处理器程序员参考手册中的Cache-as-RAM使用.Intel 80486是首次引入该invd
指令的CPU .第12.2节阅读:
12.2内部缓存的操作
软件控制缓存的操作模式.可以启用缓存(复位初始化后的状态),可以在存在有效缓存行时缓存缓存(缓存充当快速内部RAM的模式),或者可以完全禁用缓存.
禁用缓存时必须遵循预防措施.只要CD设置为1,如果副本仍在缓存中,i486处理器将无法读取外部存储器.每当NW设置为1时,如果数据在缓存中,i486处理器将不会写入外部存储器.这意味着过时的数据可以在i486 CPU缓存中开发.如果NW稍后设置为0,或者由于高速缓存未命中而稍后覆盖该高速缓存行,则该过时数据将不会写入外部存储器.通常,禁用时应刷新缓存.
通过在设置CD和NW时使用测试寄存器加载数据,可以冻结缓存中的数据.这对于为时间关键的中断代码和数据提供有保证的高速缓存命中非常有用.
请注意,所有段应从16字节边界开始,以允许程序将高速缓存行中的代码/数据对齐.
Libreboot有一个幻灯片,展示了他们对CAR的实现,描述了上述过程.invd
幻灯片21使用该指令.
AMD称之为§2.3.3中的 Cache-as-general-storage :在引导期间使用L2缓存作为通用存储.
在某些涉及由DMA(直接存储器访问)硬件引起的高速缓存不兼容的情况下,invd
也可能证明是有用的.