這節描述了IA-32架構的任務管理功能,只有當處理器運行在保護模式的時候,這個功能才是有效的,這節的側重點在32位任務和32位TSS結構上,關於16位的任務和16位TSS結構,請看7.6節,關於64位模式中,具體任務管理的信息,請看7.7節 7.1 任務管理概述 任務是處理器可以調度,執行和暫停的一 ...
這節描述了IA-32架構的任務管理功能,只有當處理器運行在保護模式的時候,這個功能才是有效的,這節的側重點在32位任務和32位TSS結構上,關於16位的任務和16位TSS結構,請看7.6節,關於64位模式中,具體任務管理的信息,請看7.7節
7.1 任務管理概述
任務是處理器可以調度,執行和暫停的一個工作單元,它可以執行一個程式,任務,進程,操作系統服務程式,中斷常式,異常常式,內核實用程式
32位架構提供了一種機制,可以保存任務狀態,調度要執行的任務,並且切換一個任務到另一個任務,當操作系統位於保護模式的時候,所有處理器的執行都發生在任務中,即使簡單的操作系統,也必須定義至少一個任務,複雜的操作系統可以使用處理器的任務管理功能來支持多任務程式
7.1.1 任務結構
任務由兩部分組成,任務執行空間和任務狀態段(TSS),任務執行空間由一個代碼段,一個棧段和一個或者更多的數據段組成,如果一個操作系統或者可執行程式使用了處理器的許可權級保護機制,那麼任務執行空間也提供了一個分開的棧為每種許可權級
TSS指定了組成任務執行空間的段和為任務狀態信息提供了存儲空間,在多任務系統中,TSS也提供了一種鏈接任務機制
任務是由它的TSS段選擇子定義的,當處理器載入一個任務並且執行的時候,段選擇子,基址,界限和TSS段描述符屬性載入進TR中(細看2.4.4),如果任務執行在分頁模式中,那麼任務使用的頁目錄基址則被載入進CR3中
7.1.2 任務狀態
下麵幾項定義了當前正在執行任務的狀態
1. 由段寄存器中的段選擇子定義的任務的當前執行空間(CS DS SS ES FS GS)
2. 普通寄存器的狀態
3. EFLAGS寄存器的狀態
4. EIP寄存器的狀態
5. CR3寄存器的狀態
6. TR寄存器的狀態
7. LDTR寄存器的狀態
8. IO映射基址和IO映射(存在於TSS中)
9. 特權級0,1, 2的棧指針(存在於TSS中)
10. 鏈接上一個執行任務(存在於TSS中)
在調度一個任務之前,除了TR寄存器狀態,上面的所有信息都被包含在TSS中,同樣,LDTR寄存器的所有內容都不保存在TSS中,僅僅LDT的段選擇子存在
7.1.3 執行一個任務
軟體或者處理器可以利用下麵的方法調度一個任務去執行
1. 顯式的利用CALL指令調用一個任務
2. 顯式的利用JMP指令跳轉到任務中
3. 顯式的調用一個中斷處理程式任務(通過處理器)
4. 顯式的調用一個異常處理程式任務
5. 一個return (一個IRET指令),當EFLAGS寄存器中的NT標誌置1的時候
以上所有的調度一個任務的方法標識著任務被調度,並且段選擇子指向了一個任務門或者任務的TSS,當用CALL指令或者JMP指令調度一個任務的時候,指令中的選擇子可以直接選擇一個TSS或者保存TSS選擇子的任務門,當調度一個任務處理一個中斷或者異常的時候,IDT項必須包含一個保存中斷或者異常處理程式TSS的選擇子任務門
當任務將要被調度執行的時候,任務切換就發生在當前正在執行的任務和被調度的任務之間,在任務切換期間,當前正在執行任務的執行環境(任務的狀態或者上下文)被保存在它的TSS中並且任務被暫停,被調度任務的執行環境被載入進處理器中,並且剛剛載入的EIP寄存器指向了任務開始執行的指令,如果從上次系統初始化後,任務沒有運行,EIP將執行任務代碼的第一條指令,否則,當任務上次是active的時候,它將指向上次任務執行後的指令的後一條指令
如果當前正在執行的任務(calling task)被正在調度的任務(called task)調用,那麼calling task的段選擇子則被保存在called stack的TSS中,作為link back提供給calling task
對於所有的32位處理器來說,任務都不是遞歸的,一個任務不能CALL或者JMP它自己
中斷和異常能被Handler task的任務切換處理,處理器執行一個任務切換去處理中斷或者異常,並且返回的時候自動從一個中斷程式任務或者異常程式任務切換回到被中斷的程式,這種機制也能處理髮生在中斷任務期間的中斷
作為任務切換的一部分,處理器也能切換到另一個LDT,LDT-BASED段中,允許每個任務都有一個邏輯地址到物理地址的映射,任務切換的時候,頁目錄基址寄存器CR3會重新載入,允許每個任務有它自己的頁表,這種保護機制幫助了任務之間的隔離,並且預防了任務之間的干擾
如果保護機制不被使用,處理器不會提供任務之間的保護,即使操作系統使用了多種許可權級保護,一個任務運行在R3 ,使用與其他R3任務相同的LDT和頁表,訪問代碼,錯誤的數據和其他任務的棧
使用任務管理功能來處理多任務應用程式是可選的,多任務能在軟體中處理,每個軟體定義的任務都執行在單IA-32架構任務的上下文中
7.2 任務管理數據結構
處理器定義了五種與任務相關的數據結構
1. 任務狀態段 (TSS)
2. 任務門描述符
3. TSS描述符
4. 任務寄存器
5. EFLAGS寄存器中的NT Flag
當在保護模式的時候,在最少一個任務時,一個TSS或者TSS描述符必須被創建,並且TSS的段選擇子必須被載入到TR寄存器中
7.2.1 任務狀態段-TSS
任務需要恢復的處理器狀態信息,保存在叫做系統段的TSS中,圖片7-2顯式了32位CPU下,任務的TSS格式,TSS欄位主要分為兩類:動態欄位和靜態欄位
任務切換期間,當一個任務被暫停的時候,處理器會更新動態欄位,下麵的這些都是動態欄位
1. 普通寄存器欄位: EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP
2. 段寄存器欄位: CS DS ES SS FS GS
3. EFLAGS寄存器
4. EIP寄存器欄位
5. 上一個任務的鏈接欄位:包含了上一個任務的TSS的段選擇子(更新發生在call interrupt exception初始化造成的任務切換),這個欄位(有時叫做back link欄位)允許一個任務使用IRET指令返回到上一個任務
處理器讀取靜態欄位,通常不會改變它們,這些欄位是任務創建的時候設置的,下麵的是靜態欄位
1. LDT斷選擇子欄位:包含了任務的LDT的段選擇子
2. CR3控制寄存器欄位: 包含了任務使用的頁表的基址,總所周知,CR3也被叫做PDBR
3. 許可權級0 1 2棧指針欄位:這些棧欄位包含了棧段的段選擇子(SS0 SS1 SS2)和棧內偏移(ESP0 ESP1 ESP2)組成的邏輯地址,對於特定任務,這些欄位是靜態的,如果棧切換髮生在任務中,SS和ESP將會改變
4. T-FLAG(debug trap): 當設置這個flag的時候,當任務切換到這個任務的時候,T-flag會造成處理器產生一個調試異常
5. I/O點陣圖基址欄位:包含一個相對於TSS中的基址的16位偏移到I/O允許點陣圖和中斷重定向點陣圖,當存在的時候,這些映射被存儲在TSS中的較高地址,I/O映射基址指向了I/O允許點陣圖的基址和中斷重定向點陣圖的結束
如果分頁被使用:
1. 避免任務切換期間,處理器讀取104個位元組時,TSS存在於兩個物理頁(也就是頁邊界只有部分TSS),處理器可能執行不正確的地址翻譯,任務切換期間,處理器讀寫每個任務的TSS的104位元組(使用連續的物理地址作為TSS的第一個位元組的物理地址),如果這104個位元組不是物理連續的,處理器將會訪問不掙錢的信息,而且也不會產生PF異常
2. 上一個任務的和這次任務的TSS的物理頁,和每一個描述符表項都應該標記為可讀可寫
3. 在任務切換初始化的時候,如果包含這些結構的頁面存在於記憶體中,任務切換會更快的執行
7.2.2 TSS描述符
TSS類似於其他的段,是被段描述符定義的,圖片7-3顯式了TSS描述符的格式,TSS描述符只能位於GDT中,它不能位於LDT或者IDT中
在CALL 和 JMP期間,試圖用TI位為1(代表當前的LDT)的段選擇子訪問TSS會造成GP異常,在IRET的期間,會造成無效的TSS異常(#TS),試圖載入TSS的段選擇子到其他段寄存器也會造成GP異常
類型欄位的Busy-Flag標志著任務是否繁忙,繁忙的任務代表正在運行或者暫停,類型欄位的值如果是1001B,代表的就是一個inactive的任務,如果類型欄位是1011B,那麼就代表是一個繁忙的任務,任務不會遞歸,處理器使用Busy-FLag檢測一個試圖調用執行已經被中斷的任務,為了確保一個Busy-Flag只與一個任務相關,每個TSS應該只有一個TSS描述符指向它
基址,段界限,DPL, G,P的功能類似於數據段描述符中的使用,在32位TSS中,如果TSS描述符的G為0,limit的值必須大於等於67h, TSS的最小size大於1位元組,試圖切換一個TSS描述符的limit小於67h的任務,將會造成無效的TSS異常(#TS),如果包含一個I/O允許點陣圖,或者操作系統存儲了附加數據,那麼Limit則被要求更大,在任務切換的時候,處理器並不會檢測Limit是否大於67h, 然而當訪問I/O允許點陣圖或者中斷重定向點陣圖的時候,則會檢查
任何程式訪問描述符都能用CALL或者JMP調度任務(程式CPL的數值要小於TSS描述符的DPL)
在大多數系統中,TSS描述符的DPL的值要小於3,因此只有特權軟體能執行任務切換,然而在多任務應用程式中,一些TSS描述符的DPL可能設置為3,允許任務切換髮生在R3程式中
7.2.3 64模式下的TSS描述符
64位模式下,任務切換不再受支持,但是TSS描述符仍然存在,TSS描述符擴展到了16位元組,這個擴展也應用到LDT中,下圖描述了系統類型欄位的編碼信息
7.2.4 任務寄存器
任務寄存器保存16位段選擇子和當前任務的TSS的整個段描述符(32位基址(IA32-E模式下是64位),16位段界限和描述符屬性),這些信息是從當前任務GDT的段描述符中複製的,下圖顯示了處理器使用這些信息訪問TSS的路徑
任務寄存器有可見部分(能讀和能被軟體修改)和不可見部分(由處理器維護,軟體是無法訪問的),段選擇子在可見部分,指向了GDT中的TSS描述符,處理器使用任務寄存器的不可見部分來緩存TSS的段描述符,緩存這些值到寄存器中可以使任務的執行更加高效,LTR(載入到任務寄存器)和STR(讀取任務寄存器)指令載入和讀取任務寄存器的可見部分
LTR指令載入一個段選擇子到任務寄存器,並且指向了一個GDT中的TSS描述符,然後它從TSS描述符載入信息到任務寄存器的不可見部分,LTR是個特權級指令,只有CPL為0的時候才能被執行,它被用於系統初始化期間,把一個初始化的值push到任務寄存器,然後當任務切換髮生的時候,任務寄存器的內容被隱式的改變
STR指令存儲任務寄存器的可見部分到普通寄存器或者記憶體中,為了確定當前正在執行的任務,執行這條指令的代碼能被用在任何特權級上,通常,它只被操作系統軟體使用
處理器在加電或者充值的時候,段選擇子和基址預設設置為0,limit被設置為FFFFh
7.2.5 任務門描述符
任務門描述符提供了一個間接的,被保護的任務,它能位於GDT, LDT 或者IDT中,任務門描述符的段選擇子欄位,指向了一個GDT中的TSS描述符,這個段選擇子的RPL不被使用
在一個任務切換期間,任務門描述符的DPL控制了TSS描述符的訪問,當一個程式通過任務門,執行CALL或者JMP到一個任務,任務門選擇子的CPL和RPL欄位指向的任務門必須小於或者等於任務門描述符的DPL,當一個任務門被使用的時候,目標TSS描述符的DPL則不被使用
任務可以被任務門描述符和TSS描述符訪問,這些結構都滿足下列需要
1. 一個任務需要只有一個busy-flag:因為一個任務的busy-flag是存儲在TSS描述符中,每個任務應該只有一個TSS描述符,然而,幾個任務門可能會引用同一個TSS描述符
2. 需要提供對任務的選擇性訪問:任務門滿足這個需要,因為它們可以存在於LDT中,並且他們的DPL與TSS描述符的DPL不同,程式沒有足夠的許可權來訪問GDT中一個任務的TSS描述符,但是可能通過任務門的更高DPL的任務門允許訪問任務,對於限制特殊任務的訪問,任務門給出了更大的範圍
3. 需要通過一個獨立的任務處理中斷或者異常:任務門也可以存在於IDT中,允許中斷和異常被任務處理程式處理,當一個中斷或者異常向量指向了一個任務門的時候,處理器會切換到指定的任務
下圖展示了GDT中的任務門,LDT中的任務門,IDT中的任務門如何指向同一個任務的
7.3 任務切換
下麵幾種情況,處理器迴轉移到另外一個任務執行
1. 當前的程式或者任務執行了一個CALL 或者 JMP指令到一個GDT的TSS描述符
2. 當前程式或者任務執行一個CALL或者JMP指令到一個GDT或者當前LDT的任務門描述符中
3. 一個中斷或者異常向量指向了一個IDT中的任務門描述符
4. 檔EFLAGS寄存器的NT flag置1的時候,當前任務執行了一個IRET指令
JMP,CALL,IRET指令與中斷和異常一樣,都是重定向到一個程式的機制,引用一個TSS描述符或者一個任務門(calling或者Jmping到一個任務)或者NT flag的狀態(當執行一個IRET指令的時候),取決於是否一個任務切換髮生了
當切換到一個新的任務的時候,處理器執行以下操作
1. 從一個任務門或者上一個任務的link欄位(使用IRET指令初始化的任務),獲得新任務的TSS段選擇子作為JMP或者CALL指令的操作數
2. 檢查當前任務是否被允許切換到一個新任務,數據訪問特權規則應用與JMP和CALL指令,當前任務的CPL和新任務段選擇子的RPL必須小於或者等於TSS描述符或者被引用的任務門的DPL。異常,中斷(除了INT N指令產生的中斷),和IRET指令被允許任務切換不管目標任務門或者TSS描述符的DPL如何,關於INT n指令產生的中斷,DPL是被檢查的
3. 檢查新任務的TSS描述符被標記為存在,並且有一個有效的界限(limit必須大於或者等於67h)
4. 檢查新任務是available(call jmp 異常或者中斷)或者busy(IRET返回)
5. 檢查被用於任務切換的,當前TSS,新的TSS和所有的段描述符 在系統記憶體中是分頁的
6. 如果任務切換是一個JMP或者IRET指令初始化的,處理器會把當前任務的TSS描述符的busy flag清零,如果被初始化是用了一個call指令,中斷,或者異常,busy flag被置1
7. 如果任務切換是一個IRET指令初始化的,處理器會清除臨時被保存在EFLAGS寄存器鏡像的NT flag,如果使用一個JMP CALL中斷或者異常初始化,被保存在EFLAGS鏡像的NT flag保持不變
8. 保存當前任務的狀態到當前任務的TSS,處理器查找當前TSS基址在TR寄存器中,並且複製下列寄存器的狀態到當前TSS中:所有的通用寄存器,段寄存器中的段選擇子,EFLAGS寄存器中暫時被保存的鏡像,和指令指針寄存器EIP
9. 如果任務切換是用一個CALL指令,一個異常,或者一個中斷初始化的,處理器將設置被載入到新任務的EFLAGS寄存器中的NT flag為1。如果初始化是一個IRET指令,或者JMP指令,NT flag將映反射從新任務載入的EFLAGS中的NT的狀態
10. 如果任務切換是用一個CALL指令,JMP指令,異常或者中斷初始化的,處理器將設置新任務TSS描述符的busy flag為1。如果是IRET指令初始化的,busy flag將不會設置
11. 載入任務寄存器的段選擇子和新任務的TSS描述符
12. 處理器載入TSS狀態:LDTR寄存器,PDBR (CR3寄存器),EFLAGS寄存器,EIP寄存器,普通寄存器,段選擇子。載入這些狀態期間發生錯誤,可能會造成架構狀態損壞(如果分頁模式沒有開啟,PDBR的值是從新任務的TSS中讀取的,但是它不載入進CR3)
13. 與段選擇子相關的描述符合格的被載入,載入描述符的過程中,任何錯誤發生在新任務的上下文中,都有可能破壞架構狀態
14. 開始執行新的任務(關於異常常式,出現在新任務的第一條指令並沒有被執行)
NOTES:
如果所有的檢查和保存已經被成功執行,處理器提交任務切換,如果在步驟1-11的過程中發生不可恢復的錯誤,處理器不會完成任務切換,確保處理器返回到它的狀態在執行被初始化的任務切換的指令之前
如果一個不可恢復的錯誤發生在步驟12,架構狀態可能被破壞,但是將嘗試處理執行環境之前的錯誤
如果一個不可恢復的錯誤發生在步驟13,處理器完成任務切換,併在執行新任務的指令前產生一個適當的異常
如果異常發生在步驟14,在允許處理器開始執行一個新任務之前,異常處理程式必須完成它自己的任務切換
當前執行的任務狀態總是被保存,當任務切換成功發生時,如果任務被恢復, 開始執行的指令是由被保存在EIP中的值指向的,並且寄存器被恢復為任務被暫停的時候的值
當任務切換髮生時,新任務的特權級並不繼承被暫停任務的特權級,新的任務開始執行在由TSS的CS寄存器的CPL欄位指定的特權級上,因為任務被獨立空間和TSS隔離,因為特權級規則控制對一個TSS的訪問,軟體並不需要在任務切換上執行顯示的特權級檢查
下圖顯示了當任務切換的時候處理器檢查的異常條件,如果一個錯誤被髮現和錯誤碼引用的段,它也顯示了每種檢查產生的異常(表中檢查的順序,順序在P6家族處理器中被使用,額外的順序是特殊模式,在32位其他處理器中可能不同), 如果他們試圖重新載入產生異常的段選擇子,異常常式指定處理這些異常可能會受到遞歸調用,在重新載入選擇子之前,應該修複造成的異常
每次一個任務切換髮生時,CR0寄存器的TS flag都被置1。當其他處理器產生浮點異常的時候,系統軟體使用TS flag來協調浮點單元的操作,TS flag標識著浮點單元的上下文可能與當前任務的不同