2016-11-17 10 views
1

アクティブ(TRレジスタがポイントするもの)のとき、TSSのフィールドは変更されますか?特に、ESP0/RSP0フィールドへの変更は直ちに有効ですか?または、プロセッサはセグメントセレクタと同様にTSSのキャッシュを維持するので、プロセッサにTSSフィールドをリロードさせるにはLTR命令が必要ですか?x86/x64:TSSフィールドを変更する

答えて

5

プロセッサはTSSを使用して、現在のコンテキストを保存し、次のスケジュールされたコンテキストをタスク切り替え中にロードします
TSS構造を変更しても、CPUがそのようなTSSに切り替えるまでは、どのようなコンテキストにも影響しません。 CALL命令でタスクを明示的に呼び出します

:ソフトウェアまたはプロセッサは、次のいずれかの方法で実行するためのタスクをディスパッチすることができたときに

CPUは、タスクスイッチを実行します。
•JMP命令によるタスクへの明示的なジャンプ。
割り込みハンドラタスクへの(プロセッサによる)暗黙的な呼び出し。
•例外ハンドラタスクへの暗黙的な呼び出し。
•EFLAGSレジスタのNTフラグがセットされているときのリターン(IRET命令で開始)。セグメントの後

:あなたはインテルのマニュアルの第7章3


ltrは、インテルのマニュアル2から、スイッチを実行していない上TSSについて読むことができます

セレクタがタスクレジスタにロードされると、プロセッサはセグメントセレクタを使用して、グローバルディスクリプタテーブル(GDT)のTSSのセグメント記述子を に配置します。
次に、セグメント制限をロードし、TSSのアドレスをセグメント記述子からタスクレジスタに設定します( )。
タスクレジスタが指すタスクがビジー状態の ですが、タスクへの切り替えは発生しません。


EDIT:CPUはTSSからの静的な値をキャッシュされた場合、私は実際にテストしてみました。
試験は

  • がDPL 0および3、DPL 0および3、DPL 3とTSS及びコールゲートを持つ2つのデータセグメントを有する2つのコードセグメントとGDTを作成すること(添付)ブートプログラムで成っDPL 0
  • 保護モードに切り替えてコードセグメントに、V1にTSSにESP0の値を設定し、trを読み込みます。
  • DPL 3のコードセグメントに戻り、ESP0の値をv2に変更し、コールゲートを呼び出します。
  • ESPが(何らかの理由なし一致する場合は0)V1 -10H又はV2それぞれ-10H、プリント1又は2であるかどうかを確認。

私のHaswellとBochsでは、結果は2です。つまり、CPUは必要に応じてメモリ(階層)からTSSを読み込みます。

モデルのテストをISAに一般化することはできませんが、そうではないようです。


BITS 16 

xor ax, ax   ;Most EFI CPS need the first instruction to be this 

;But I like to have my offset to be close to 0, not 7c00h 

jmp 7c0h : WORD __START__ 

__START__: 

    cli 

    ;Set up the segments to 7c0h 

    mov ax, cs 
    mov ss, ax 
    xor sp, sp 
    mov ds, ax 


    ;Switch to PM 

    lgdt [GDT] 

    mov eax, cr0 
    or ax, 1 
    mov cr0, eax 

    ;Set CS 

    jmp CS_DPL0 : WORD __PM__ + 7c00h 

__PM__: 

    BITS 32 

    ;Set segments 

    mov ax, DS_DPL0 
    mov ss, ax 
    mov ds, ax 
    mov es, ax 

    mov esp, ESP_VALUE0 

    ;Make a minimal TSS BEFORE loading TR 

    mov eax, DS_DPL0 
    mov DWORD [TSS_BASE + TSS_SS0], eax 
    mov DWORD [TSS_BASE + TSS_ESP0], ESP_VALUE1 


    ;Load TSS in TR 

    mov ax, TSS_SEL 
    ltr ax 

    ;Go to CPL = 3 

    push DWORD DS_DPL3 | RPL_3 
    push DWORD ESP_VALUE0 
    push DWORD CS_DPL3 | RPL_3 
    push DWORD __PMCPL3__ + 7c00h 
    retf 

__PMCPL3__: 

    ;UPDATE ESP IN TSS 

    mov ax, DS_DPL3 | RPL_3 
    mov ds, ax 

    mov DWORD [TSS_BASE + TSS_ESP0], ESP_VALUE2 


    ;SWITCH STACK 

    call CALL_GATE : 0 

    jmp $ 


__PMCG__: 

    mov eax, esp 


    mov bx, 0900h | '1' 
    cmp eax, ESP_VALUE1 - 10h 
    je __write 

    mov bl, '2' 
    cmp eax, ESP_VALUE2 - 10h 
    je __write 

    mov bl, '0' 

__write: 

    mov WORD [0b8000h + 80*5*2], bx 

    cli 
    hlt 


