現在,我們知道了
80x86
微處理器在硬體級對中斷和異常做了些什麼,接下來,我們可以繼續描述如何初始化中斷描述表。
核心啟用中斷以前,必須把
idt表的初始位址裝到
idtr
暫存器,並初始化表中的每項。這項工作是在初始化系統時完成的。
int指令允許使用者態程序發出乙個中斷訊號,其值可以是
0~255
的任意乙個向量。因此,為了防止使用者通過
int指令模擬非法的中斷和異常,
idt的初始化必須非常小心。這可以通過把中斷或陷阱門描述符的
dpl欄位設定成
0來實現。如果程序試圖發出其中的乙個中斷訊號,控制單元將檢查出
cpl的值與
dpl欄位有衝突,並且產生乙個」
generalprotection」
異常。然而,在少數情況下,使用者態程序必須能發出乙個程式設計異常。為此,只要把中斷或陷阱門描述符的
dpl欄位設定成
3,即特權級盡可能一樣高就足夠了。
現在,讓我們來看一下
linux
是如何實現這種策略的。
中斷門、陷阱門及系統門
與在前面」中斷描述符表」中所提到的一樣,
intel
提供了三種型別的中斷描述符:任務門、中斷門及陷阱門描述符。
linux
使用與intel
稍有不同的細目分類和術語,把它們如下進行分類:
中斷門使用者態的程序不能訪問的乙個
intel
中斷門。所有的
linux
中斷處理程式都通過中斷門啟用,並全部限制在核心態。
系統門使用者態的程序可以訪問的乙個
intel
陷阱門。通過系統門來啟用三個
linux
異常處理程式,它們的向量是4,
5及128。因此,在使用者態下,可以發布
into
、bound
及int$0x80
三條組合語言指令。
系統中斷門
能夠被使用者態程序訪問的
intel
中斷門。與向量
3相關的異常處理程式是由系統中斷門啟用的,因此,在使用者態可以使用組合語言指令
int3
。陷阱門
使用者態的程序不能訪問的乙個
intel
陷阱門。大部分
linux
異常處理程式都通過陷阱門來啟用。
任務門不能被使用者態程序訪問的
intel
任務門。
linux
對」doublefault」
異常的處理程式是由任務門啟用的。
下列體系結構相關的函式用來
idt中插入門:
set_intr_gate(n,addr)
在idt的第n
個表項插入乙個中斷門。門中的段選擇符設定成核心**的段選擇符,偏移量設定成中斷處理程式的位址
addr
,dpl
字段設定成0。
set_system_gate(n,addr)
在idt的每n
個表項插入乙個陷阱門。門中的段選擇符設定成核心**的段選擇符,偏移量設定成中斷處理程式的位址
addr
,dpl
字段設定成0。
set_system_intr_gate(n,addr)
在idt的第n
個表項插入乙個中斷門。門中的段選擇符設定成核心**的段選擇符,偏移量設定成中斷處理程式的位址
addr
,dpl
字段設定成0。
set_trap_gate(n,addr)
與前乙個函式類似,只不過
dpl的字段設定成0。
set_task_gate(n,gdt)
在idt的第n
個表項插入乙個中斷門。門中的段選擇符存放乙個
tss的全域性描述符指標,該
tss中包含要被啟用的函式,偏移量設定成0,
dpl欄位設定成3。
idt的初步初始化
當計算機還執行在模式時,
idt被初始化並由
bios
例程使用。然而,一旦
linux
接管,idt
就被移到
ram的另乙個區域,並進行第二次初始化,因為
linux
沒有利用任何
bios
例程。idt
存放在idt_table
表中,有
256個表項。
6位元組的
idt_descr
變數指定了
idt的大小和它的位址,只有當核心用
lidt
彙編指令初始化
idtr
暫存器時才用到這個變數。
在核心初始化過程中,
setup_idt()
彙編函式用同乙個斷門來填充所有這
256個
idt_table
表項。用組合語言寫成的
ignore_int()
中斷處理程式,可以看作乙個空的處理程式,它執行下列動作:
在棧中儲存一些暫存器的內容。
呼叫printk()
函式列印」
unknowninterrupt」
系統訊息。
從棧恢復暫存器的內容。
執行iret
指令以恢復被中斷的程式。
ignore_int()
處理程式應該從不被執行,在控制台或日誌檔案中出現的」
unknowninterrupt」
訊息標誌著要麼是出現了乙個硬體問題,要麼就是出現了乙個核心的問題。
緊接著這個預初始化,核心將在
idt中進行第二遍初始化,用有意義的陷阱和斷處理程式替換這個空處理程式。一旦這個過程完成,對控制單元產生的每個不同的異常,
idt都有乙個專門的陷阱或系統門,而對於可程式設計中斷控制器確認的每乙個
irq,
idt都將包含乙個專門的中斷門。
在接下來的兩節中,將分別針對異常和中斷來詳細地說明這個工作是如何完成。
中斷和異常 中斷描述符表的初始化
一 中斷描述符表的初始化 從作業系統角度描述中斷描述符表的初始化。linux核心在系統的初始化階段需要進行大量的初始化工作,與中斷相關的工作有 初始化可程式設計控制器 中斷控制器 8259a 將中斷描述符表的起始位址載入idtr暫存器,並初始化表中的每一項。使用者程序通過int指令發出乙個中斷請求,...
zynq freeRTOS初始化中斷
問題描述 zynq7000 上 ps standalone裸跑,ps timer計時器中斷,pl ps中斷均工作正常,將 移植到freertos工程時,中斷不執行,task執行正常。解決 xilinx freertos 9.0.1 bsp,中有乙個檔案 portzynq7000.c.定義了乙個全域性...
Fw 中斷的初始化
要使用中斷肯定得初始化,這些初始化在系統啟動時已經為你做好了,但是我們還是來看看怎樣初始化的,這樣就能更好的理解中斷機制了。先看下面函式 355 void init init isa irqs void 356 else 381 382 上面的函式分為兩個部分,一 個是init 8259a 0 另乙...