Linux 从内核模块读取x86 MSR

Linux 从内核模块读取x86 MSR,linux,linux-kernel,cpu-registers,msr,Linux,Linux Kernel,Cpu Registers,Msr,我的主要目标是在程序崩溃时获取LBR寄存器维护的最后16个分支的地址值。到目前为止,我试过两种方法- 1) msr工具 这允许我从命令行读取msr值。我从C程序本身对其进行系统调用,并尝试读取值。但寄存器值似乎与程序本身的地址无关。很可能是系统代码中的其他分支污染了寄存器。我试着关闭0环和跳远中的分支记录。但那没用。仍然得到不相关的值 2) 通过内核模块访问 好的,我写了一个非常简单的模块(我以前从未这样做过),直接访问msr寄存器,并可能避免寄存器污染 这是我所拥有的- #define LBR

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

1) msr工具 这允许我从命令行读取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)

这里有什么我忘了的吗? 有什么帮助吗?谢谢

请使用以下内容:

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;
}
无符号长x86\u get\u msr(int msr)
{
无符号长msrl=0,msrh=0;
/*注意:rdmsr始终返回EDX:EAX对值*/
asm volatile(“rdmsr”:“=a”(msrl),“=d”(msrh):“c”(msr));

return((unsigned long long)msrh asm语句无效。
rdmsr
返回EAX:EDX对,详细信息请参见我的答案。好吧,我尝试了你的建议。但结果仍然是零。以下是我得到的-
asm\uuuuuu volatile\uuu(“rdmsr”:“=a”(msrl),“=d”(msrh):“c(msr));msr\u value=((unsigned long long long)msrh我在0x01D9 MSR上有相同的0值。因此我假设IA32_DEBUGCTL是空的,因为它以前未初始化。根据英特尔的手册,尝试通过将1写入IA32_DEBUGCTL来启用LBR。之后读取IA32_DEBUGCTL的值。是的,这很好。0只是一个示例。无论我在0x1D9中将值设置为什么,它仍然读取0。