GDT dw 37h 
    dd GDT + 7c00h  ;GDT symbol is relative to 0 for the assembler 
       ;We translate it to linear 

    dw 0 


    ;Index 1 (Selector 08h) 
    ;TSS starting at 8000h and with length = 64KiB 

    dw 0ffffh 
    dw TSS_BASE 
    dd 0000e900h 


    ;Index 2 (Selector 10h) 
    ;Code segment with DPL=3 

    dd 0000ffffh, 00cffa00h 

    ;Index 3 (Selector 18h) 
    ;Data segment with DPL=0 

    dd 0000ffffh, 00cff200h 


    ;Index 4 (Selector 20h) 
    ;Code segment with DPL=0 

    dd 0000ffffh, 00cf9a00h 

    ;Index 5 (Selector 28h) 
    ;Data segment with DPL=0 

    dd 0000ffffh, 00cf9200h 

    ;Index 6 (Selector 30h) 
    ;Call gate with DPL = 3 for SEL=20 

    dw __PMCG__ + 7c00h 
    dw CS_DPL0 
    dd 0000ec00h 


    ;Fake partition table entry 

    TIMES 446-($-$$) db 0 

    db 80h, 0,0,0, 07h 


    TIMES 510-($-$$) db 0 
    dw 0aa55h 

    TSS_BASE EQU  8000h 
    TSS_ESP0 EQU  4 
    TSS_SS0 EQU  8 

    ESP_VALUE0 EQU 7c00h 
    ESP_VALUE1 EQU 6000h 
    ESP_VALUE2 EQU 7000h 

    CS_DPL0 EQU 20h 
    CS_DPL3 EQU 10h 
    DS_DPL0 EQU 28h 
    DS_DPL3 EQU 18h 
    TSS_SEL EQU 08h 
    CALL_GATE EQU 30h 


    RPL_3  EQU 03h 
+0

修正済みですが、詳細はまだあります。TSSには特権レベル変更のためのスタックポインタも含まれています。彼らはコンテキストスイッチで "すぐに"使用されません。プロセッサはコンテキストシャドウコピーを「シャドウコピー」にロードし、必要に応じてコピーを使用しますか? –

+1

@GiuseppeGuerrini私は彼らが必要に応じて読み込まれると信じています。マニュアルの 'call'命令の説明とcall gateの記述はそう思われます。これは簡単にテストすることができますが、おそらく私は調査することができます。 –

+2

@GiuseppeGuerrini私は実際にCPUの動作をテストしました。私のモデルでは、値は必要に応じてメモリから読み込まれます。私はこれがどんなモデルにも一般化できると信じています。 –

3

TSSは、必要なときにだけ読んで、そして特別なTSSキャッシュはありません。 (GDT内のTSSディスクリプタはセグメント記述子のようにキャッシュされますが、TSS自体の内容はキャッシュされません)TSSは他のメモリ領域と同様に通常のL1/L2/L3メモリキャッシュにキャッシュできます。異なる状況から読み取られるTSSの3つの異なる領域があります。適切な状況が発生するまで、TSSの値を変更しても効果はありません。

  1. 仮想8086モードまたはCPL> IOPLの場合、I/O命令(IN、INS、OUT、OUTS)が実行されます。これにより、I/Oマップ・ベース・アドレス・フィールドとそれが指すI/Oマップが読み取られます。
  2. CR4.VMEが1のとき、仮想8086モードでソフトウェア割り込み(INT)が実行されます。これにより、I/Oマップベースフィールドとそれが指す割り込みリダイレクションビットマップが読み出されます。
  3. より低い特権レベルからより高い特権レベル(高い番号のリングから低い番号のリングへの変更)は、スタック切り替えをもたらします。これにより、新しい特権レベルに応じて、SS0/ESP0、SS1/ESP1、SS2/ESP2、RSP0、RSP1、またはRSP2フィールドが読み取られます。
  4. I/Oマップベースアドレス、SS0/ESP0、SS1/ESP1、SS2/ESP2、および前のタスクリンクフィールドを除き、新しいTSS内のすべての定義済みフィールドが読み取られるタスクスイッチが発生します。古いTSSのPrevious Task Linkフィールドは、IRET命令の結果、ネストされたタスクにタスクが戻るときに読み込まれます。
  5. 64ビットモードで割り込みまたは例外が発生し、対応するIDTエントリのISTフィールドが0ではありません。これにより、TSSの適切なISTnフィールドが読み取られます。 64ビットモードでのみケース1,3及び5は、64ビットモードとして発生する可能性があること

注バーチャル8086モードをサポートせず、またそれは、タスクの切り替えをサポートしていません。

LTR命令は、指定されたセレクタに対応するGDT内のエントリを除いて、メモリ領域を読み取らせず、フラッシュするための内部TSSキャッシュも存在しません。

+0

私の質問は特に(3)の点でした。私は、RSPxの変更がその後のプロファイル変更に影響を与えるかどうか、あるいは何らかの種類の「フラッシュ/リロード」アクションが必要かどうかを知りたいと思います。あなたの答えはRSPxの変更が十分であることを意味しますが、Margaret Bloomの意見は反対です(上記の私のコメントを参照してください) –

+2

@GiuseppeGuerriniロスと私は同じことを言っていると確信しています。TSSは必要に応じてメモリ階層。 –

関連する問題