如何从程序访问控制寄存器cr0,cr2,cr3?获取细分错误 [英] How to access the control registers cr0,cr2,cr3 from a program? Getting segmentation fault

查看:600
本文介绍了如何从程序访问控制寄存器cr0,cr2,cr3?获取细分错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个试图读取和写入控制寄存器的程序。

I have written a program which tries to read from and write to the control registers.

该程序可以正常编译,但是当内联汇编即将执行时,则会产生分段错误。

The program compiles fine, but when the inline assembly is about to be executed, it produces a segmentation fault.

代码:

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

我使用了GDB并逐步通过了每条装配线,它位于 mov%cr0,%eax 表示发生了分段错误。

I used GDB and stepped through each assembly line and it is on the mov %cr0,%eax that the segmentation fault is occurring.

谁知道出什么问题了?

推荐答案

英特尔®64和IA-32架构软件开发人员手册3-650卷。 2A
往返于控制寄存器:


仅当当前特权级别时,该指令才能执行是0。

This instruction can be executed only when the current privilege level is 0.

这意味着该指令只能在内核模式下执行。

Which means the instruction can only be executed in kernel mode.

一个最小的内核模块,它记录cr0,cr2和cr3的内容可能看起来像这样(未经测试的32位代码路径):

A minimal kernel module, that logs the contents of cr0, cr2 and cr3 could look something like this (32-bit code path untested):

/* 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

这篇关于如何从程序访问控制寄存器cr0,cr2,cr3?获取细分错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