在 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<<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 上设置写缓存策略以写回的主要内容,如果未能解决你的问题,请参考以下文章