在 Intel CPU 上设置写缓存策略以写回

Posted

技术标签:

【中文标题】在 Intel CPU 上设置写缓存策略以写回【英文标题】:Set write cache policy on Intel CPU to write back 【发布时间】:2015-11-11 19:07:54 【问题描述】:

我正在尝试将我的 CPU 缓存写入策略设置为“回写”,因此我需要设置 CR0.NW = 1。

我写了一个内核模块:

int
init_module (void)

  printk (KERN_INFO "init_module\n\n\n");
  uint64_t cr0;
  asm volatile ("mov %%cr0,%%rax\n\t":"=a"(cr0));
  printk(KERN_INFO"CR0 ===== %ld\n",cr0);

  asm volatile("push %rax\n\t" "push %rbx\n\t");

    asm volatile( //disable cache before changing cr0.nw
    "mov $1,%rbx\n\t"
    "shl $30,%rbx\n\t"
    "mov %cr0,%rax\n\t"
    "xor %rbx,%rax\n\t"
    "mov %rax,%cr0\n\t"
    "wbinvd\n\t"  //flush
  );

  asm volatile( //invert bit
    "mov $1,%rbx\n\t"
    "shl $29,%rbx\n\t"
    "mov %cr0,%rax\n\t"
    "xor %rbx,%rax\n\t"
    "mov %rax,%cr0\n\t"
  );

      asm volatile( //enable cache
        "mov $1,%rbx\n\t"
        "shl $30,%rbx\n\t"
        "mov %cr0,%rax\n\t"
        "xor %rbx,%rax\n\t" //xor : 1 => 0 , 0 => 1
       "mov %rax,%cr0\n\t"
       "wbinvd\n\t"  //flush
    );
     asm volatile("pop %rbx\n\t" "pop %rax\n\t");
    return 0;
    

但它不起作用。 dmesg给我:

