1. 程式人生 > >TSS詳解 ——《x86組合語言:從真實模式到保護模式》讀書筆記33

TSS詳解 ——《x86組合語言:從真實模式到保護模式》讀書筆記33

TSS(Task State Segment,任務狀態段)詳解

1. TSS描述符

和LDT一樣,必須為每個TSS在GDT中建立對應的描述符。TSS描述符的格式如下圖:


B位是“忙”位(Busy)。在任務剛剛建立的時候,它應該為0,表明任務不忙。當任務開始執行時,或者處於掛起狀態(臨時被中斷執行)時,由處理器韌體把B位置1.

任務是不可重入的。就是說在多工環境中,如果一個任務是當前任務,那麼它可以切換到其他任務,但是不能從自己切換到自己。在TSS描述符中設定B位,並由處理器韌體進行管理,可以防止這種情況的發生。

2. TSS的格式

在一個多工環境中,當任務發生切換時,必須儲存現場(比如通用暫存器,段暫存器,棧指標等)。為了儲存被切換任務的狀態,並且在下次執行它時恢復現場,每個任務都應當有一片記憶體區域,專門用於儲存現場資訊,這就是任務狀態段(Task State Segment)。

在建立一個任務的時候,我們要為這個任務建立TSS並填寫其中的一些欄位。

  1. 前一任務連結(TSS Back Link):TSS內偏移0處是前一個任務的TSS描述符的選擇子。
    當Call指令、中斷或者異常造成任務切換,處理器會把舊任務的TSS選擇子複製到新任務的TSS的Back Link欄位中,並且設定新任務的NT(EFLAGS的bit14)為1,以表明新任務巢狀於舊任務中。關於這點我們會在第15章學習。在建立一個任務的時候,這個欄位可以填寫0.

  2. SS0,SS1,SS2和ESP0,ESP1,ESP2分別是0,1,2特權級堆疊的選擇子和棧頂指標。這些內容應當由任務的建立者填寫,且屬於填寫後一般不變的靜態欄位。

  3. CR3和分頁有關,我們會在第16章學習。如果沒有啟用分頁,可以填寫0.

  4. 偏移為0x20~0x5C的區域是處理器各個暫存器的快照部分,用於任務切換時儲存現場。在一個多工環境中,每次建立一個任務,核心至少要填寫EIP,EFLAGS,ESP,CS,DS,SS,ES,FS和GS。當任務首次執行時,處理器從這些暫存器中載入初始執行環境,從CS:EIP處開始執行任務的第一條指令。

  5. LDT選擇子是當前任務的LDT選擇子,由核心填寫,以指向當前任務的LDT。該資訊由處理器在任務切換時使用,在任務執行期間保持不變。

  6. T(Debug Trap)位用於軟體除錯。在多工環境中,如果T=1,則每次切換到該任務的時候,會引發一個除錯異常中斷(int 1).

  7. I/O點陣圖基地址用來決定當前的任務是否可以訪問特定的硬體埠。關於這個,下文會具體說明。

3. I/O許可點陣圖(I/O Permission Bit Map)

EFLAGS暫存器的IOPL位決定了當前任務的I/O特權級別。如果在數值上CPL<=IOPL,那麼所有的I/O操作都是允許的,針對任何硬體埠的訪問都可以通過;如果在數值上CPL>IOPL,也並不是說就不能訪問硬體埠。事實上,處理器的意思是總體上不允許,但個別埠除外。至於個別埠是哪些埠,要找到當前任務的TSS,並檢索I/O許可點陣圖。

I/O許可點陣圖(I/O Permission Bit Map)是一個位元序列,因為處理器最多可以訪問65536個埠,所以這個位元序列最多允許65536位元(即8KB)。

如下圖中的綠色部分,第一個位元組代表埠0~7,第二個位元組代表埠8~15,以此類推。每個位元的值決定了相應的埠是否允許訪問。為1時禁止訪問,為0時允許訪問。

在TSS內偏移為102位元組的那個字單元,是I/O點陣圖基地址欄位,它指明瞭I/O許可點陣圖相對於TSS起始處的偏移,例如下圖中這個欄位的值是144.

有幾點需要說明:
1. 如果I/O點陣圖基地址的值>=TSS的段界限(就是TSS描述符中的段界限),就表示沒有I/O許可點陣圖。
2. 處理器要求I/O點陣圖的末尾必須附加一個全1的位元組,即0xFF.
3. 處理器不要求為每一個I/O埠都提供位對映,對於那些沒有在點陣圖中對映的位,處理器假定它對應的位元是1(禁止訪問)。
4. TSS描述符中的界限值包括I/O許可點陣圖在內,也包括最後附加的0xFF. 以下圖為例,TSS的界限值是149(總大小150減去1)。

【end】