在intel 64bit机器上启用/禁用缓存:CD位总是设置?

时间:2014-01-21 18:03:37

标签: c assembly linux-kernel 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;

代码可以编译和运行。运行禁用缓存代码后,系统变得非常慢,这确认缓存被禁用。此外,CR0的值表示在运行禁用缓存代码时设置了CD位。

但是,当我运行show cache代码时,输​​出显示CR0的CD位为0,无论我禁用/启用缓存。

我的问题是:

当禁用缓存时,CR0寄存器的CD位(30位)是否始终设置为1?

如果没有,我的代码肯定有问题,你能帮我指出我犯的错误吗?

解答:

以上代码仅在运行代码的核心上设置CR0寄存器的CD位。我们需要使用smp_call_function()来调用所有内核上的代码!

我的新问题是:

如果我禁用缓存然后使用上面的代码启用缓存,则清除CR0的CD位。但是,系统的性能仍然非常慢,就像我禁用缓存一样。所以在我看来,启用缓存代码不起作用?但是,由于CD位已被清除,启用缓存代码应该可以工作!所以问题是:在启用缓存后我应该等多久才能获得与禁用缓存之前的性能相同的性能?

BTW,当我运行enble缓存代码时,printk输出显示CR0的CD位为0。

1 个答案:

答案 0 :(得分:6)

如果您使用的是SMP系统,则应为smp_call_function()的每个核心调用disable-cache代码,因为理论上您的show-cache代码可能在不同的处理器上运行。要使用该功能,#include <include/linux/smp.h>

编辑:smp_call_function()调用仅在其他核上给出的函数指针,而不是当前的。确保通过在调用smp_call_function()的核心上自行调用该函数来在所有核心上运行该函数。