从内核模块读取x86 MSR

时间:2012-04-20 20:46:33

标签: linux linux-kernel cpu-registers msr

我的主要目的是在程序崩溃时获取LBR寄存器维护的最后16个分支的地址值。到目前为止我尝试了两种方式 -

1)msr-tools 这允许我从命令行读取msr值。我从C程序本身对它进行系统调用,并尝试读取值。但寄存器值似乎与程序本身的地址无关。很可能寄存器在系统代码中受到其他分支的污染。我尝试关闭环0和远跳的分支记录。但这没有用。仍然得到无关的价值观。

2)通过内核模块访问 好吧,我写了一个非常简单的模块(我以前从未这样做过)直接访问msr寄存器,可能避免寄存器污染。

这就是我所拥有的 -

#define LBR 0x1d9 //IA32_DEBUGCTL MSR
                  //I first set this to some non 0 value using wrmsr (msr-tools)
static void __init do_rdmsr(unsigned msr, unsigned unused2)
{
    uint64_t msr_value;
    __asm__ __volatile__ ("                 rdmsr"
                    : "=A" (msr_value)
                    : "c" (msr)
                    );

    printk(KERN_EMERG "%lu \n",msr_value);
}
static int hello_init(void)
{
    printk(KERN_EMERG "Value is ");
    do_rdmsr (LBR,0);
    return 0;
}

static void hello_exit(void)
{
    printk(KERN_EMERG "End\n");
}

module_init(hello_init);
module_exit(hello_exit);

但问题是每次我使用dmesg来读取输出我只是

Value is 0 

(我已尝试过其他寄存器 - 它总是为0)

我在这里忘记了什么吗? 有帮助吗?感谢

1 个答案:

答案 0 :(得分:1)

使用以下内容:

unsigned long long x86_get_msr(int msr)
{
    unsigned long msrl = 0, msrh = 0;

    /* NOTE: rdmsr is always return EDX:EAX pair value */
    asm volatile ("rdmsr" : "=a"(msrl), "=d"(msrh) : "c"(msr));

    return ((unsigned long long)msrh << 32) | msrl;
}