как установить 0 (cr0) бит управления регистром в x86-64, используя сборку gcc в linux - PullRequest
8 голосов
/ 19 октября 2010

Я использую следующий код, чтобы установить бит 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;
}

Я получаю сообщение о том, что операнды недопустимы для mov.

Может ли кто-нибудь указать мне хорошее руководство по gcc x86-64 для таких вещей? И что именно не так с приведенным выше кодом?

Ответы [ 5 ]

8 голосов
/ 19 октября 2010

Хорошо, наконец, я написал следующий модуль ядра.Я не уверен, что это правильно, поскольку я не наблюдаю резкого замедления, которое должно сопровождаться при отключении кеша.Но это компилируется и вставляется правильно.

Любые указатели будут полезны.

Спасибо!

#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);
4 голосов
/ 04 декабря 2012

Я думаю, что вы не видите "резкого замедления", потому что у вас есть несколько ядер, верно? Я провел несколько экспериментов, и мне кажется, что установка CD в% cr0 влияет только на процессор, на котором вы запускаете модуль.

Убедитесь, что вы запускаете свой код на всех ядрах, где вы хотите отключить кэширование. Например, вы можете создать файл / proc / cachedisable, в котором чтение запускает ваш код. Тогда используйте

taskset -c cpu_number cat /proc/cachedisable

для отключения кэшей на процессоре cpu_number. Сделайте то же самое с / proc / cacheenable, и у вас есть все, что вам нужно. Это работает для меня, и нет необходимости изменять MTRR, что довольно сложно. Если у вас несколько процессоров, вы можете отключить кэширование только на одном из них и провести эксперименты на этом процессоре. Тогда остальная часть системы останется пригодной для использования.

3 голосов
/ 19 октября 2010

Вы не можете выполнять такие операции из кода пользователя, и даже запуск от имени пользователя root является кодом пользователя.

Вам нужно будет сделать это в модуле драйвера и загрузить его с помощью insmod.

1 голос
/ 19 октября 2010

Попробуйте это: "mov %% cr0, %% eax \ n"

Простой% интерпретируется как пользовательский аргумент (я думаю).

Вы должны прочитать это

0 голосов
/ 19 октября 2010

Код компилируется нормально для меня на 32-битной версии x86, а не на x86-64 - это с gcc 4.2.1 на Mac OS X:

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

Нет ошибок или предупреждений.

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

Так что, я думаю, здесь есть более глубокие проблемы, чем просто инструкция mov %eax,%cr0 с asm на x86-64.

Глядя на ISA x86-64, кажется, что для 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;
}

Я не знаю, работает ли это, но, по крайней мере, он компилируется / собирается. ОК:

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