RFC-0070:PCI 通訊協定變更,以支援舊版中斷 | |
---|---|
狀態 | 已接受 |
領域 |
|
說明 | 緩解 PCI 傳統中斷情形所導致的因應措施。 |
問題 | |
毛皮變化 | |
作者 | |
審查人員 | |
提交日期 (年-月-日) | 2020-01-17 |
審查日期 (年-月-日) | 2020-02-25 |
摘要
PCI Bus 驅動程式庫需要在使用者空間中停用舊版級別 才會觸發中斷,直到裝置中斷為止 來自於持續喚醒 Bus Driver IRQ 執行緒的 IRQ。 為此,我們需要讓裝置驅動程式庫能夠通知公車驅動程式庫 這項服務準備好迎接新的中斷情形,並重新啟用舊版服務 產生幹擾
提振精神
大多數新型 PCI 裝置都是透過訊息訊號中斷 (MSI) 運作
透過 PCI 中的選用 MSI 或 MSI-X 功能控制
設定空間這類中斷情形僅適用於特定裝置,且
由核心控點與
MsiInterruptDispatcher
。每項 MSI 都只會提供給一部裝置
都可視為一般系統中斷情形。
但是,PCI 舊版中斷是透過一組共用的中斷線運作。 並詳列系統韌體表格,如 ACPI 由 PCI 韌體規格定義。這些幹擾元素 但因規格而呼叫的觸發率最低觸發中斷時 系統軟體必須負責判斷 負責中斷作業,以便服務並釋放連線。於 核心 PCI 匯流排驅動程式 (kPCI) 由所有舊版中斷式處理處理 擁有向所有 PciInterruptDispatcher 註冊的共用中斷處理常式 核心部分。這個處理常式會判斷哪個裝置已產生 中斷並指示適當的中斷物件。裝置的功能 以免產生幹擾下次驅動程式庫在下次等候時 調度工具的 Unmask 掛鉤將會取消遮罩並重新啟用裝置的 舊版中斷產生能力
憑藉使用者空間 PCI 匯流排 (uPCI) 所有的機器
使用者空間uPCI 本身就是一個低負載的 IRQ 工作站。
由裝置負責,並發出虛擬中斷狀態
與裝置的驅動程式庫互動。不過,由於中斷是在不同的層級
如果我們沒有裝置的驅動程式庫,或
指定的驅動程式庫無法正確服務中斷。不過,如果 uPCI 停用了
中斷,讓驅動程式庫可以處理,但系統並沒有
PCI 裝置驅動程式的方法,以便重新啟用中斷作業。目前有
沒有任何方法可通知 uPCI 匯流排驅動程式,裝置驅動程式庫已呼叫
虛擬中斷的 zx_interrupt_wait
或 zx_port_wait
,因此
匯流排驅動程式不知道何時應重新啟用裝置的中斷情形。
設計
我們需要設計 PCI 驅動程式中的兩種不同中斷用途。
- 確定他們是 PCI 驅動程式,並直接呼叫
PciProtocol
方法的驅動程式。 - 以阻礙使用
PciProtocol
方法的方式使用中斷的驅動程式。
當使用 PCI_IRQ_MODE_LEGACY
設定的舊版中斷情形觸發
共用線,公車驅動程式庫負責通知正確的裝置。
與 kPCI 驅動程式庫類似,匯流排會停用裝置的舊版幹擾
向驅動程式庫發出中斷訊號時
有效掩蓋資料我們將在產品中新增 PCI 通訊協定
方法
讓裝置驅動程式要求重新啟用中斷。
。可能與使用者互動的駕駛需要這類通話
某些設定使用舊版中斷,但將會需要
只透過 MSI 運作的裝置不會發生任何異動。這樣一來,
,才符合首次使用需求。
這與 Linux 處理 Userspace I/O 中斷時的處理方式類似。
針對第二次用量,我們會建立替代的舊版 IRQ 模式
PCI_IRQ_MODE_LEGACY_ACKLESS
。系統不會選取這個模式
ConfigureIrqMode()
,必須由駕駛特別選取
這個特殊規定已設定乾擾服務的裝置
監控方式,看看
超過一個設定的數字。如果發生這種情況,裝置
系統將停用乾擾功能做法與 Linux 處理
啟動中斷
實作
可以按順序進行變更,而且完全不需要遷移或 CQ 方面的問題。
- 修改
pci_configure_irq_mode
以加入外部參數,儲存 IRQ 為不受干擾模式的駕駛人選擇,並且 現有來電者。 - 新增通訊協定方法
pci_legacy_interrupt_ack
(或直接pci_interrupt_ack
),重新啟用裝置上的舊版幹擾服務 並傳回ZX_OK
或ZX_ERR_BAD_STATE
(如果裝置並非如此) 改為使用舊版中斷 - 更新
pci_configure_irq_mode
的現有呼叫者和PCI_IRQ_MODE_LEGACY
會在幹擾訊息中使用新的通訊協定方法 處理和處理資料 - 更新可簡化中斷作業的驅動程式,並確保其使用
PCI_IRQ_MODE_LEGACY_NOACK
取代PCI_IRQ_MODE_LEGACY
。 - 要求 uPCI IRQ 工作站停用裝置的舊版中斷產生機制 發出信號,告知裝置驅動程式庫的虛擬中斷 會進行遷移
- 大量記錄
PciProtocol
班鳩琴中的 PCI 中斷使用情形 以及 Fuchsia.dev。
成效
遇到的大多數 PCI 裝置將透過 MSI 運作。由於 裝置若仍使用舊版中斷功能,通常僅可使用較舊的版本 硬體,搭載低效能需求的整合式 SOC 裝置,模擬 不支援 MSI 的環境,以及使用中斷功能的裝置 極少
需要處理舊版中斷的驅動程式將新增額外管道 依照此新 PCI 通訊協定的性質,寫入其中斷處理常式 方法,需要從驅動程式庫 devhost Proxy 寫入 uPCI。可用的值包括 ,或檢查 使用 Zircon 匯總基準
安全性考量
無。
隱私權注意事項
無。
測試
請確認 CQ/CI 中現有的整合和端對端測試
變更之後,幹擾仍繼續正常運作,以及執行新的單元測試
會驗證 pci_configure_irq_mode
的變更作業
通訊協定方法
說明文件
這需要展開 PCI 文件來說明運算理論
幹擾模式此外,標示出
zx_interrupt_wait
和zx_port_wait
的pci_legacy_interrupt_ack
說明文件。
缺點、替代方案和未知
缺點
大多數駕駛人偏好只使用 MSI / MSI-X 中斷模式, 這個 API 完全不需擔憂 變更系統的變更內容,僅對可能使用 而不是所有驅動程式。不過 這麼做會承擔驅動程式庫基於特定裝置設定所編寫的風險 否則應用程式只會在 他們無法阻止攻擊如果駕駛人 裝置。
使用多個後端的情況也會增加一些複雜度。例如: xHCI 驅動程式庫類似如果 PCI 支援 但舊版的中斷作業可能看起來會像這樣:
// Initialize the proper setup and obtain an interrupt
if (pci_.is_valid()) {
pci_init();
} else {
mmio_init();
}
do {
// Wait loop on the interrupt
// Handle the interrupt
if (mode_ == XHCI_MODE_PCI && irq_mode_ == PCI_IRQ_MODE_LEGACY)
status = pci_.LegacyInterruptAck();
}
}
如果省略確認程式碼,此驅動程式庫可與 MSI 搭配使用,但 版本更新完成後就不會中斷改善測試效率 PCI 驅動因素的架構將引出更好的解決方案來捕捉這些 發生錯誤。
考慮的替代品
將過多未處理的中斷情形標示為嚴重,並停用乾擾
和 Linux 一樣,我們只需設定 中斷點,而我們可以在到達時停用或忽略中斷行 直到重新啟動為止這種做法的主要問題是 處理共用中斷,它會透過硬 IRQ 呼叫處理常式鏈 再呼叫核心中的處理常式來處理中斷情形。 已完成。這可確保所有驅動程式庫中斷處理常式皆執行 ,因此只有在處理常式未正確執行時,才會發生不實的中斷情形 處理中斷在 Zircon 和裝置驅動程式中 程序脫落,我們可以指示他們喚醒執行緒處理執行緒,但我們 無法得知已完成的任務這會導致 一般情況是否可能會造成中斷,具體取決於驅動程式庫駕駛速度 排定 IRQ 執行緒,並處理指定的中斷狀況。不過 與確認提案相較,這種方式還是會導致嚴重的中斷情形。 常見用途
新增 PCI 通訊協定方法,以等待中斷作業
您可以選擇新增一種方法來處理等待任何類型的
中斷,有效pci_interrupt_wait
,避免需要使用額外的
在中斷中傳回條件
不幸的是,這會導致 PCI 中斷需要處理
與其他幹擾不同Google 提供最優質的功能
將任何中斷物件設為與任何其他中斷物件相同的介面
很有價值
可以使用「zx_interrupt_wait
」、「zx_port_bind
」、「zx_port_wait
」和
zx_object_wait_async
。我們的系統中多數的驅動程式會同時產生
多次中斷的 IRQ 連接埠,或多個後端 (UART、PCI、USB)
因此務必不要違反網頁服務中斷
如需儲存大量結構化物件
建議使用 Cloud Bigtable
在衍生的 InterruptDispatcher 中處理這個問題
我們可以保留 kPCI 的 PciInterruptDispatcher
概念,並委派這張專輯
並在 PCI 裝置驅動程式庫和
與核心部分相同可惜的是
使用者空間 PCI 驅動程式庫和 Zircon 核心
- 每個專用
InterruptDispatcher
都必須能寫入 PCI 裝置的控制註冊器,以停用舊版中斷情形。這會導致 最好是 VMO,與 MSI 的做法不同 提供給任何 syscall 建立此物件根本無法 因為調度員必須知道 。 - 中斷停用是控制暫存器中 userspace Bus 驅動程式庫在公車和裝置期間經常修改 這類初始化作業可能代表競爭狀況, 以免造成任何待處理的干擾
- 如果在裝置上使用衍生的
InterruptDispatcher
必須處理確定誰在共用線上觸發的中斷。開始時間 裝置不再隨著公車班次繼續處理 這表示我們需要使用類似於 kPCI 的SharedIrqHandler
的邏輯,在 與核心部分相同 - 現在,我們也需要更加瞭解 PCI 舊版 IRQ 再次透過核心從 ACPI / 主機板檔案轉送資料表。這是 會在使用者空間中處理立即啟動 ACPI。
目前,除非 我們願意承認 PCI 是特殊的驅動程式庫,需要自訂 以及約 2 個其他系統呼叫來處理其工作。
既有藝術品和參考資料
在我的研究中,完全在使用者空間中處理這片是一個獨特的 Zircon 問題。
OSX 的 DriverKit 使用
IOInterruptDispatchSource
可協同運作 並在核心中處理中斷設定和處理作業此外, PCIDriverKit 僅支援 MSI 和 MSI-X 中斷模式。大多數 Linux PCI 中斷都會在核心本身中處理。共用項目 中斷具有由驅動程式註冊的處理常式鏈結。如果 中斷時,核心會依序呼叫每個處理常式,直到 處理中斷如果共用中斷線 任何由核心未處理的中斷情形,就會停用 幹擾。
Linux 也支援透過 Userspace I/O 支援簡易的使用者空間驅動程式 (UIO) 介面。這可讓驅動程式庫對
read()
提供了/dev/uioX
sysfs 節點等待中斷作業。「中斷」為 會在觸發時停用,但驅動程式庫可透過 對 sysfs 節點發出的write()
呼叫。大多數 Windows PCI 驅動程式皆以核心模式驅動程式架構建構 (KMDF)。他們的中斷處理常式會在核心中斷時呼叫 調度程式和驅動程式註冊處理常式,在 IRQ 環境中執行。