2012-04-20 73 views
1

我的主要目標是在程序崩潰時獲取由LBR寄存器維護的最後16個分支的地址值。我嘗試了兩種方法,直到現在 -從內核模塊讀取x86 MSR

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)

有什麼,我忘了在這裏? 有什麼幫助嗎?由於

+0

__asm__語句無效。 'rdmsr'返回EAX:EDX對,請參閱我的答案瞭解詳情。 – 2012-04-23 07:09:36

回答

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

好吧,我嘗試了你的建議。但結果仍然是零。這裏是我的 - '__asm__ __volatile__(「rdmsr」:「= a」(msrl),「= d」(msrh):「c(msr)); msr_value =((unsigned long long)msrh < <32)| MSRL; printk的(KERN_EMERG 「讀%×%LLX \ n」 個,MSR msr_value); } ' 爲0x1d9它始終打印 '[60033.285400]讀1D9 0' 不知道我可能會丟失什麼 – sg88 2012-04-29 16:47:10

+0

我在0x01D9 MSR處有相同的0值,所以我想IA32_DEBUGCTL是空的,因爲它之前是未初始化的,根據英特爾的手冊,嘗試通過向IA32_DEBUGCTL寫入1來啓用LBR,之後讀取IA32_DEBUGCTL的值 – 2012-05-02 13:08:25

+0

你們啊,那很好。 0只是一個例子。不管我將值設置爲0x1D9,它仍然讀取0。 – sg88 2012-05-04 14:56:33