2012-07-16 31 views
2

我試圖弄清楚Linux內核中MACRO電流的細節。 電流的最終彙編代碼:有關Linux x86 x86中MSR_GS_BASE的詳細信息

movq %%gs:0xb000,%0 

上面的代碼可以工作!但是當我打印%% gs時,它的值爲0,所以%% gs指向GDT NULL的第一項!怎麼運行的?

mov %%gs, %0 

相反,GS的基地在MSR_GS_BASE,而目前可以更換,如:

/*0xb000 is the offset of per_cpu__current_task*/ 
cur_task = (unsigned long*)(x86_rdmsr64(MSR_GS_BASE) + 0xb000); 
println("cur_task:%p",*cur_task); 

我的問題是:

%GS點GDT NULL的第一項!! ??它如何從MSR_GS_BASE中讀取,它是一個CPU特性?我需要一些關於這個的參考。

回答

6

AMD Architecture Programmer's Manual Volume 2: System Programming,第4.5.3節:

FS和GS寄存器在64位模式。與CS,DS,ES和SS段不同,FS和GS段覆蓋可以在64位模式下使用。在64位模式下使用FS和GS段覆蓋時,它們各自的基址將用於有效地址(EA)計算。完整的EA計算然後變爲(FS或GS).base + base +(scale * index)+位移。 FS.base和GS.base值也擴展爲完整的64位虛擬地址大小,如圖4-5所示。產生的EA計算允許包裹正面和負面地址。

[...]

有兩種方法來更新FS.base和GS.base隱藏描述字段的內容。第一個專用於特權軟件(CPL = 0)。 FS.base和GS.base隱藏描述符寄存器字段被映射到MSR。特權軟件可以使用單個WRMSR指令將規範形式的64位基址加載到FS.base或GS.base中。 FS.base MSR地址是C000_0100h,而GS.base MSR地址是C000_0101h。

更新FS和GS基本字段的第二種方法可用於在任何特權級別運行的軟件(實現支持並通過設置CR4 [FSGSBASE]啓用時)。 WRFSBASE和WRGSBASE指令分別將GPR的內容複製到FS.base和GS.base字段。當操作數大小爲32位時,基址的高位雙字清零。 WRFSBASE和WRGSBASE僅在64位模式下受支持。

+0

謝謝!這是一個很好的幫助! – hellolwq 2012-07-16 04:45:22

+0

鏈接已損壞。 [This](http://developer.amd.com/wordpress/media/2012/10/24593_APM_v21.pdf)可能是正確的。 – Ruslan 2015-07-30 05:57:45