PCI中斷路由
1
PCI設備中斷
PCI spec為每個PCI設備定義了四個中斷引腳,分別是INTA#,INTB#,INTC#和INTD#,如圖:
如果PCI設備為單功能設備,則必須使用INTA#,對于多功能設備,各功能設備可任意接至PCI 總線的四條中斷申請線INTA# - INTD# 。那么如何設定某個PCI設備的某個功能使用那個中斷引腳呢?實際上這個是由PCI設備制造商決定的,并不能由主板固件后期更改。我們翻出PCI體系結構文中介紹的PCI配置空間,在其中interrupt pin會告知主板固件該func使用了哪個引腳,如圖中紅色圈標注:
一個PCI設備可以有8個func,而4個終端引腳意味著中斷共享不可避免。PCI為了方便中斷共享,定義中斷是電平觸發,低電平有效。中斷信號與PCI CLK異步,設備一旦Assert為低,則要維持低電平狀態,直到驅動程序清除這個中斷請求。這樣PCI中斷可以為通過鏈的方式來共享,某個設備中斷處理完畢后將其電平置高,只有該中斷信號上所有的設備中斷處理都結束了,該中斷信號才能恢復高電平,整個中斷處理才能結束。實際上中斷共享不僅僅存在PCI設備各個func中,假設系統中有10個PCI設備,每個設備有4個中斷引腳,要它們每個都獨立意味著中斷控制器需要有40個引腳。我們通過前文知道PIC只有15個引腳,IOAPIC通常有24個引腳,還有很多保留不可用,而一臺計算機內部PCI設備往往超過20個。所以,中斷更需要在設備之間共享。
讓我們舉個形象的比喻來理解中斷共享的處理。想象操作系統中斷處理調度器是個嚴厲的老師,設備中斷處理例程是一群可愛的小朋友,他們被按照連接在PIC/IOAPIC引腳數分成若干排。每個小朋友手里都有個按鈕,小朋友想要問問題,就按下按鈕,老師回答完后他會再按一下恢復彈起狀態。問題是老師是個近視眼,他看不見后面的小朋友。為了解決這個問題,在每排座位前面安裝了個燈泡,當這排小朋友有人的按鍵被按下,燈就亮了。老師上課時,看見第2排燈亮了,他就停下來,問:“第2排第1個小朋友,是不是你要問問題?”得到肯定的答復就解答該小朋友,否定的話就問下一個,如此往復,直到該排沒有人有問題,燈才滅,老師才能繼續講課。
看來在老師沒有換個更好的眼鏡或者做個近視矯正手術之前這是唯一的辦法了。那么該如何為這些小朋友分組呢,老師把這個任務交給了班長小張。我們幫小張想想,怎么分配才能既公平又上課效率高呢?是不是平均分最好呢?假設小朋友都很乖,這樣是最好的辦法,但是小張知道班里有個話癆小朋友--小明,他什么都不懂但問題很多,他會頻繁提問。假設他被分在第3排最后一個,老師每次看到第3排燈亮了,都從第一個小朋友問,經過了好久才問到小明,效率好低,小明每次很久才輪到他也很不滿,上課節奏整體也被拖慢了!
怎么辦?開除小明嗎?可惜小明是校董的兒子,絕對不能少!讓小明坐第一個位置嗎?校規規定座位是流水席,每排都先來先坐,再說讓小明又高問題又多,誰坐他后面別想問問題了,太不公平。看來只有給小明開小灶了,讓他單獨坐一排!
世界上沒有絕對的公平,在資源捉襟見肘時會叫的孩子有奶吃在我們天朝還少嗎?班長小張也只有做些妥協了。我們的計算機固件和主板硬件工程師在很多時候就扮演了左右為難的小張的角色,在硬件的限制下,盡量保證系統的響應時間。他們基于一些簡單的原則:
A. 公平:盡量減少中斷共享。
B. 效率:緊急或者頻繁的設備可以獨占中斷
同時要充分理解PC系統中絕大多數設備都是單功能設備,所以僅使用INTA#信號,很少使用INTB#和INTC#信號,而INTD#信號更是極少使用。映射INTA#~INTD#到PIC/IOAPIC IRQ的機制稱為“Swizzling”,它在不同情況下實現機制有很大不同,我們分別來看看。
2
PCI/PCIe擴展插槽
對主板上的PCI擴展插槽,用戶插入什么設備,插在哪個槽內都不能在出廠時確定。我們這里要盡量考慮平衡原則和效率原則。我們將所有插槽的INTA#~INTD#分成四組串聯起來如何?這樣離得最近的Slot 1高興了,每個都是我優先!萬一有個用戶把重要的網卡插在slot 4,效率會嚴重下降。在充分考慮到PCI設備絕大多數都是單功能設備(僅使用INTA#信號,很少使用INTB#和INTC#信號,而INTD#信號更是極少使用),PCI SIG推薦PCI to PCI bridge后slot連接關系應該組成如下圖:
即Slot1 INTA#->Slot2 INT B#->Slot3 INTC#->Slot4 INTD#等等。這樣,當然slot 1還是占些小便宜,但其他slot也有很大機會獨占某個中斷線(想想為什么)。這種Swizzling是主板設計硬件連線決定的,不由主板固件決定,但是主板固件需要了解這些信息。
PCI橋則將它下面的轉換結果INTx轉化為本身的INTx,接入芯片組內部的Swizzling。PCIe的插槽是1:1對應PCIe root port,PCIe root port可以看作PCI橋,等同處理。
3
芯片組內部
PCI SIG并沒有規定芯片組內部Swizzling的規則,而芯片組內部設備在出廠時就已經確定了,芯片是不是可以hard code一個中斷路由關系呢?實際上有些芯片組就是這么做的,在芯片硬件說明書中注明各種PCI設備INTx到IRQ的關系表,BIOS只要照著報告給OS就可以了。而Intel芯片組提供了更靈活的方式,BIOS可以根據需要設置中斷路由,以適應不同的應用市場。不同的芯片組設置方法不同,有些給出了幾組應用場景,BIOS可以根據需要選擇一種,而在很早開始南橋芯片組ICH/PCH就給出了一種更靈活的方式,就是我們前文提到的PIRQ。簡單來說就是在ICH/PCH內部加入了幾個新的寄存器:IR寄存器組。IR寄存器組用于設定芯片組內部PCI設備中斷INTA#-H# 連接到具體PIC/IOAPIC的哪個引腳上。這樣BIOS就可以根據面向市場不同重新繪制中斷路由圖了,好方便!
OS接口
班長小張終于給小朋友排好了座位,他怎么把這些信息告訴各個老師呢?一個個告訴太麻煩,不如把所有情況打印成一張表貼子講臺上。我們的固件也是通過表告訴OS的,這里有兩種表。
1
MP table
有感于DOS階段中斷設置的混亂,微軟在推出Win95時聯合Intel提出了PCI Interrupt Routing Table的數據結構,它的作用就是用來描述在使用8259中斷控制器的系統下,PCI中斷的路由關系。它和其他一些表構成了傳統的MP table。它只在PIC模式下起作用,而PIC模式已經被淘汰,所以它的具體結構我們這里略過。這里要特別指出的是,固件在提交PIRQ table時要同步更新PCI配置空間的Interrupt line寄存器,如圖籃圈部分:
2
ACPI table
在APIC模式下,固件應該通過ACPI的_PRT(PCI Routing Table) method返回主板上無論硬件還是固件設定的中斷路由信息。ACPI spec有示例,但內容比較單薄。我們來看一個Intel開源硬件平臺Minnowboard MAX固件是怎么處理的。
_PRT代碼如下:
Method(_PRT,0)
{
If(PICM) {Return(AR00)} // APIC mode
Return (PR00) // PIC Mode
} // end _PRT
這里判斷如果是PIC模式,返回PR00,如果是APIC模式返回AR00表。PR00和AR00其實是同一個中斷路由關系的兩個view,其實質內容是一致的。我們單看一下AR00就好:
Name(AR00, Package()
{
// SD Host #0 - eMMC
Package() {0x0010FFFF, 0, 0, 16 },
// SD Host #1 - SDIO
Package() {0x0011FFFF, 0, 0, 17 },
// SD Host #2 - SD Card
Package() {0x0012FFFF, 0, 0, 18 },
// SATA Controller
Package() {0x0013FFFF, 0, 0, 19 },
// xHCI Host
Package() {0x0014FFFF, 0, 0, 20 },
// Low Power Audio Engine
Package() {0x0015FFFF, 0, 0, 21 },
// USB OTG
Package() {0x0016FFFF, 0, 0, 22 },
//
// MIPI-HSI
Package() {0x0017FFFF, 0, 0, 23 },
//
// LPSS2 DMA
// LPSS2 I2C #4
Package() {0x0018FFFF, 0, 0, 17 },
// LPSS2 I2C #1
// LPSS2 I2C #5
Package() {0x0018FFFF, 2, 0, 19 },
// LPSS2 I2C #2
// LPSS2 I2C #6
Package() {0x0018FFFF, 3, 0, 18 },
// LPSS2 I2C #3
// LPSS2 I2C #7
Package() {0x0018FFFF, 1, 0, 16 },
// SeC
Package() {0x001AFFFF, 0, 0, 21 },
//
// High Definition Audio Controller
Package() {0x001BFFFF, 0, 0, 22 },
//
// EHCI Controller
Package() {0x001DFFFF, 0, 0, 23 },
// LPSS DMA
Package() {0x001EFFFF, 0, 0, 19 },
// LPSS I2C #0
Package() {0x001EFFFF, 3, 0, 16 },
// LPSS I2C #1
Package() {0x001EFFFF, 1, 0, 17 },
// LPSS PCM
Package() {0x001EFFFF, 2, 0, 18 },
// LPSS I2S
// LPSS HS-UART #0
// LPSS HS-UART #1
// LPSS SPI
// LPC Bridge
//
// SMBus Controller
Package() {0x001FFFFF, 1, 0, 18 },
//
。。。。
}
通過這張大表,OS才能確定主板PCI設備和IRQ的連接關系。
其他中斷信息
除了中斷路由表之外,還有很多和中斷相關的信息也需要通過ACPI向OS報告
1. LAPIC和IOAPIC
固件需要在ACPI的MADT表里向OS報告所有的LAPIC和IOAPIC。LAPIC默認映射到物理地是0xFEE00000(想想為什么不會互相沖突?),不需要報告,只要LAPIC ID即可。需要特別說明的是,因為APIC ID不一定從0開始,也不一定連續,所以其值要動態枚舉而得。同時由于很多OS在調度processor時是挨個調度的,而HT的兩個thread的APIC ID往往連續,同時被調度效能大大降低,Intel推薦HT的兩個thread隔開報告。如果多個CPU socket,情況又有變化,這是系統調優的手段之一,這里不再贅述。
IOAPIC的地址和ID都由固件指定,必選準確的在MADT里向OS報告,每個IOAPIC的GSI偏移量也要報告。
2. SCI
在Intel的芯片組中,SCI通常缺省占用了中斷9。它的值可以在芯片組的寄存器中修改,并需要通過FADT報告OS。因為這是個特殊指定的中斷,所以在MADT中還要通過interrupt override節予以保留。
-
寄存器
+關注
關注
31文章
5421瀏覽量
123297 -
中斷處理
+關注
關注
0文章
94瀏覽量
11195 -
中斷控制器
+關注
關注
0文章
61瀏覽量
9633 -
PCI協議
+關注
關注
0文章
2瀏覽量
5544 -
調度器
+關注
關注
0文章
98瀏覽量
5455
發布評論請先 登錄
請問amc1200輸出voutp和Voutn怎么直接連接到28335的AD采集引腳上?
單端信號何連接到ADFS1256的引腳上呢?
無法連接到PIC32MX
請問是否有必要將數據引腳也連接到外部中斷?
PIC16F639上的SPI端口也可以用來連接外部設備嗎?
PIC32是否使用Eithernet引腳使用內部生成的中斷?
怎么通過USB連接將pic32連接到API設備?
PIC24引腳上使用了內部下拉功能
SPI是否應該連接到j11引腳上的VDDIO和VDDI2C引腳?
PIC單片機引腳中斷程序的設計技巧
PCI總線的中斷信號與中斷控制器的連接關系
簡述PCI總線的中斷機制
連接器引腳上錫不良分析

評論