【问题标题】:Reading x86 MSR from kernel module从内核模块读取 x86 MSR
【发布时间】:2012-05-02 10:59:25
【问题描述】:

我的主要目标是在程序崩溃时获取由 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)

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

【问题讨论】:

  • asm 语句无效。 rdmsr 返回 EAX:EDX 对,详见我的回答。

标签: linux linux-kernel cpu-registers msr


【解决方案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;
}

【讨论】:

  • 好吧,我尝试了你的建议。但结果仍然是零。这就是我所拥有的 - __asm__ __volatile__ ("rdmsr ": "=a" (msrl), "=d" (msrh): "c (msr)); msr_value = ((unsigned long long)msrh &lt;&lt; 32) | msrl; printk(KERN_EMERG "read %x %llx \n",msr,msr_value); } for 0x1d9 它总是打印 [60033.285400] read 1d9 0 不确定我可能会丢失什么
  • 我在 0x01D9 MSR 有相同的 0 值。所以我认为 IA32_DEBUGCTL 是空的,因为它之前未初始化。根据英特尔的手册,尝试通过将 1 写入 IA32_DEBUGCTL 来启用 LBR。之后读取 IA32_DEBUGCTL 的值。
  • 是的,没关系。 0 只是一个例子。无论我在 0x1D9 中将值设置为什么,它仍然显示为 0。
【解决方案2】:

您可以使用 Ilya Matveychikov 的答案...或者...或者:

#include <asm/msr.h>
int err;
unsigned int msr, cpu;
unsigned long long val;
/* rdmsr without exception handling */
val = rdmsrl(msr);
/* rdmsr with exception handling */
err = rdmsrl_safe(msr, &val);
/* rdmsr on a given CPU (instead of current one) */
err = rdmsrl_safe_on_cpu(cpu, msr, &val);

还有更多功能,例如:

  • int msr_set_bit(u32 msr, u8 bit)
  • int msr_clear_bit(u32 msr, u8 bit)
  • void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
  • int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])

看看/lib/modules/&lt;uname -r&gt;/build/arch/x86/include/asm/msr.h

【讨论】:

    猜你喜欢
    • 2017-04-02
    • 1970-01-01
    • 1970-01-01
    • 2017-11-20
    • 2020-04-30
    • 2014-10-29
    • 2016-05-09
    • 2015-01-13
    • 2021-04-30
    相关资源
    最近更新 更多