我使用以下代码将cr0位设置为禁用缓存。 当我编译这个
#include <stdio.h>
int main()
{
__asm__("pushl %eax\n\t"
"mov %cr0,%eax;\n\t"
"orl $(1 << 30),%eax;\n\t"
"mov %eax,%cr0;\n\t"
"wbinvd\n\t"
"popl %eax"
);
return 0;
}
我收到错误,说操作数对mov无效。
任何人都可以指点我做一个好的gcc x86-64指南来做这些事吗? 以上代码究竟出了什么问题?
答案 0 :(得分:8)
好的,最后我写了以下内核模块。我不确定它是否正确,因为我没有观察到禁用缓存时应该伴随的急剧减速。但是这会正确编译和插入。
任何指针都会有所帮助。
谢谢!
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
__asm__("push %rax\n\t"
"mov %cr0,%rax;\n\t"
"or $(1 << 30),%rax;\n\t"
"mov %rax,%cr0;\n\t"
"wbinvd\n\t"
"pop %rax"
);
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
__asm__("push %rax\n\t"
"mov %cr0,%rax;\n\t"
"and $~(1 << 30),%rax;\n\t"
"mov %rax,%cr0;\n\t"
"wbinvd\n\t"
"pop %rax"
);
}
module_init(hello_init);
module_exit(hello_exit);
答案 1 :(得分:4)
我认为你没有看到“急剧放缓”,因为你有多个核心,对吧? 我做了一些实验,在我看来,在%cr0中设置CD只会影响运行该模块的处理器。
确保在要禁用缓存的所有核心上运行代码。例如,您可以创建一个/ proc / cachedisable文件,其中读取会触发您的代码。然后使用
taskset -c cpu_number cat /proc/cachedisable
禁用CPU cpu_number上的缓存。使用/ proc / cacheenable执行相同操作,即可获得所需的一切。这对我有用,没有必要改变MTRR,这是非常复杂的。如果您有多个处理器,那么您只能在其中一个处理器上禁用缓存并在此cpu上执行实验。然后系统的其余部分仍然可用。
答案 2 :(得分:3)
您不能从用户代码执行此类操作,甚至以root身份运行也是用户代码。
您需要将其转换为驱动程序模块并使用insmod加载它。
答案 3 :(得分:1)
答案 4 :(得分:0)
代码在32位x86位上编译好,而不是在x86-64上 - 这是在Mac OS X上使用gcc 4.2.1:
$ gcc -Wall -m32 cr0.c -o cr0
$
没有错误或警告。
$ gcc -Wall -m64 cr0.c -o cr0
/var/folders/.../cce0FYAB.s:9:suffix or operands invalid for `push'
/var/folders/.../cce0FYAB.s:10:suffix or operands invalid for `mov'
/var/folders/.../cce0FYAB.s:12:suffix or operands invalid for `mov'
/var/folders/.../cce0FYAB.s:14:suffix or operands invalid for `pop'
$
所以我猜这里有更深层次的问题,而不仅仅是x6-64上asm的mov %eax,%cr0
指令。
看看x86-64 ISA似乎你可能需要x86-64这样的东西:
#include <stdio.h>
int main()
{
__asm__("pushq %rax\n\t"
"movq %cr0,%rax\n\t"
"orl $(1 << 30),%eax\n\t"
"movq %rax,%cr0\n\t"
"wbinvd\n\t"
"popq %rax"
);
return 0;
}
我不知道这是否有效,但它至少可以编译/组装好:
$ gcc -Wall -m64 cr0.c -o cr0
$