Mik*_*ike 8 c assembly kernel linux-kernel
我正在尝试在Xen中禁用我的机器Intel(R)Xeon(R)CPU E5-1650 v2 @ 3.50GHz的所有级别的缓存.我编写了一个工具来调用以下汇编代码来禁用/启用缓存并显示CR0寄存器的值.
case XENMEM_disable_cache:
__asm__ __volatile__(
"pushq %%rax\n\t"
"movq %%cr0,%%rax\n\t"
"orq $0x40000000,%%rax\n\t"
"movq %%rax,%%cr0\n\t"
"movq %%cr0, %0\n\t"
"wbinvd\n\t"
"popq %%rax"
: "=r"(cr0)
:
:);
// gdprintk(XENLOG_WARNING, "gdprintk:XENMEM_disable_cache disable cache!
// TODO IMPLEMENT\n");
printk("<1>printk: disable cache! cr0=%#018lx\n", cr0);
rc = 0;
break;
case XENMEM_enable_cache:
__asm__ __volatile__(
"pushq %%rax\n\t"
"movq %%cr0,%%rax\n\t"
"andq $0xffffffffbfffffff,%%rax\n\t" /*~0x4000000*/
"movq %%rax,%%cr0\n\t"
"movq %%cr0, %0\n\t"
"popq %%rax"
: "=r"(cr0)
:
:);
printk("<1>printk: enable cache; cr0=%#018lx\n", cr0);
rc = 0;
break;
case XENMEM_show_cache:
__asm__ __volatile__(
"pushq %%rax\n\t"
"movq %%cr0, %%rax\n\t"
"movq %%rax, %0\n\t"
"popq %%rax"
: "=r"(cr0)
:
:);
// gdprintk(XENLOG_WARNING, "gdprintk:XENMEM_show_cache_status! CR0 value is
// %#018lx\n", cr0);
printk("<1>printk: XENMEM_show_cache_status! CR0 value is %#018lx\n", cr0);
return (long)cr0;
Run Code Online (Sandbox Code Playgroud)
代码可以编译和运行.运行禁用缓存代码后,系统变得非常慢,这确认缓存被禁用.此外,CR0的值表示在运行禁用缓存代码时设置了CD位.
但是,当我运行show cache代码时,输出显示CR0的CD位为0,无论我禁用/启用缓存.
我的问题是:
当禁用缓存时,CR0寄存器的CD位(30位)是否始终设置为1?
如果没有,我的代码肯定有问题,你能帮我指出我犯的错误吗?
回答:
上面的代码只在运行代码的内核上设置CR0寄存器的CD位.我们需要使用smp_call_function()来调用所有内核上的代码!
我的新问题是:
如果我禁用缓存然后使用上面的代码启用缓存,则清除CR0的CD位.但是,系统的性能仍然非常慢,就像我禁用缓存一样.所以在我看来,启用缓存代码不起作用?但是,由于CD位已被清除,启用缓存代码应该可以工作!所以问题是:在启用缓存之后我应该等待多长时间才能获得与禁用缓存之前的性能相同的性能?
顺便说一下,当我运行enble缓存代码时,printk输出显示CR0的CD位为0.
如果您使用的是SMP系统,则应为每个内核调用disable-cache代码smp_call_function(),因为理论上您的show-cache代码可能在不同的处理器上运行.要使用该功能,#include <include/linux/smp.h>.
编辑:smp_call_function()调用仅在其他核心上给出的函数指针,而不是在当前核心上.确保通过在调用的核心上调用该函数来在所有核心上运行该函数smp_call_function().