Как получить доступ к управляющим регистрам cr0, cr2, cr3 из программы?Получение ошибки сегментации - PullRequest
10 голосов
/ 14 сентября 2011

Я написал программу, которая пытается читать и записывать в управляющие регистры.

Программа компилируется нормально, но когда собирается выполнить встроенную сборку, возникает ошибка сегментации.

Код:

void instructions(int val)
{
    int i;
    int value;
    for(i = 0; i < val; i++)
         __asm__("mov %cr0, %eax");
}

Я использовал GDB и прошел через каждую сборочную линию, и именно на mov %cr0,%eax происходит ошибка сегментации.

Кто-нибудь, кто знает, что не так?

1 Ответ

18 голосов
/ 14 сентября 2011

Цитирование из Руководства разработчика программного обеспечения для архитектуры Intel® 64 и IA-32 3-650 Vol. 2A при переходе в регистры управления и из них:

Эта инструкция может быть выполнена, только если текущий уровень привилегий равен 0.

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

Минимальный модуль ядра, который регистрирует содержимое cr0, cr2 и cr3, может выглядеть примерно так (32-битный путь кода не проверен):

/* hello.c */
#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void)
{
#ifdef __x86_64__
    u64 cr0, cr2, cr3;
    __asm__ __volatile__ (
        "mov %%cr0, %%rax\n\t"
        "mov %%eax, %0\n\t"
        "mov %%cr2, %%rax\n\t"
        "mov %%eax, %1\n\t"
        "mov %%cr3, %%rax\n\t"
        "mov %%eax, %2\n\t"
    : "=m" (cr0), "=m" (cr2), "=m" (cr3)
    : /* no input */
    : "%rax"
    );
#elif defined(__i386__)
    u32 cr0, cr2, cr3;
    __asm__ __volatile__ (
        "mov %%cr0, %%eax\n\t"
        "mov %%eax, %0\n\t"
        "mov %%cr2, %%eax\n\t"
        "mov %%eax, %1\n\t"
        "mov %%cr3, %%eax\n\t"
        "mov %%eax, %2\n\t"
    : "=m" (cr0), "=m" (cr2), "=m" (cr3)
    : /* no input */
    : "%eax"
    );
#endif
    printk(KERN_INFO "cr0 = 0x%8.8X\n", cr0);
    printk(KERN_INFO "cr2 = 0x%8.8X\n", cr2);
    printk(KERN_INFO "cr3 = 0x%8.8X\n", cr3);
    return 0;
}

void cleanup_module(void)
{
}

# Makefile

obj-m += hello.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

test: all
    sudo insmod ./hello.ko
    sudo rmmod hello
    dmesg | tail
...