中斷/例外處理

中斷描述表


概論

在發生中斷(或例外)時,處理器由中斷描述表(Interrupt Descriptor Table,IDT)中查出該中斷向量的 gate descriptor,才能找到該中斷向量的處理程序。IDT 就如同 GDT 或 LDT 一樣,是由一堆 descriptor 組成的陣列。IDT 的基底位址存放在 IDTR 中,包含一個 32 bit 的線性位址和一個 16 bit 的邊界值。邊界值存放的是最後一個有效位址的值,因此,若邊界值為 0,則有一個有效位元組。因為 descriptor 必定是 8 bytes,因此 IDTR 中的邊界值一定要是 8N-1 的形式。IDT 中並不一定要存放 256 個 descriptor,只需要存放有用到的數目就可以了。如果有一中斷的中斷向量超出 IDT 的範圍,則處理器會發出 general-protection(#GP)的例外。
利用 LIDT 指令可以把記憶體中的值載入到 IDTR 中,而用 SIDT 指令可以把 IDTR 中的位址存到記憶體中。這兩個指令只能在 ring 0 中執行。
 

IDT 中的 descriptor

在 IDT 中可以有三種 descriptor:task-gate descriptor、interrupt-gate descriptor、和 trap-gate descriptor。在 IDT 中的 gate descriptor 的格式就和在 GDT 中所使用格式相同。其中,interrupt-gate 和 trap-gate 的 descriptor 和 call-gate descriptor 的格式很像(參考「保護機制」的「特權等級」)。而 task-gate descritor 則是指向中斷處理程序的 TSS segment。它們的格式如下:
在中斷發生時,若在 IDT 中相對映的 descriptor 是 interrupt-gate 或 trap-gate 的 descriptor,則處理器的行為會和用 CALL 在呼叫一個 call-gate 的時候很類似。而若相對映的 descriptor 是 task-gate descriptor,則處理器的行為會類似用 CALL 呼叫一個 task-gate(參考「多工處理」)。
 

Interrupt gate 和 Trap gate

如果中斷的 gate 是 interrupt gate 或 trap gate,則表示這是一個在目前執行的工作中執行的中斷處理程序。也就是說,這個中斷處理程序並不會進行工作切換。這時候,處理器就如同是經由 call gate 來呼叫一個程序一般。
發生中斷後,處理器會依序將 EFLAGS、CS、和 EIP 推入堆疊中。如果這是一個有錯誤碼的例外,則還會把錯誤碼推入堆疊中。若中斷處理程序的特權等級和 CPL 相同,則不會有堆疊切換。而如果中斷處理程序的特權等級較高,則處理器會切換堆疊,並把 SS、SP 也推入堆疊中(會在推入 EFLAGS 等之前推入),並把所有推入堆疊中的資料複製到新的堆疊中。
由中斷處理程序中返回時,必須使用 IRET 指令。IRET 和 RET 指令不同的地方,即在於它會取回 EFLAGS 的值。不過,EFLAGS 中的 IOPL 只有在 CPL 為 0 時,才會改變。而 EFLAGS 中的 IF 旗標只有在 CPL 小於或等於 IOPL 時,才會改變。如果在中斷時有切換堆疊,IRET 也會把堆疊切換回來。
Trap gate 和 interrupt gate 的唯一不同點,是在處理旗標的方式。當中斷(或例外)是經由 interrupt gate 時,處理器會把 IF 設為 0,以避免在
中斷處理程序中再度發生中斷。在返回時,處理器會恢復 IF 的值。但是,若中斷是經由 trap gate,則處理器不會改變 IF 的值。也就是說,在中斷處理程序中有可能會再度發生中斷。
 

Task gate

若中斷是經由 task gate,則在中斷發生時,會導致工作切換。利用工作切換的中斷處理程序有幾個好處: 經由 task gate 的中斷處理程序的主要缺點,就是在每次中斷時的工作切換會花費很多時間,而減低了系統的效率。
 

中斷處理程序的保護

和一般的程序一樣,處理器不允許進入特權等級較低的中斷處理程序中。如果發生中斷時,會進入特權等級比 CPL 更低的中斷處理程序中,則處理器會發出 general-protection(#GP)例外。
和處理一般的程序不同的是,中斷向量中並沒有 RPL,所以處理器並不會檢查 RPL。而且,處理器只有在中斷(或例外)是由 INT n、INT3、INTO 指令產生的時候,才會檢查 gate 的 CPL 是否比 DPL 小,這可以避免等級較低的程序利用這些指令破壞系統的中斷處理程序(如分頁錯誤的處理程序)。對硬體產生的中斷(或例外),處理器並不會檢查 gate 的 DPL。
因為中斷隨時都可能發生,因此這些限制可能會導致不適當的錯誤。下面有兩個方法,都可以避免這個問題: