6

Linux カーネルにおける MACRO current の詳細を調べてみました。現在の最終的なアセンブリ コードは次のとおりです。

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 の機能ですか? これについては参考文献が必要です。

4

1 に答える 1

11

AMD Architecture Programmer's Manual Volume 2: System Programmingのセクション 4.5.3 から:

64 ビット モードの FS および GS レジスタ。CS、DS、ES、および SS セグメントとは異なり、FS および GS セグメントのオーバーライドは 64 ビット モードで使用できます。FS および GS セグメント オーバーライドが 64 ビット モードで使用される場合、それぞれのベース アドレスが実効アドレス (EA) 計算で使用されます。完全な EA 計算は、(FS または GS) ベース + ベース + (スケール * インデックス) + 変位になります。図 4-5 に示すように、FS.base および GS.base の値も完全な 64 ビットの仮想アドレス サイズに拡張されます。結果の EA 計算は、正と負のアドレスをまたいでラップすることができます。

[...]

FS.base および GS.base 隠し記述子フィールドの内容を更新するには、2 つの方法があります。1 つ目は、特権ソフトウェア (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 ベース フィールドを更新する 2 番目の方法は、任意の特権レベルで実行されているソフトウェアで使用できます (実装によってサポートされ、CR4[FSGSBASE] を設定することによって有効になっている場合)。WRFSBASE 命令と WRGSBASE 命令は、GPR の内容をそれぞれ FS.base フィールドと GS.base フィールドにコピーします。オペランドのサイズが 32 ビットの場合、基数の上位ダブルワードがクリアされます。WRFSBASE と WRGSBASE は 64 ビット モードでのみサポートされます。

于 2012-07-16T03:19:33.077 に答える