【问题标题】:How to execute "invd" instruction?如何执行“invd”指令?
【发布时间】:2021-05-14 17:22:30
【问题描述】:

我正在尝试将缓存用作临时内存。在使用缓存之后,我不想存储任何修改过的缓存行。我开始知道我可以通过运行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 invd\n", new_invd());

    return 0;
}

static void __exit hello_end(void)
{
    printk(KERN_INFO "Goodbye\n");
}

module_init(hello_start);
module_exit(hello_end);

编译并插入模块后,我得到Segmentation fault (core dumped)dmesg 显示,

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

我使用asm volatile ("invd" : : : "memory"); 中提到的chromium。现在我认为我收到了错误,因为执行invd 违反了主内存和缓存的一致性,正如@Gunther Piez 在How can I do a CPU cache flush in x86 Windows? 中指出的那样。但是,我不确定是否是这种情况。

那么,为什么我得到这个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 系统中(即有一些脏缓存行)。丢弃所有最近的商店显然会破坏所有东西。
  • @PeterCordes 如果其他核心处于无填充模式,仍然是真的吗?
  • @PeterCordes,有没有 invd 的替代品来实现同样的目标?
  • 不支持丢弃特定缓冲区的内容,而且我认为invd 仍然很慢。加上睡眠所有其他内核的成本(在深度睡眠刷新私有缓存的 CPU 模型上)并以某种方式确保甚至 L3 缓存同步,比如在运行这个临时缓冲区之前可能wbinvd(也非常慢)+@987654342 @(禁用中断,其他内核一直处于休眠状态)。几乎可以肯定的是,让硬件最终写回你的缓冲区对性能来说要好得多。保持小并重复使用它,也许它不会在使用之间写回。
  • 查找支持 CAT 技术的 CPU。 Linux内核中甚至有(曾经?)驱动程序。 software.intel.com/content/www/us/en/develop/articles/…

标签: linux caching x86-64 kernel-module cpu-cache


【解决方案1】:

您无法在 Linux 启动后安全地执行 invd,尤其是在其他内核可能正在执行任何操作(即有一些脏缓存行)的 SMP 系统中。丢弃所有最近的存储显然会破坏所有东西,就像宇宙射线翻转缓存或 RAM 中的一堆位一样。

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

不支持丢弃特定缓冲区的内容,而且invd 无论如何我认为很慢。加上休眠所有其他内核的成本(在深度睡眠刷新私有缓存的 CPU 型号上)并以某种方式确保甚至 L3 缓存同步,比如在运行这个临时缓冲区之前可能wbinvd(也非常慢)+@987654324 @(禁用中断,其他内核一直处于休眠状态)。

让硬件最终写回您的缓冲区几乎可以肯定性能要好得多。保持小并重复使用它,也许它不会在使用之间写回。

我认为没有任何方法可以安全地使用invd,这可能会赢得任何性能。即使您只关心单核性能,也可能不会。 (NT 商店和/或clflush 可以让一些商店在invd 之前使用 DRAM,因此使用它几乎不可能,但它可能太贵了,根本不值得。)

【讨论】:

  • 谢谢。我不担心性能。因为我的目标只是验证,所以我在缓存中运行的任何内容都不会显示在主内存中。
  • @user45698746:如果您为此在无填充模式下运行,那么在重新启用回写+填充之前,只需在缓冲区上使用memset(0)
猜你喜欢
  • 2017-06-06
  • 2021-06-11
  • 1970-01-01
  • 1970-01-01
  • 2017-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多