如何在linux上使用gcc程序集在x86-64中设置控制寄存器0(cr0)位

时间:2021-11-06 02:58:22

I am using the following code to set the cr0 bit to disable cache. When I compile this

我使用以下代码将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;
}

I am getting error saying that the operands are invalid for mov.

我收到错误说操作数对mov无效。

Can anyone please point me to a good gcc x86-64 guide for doing these kinds of things? Also what exactly is wrong with the above code?

谁能指点我做一个好的gcc x86-64指南来做这些事情?上面的代码究竟出了什么问题呢?

5 个解决方案

#1


6  

Ok, so finally I wrote the following kernel module. Am not sure it is right, since I don't observe the drastic slowdown which should accompany when you disable cache. But this compiles and inserts properly.

好的,最后我写了下面的内核模块。我不确定它是否正确,因为我没有观察到禁用缓存时应该伴随的急剧减速。但是这会正确编译和插入。

Any pointers will be helpful.

任何指针都会有所帮助。

Thanks!

#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);

#2


4  

I think you don't see the "drastic slowdown" because you have multiple cores, right? I made some experiments and it seems to me that setting CD in %cr0 only affects the processor your are running the module on.

我认为你没有看到“急剧减速”,因为你有多个核心,对吗?我做了一些实验,在我看来,在%cr0中设置CD只会影响你运行模块的处理器。

Make sure that you run your code on all cores where you want to disable caching. You could, for example, create a /proc/cachedisable file where a read triggers your code. Then use

确保在要禁用缓存的所有核心上运行代码。例如,您可以创建一个/ proc / cachedisable文件,其中读取会触发您的代码。然后用

taskset -c cpu_number cat /proc/cachedisable

to disable the caches on CPU cpu_number. Do the same with /proc/cacheenable and you have everything you need. This works for me and there is no need to alter the MTRRs, which is pretty complicated. If you have multiple processors then you can disable caching on only one of them and perform your experiments on this cpu. Then the rest of the system remains usable.

禁用CPU cpu_number上的缓存。使用/ proc / cacheenable执行相同的操作,即可获得所需的一切。这对我有用,没有必要改变MTRR,这是非常复杂的。如果您有多个处理器,那么您只能在其中一个处理器上禁用缓存并在此cpu上执行实验。然后系统的其余部分仍然可用。

#3


3  

You cannot do operations like this from user code and even running as root is user code.

您无法从用户代码执行此类操作,甚至以root身份运行也是用户代码。

You will need to make this into a driver module and load it using insmod.

您需要将其转换为驱动程序模块并使用insmod加载它。

#4


1  

Try this: "mov %%cr0, %%eax \n"

试试这个:“mov %% cr0,%% eax \ n”

A simple % is interpreted as user argument (I think).

一个简单的%被解释为用户参数(我认为)。

You should read this

你应该读这个

#5


0  

The code compiles OK for me on 32-bit x86 bit not on x86-64 - this is with gcc 4.2.1 on Mac OS X:

代码在32位x86位上编译好,而不是在x86-64上 - 这与Mac OS X上的gcc 4.2.1一致:

$ gcc -Wall -m32 cr0.c -o cr0
$

No errors or warnings.

没有错误或警告。

$ 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'
$

So I guess there are deeper issues than just the mov %eax,%cr0 instruction here with asm on x86-64.

所以我想有更深层次的问题,而不仅仅是mov%eax,%cr0指令在x86-64上使用asm。

Looking at the x86-64 ISA it seems that you probably need something like this for x86-64:

看看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;
}

I don't know if this works but it at least compiles/assembles OK:

我不知道这是否有效,但它至少可以编译/组装好:

$ gcc -Wall -m64 cr0.c -o cr0
$ 

#1


6  

Ok, so finally I wrote the following kernel module. Am not sure it is right, since I don't observe the drastic slowdown which should accompany when you disable cache. But this compiles and inserts properly.

好的,最后我写了下面的内核模块。我不确定它是否正确,因为我没有观察到禁用缓存时应该伴随的急剧减速。但是这会正确编译和插入。

Any pointers will be helpful.

任何指针都会有所帮助。

Thanks!

#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);

#2


4  

I think you don't see the "drastic slowdown" because you have multiple cores, right? I made some experiments and it seems to me that setting CD in %cr0 only affects the processor your are running the module on.

我认为你没有看到“急剧减速”,因为你有多个核心,对吗?我做了一些实验,在我看来,在%cr0中设置CD只会影响你运行模块的处理器。

Make sure that you run your code on all cores where you want to disable caching. You could, for example, create a /proc/cachedisable file where a read triggers your code. Then use

确保在要禁用缓存的所有核心上运行代码。例如,您可以创建一个/ proc / cachedisable文件,其中读取会触发您的代码。然后用

taskset -c cpu_number cat /proc/cachedisable

to disable the caches on CPU cpu_number. Do the same with /proc/cacheenable and you have everything you need. This works for me and there is no need to alter the MTRRs, which is pretty complicated. If you have multiple processors then you can disable caching on only one of them and perform your experiments on this cpu. Then the rest of the system remains usable.

禁用CPU cpu_number上的缓存。使用/ proc / cacheenable执行相同的操作,即可获得所需的一切。这对我有用,没有必要改变MTRR,这是非常复杂的。如果您有多个处理器,那么您只能在其中一个处理器上禁用缓存并在此cpu上执行实验。然后系统的其余部分仍然可用。

#3


3  

You cannot do operations like this from user code and even running as root is user code.

您无法从用户代码执行此类操作,甚至以root身份运行也是用户代码。

You will need to make this into a driver module and load it using insmod.

您需要将其转换为驱动程序模块并使用insmod加载它。

#4


1  

Try this: "mov %%cr0, %%eax \n"

试试这个:“mov %% cr0,%% eax \ n”

A simple % is interpreted as user argument (I think).

一个简单的%被解释为用户参数(我认为)。

You should read this

你应该读这个

#5


0  

The code compiles OK for me on 32-bit x86 bit not on x86-64 - this is with gcc 4.2.1 on Mac OS X:

代码在32位x86位上编译好,而不是在x86-64上 - 这与Mac OS X上的gcc 4.2.1一致:

$ gcc -Wall -m32 cr0.c -o cr0
$

No errors or warnings.

没有错误或警告。

$ 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'
$

So I guess there are deeper issues than just the mov %eax,%cr0 instruction here with asm on x86-64.

所以我想有更深层次的问题,而不仅仅是mov%eax,%cr0指令在x86-64上使用asm。

Looking at the x86-64 ISA it seems that you probably need something like this for x86-64:

看看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;
}

I don't know if this works but it at least compiles/assembles OK:

我不知道这是否有效,但它至少可以编译/组装好:

$ gcc -Wall -m64 cr0.c -o cr0
$