在Intel 64位计算机上启用/禁用缓存:CD位始终设置?

8

我想要在我的Intel(R) Xeon(R) CPU E5-1650 v2 @ 3.50GHz机器上禁用所有的缓存级别,并使用Xen技术。我编写了一个工具,调用以下汇编代码来禁用/启用缓存并显示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;

这段代码可以编译并运行。当我运行“disable cache”代码后,系统变得异常缓慢,这证实缓存已经被禁用。此外,当我运行“disable cache”代码时,CR0的值显示CD位被设置。

然而,当我运行“show cache”代码时,输出显示无论是否禁用/启用缓存,CR0的CD位都是0。

我的问题是:

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

如果不是,那么我的代码一定有问题,请帮我指出错误。

答案:

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

我的新问题是:

如果我使用以上代码禁用缓存,然后再启用缓存,CR0的CD位会被清除。但是系统的性能仍然非常缓慢,就像缓存被禁用时一样。因此,对我来说好像启用缓存代码没有起作用?然而,既然CD位已经被清除,启用缓存代码应该起作用了!所以问题是:我需要等多久才能在启用缓存后拥有与禁用缓存前相同的性能?

顺便说一下,当我运行启用缓存代码时,printk输出显示CR0的CD位为0。


2
如果您正在使用SMP系统,是否需要使用smp_call_function()为每个核心调用禁用缓存代码?理论上可能会出现您的显示缓存代码在不同的处理器上运行的情况。我还建议您阅读英特尔的软件开发手册,第3卷,第11章(内存缓存控制),特别是第11.5.1节“缓存控制寄存器和位”。 - Iwillnotexist Idonotexist
嗨@IwillnotexistIdonotexist,非常感谢您指出smp_call_function()的问题;我同意这可能是原因。我正在修改代码。但我找不到应该包含哪个头文件来使用此函数。您有任何想法如何找到头文件吗? - Mike
1
我猜想应该是 include/linux/smp.h - Iwillnotexist Idonotexist
1
它最终成功了吗? - Iwillnotexist Idonotexist
1
是的! @IwillnotexistIdonotexist,它终于起作用了!但是在设置所有内核的CR0 CD后,速度极慢。在Xwindows中,我甚至无法使用键盘。我配置串行输出以在线获取输出。最终可以显示CR0的结果。 :) - Mike
显示剩余3条评论
1个回答

6
如果您使用的是SMP系统,应该对每个核心使用smp_call_function()禁用缓存代码,因为理论上您的show-cache代码可能在另一个处理器上运行。要使用该函数,请包含#include <include/linux/smp.h>
编辑:smp_call_function()仅在其他核心上调用所给定的函数指针,而不是在当前核心上调用。通过在调用smp_call_function()的核心上自己调用该函数,确保在所有核心上运行该函数。

你好!内核模块的最终源代码将是什么?可以用于https://dev59.com/xVYM5IYBdhLWcg3wzCdg吗? - osgx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接