how to set control register 0 (cr0) bits in x86-64 using gcc assembly on linux

pranith picture pranith · Oct 18, 2010 · Viewed 8.2k times · Source

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

#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.

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?

Answer

pranith picture pranith · Oct 18, 2010

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