QAIC 驅動程式¶
QAIC 驅動程式是 AIC100 系列 AI 加速器產品的核心模式驅動程式 (KMD)。
中斷¶
中斷風暴緩解¶
儘管 AIC100 DMA 橋硬體實現了中斷風暴緩解機制,但中斷風暴仍然可能發生。如果工作負載特別快,並且主機響應迅速,就可能發生中斷風暴。如果主機能夠像裝置插入元素一樣快速地從響應 FIFO 中排出元素,那麼裝置將頻繁地將響應 FIFO 從空轉換為非空,並以與工作負載處理輸入能力相當的速度生成 MSI。已知 lprnet(車牌識別網路)工作負載會觸發此情況,每秒可生成超過 10 萬個 MSI。已觀察到大多數系統無法長時間容忍這種情況,並且會因中斷控制器中斷主機 CPU 的開銷而導致某種形式的看門狗崩潰。
為緩解此問題,QAIC 驅動程式實現了特定的中斷處理。當 QAIC 接收到中斷時,它會停用該線路。這可以防止中斷控制器中斷 CPU。然後 AIC 排空 FIFO。一旦 FIFO 排空,QAIC 會實現一個“最後機會”輪詢演算法,其中 QAIC 會休眠一段時間,以檢視工作負載是否會產生更多活動。在此期間,中斷線路保持停用狀態。如果未檢測到活動,QAIC 會退出輪詢模式並重新啟用中斷線路。
QAIC 中的此緩解措施非常有效。同樣的 lprnet 用例,每秒生成 10 萬個中斷(根據 /proc/interrupts),但在 5 分鐘內可減少到大約 64 箇中斷,同時保持主機系統穩定,並具有相同的工作負載吞吐量效能(在執行間的噪聲變化範圍內)。
單 MSI 模式¶
MultiMSI 在所有系統上都未得到良好支援;虛擬化系統更是如此(約 2023 年)。鑑於虛擬機器監控程式會掩蓋 PCIe MSI 功能結構,以及 vIOMMU 對大記憶體的需求(支援 MultiMSI 所必需),因此在需要時能夠回退到單個 MSI 是很有用的。
為了支援這種回退,我們允許只分配一個 MSI 的情況,並在 MHI 和 DBC 之間共享該 MSI。當裝置檢測到只配置了一個 MSI 時,它會將 DBC 的中斷重定向到通常用於 MHI 的中斷。不幸的是,這意味著每個 DBC 和 MHI 的中斷處理程式都會為每個到達的中斷喚醒;但是,DBC 執行緒化的中斷處理程式只有在檢測到有工作要做時才啟動(MHI 總是會啟動其執行緒化處理程式)。
如果 DBC 被配置為強制 MSI 中斷,這可以規避上述軟體中斷風暴緩解措施。由於 MSI 是共享的,它永遠不會被停用,從而允許 FIFO 中的每個新條目觸發一個新的中斷。
神經網路控制 (NNC) 協議¶
NNC 的實現分為 KMD (QAIC) 和 UMD 兩部分。通常,QAIC 瞭解如何編碼/解碼 NNC 有線協議,以及需要核心空間知識才能處理的協議元素(例如,將主機記憶體對映到裝置 IOVA)。QAIC 瞭解訊息結構以及所有事務。QAIC 不理解命令(直通事務的有效載荷)。
QAIC 在力所能及的範圍內處理並強制執行所需的小端序和 64 位對齊。由於 QAIC 不知道直通事務的內容,因此它依賴 UMD 來滿足要求。
終止事務對 QAIC 特別有用。QAIC 不知道載入到裝置上的資源,因為大部分活動發生在 NNC 命令內部。因此,QAIC 無法回滾使用者空間活動。為確保在程序崩潰或出現 bug 時使用者空間客戶端的資源得到完全釋放,QAIC 使用終止命令通知 QSM 使用者已退出,並且資源可以被釋放。
QSM 可以報告其支援的 NNC 協議版本號。這以主版本號和次版本號的形式呈現。
主版本號更新表示 NNC 協議發生了更改,這會影響訊息格式或事務(影響 QAIC)。
次版本號更新表示 NNC 協議發生了更改,這會影響命令(不影響 QAIC)。
uAPI¶
QAIC 為每個物理 PCIe 裝置建立一個加速裝置。只要 Linux 識別該 PCIe 裝置,該加速裝置就存在。
PCIe 裝置可能並非總是處於接受使用者空間請求的狀態。QAIC 將觸發 KOBJ_ONLINE/OFFLINE uevents,以通告裝置何時可以接受請求 (ONLINE) 以及何時由於復位或其他狀態轉換而不再接受請求 (OFFLINE)。
QAIC 定義了多個驅動程式特定的 IOCTL 作為使用者空間 API 的一部分。
- DRM_IOCTL_QAIC_MANAGE
此 IOCTL 允許使用者空間向 QSM 傳送 NNC 請求。該呼叫將阻塞,直到收到響應或請求超時。
- DRM_IOCTL_QAIC_CREATE_BO
此 IOCTL 允許使用者空間分配一個緩衝區物件 (BO),該物件可以從工作負載傳送或接收資料。該呼叫將返回一個表示已分配緩衝區的 GEM 控制代碼。BO 在被切片之前不可用(參見 DRM_IOCTL_QAIC_ATTACH_SLICE_BO)。
- DRM_IOCTL_QAIC_MMAP_BO
此 IOCTL 允許使用者空間準備一個已分配的 BO,以便將其 mmap 到使用者空間程序中。
- DRM_IOCTL_QAIC_ATTACH_SLICE_BO
此 IOCTL 允許使用者空間對 BO 進行切片,以準備將 BO 傳送到裝置。切片操作描述了 BO 的哪些部分發送到工作負載的哪個位置。這需要為 DMA 橋進行一系列 DMA 傳輸,因此會將 BO 鎖定到特定的 DBC。
- DRM_IOCTL_QAIC_EXECUTE_BO
此 IOCTL 允許使用者空間向裝置提交一組已切片的 BO。該呼叫是非阻塞的。成功僅表示 BO 已排隊到裝置,但不保證它們已執行。
- DRM_IOCTL_QAIC_PARTIAL_EXECUTE_BO
此 IOCTL 的操作方式與 DRM_IOCTL_QAIC_EXECUTE_BO 類似,但它允許使用者空間縮小為此次特定呼叫傳送到裝置的 BO 大小。如果一個 BO 通常有 N 個輸入,但只有其中一部分可用,此 IOCTL 允許使用者空間指示只應將 BO 的前 M 位元組傳送到裝置,以最大程度地減少資料傳輸開銷。此 IOCTL 會動態重新計算切片,因此在 BO 排隊到裝置之前會產生一些處理開銷。
- DRM_IOCTL_QAIC_WAIT_BO
此 IOCTL 允許使用者空間確定特定 BO 何時已由裝置處理。該呼叫將阻塞,直到 BO 已處理並可以重新排隊到裝置,或者發生超時。
- DRM_IOCTL_QAIC_PERF_STATS_BO
此 IOCTL 允許使用者空間收集 BO 最近一次執行的效能統計資訊。這允許使用者空間構建 BO 處理的端到端時間線,以便進行效能分析。
- DRM_IOCTL_QAIC_DETACH_SLICE_BO
此 IOCTL 允許使用者空間從 BO 中移除最初由 DRM_IOCTL_QAIC_ATTACH_SLICE_BO 呼叫提供的切片資訊。這是 DRM_IOCTL_QAIC_ATTACH_SLICE_BO 的反向操作。必須在 BO 空閒時才能呼叫 DRM_IOCTL_QAIC_DETACH_SLICE_BO。在成功執行分離切片操作後,BO 可以透過新的 DRM_IOCTL_QAIC_ATTACH_SLICE_BO 呼叫附加新的切片資訊。分離切片後,BO 無法執行,直到執行新的附加切片操作。結合附加切片和分離切片呼叫,使用者空間可以使用一個 BO 處理多個工作負載。
使用者空間客戶端隔離¶
AIC100 支援多個客戶端。單個客戶端可以佔用多個 DBC,而多個客戶端可以各自佔用一個或多個 DBC。工作負載可能包含敏感資訊,因此只有擁有該工作負載的客戶端才應被允許與 DBC 互動。
客戶端透過與其 open() 呼叫關聯的例項進行識別。客戶端只能使用其分配的記憶體以及分配給其工作負載的 DBC。嘗試訪問分配給其他客戶端的資源將被拒絕。
模組引數¶
QAIC 支援以下模組引數
datapath_polling (布林型)
配置 QAIC 使用輪詢執行緒處理資料路徑事件,而不是依賴裝置中斷。適用於 MultiMSI 損壞的平臺。必須在 QAIC 驅動程式初始化時設定。預設值為 0(關閉)。
mhi_timeout_ms (無符號整型)
設定 MHI 操作的超時值,單位為毫秒 (ms)。必須在驅動程式檢測到裝置時設定。預設值為 2000(2 秒)。
control_resp_timeout_s (無符號整型)
設定 QSM 響應 NNC 訊息的超時值,單位為秒 (s)。必須在驅動程式向 QSM 傳送請求時設定。預設值為 60(一分鐘)。
wait_exec_default_timeout_ms (無符號整型)
設定 wait_exec ioctl 的預設超時時間,單位為毫秒 (ms)。必須在呼叫 wait_exec ioctl 之前設定。ioctl 呼叫中指定的值將覆蓋該次呼叫的此預設值。預設值為 5000(5 秒)。
datapath_poll_interval_us (無符號整型)
設定資料路徑輪詢啟用時的輪詢間隔,單位為微秒 (us)。在下一個輪詢間隔生效。預設值為 100(100 微秒)。
timesync_delay_ms (無符號整型)
設定兩次連續的時間同步操作之間的時間間隔,單位為毫秒 (ms)。預設值為 1000(1000 毫秒)。