如何执行"invd"指令?



我正在尝试使用缓存作为临时内存。在使用缓存之后,我不想存储任何修改过的缓存行。我知道我可以通过运行invd指令来实现这一点。因为与wbinvd不同,invd会使处理器的内部缓存失效(刷新),而不会将它们存储在主存中。

我写了一个内核模块来检查我是否可以执行invd指令。

#include <linux/module.h>     /* Needed by all modules */
#include <linux/kernel.h>     /* Needed for KERN_INFO */
#include <linux/init.h>       /* Needed for the macros */
int new_invd(void){
asm volatile ("invd" : : : "memory");
return 1;
}
static int __init hello_start(void)
{
printk(KERN_INFO "Loading hello module...n");
//check if invd instruction executes  
printk(KERN_INFO "running invdn", new_invd());
return 0;
}
static void __exit hello_end(void)
{
printk(KERN_INFO "Goodbyen");
}
module_init(hello_start);
module_exit(hello_end);
在编译和插入模块后,我得到Segmentation fault (core dumped)dmesg显示,

[7525.227059]正在加载hello模块…[7525.227088]一般保护故障:0000 [#1]SMP

我使用铬中提到的asm volatile ("invd" : : : "memory");。现在我认为我得到的错误,因为执行invd违反了主存和缓存的一致性指出这里我怎么能做一个CPU缓存刷新在x86 Windows?作者:@Gunther Piez然而,我不确定情况是否如此。

所以,有人帮助我为什么得到这个segfault吗?如果这是由于违反缓存一致性,我该如何修复?如果没有,如何执行invd?

我用Linux xxx 4.4.0-200-generic #232-Ubuntu SMP Wed Jan 13 10:18:39 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

cat /proc/cpuinfo显示

vendor_id   : GenuineIntel
cpu family  : 6
model       : 158
model name  : Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz

您不能在Linux引导后安全地执行invd,特别是在SMP系统中,其他内核可能正在做任何事情(例如,有一些脏缓存行)。丢弃所有最近的存储显然会破坏所有地方的东西,就像宇宙射线在缓存或RAM中翻转了一堆位一样。

如果你想通过运行invd来破坏你的系统,你的内联asm语句是正确的。

不支持丢弃特定缓冲区的内容,而且我认为invd无论如何都很慢。加上睡眠所有其他核心的成本(在CPU模型上,深度睡眠会刷新私人缓存),并以某种方式确保L3缓存同步,比如wbinvd(也非常慢)在你运行这个温度缓冲的东西+invd(禁用中断和其他核心睡眠的整个时间)。

对于性能来说,让硬件最终回写你的缓冲区肯定要好得多。保持它的小,重用它,也许它不会在两次使用之间被写回来。

我不认为有任何方法可以安全地使用invd,这可能是性能上的胜利。即使您只关心单核性能,也可能不会。(NT存储和/或clflush可以使一些存储在invd之前转到DRAM,所以使用它几乎是不合理的,但它可能太贵了,根本不值得。)

最新更新