[ 1190.301973] general protection fault: 0000 [#1] SMP
[ 1190.301975] Modules linked in: cache(POE+) ipt_MASQUERADE iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ipt_REJECT xt_CHECKSUM iptable_mangle xt_tcpudp bridge stp llc ip6table_filter ip6_tables iptable_filter ip_tables ebtable_nat ebtables x_tables bnep rfcomm bluetooth 6lowpan_iphc binfmt_misc nls_iso8859_1 nvidia(POE) cp210x usbserial joydev snd_hda_codec_hdmi eeepc_wmi asus_wmi sparse_keymap snd_hda_codec_realtek snd_hda_codec_generic intel_rapl snd_hda_intel x86_pkg_temp_thermal intel_powerclamp snd_hda_controller coretemp snd_hda_codec kvm_intel snd_hwdep snd_pcm kvm snd_seq_midi snd_seq_midi_event crct10dif_pclmul crc32_pclmul snd_rawmidi ghash_clmulni_intel aesni_intel snd_seq aes_x86_64 lrw gf128mul glue_helper ablk_helper cryptd nouveau serio_raw mxm_wmi ttm snd_seq_device snd_timer lpc_ich drm_kms_helper drm snd mei_me mei soundcore i2c_algo_bit shpchp wmi video mac_hid soc_button_array tpm_infineon parport_pc ppdev lp parport uas usb_storage hid_generic usbhid hid ahci r8169 psmouse libahci mii
[ 1190.302013] CPU: 5 PID: 5159 Comm: insmod Tainted: P           OE 3.16.0-45-generic #60~14.04.1-Ubuntu
[ 1190.302014] Hardware name: ASUS All Series/Z87-A, Bios 1007 05/17/2013
[ 1190.302015] task: ffff8807d95765e0 ti: ffff8807d95b0000 task.ti: ffff8807d95b0000
[ 1190.302016] RIP: 0010:[<ffffffffc0fd402a>]  [<ffffffffc0fd402a>] init_module+0x2a/0x40 [cache]
[ 1190.302019] RSP: 0018:ffff8807d95b3d30  EFLAGS: 00010206
[ 1190.302019] RAX: 00000000a0050033 RBX: 0000000020000000 RCX: 0000000000000000
[ 1190.302020] RDX: ffff88081ed4ee40 RSI: ffff88081ed4d418 RDI: 0000000000000246
[ 1190.302021] RBP: ffff8807d95b3d40 R08: 0000000000000082 R09: 00000000000012e5
[ 1190.302022] R10: 0000000000000000 R11: ffff8807d95b3a5e R12: ffff8807ef817de0
[ 1190.302022] R13: 0000000000000000 R14: ffffffffc0fd4000 R15: ffffffffc0fd6000
[ 1190.302023] FS:  00007f405d04f740(0000) GS:ffff88081ed40000(0000) knlGS:0000000000000000
[ 1190.302024] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1190.302025] CR2: 00007f405d26a248 CR3: 00000007e5d81000 CR4: 00000000001407e0
[ 1190.302026] Stack:
[ 1190.302026]  ffffffff81c1a020 000000000000000d ffff8807d95b3db8 ffffffff81002144
[ 1190.302028]  0000000000000001 0000000000000001 0000000000000001 ffff8800dca9b440
[ 1190.302029]  0000000000000001 ffff8807d95b3da0 ffffffff8119d7d2 ffffffffc0fd6018
[ 1190.302030] Call Trace:
[ 1190.302035]  [<ffffffff81002144>] do_one_initcall+0xd4/0x210
[ 1190.302037]  [<ffffffff8119d7d2>] ? __vunmap+0xb2/0x100
[ 1190.302039]  [<ffffffff810edd79>] load_module+0x13d9/0x1b90
[ 1190.302043]  [<ffffffff810e9910>] ? store_uevent+0x40/0x40
[ 1190.302044]  [<ffffffff810ee6a6>] SyS_finit_module+0x86/0xb0
[ 1190.302048]  [<ffffffff8176e34d>] system_call_fastpath+0x1a/0x1f
[ 1190.302048] Code: <0f> 22 c0 5b 58 31 c0 5d c3 66 66 66 66 2e 0f 1f 84 00 00 00 00 00
[ 1190.302055] RIP  [<ffffffffc0fd402a>] init_module+0x2a/0x40 [cache]
[ 1190.302056]  RSP <ffff8807d95b3d30>
[ 1190.302057] ---[ end trace bf14887f4e905bad ]---

你知道发生了什么吗?这不是说我不能改变 CR0.NW 吗?

我的 CPU : i7-4770K

【问题讨论】:

为什么不直接告诉 gcc 你破坏了一个寄存器,使用带约束的扩展 asm?假设编译器没有在您的 asm volatile 语句之间放置任何代码也是不安全的。此外,xor 可以采用 32 位立即参数。因此,与其浪费两条指令加载立即的0x00000001,然后在运行时移动它,您应该刚刚完成xor $(1&lt;&lt;29), %rax。或者使用 inline-asm 将 %cr0 转换为 C long,与 C 进行异或,然后将其放入 %cr0 对于将来想做类似事情的人,不要复制这个内联汇编;真恶心。 【参考方案1】:

根据Intel's manual提供的信息(见表11-5), 当 CR0.CD 为 0 时,不允许将 CR0.NW 设置为 1。

我假设您尝试同时更改写入策略 (CR.NW=1) 和使用缓存 (CR.CD = 0),这是无效的。

我在找和你一样的东西时发现了它......

【讨论】:

以上是关于在 Intel CPU 上设置写缓存策略以写回的主要内容,如果未能解决你的问题,请参考以下文章

并发编程MESI--CPU缓存一致性协议

缓存策略了解一下(完整版)

高速缓存一致性协议MESI与内存屏障

直写与回写

Intel CPU 漏洞分析

关于并发可见性的一点理解