sg88
sg88

Reputation: 155

Reading x86 MSR from kernel module

My main aim is to get the address values of the last 16 branches maintained by the LBR registers when a program crashes. I tried two ways till now -

1) msr-tools This allows me to read the msr values from the command line. I make system calls to it from the C program itself and try to read the values. But the register values seem no where related to the addresses in the program itself. Most probably the registers are getting polluted from the other branches in system code. I tried turning off recording of branches in ring 0 and far jumps. But that doesn't help. Still getting unrelated values.

2) accessing through kernel module Ok I wrote a very simple module (I've never done this before) to access the msr registers directly and possibly avoid register pollution.

Here's what I have -

#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);

But the problem is that every time I use dmesg to read the output I get just

Value is 0 

(I have tried for other registers - it always comes as 0)

Is there something that I am forgetting here? Any help? Thanks

Upvotes: 1

Views: 7090

Answers (2)

NovHak
NovHak

Reputation: 111

You can use Ilya Matveychikov's answer... or... OR :

#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);

And there are many more functions, such as :

  • 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])

Have a look at /lib/modules/<uname -r>/build/arch/x86/include/asm/msr.h

Upvotes: 1

Ilya Matveychikov
Ilya Matveychikov

Reputation: 4024

Use the following:

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;
}

Upvotes: 5

Related Questions