IOMMUFD¶
- 作者:
Jason Gunthorpe
- 作者:
Kevin Tian
概述¶
IOMMUFD 是使用者 API,用於控制 IOMMU 子系統,因為它涉及使用檔案描述符從使用者空間管理 IO 頁表。 它旨在通用並可被任何想要向用戶空間公開 DMA 的驅動程式使用。 預計這些驅動程式最終將棄用它們可能已經/歷史上實現的任何內部 IOMMU 邏輯(例如,vfio_iommu_type1.c)。
IOMMUFD 至少提供對所有 IOMMU 的 I/O 地址空間和 I/O 頁表的通用管理支援,並在設計中留有空間以新增非通用功能以滿足特定硬體功能。
在這種上下文中,大寫字母 (IOMMUFD) 指的是子系統,而小寫字母 (iommufd) 指的是透過 /dev/iommu 建立的供使用者空間使用的檔案描述符。
關鍵概念¶
使用者可見物件¶
以下 IOMMUFD 物件暴露給使用者空間
IOMMUFD_OBJ_IOAS,表示 I/O 地址空間 (IOAS),允許將使用者空間記憶體對映/取消對映到 I/O 虛擬地址 (IOVA) 範圍中。
IOAS 是 VFIO 容器的功能替代品,與 VFIO 容器一樣,它將 IOVA 映射覆制到其中包含的 iommu_domains 列表中。
IOMMUFD_OBJ_DEVICE,表示由外部驅動程式繫結到 iommufd 的裝置。
IOMMUFD_OBJ_HWPT_PAGING,表示由 iommu 驅動程式管理的實際硬體 I/O 頁表(即,單個 struct iommu_domain)。“PAGING”主要指示此型別的 HWPT 應連結到 IOAS。它還表明它由具有 __IOMMU_DOMAIN_PAGING 特性標誌的 iommu_domain 支援。這可以是執行在使用者空間中的裝置的 UNMANAGED 階段 1 域,也可以是從客戶機級別物理地址到主機級別物理地址的對映的巢狀父級階段 2 域。
IOAS 具有共享相同 IOVA 對映的 HWPT_PAGING 列表,它將使其對映與每個成員 HWPT_PAGING 同步。
IOMMUFD_OBJ_HWPT_NESTED,表示由使用者空間(例如,客戶機作業系統)管理的實際硬體 I/O 頁表(即,單個 struct iommu_domain)。“NESTED”表示此型別的 HWPT 應連結到 HWPT_PAGING。它還表明它由型別為 IOMMU_DOMAIN_NESTED 的 iommu_domain 支援。這必須是執行在使用者空間中的裝置的階段 1 域(例如,在啟用 IOMMU 巢狀轉換特性的客戶機 VM 中。)因此,必須使用給定的巢狀父級階段 2 域來建立它才能關聯。此由使用者空間管理的巢狀階段 1 頁表通常具有從客戶機級別 I/O 虛擬地址到客戶機級別物理地址的對映。
IOMMUFD_FAULT,表示一個軟體佇列,用於 HWPT 使用 IOMMU HW 的 PRI(頁面請求介面)報告 IO 頁面錯誤。此佇列物件為使用者空間提供一個 FD 來輪詢頁面錯誤事件並響應這些事件。必須首先建立一個 FAULT 物件以獲得一個 fault_id,然後可以透過在 IOMMU_HWPT_ALLOC 命令中設定其 flags 欄位中的 IOMMU_HWPT_FAULT_ID_VALID 位來分配一個啟用錯誤的 HWPT。
IOMMUFD_OBJ_VIOMMU,表示物理 IOMMU 例項的一個切片,傳遞給 VM 或與 VM 共享。它可能是某些 HW 加速的虛擬化特性和 VM 使用的一些 SW 資源。例如
客戶機擁有的 ID 的安全名稱空間,例如,客戶機控制的快取標記
非裝置相關的事件報告,例如,無效佇列錯誤
跨物理 IOMMU 訪問可共享的巢狀父級頁表
各種平臺 ID 的虛擬化,例如,RID 和其他 ID
提供準虛擬化無效
直接分配的無效佇列
直接分配的中斷
這樣的 vIOMMU 物件通常可以訪問巢狀父級頁表以支援某些 HW 加速的虛擬化特性。因此,必須給定一個巢狀父級 HWPT_PAGING 物件來建立 vIOMMU 物件,然後它將封裝該 HWPT_PAGING 物件。因此,可以使用 vIOMMU 物件來分配封裝的 HWPT_PAGING 物件,而不是分配 HWPT_NESTED 物件。
注意
名稱“vIOMMU”不一定與 VM 中的虛擬化 IOMMU 相同。VM 可以在具有多個物理 IOMMU 的機器上執行一個巨大的虛擬化 IOMMU,在這種情況下,VMM 會將來自此單個虛擬化 IOMMU 例項的請求或配置分派給為不同物理 IOMMU 的各個切片建立的多個 vIOMMU 物件。換句話說,vIOMMU 物件始終是一個物理 IOMMU 的表示,不一定是虛擬化 IOMMU 的表示。對於想要來自物理 IOMMU 的完整虛擬化特性的 VMM,建議構建與物理 IOMMU 數量相同的虛擬化 IOMMU,以便傳遞的裝置連線到由相應 vIOMMU 物件支援的它們自己的虛擬化 IOMMU,在這種情況下,客戶機作業系統會自然地進行“分派”,而不是 VMM 陷阱。
IOMMUFD_OBJ_VDEVICE,表示針對 IOMMUFD_OBJ_VIOMMU 的 IOMMUFD_OBJ_DEVICE 的虛擬裝置。此虛擬裝置儲存裝置的虛擬資訊或屬性(與 vIOMMU 相關)在 VM 中。一個直接的 vDATA 示例可以是裝置在 vIOMMU 上的虛擬 ID,這是一個 VMM 分配給裝置的唯一 ID,用於 vIOMMU 的轉換通道/埠,例如 ARM SMMUv3 的 vSID、AMD IOMMU 的 vDeviceID 和 Intel VT-d 的 vRID 到上下文表。一些高階安全資訊的潛在用例也可以透過此物件轉發,例如,機密計算架構中的安全級別或領域資訊。當 VMM 將裝置連線到 vIOMMU 時,它應該建立一個 vDEVICE 物件以轉發 VM 中的所有裝置資訊,這是與將同一裝置附加到 vIOMMU 保持的 HWPT_PAGING 分開的 ioctl 呼叫。
IOMMUFD_OBJ_VEVENTQ,表示 vIOMMU 用於報告其事件(例如,發生到巢狀階段 1 的轉換錯誤(不包括應透過 IOMMUFD_OBJ_FAULT 發生的 I/O 頁面錯誤)和特定於 HW 的事件)的軟體佇列。此佇列物件為使用者空間提供一個 FD 來輪詢/讀取 vIOMMU 事件。必須首先建立一個 vIOMMU 物件以獲得其 viommu_id,然後可以使用該 viommu_id 來分配 vEVENTQ。每個 vIOMMU 可以支援多種型別的 vEVENT,但每個 vEVENTQ 型別限制為一個 vEVENTQ。
所有使用者可見的物件都透過 IOMMU_DESTROY uAPI 銷燬。
下圖顯示了使用者可見物件和核心資料結構(iommufd 外部)之間的關係,數字是指建立物件和連結的操作
_______________________________________________________________________
| iommufd (HWPT_PAGING only) |
| |
| [1] [3] [2] |
| ________________ _____________ ________ |
| | | | | | | |
| | IOAS |<---| HWPT_PAGING |<---------------------| DEVICE | |
| |________________| |_____________| |________| |
| | | | |
|_________|____________________|__________________________________|_____|
| | |
| ______v_____ ___v__
| PFN storage | (paging) | |struct|
|------------>|iommu_domain|<-----------------------|device|
|____________| |______|
_______________________________________________________________________
| iommufd (with HWPT_NESTED) |
| |
| [1] [3] [4] [2] |
| ________________ _____________ _____________ ________ |
| | | | | | | | | |
| | IOAS |<---| HWPT_PAGING |<---| HWPT_NESTED |<--| DEVICE | |
| |________________| |_____________| |_____________| |________| |
| | | | | |
|_________|____________________|__________________|_______________|_____|
| | | |
| ______v_____ ______v_____ ___v__
| PFN storage | (paging) | | (nested) | |struct|
|------------>|iommu_domain|<----|iommu_domain|<----|device|
|____________| |____________| |______|
_______________________________________________________________________
| iommufd (with vIOMMU/vDEVICE) |
| |
| [5] [6] |
| _____________ _____________ |
| | | | | |
| |----------------| vIOMMU |<---| vDEVICE |<----| |
| | | | |_____________| | |
| | | | | |
| | [1] | | [4] | [2] |
| | ______ | | _____________ _|______ |
| | | | | [3] | | | | | |
| | | IOAS |<---|(HWPT_PAGING)|<---| HWPT_NESTED |<--| DEVICE | |
| | |______| |_____________| |_____________| |________| |
| | | | | | |
|______|________|______________|__________________|_______________|_____|
| | | | |
______v_____ | ______v_____ ______v_____ ___v__
| struct | | PFN | (paging) | | (nested) | |struct|
|iommu_device| |------>|iommu_domain|<----|iommu_domain|<----|device|
|____________| storage|____________| |____________| |______|
IOMMUFD_OBJ_IOAS 是透過 IOMMU_IOAS_ALLOC uAPI 建立的。一個 iommufd 可以儲存多個 IOAS 物件。IOAS 是最通用的物件,並且不公開特定於單個 IOMMU 驅動程式的介面。對 IOAS 的所有操作都必須在其中的每個 iommu_domain 上平等地操作。
當外部驅動程式呼叫 IOMMUFD kAPI 以將裝置繫結到 iommufd 時,會建立 IOMMUFD_OBJ_DEVICE。預期該驅動程式實現一組 ioctl 以允許使用者空間啟動繫結操作。成功完成此操作將建立對裝置的所需 DMA 所有權。驅動程式還必須設定 driver_managed_dma 標誌,並且在此操作成功之前不得觸控該裝置。
IOMMUFD_OBJ_HWPT_PAGING 可以透過兩種方式建立
當外部驅動程式呼叫 IOMMUFD kAPI 以將繫結的裝置附加到 IOAS 時,會自動建立 IOMMUFD_OBJ_HWPT_PAGING。同樣,外部驅動程式 uAPI 允許使用者空間啟動附加操作。如果 IOAS 的 HWPT_PAGING 列表中存在相容的成員 HWPT_PAGING 物件,則將重複使用它。否則,將建立一個表示使用者空間的 iommu_domain 的新 HWPT_PAGING,然後將其新增到列表中。成功完成此操作將設定 IOAS、裝置和 iommu_domain 之間的連結。一旦完成,裝置就可以進行 DMA。
可以透過 IOMMU_HWPT_ALLOC uAPI 手動建立 IOMMUFD_OBJ_HWPT_PAGING,前提是提供透過 @pt_id 的 ioas_id 以將新的 HWPT_PAGING 關聯到相應的 IOAS 物件。此手動分配的好處是允許分配標誌(在
enum iommufd_hwpt_alloc_flags中定義),例如,如果設定了 IOMMU_HWPT_ALLOC_NEST_PARENT 標誌,則它會分配一個巢狀父級 HWPT_PAGING。
只能透過 IOMMU_HWPT_ALLOC uAPI 手動建立 IOMMUFD_OBJ_HWPT_NESTED,前提是提供透過 @pt_id 的 HWPT_PAGING 或封裝巢狀父級 HWPT_PAGING 的 vIOMMU 物件的 hwpt_id 或 viommu_id 以將新的 HWPT_NESTED 物件關聯到相應的 HWPT_PAGING 物件。關聯的 HWPT_PAGING 物件必須是先前透過同一 uAPI 使用 IOMMU_HWPT_ALLOC_NEST_PARENT 標誌手動分配的巢狀父級,否則分配將失敗。IOMMU 驅動程式將進一步驗證該分配以確保巢狀父級域和要分配的巢狀域是相容的。成功完成此操作將設定 IOAS、裝置和 iommu_domains 之間的連結。一旦完成,裝置就可以透過兩階段轉換(也稱為巢狀轉換)進行 DMA。請注意,可以透過(然後關聯到)同一巢狀父級分配多個 HWPT_NESTED 物件。
注意
手動 IOMMUFD_OBJ_HWPT_PAGING 或 IOMMUFD_OBJ_HWPT_NESTED 都是透過同一 IOMMU_HWPT_ALLOC uAPI 建立的。區別在於透過 iommufd_hwpt_alloc 結構的 @pt_id 欄位傳遞的物件型別。
只能透過 IOMMU_VIOMMU_ALLOC uAPI 手動建立 IOMMUFD_OBJ_VIOMMU,前提是提供 dev_id(用於支援 vIOMMU 的裝置的物理 IOMMU)和 hwpt_id(用於將 vIOMMU 關聯到巢狀父級 HWPT_PAGING)。iommufd 核心會將 vIOMMU 物件連結到
struct device後面的 struct iommu_device。並且 IOMMU 驅動程式可以實現一個 viommu_alloc 操作以分配其自己的 vIOMMU 資料結構,該資料結構嵌入了核心級結構 iommufd_viommu 和一些驅動程式特定的資料。如有必要,該驅動程式還可以為該 vIOMMU(以及因此為 VM)配置其 HW 虛擬化特性。成功完成此操作將設定 vIOMMU 物件和 HWPT_PAGING 之間的連結,然後可以使用此 vIOMMU 物件作為巢狀父級物件來分配上面描述的 HWPT_NESTED 物件。只能透過 IOMMU_VDEVICE_ALLOC uAPI 手動建立 IOMMUFD_OBJ_VDEVICE,前提是提供 iommufd_viommu 物件的 viommu_id 和 iommufd_device 物件的 dev_id。vDEVICE 物件將是這兩個父物件之間的繫結。另一個 @virt_id 也將透過 uAPI 設定,從而為 iommufd 核心提供一個索引,用於將 vDEVICE 物件儲存到每個 vIOMMU 的 vDEVICE 陣列中。如有必要,IOMMU 驅動程式可以選擇實現一個 vdevce_alloc 操作以初始化其 HW 以實現與 vDEVICE 相關的虛擬化特性。成功完成此操作將設定 vIOMMU 和裝置之間的連結。
由於 DMA 所有權宣告,裝置只能繫結到 iommufd,並且最多隻能附加到一個 IOAS 物件(尚不支援 PASID)。
核心資料結構¶
使用者可見的物件由以下資料結構支援
IOMMUFD_OBJ_IOAS 的 iommufd_ioas。
IOMMUFD_OBJ_DEVICE 的 iommufd_device。
IOMMUFD_OBJ_HWPT_PAGING 的 iommufd_hwpt_paging。
IOMMUFD_OBJ_HWPT_NESTED 的 iommufd_hwpt_nested。
IOMMUFD_OBJ_FAULT 的 iommufd_fault。
IOMMUFD_OBJ_VIOMMU 的 iommufd_viommu。
IOMMUFD_OBJ_VDEVICE 的 iommufd_vdevice。
IOMMUFD_OBJ_VEVENTQ 的 iommufd_veventq。
檢視這些資料結構時,有幾個術語
自動域 - 指將裝置附加到 IOAS 物件時自動建立的 iommu 域。這與 VFIO type1 的語義相容。
手動域 - 指使用者指定為要由裝置附加的目標頁表的 iommu 域。雖然當前沒有直接建立此類域的 uAPI,但資料結構和演算法已準備好處理該用例。
核心使用者 - 指像 VFIO mdev 這樣的東西,它使用 IOMMUFD 訪問介面來訪問 IOAS。這首先建立一個 iommufd_access 物件,該物件類似於繫結物理裝置的域。然後,訪問物件將允許將 IOVA 範圍轉換為 struct page * 列表,或對 IOVA 進行直接讀/寫。
iommufd_ioas 用作元資料資料結構來管理 IOVA 範圍如何對映到記憶體頁面,由以下組成
儲存 IOVA 對映的 struct io_pagetable
表示已填充 IOVA 部分的 struct iopt_area
表示 PFN 儲存的 struct iopt_pages
表示 IOMMU 中的 IO 頁表的 struct iommu_domain
表示 PFN 的核心使用者的 struct iopt_pages_access
struct xarraypinned_pfns,儲存由核心使用者固定的頁面列表
每個 iopt_pages 表示一個完整的 PFN 的邏輯線性陣列。PFN 最終透過 mm_struct 從使用者空間 VA 派生。一旦固定,PFN 將儲存在 iommu_domain 的 IOPTE 中,或者如果它們已透過 iommufd_access 固定,則儲存在 pinned_pfns xarray 中。
PFN 必須在所有儲存位置的組合之間複製,具體取決於存在哪些域以及存在哪些型別的核心“軟體訪問”使用者。該機制確保一個頁面僅固定一次。
io_pagetable 由指向 iopt_pages 的 iopt_areas 組成,以及映象 IOVA 到 PFN 對映的 iommu_domains 列表。
多個 io_pagetable-s 可以透過它們的 iopt_area-s 共享一個 iopt_pages,這避免了多重固定和頁面消耗的雙重計算。
iommufd_ioas 可在子系統(例如,VFIO 和 VDPA)之間共享,只要由不同子系統管理的裝置繫結到同一個 iommufd。
IOMMUFD 使用者 API¶
通用 ioctl 格式
ioctl 介面遵循通用格式以允許擴充套件。每個 ioctl 都將一個結構指標作為引數傳遞,該引數在第一個 u32 中提供結構的大小。核心檢查它不理解的任何結構空間是否為 0。這允許使用者空間使用向後相容的部分,同時始終使用更新、更大的結構。
ioctls 對常見錯誤使用標準含義
ENOTTY:根本不支援 IOCTL 編號本身
E2BIG:支援 IOCTL 編號,但提供的結構在核心不理解的部分中具有非零值。
EOPNOTSUPP:支援 IOCTL 編號,並且理解該結構,但是已知欄位具有核心不理解或不支援的值。
EINVAL:理解了關於 IOCTL 的所有內容,但欄位不正確。
ENOENT:提供的 ID 或 IOVA 不存在。
ENOMEM:記憶體不足。
EOVERFLOW:數學溢位。
以及特定 ioctl 中的其他錯誤。
-
struct iommu_destroy¶
ioctl(IOMMU_DESTROY)
定義:
struct iommu_destroy {
__u32 size;
__u32 id;
};
成員
sizesizeof(
struct iommu_destroy)id要銷燬的 iommufd 物件 ID。可以是任何可銷燬的物件型別。
描述
銷燬 iommufd 中儲存的任何物件。
-
struct iommu_ioas_alloc¶
ioctl(IOMMU_IOAS_ALLOC)
定義:
struct iommu_ioas_alloc {
__u32 size;
__u32 flags;
__u32 out_ioas_id;
};
成員
sizesizeof(
struct iommu_ioas_alloc)flags必須為 0
out_ioas_id分配的物件的輸出 IOAS ID
描述
分配一個 IO 地址空間 (IOAS),該空間儲存一個 IO 虛擬地址 (IOVA) 到記憶體的對映。
-
struct iommu_iova_range¶
ioctl(IOMMU_IOVA_RANGE)
定義:
struct iommu_iova_range {
__aligned_u64 start;
__aligned_u64 last;
};
成員
start第一個 IOVA
last包含性的最後一個 IOVA
描述
IOVA 空間中的一個間隔。
-
struct iommu_ioas_iova_ranges¶
ioctl(IOMMU_IOAS_IOVA_RANGES)
定義:
struct iommu_ioas_iova_ranges {
__u32 size;
__u32 ioas_id;
__u32 num_iovas;
__u32 __reserved;
__aligned_u64 allowed_iovas;
__aligned_u64 out_iova_alignment;
};
成員
sizesizeof(
struct iommu_ioas_iova_ranges)ioas_id要從中讀取範圍的 IOAS ID
num_iovas輸入/輸出 IOAS 中範圍的總數
__reserved必須為 0
allowed_iovas指向
struct iommu_iova_range的輸出陣列的指標out_iova_alignment對映 IOVA 所需的最小對齊
描述
查詢 IOAS 中允許的 IOVA 範圍。不允許在這些範圍之外對映 IOVA。num_iovas 將設定為 iova 的總數,並且 allowed_iovas[] 將在空間允許的情況下填充。
允許的範圍取決於 DMA 操作採用的 HW 路徑,並且可以在 IOAS 的生命週期內更改。一個新的空 IOAS 將具有一個完整範圍,並且每個附加的裝置將根據該裝置的 HW 限制縮小範圍。分離裝置可以擴大範圍。使用者空間應在每次附加/分離後查詢範圍,以瞭解哪些 IOVA 可用於對映。
在輸入時,num_iovas 是 allowed_iovas 陣列的長度。在輸出時,它是填充的 iova 的總數。如果 num_iovas 太小,則 ioctl 將返回 -EMSGSIZE 並將 num_iovas 設定為所需的值。在這種情況下,呼叫者應分配一個更大的輸出陣列並重新發出 ioctl。
out_iova_alignment 返回可以提供給 IOMMU_IOAS_MAP/COPY 的最小 IOVA 對齊方式。IOVA 必須滿足
starting_iova % out_iova_alignment == 0
(starting_iova + length) % out_iova_alignment == 0
out_iova_alignment 可以為 1,指示允許任何 IOVA。它不能高於系統 PAGE_SIZE。
-
struct iommu_ioas_allow_iovas¶
ioctl(IOMMU_IOAS_ALLOW_IOVAS)
定義:
struct iommu_ioas_allow_iovas {
__u32 size;
__u32 ioas_id;
__u32 num_iovas;
__u32 __reserved;
__aligned_u64 allowed_iovas;
};
成員
sizesizeof(
struct iommu_ioas_allow_iovas)ioas_id要從中允許 IOVA 的 IOAS ID
num_iovas輸入/輸出 IOAS 中範圍的總數
__reserved必須為 0
allowed_iovas指向
struct iommu_iova_range陣列的指標
描述
確保始終可以分配一系列 IOVA。如果此呼叫成功,則 IOMMU_IOAS_IOVA_RANGES 將永遠不會返回比此處提供的範圍更窄的 IOVA 範圍列表。如果 IOMMU_IOAS_IOVA_RANGES 當前比給定的範圍更窄,則此呼叫將失敗。
首次建立 IOAS 時,IOVA_RANGES 將最大程度地調整大小,並且隨著裝置的附加,IOVA 將根據裝置限制縮小。指定允許的範圍後,將拒絕任何縮小,即,如果裝置需要在允許的範圍內進行限制,則裝置附加可能會失敗。
自動 IOVA 分配也會受到此呼叫的影響。如果存在允許的 IOVA,則 MAP 將僅在允許的 IOVA 中分配。
此呼叫將整個允許列表替換為給定的列表。
-
enum iommufd_ioas_map_flags¶
對映和複製的標誌
常量
IOMMU_IOAS_MAP_FIXED_IOVA如果清除,核心將計算一個適當的 IOVA 來放置對映
IOMMU_IOAS_MAP_WRITEABLE允許 DMA 寫入此對映
IOMMU_IOAS_MAP_READABLE允許 DMA 從此對映讀取
-
struct iommu_ioas_map¶
ioctl(IOMMU_IOAS_MAP)
定義:
struct iommu_ioas_map {
__u32 size;
__u32 flags;
__u32 ioas_id;
__u32 __reserved;
__aligned_u64 user_va;
__aligned_u64 length;
__aligned_u64 iova;
};
成員
sizesizeof(
struct iommu_ioas_map)flagsioas_idIOAS ID 用於更改對映
__reserved必須為 0
user_va使用者空間指標,用於從開始對映
length要對映的位元組數
iova對映放置的 IOVA。如果設定了 IOMMU_IOAS_MAP_FIXED_IOVA,則必須將其作為輸入提供。
描述
從使用者指標設定 IOVA 對映。如果指定了 FIXED_IOVA,則對映將在 iova 處建立;否則,將自動選擇一個基於保留列表和允許列表的合適位置,並在 iova 中返回。
如果指定了 IOMMU_IOAS_MAP_FIXED_IOVA,則 iova 範圍當前必須未使用,不能替換現有的 IOVA。
-
struct iommu_ioas_map_file¶
ioctl(IOMMU_IOAS_MAP_FILE)
定義:
struct iommu_ioas_map_file {
__u32 size;
__u32 flags;
__u32 ioas_id;
__s32 fd;
__aligned_u64 start;
__aligned_u64 length;
__aligned_u64 iova;
};
成員
sizesizeof(
struct iommu_ioas_map_file)flags與 iommu_ioas_map 相同
ioas_id與 iommu_ioas_map 相同
fd要對映的 memfd
start從檔案開頭開始對映的位元組偏移量
length與 iommu_ioas_map 相同
iova與 iommu_ioas_map 相同
描述
從 memfd 檔案設定 IOVA 對映。所有其他引數和語義都與 IOMMU_IOAS_MAP 的引數和語義匹配。
-
struct iommu_ioas_copy¶
ioctl(IOMMU_IOAS_COPY)
定義:
struct iommu_ioas_copy {
__u32 size;
__u32 flags;
__u32 dst_ioas_id;
__u32 src_ioas_id;
__aligned_u64 length;
__aligned_u64 dst_iova;
__aligned_u64 src_iova;
};
成員
sizesizeof(
struct iommu_ioas_copy)flagsdst_ioas_idIOAS ID 用於更改對映
src_ioas_id要從中複製的 IOAS ID
length要複製和對映的位元組數
dst_iova對映放置的 IOVA。如果設定了 IOMMU_IOAS_MAP_FIXED_IOVA,則必須將其作為輸入提供。
src_iova啟動複製的 IOVA
描述
從 src_ioas_id 複製一個已存在的對映,並在 dst_ioas_id 中建立它。src iova/length 必須與 IOMMU_IOAS_MAP 使用的範圍完全匹配。
這可以用於有效地將 IOAS 的一個子集克隆到另一個 IOAS,或者作為一種“快取”來加速對映。與建立等效的新對映相比,複製具有效率優勢,因為內部資源是共享的,並且核心只會固定使用者記憶體一次。
-
struct iommu_ioas_unmap¶
ioctl(IOMMU_IOAS_UNMAP)
定義:
struct iommu_ioas_unmap {
__u32 size;
__u32 ioas_id;
__aligned_u64 iova;
__aligned_u64 length;
};
成員
sizesizeof(
struct iommu_ioas_unmap)ioas_idIOAS ID 用於更改對映
iova開始取消對映的 IOVA
length要取消對映的位元組數,並返回已取消對映的位元組
描述
取消對映一個 IOVA 範圍。iova/length 必須是先前使用 IOMMU_IOAS_MAP 或 IOMMU_IOAS_COPY 對映的範圍的超集。不允許拆分或截斷範圍。值 0 到 U64_MAX 將取消對映所有內容。
-
enum iommufd_option¶
ioctl(IOMMU_OPTION_RLIMIT_MODE) 和 ioctl(IOMMU_OPTION_HUGE_PAGES)
常量
IOMMU_OPTION_RLIMIT_MODE更改 RLIMIT_MEMLOCK 記帳的工作方式。呼叫者必須具有呼叫此函式的許可權。值 0(預設)是基於使用者的記帳,1 使用基於程序的記帳。全域性選項,object_id 必須為 0
IOMMU_OPTION_HUGE_PAGES值 1(預設)允許在生成 iommu 對映時組合連續的頁面。值 0 停用組合,所有內容都對映到 PAGE_SIZE。這對於基準測試很有用。這是一個按 IOAS 選項,object_id 必須是 IOAS ID。
-
enum iommufd_option_ops¶
ioctl(IOMMU_OPTION_OP_SET) 和 ioctl(IOMMU_OPTION_OP_GET)
常量
IOMMU_OPTION_OP_SET設定選項的值
IOMMU_OPTION_OP_GET獲取選項的值
-
struct iommu_option¶
iommu 選項複用器
定義:
struct iommu_option {
__u32 size;
__u32 option_id;
__u16 op;
__u16 __reserved;
__u32 object_id;
__aligned_u64 val64;
};
成員
sizesizeof(
struct iommu_option)option_idop__reserved必須為 0
object_id如果需要,物件的 ID
val64要設定的選項值或在 get 上返回的值
描述
更改一個簡單的選項值。此多路複用器允許控制物件的選項。IOMMU_OPTION_OP_SET 將載入一個選項,IOMMU_OPTION_OP_GET 將返回當前值。
-
enum iommufd_vfio_ioas_op¶
IOMMU_VFIO_IOAS_* ioctl
常量
IOMMU_VFIO_IOAS_GET獲取當前的相容性 IOAS
IOMMU_VFIO_IOAS_SET更改當前的相容性 IOAS
IOMMU_VFIO_IOAS_CLEAR停用 VFIO 相容性
-
struct iommu_vfio_ioas¶
ioctl(IOMMU_VFIO_IOAS)
定義:
struct iommu_vfio_ioas {
__u32 size;
__u32 ioas_id;
__u16 op;
__u16 __reserved;
};
成員
sizesizeof(
struct iommu_vfio_ioas)ioas_id對於 IOMMU_VFIO_IOAS_SET,輸入要設定的 IOAS ID。對於 IOMMU_VFIO_IOAS_GET,將輸出 IOAS ID
op__reserved必須為 0
描述
VFIO 相容性支援使用單個 ioas,因為 VFIO API 不支援 ID 欄位。設定或獲取 VFIO 相容性將使用的 IOAS。當在 iommufd 上使用 VFIO_GROUP_SET_CONTAINER 時,它將獲取相容性 ioas,無論是透過獲取已設定的內容還是自動建立一個。從那時起,VFIO 將繼續使用該 ioas,並且不受此 ioctl 的影響。SET 或 CLEAR 不會銷燬任何自動建立的 IOAS。
-
enum iommufd_hwpt_alloc_flags¶
HWPT 分配的標誌
常量
IOMMU_HWPT_ALLOC_NEST_PARENT如果設定,則分配一個 HWPT,該 HWPT 可以在巢狀配置中用作父 HWPT。
IOMMU_HWPT_ALLOC_DIRTY_TRACKING在裝置連線時強制執行裝置 IOMMU 的髒跟蹤支援
IOMMU_HWPT_FAULT_ID_VALIDhwpt 分配資料的 fault_id 欄位有效。
IOMMU_HWPT_ALLOC_PASID請求一個可以與 PASID 一起使用的域。該域可以連線到裝置上的任何 PASID。連線到裝置的非 PASID 部分的任何域也必須標記,否則連線 PASID 將被阻止。對於想要連線 PASID 的使用者,不建議為裝置的非 PASID 部分和 PASID 部分使用 ioas。如果 IOMMU 不支援 PASID,它將返回錯誤 (-EOPNOTSUPP)。
-
enum iommu_hwpt_vtd_s1_flags¶
Intel VT-d stage-1 頁表條目屬性
常量
IOMMU_VTD_S1_SRESupervisor 請求
IOMMU_VTD_S1_EAFE擴充套件訪問啟用
IOMMU_VTD_S1_WPE防寫啟用
-
struct iommu_hwpt_vtd_s1¶
Intel VT-d stage-1 頁表資訊 (IOMMU_HWPT_DATA_VTD_S1)
定義:
struct iommu_hwpt_vtd_s1 {
__aligned_u64 flags;
__aligned_u64 pgtbl_addr;
__u32 addr_width;
__u32 __reserved;
};
成員
flagspgtbl_addrstage-1 頁表的基地址。
addr_widthstage-1 頁表的地址寬度
__reserved必須為 0
-
struct iommu_hwpt_arm_smmuv3¶
ARM SMMUv3 巢狀 STE (IOMMU_HWPT_DATA_ARM_SMMUV3)
定義:
struct iommu_hwpt_arm_smmuv3 {
__aligned_le64 ste[2];
};
成員
ste用於轉換的使用者空間 Stream Table Entry 的前兩個雙字。必須是小端序。允許的欄位:(請參閱 SMMUv3 HW Spec 中的“5.2 Stream Table Entry”) - word-0: V, Cfg, S1Fmt, S1ContextPtr, S1CDMax - word-1: EATS, S1DSS, S1CIR, S1COR, S1CSH, S1STALLD
描述
如果 ste 不合法或包含任何不允許的欄位,將返回 -EIO。Cfg 可用於選擇 S1、Bypass 或 Abort 配置。Bypass 巢狀域將與巢狀父域以相同的方式進行轉換。S1 將安裝一個指向使用者空間記憶體的 Context Descriptor Table,該記憶體由巢狀父域進行轉換。
-
enum iommu_hwpt_data_type¶
IOMMU HWPT 資料型別
常量
IOMMU_HWPT_DATA_NONE無資料
IOMMU_HWPT_DATA_VTD_S1Intel VT-d stage-1 頁表
IOMMU_HWPT_DATA_ARM_SMMUV3ARM SMMUv3 Context Descriptor Table
-
struct iommu_hwpt_alloc¶
ioctl(IOMMU_HWPT_ALLOC)
定義:
struct iommu_hwpt_alloc {
__u32 size;
__u32 flags;
__u32 dev_id;
__u32 pt_id;
__u32 out_hwpt_id;
__u32 __reserved;
__u32 data_type;
__u32 data_len;
__aligned_u64 data_uptr;
__u32 fault_id;
__u32 __reserved2;
};
成員
sizesizeof(
struct iommu_hwpt_alloc)flagsdev_id要為其分配此 HWPT 的裝置
pt_id要將此 HWPT 連線到的 IOAS 或 HWPT 或 vIOMMU
out_hwpt_id新 HWPT 的 ID
__reserved必須為 0
data_typedata_len型別特定資料的長度
data_uptr指向型別特定資料的使用者指標
fault_idIOMMUFD_FAULT 物件的 ID。僅當設定了 IOMMU_HWPT_FAULT_ID_VALID 的標誌欄位時有效。
__reserved2填充到 64 位對齊。必須為 0。
描述
顯式分配一個硬體頁表物件。這與 iommufd_device_attach() 返回的物件型別相同,並且表示底層 iommu 驅動程式的 iommu_domain 核心物件。
將建立一個核心管理的 HWPT,其中包含來自給定 IOAS 的對映,透過 pt_id。此分配的 data_type 必須設定為 IOMMU_HWPT_DATA_NONE。透過 flags 傳遞 IOMMU_HWPT_ALLOC_NEST_PARENT,可以將 HWPT 分配為巢狀配置的父 HWPT。
將透過給定的 vIOMMU(包裝父 HWPT)或父 HWPT(透過 pt_id)建立一個使用者管理的巢狀 HWPT,其中父 HWPT 必須先前透過相同的 ioctl 從給定的 IOAS (pt_id) 分配。在這種情況下,data_type 必須設定為與底層 IOMMU 硬體支援的 I/O 頁表型別相對應的預定義型別。透過 dev_id 的裝置和透過 pt_id 的 vIOMMU 必須與同一個 IOMMU 例項關聯。
如果 data_type 設定為 IOMMU_HWPT_DATA_NONE,則 data_len 和 data_uptr 應為零。否則,必須同時給出 data_len 和 data_uptr。
-
enum iommu_hw_info_vtd_flags¶
VT-d hw_info 的標誌
常量
IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17如果設定,則不允許在 nested_parent 域上進行只讀對映。https://www.intel.com/content/www/us/en/content-details/772415/content-details.html
-
struct iommu_hw_info_vtd¶
Intel VT-d 硬體資訊
定義:
struct iommu_hw_info_vtd {
__u32 flags;
__u32 __reserved;
__aligned_u64 cap_reg;
__aligned_u64 ecap_reg;
};
成員
flags__reserved必須為 0
cap_reg在 VT-d 規範第 11.4.2 節 Capability Register 中定義的 Intel VT-d capability 暫存器的值。
ecap_reg在 VT-d 規範第 11.4.3 節 Extended Capability Register 中定義的 Intel VT-d capability 暫存器的值。
描述
使用者需要了解 Intel VT-d 規範來解碼暫存器值。
-
struct iommu_hw_info_arm_smmuv3¶
ARM SMMUv3 硬體資訊 (IOMMU_HW_INFO_TYPE_ARM_SMMUV3)
定義:
struct iommu_hw_info_arm_smmuv3 {
__u32 flags;
__u32 __reserved;
__u32 idr[6];
__u32 iidr;
__u32 aidr;
};
成員
flags必須設定為 0
__reserved必須為 0
idrARM SMMU 非安全程式設計介面的已實現功能
iidr有關 ARM SMMU 的實現和實現者以及支援的架構版本的資訊
aidrARM SMMU 架構版本
描述
有關 idr、iidr 和 aidr 的詳細資訊,請參閱 SMMUv3 Spec 中的 6.3.1 到 6.3.6 章。
這報告了原始的 HW 功能,並非所有位對於 userspace 來說都是有意義的。只應使用以下欄位
idr[0]: ST_LEVEL, TERM_MODEL, STALL_MODEL, TTENDIAN , CD2L, ASID16, TTF idr[1]: SIDSIZE, SSIDSIZE idr[3]: BBML, RIL idr[5]: VAX, GRAN64K, GRAN16K, GRAN4K
如果可以建立 NESTED HWPT,則應假定 S1P 為 true
VFIO/iommufd 僅支援具有 COHACC 的平臺,應假定為 true。
ATS 是一個按裝置屬性。如果 VMM 在 ACPI/DT 中將任何裝置描述為具有 ATS 功能,則應設定相應的 idr。
此列表可能會在將來擴充套件(例如 E0PD、AIE、PBHA、D128、DS 等)。重要的是,VMM 不要讀取列表之外的位,以允許與未來核心相容。SMMUv3 架構中的幾個功能當前核心不支援巢狀:HTTU、BTM、MPAM 等。
-
enum iommu_hw_info_type¶
IOMMU 硬體資訊型別
常量
IOMMU_HW_INFO_TYPE_NONE由不報告硬體資訊的驅動程式使用
IOMMU_HW_INFO_TYPE_INTEL_VTDIntel VT-d iommu 資訊型別
IOMMU_HW_INFO_TYPE_ARM_SMMUV3ARM SMMUv3 iommu 資訊型別
-
enum iommufd_hw_capabilities¶
常量
IOMMU_HW_CAP_DIRTY_TRACKINGIOMMU 硬體支援髒跟蹤。如果可用,則表示支援以下 API
IOMMU_HWPT_GET_DIRTY_BITMAP IOMMU_HWPT_SET_DIRTY_TRACKING
IOMMU_HW_CAP_PCI_PASID_EXEC支援執行許可權,當
struct iommu_hw_info::out_max_pasid_log2 為零時,使用者忽略它。IOMMU_HW_CAP_PCI_PASID_PRIV支援特權模式,當
struct iommu_hw_info::out_max_pasid_log2 為零時,使用者忽略它。
-
struct iommu_hw_info¶
ioctl(IOMMU_GET_HW_INFO)
定義:
struct iommu_hw_info {
__u32 size;
__u32 flags;
__u32 dev_id;
__u32 data_len;
__aligned_u64 data_uptr;
__u32 out_data_type;
__u8 out_max_pasid_log2;
__u8 __reserved[3];
__aligned_u64 out_capabilities;
};
成員
sizesizeof(
struct iommu_hw_info)flags必須為 0
dev_id繫結到 iommufd 的裝置
data_len輸入使用者緩衝區長度(以位元組為單位)。輸出核心支援的資料長度
data_uptr指向使用者空間緩衝區的使用者指標,核心使用該緩衝區填充 iommu 型別特定的硬體資訊資料
out_data_type輸出 iommu 硬體資訊型別,如
enum iommu_hw_info_type中所定義。out_max_pasid_log2輸出 PASID 的寬度。0 表示不支援 PASID。PCI 裝置轉向 out_capabilities 以檢查是否支援特定功能。
__reserved必須為 0
out_capabilities輸出通用 iommu 功能資訊型別,如 enum iommu_hw_capabilities 中所定義。
描述
從繫結到 iommufd 的給定裝置後面的 iommu 查詢 iommu 型別特定的硬體資訊資料。此硬體資訊資料將用於同步虛擬 iommu 和物理 iommu 之間的功能,例如,巢狀轉換設定需要檢查硬體資訊,以便訪客 stage-1 頁表可以與物理 iommu 相容。
要捕獲 iommu 型別特定的硬體資訊資料,必須提供 data_uptr 及其長度 data_len。如果使用者緩衝區大於核心擁有的資料,則尾隨位元組將被置零。否則,核心只使用 data_len 中給定的長度填充緩衝區。如果 ioctl 成功,data_len 將更新為核心實際支援的長度,out_data_type 將被填充以解碼 data_uptr 指向的緩衝區中填充的資料。允許輸入 data_len == 零。
-
struct iommu_hwpt_set_dirty_tracking¶
ioctl(IOMMU_HWPT_SET_DIRTY_TRACKING)
定義:
struct iommu_hwpt_set_dirty_tracking {
__u32 size;
__u32 flags;
__u32 hwpt_id;
__u32 __reserved;
};
成員
sizeflagsenum iommufd_hwpt_set_dirty_tracking_flags 的組合
hwpt_id表示 IOMMU 域的 HW 頁表 ID
__reserved必須為 0
描述
切換 HW 頁表上的髒頁追蹤。
-
enum iommufd_hwpt_get_dirty_bitmap_flags¶
獲取髒位的標誌
常量
IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR僅讀取 PTE,而不清除任何髒位元資料。可以在期望下一次操作是對相同 IOVA 範圍進行取消對映的情況下傳遞此標誌。
-
struct iommu_hwpt_get_dirty_bitmap¶
ioctl(IOMMU_HWPT_GET_DIRTY_BITMAP)
定義:
struct iommu_hwpt_get_dirty_bitmap {
__u32 size;
__u32 hwpt_id;
__u32 flags;
__u32 __reserved;
__aligned_u64 iova;
__aligned_u64 length;
__aligned_u64 page_size;
__aligned_u64 data;
};
成員
sizehwpt_id表示 IOMMU 域的 HW 頁表 ID
flags__reserved必須為 0
iova點陣圖第一位的基本 IOVA
lengthIOVA 範圍大小
page_size點陣圖中每個位的頁面大小粒度
data用於設定髒位的點陣圖。點陣圖中的每個位代表一個 page_size,它與任意 iova 偏差。
描述
檢查給定的 IOVA 是否為髒頁
data[(iova / page_size) / 64] & (1ULL << ((iova / page_size) % 64))
遍歷給定 IOVA 範圍的 IOMMU 頁表,以返回包含髒 IOVA 的點陣圖。這樣做的同時,預設情況下還會清除 IOPTE 中設定的所有髒位元資料。
-
enum iommu_hwpt_invalidate_data_type¶
IOMMU HWPT 快取無效化資料型別
常量
IOMMU_HWPT_INVALIDATE_DATA_VTD_S1VTD_S1 的無效化資料
IOMMU_VIOMMU_INVALIDATE_DATA_ARM_SMMUV3ARM SMMUv3 的無效化資料
-
enum iommu_hwpt_vtd_s1_invalidate_flags¶
Intel VT-d 階段 1 快取無效化的標誌
常量
IOMMU_VTD_INV_FLAGS_LEAF指示無效化是應用於所有級別的頁面結構快取,還是僅應用於葉 PTE 快取。
-
struct iommu_hwpt_vtd_s1_invalidate¶
Intel VT-d 快取無效化 (IOMMU_HWPT_INVALIDATE_DATA_VTD_S1)
定義:
struct iommu_hwpt_vtd_s1_invalidate {
__aligned_u64 addr;
__aligned_u64 npages;
__u32 flags;
__u32 __reserved;
};
成員
addr要無效化的範圍的起始地址。 它需要 4KB 對齊。
npages要無效化的連續 4K 頁面的數量。
flags__reserved必須為 0
描述
用於巢狀轉換中使用者管理的階段 1 快取無效化的 Intel VT-d 特定無效化資料。 使用者空間使用此結構在修改階段 1 頁表後告訴受影響的快取範圍。
透過將 addr 設定為 0 並將 npages 設定為 U64_MAX 來使所有與頁表相關的快取無效。
如果啟用了 ATS,則裝置 TLB 將自動無效。
-
struct iommu_viommu_arm_smmuv3_invalidate¶
ARM SMMUv3 快取無效化 (IOMMU_VIOMMU_INVALIDATE_DATA_ARM_SMMUV3)
定義:
struct iommu_viommu_arm_smmuv3_invalidate {
__aligned_le64 cmd[2];
};
成員
cmd在 SMMU CMDQ 中執行的 128 位快取無效化命令。 必須是小端位元組序。
描述
- 僅在透過 hwpt_id 傳入 vIOMMU 時支援的命令列表
CMDQ_OP_TLBI_NSNH_ALL CMDQ_OP_TLBI_NH_VA CMDQ_OP_TLBI_NH_VAA CMDQ_OP_TLBI_NH_ALL CMDQ_OP_TLBI_NH_ASID CMDQ_OP_ATC_INV CMDQ_OP_CFGI_CD CMDQ_OP_CFGI_CD_ALL
如果不支援該命令,將返回 -EIO。
-
struct iommu_hwpt_invalidate¶
ioctl(IOMMU_HWPT_INVALIDATE)
定義:
struct iommu_hwpt_invalidate {
__u32 size;
__u32 hwpt_id;
__aligned_u64 data_uptr;
__u32 data_type;
__u32 entry_len;
__u32 entry_num;
__u32 __reserved;
};
成員
sizesizeof(
struct iommu_hwpt_invalidate)hwpt_id用於快取無效化的巢狀 HWPT 或 vIOMMU 的 ID
data_uptr指向驅動程式特定快取無效化資料陣列的使用者指標。
data_typeenum iommu_hwpt_invalidate_data_type之一,定義無效化請求陣列中所有條目的資料型別。 它應該是 hwpt_id 指向的 hwpt 支援的型別。entry_len請求陣列中請求條目的長度(以位元組為單位)
entry_num輸入陣列中快取無效化請求的數量。 輸出核心成功處理的請求數量。
__reserved必須為 0。
描述
使 iommu 快取對使用者管理的頁表或 vIOMMU 無效。 如果透過 hwpt_id 傳入 HWPT,則在修改使用者管理的頁表後,應執行此操作。 如果透過 hwpt_id 欄位傳入 vIOMMU,則可以重新整理其他快取,例如裝置快取或描述符快取。
每個 ioctl 可以支援陣列中的一個或多個快取無效化請求,陣列的總大小為 entry_len * entry_num。
允許透過設定 entry_num**==0 來使用空的無效化請求陣列,在這種情況下,將忽略 **entry_len 和 data_uptr。 這可用於檢查核心是否支援給定的 data_type。
-
enum iommu_hwpt_pgfault_flags¶
常量
IOMMU_PGFAULT_FLAGS_PASID_VALID故障資料的 pasid 欄位有效。
IOMMU_PGFAULT_FLAGS_LAST_PAGE它是故障組的最後一個故障。
-
enum iommu_hwpt_pgfault_perm¶
常量
IOMMU_PGFAULT_PERM_READ請求讀取許可權
IOMMU_PGFAULT_PERM_WRITE請求寫入許可權
IOMMU_PGFAULT_PERM_EXEC(PCIE 10.4.1) 使用 PASID TLP 字首中設定了 Execute Requested 位的 PASID 發出的請求。
IOMMU_PGFAULT_PERM_PRIV(PCIE 10.4.1) 使用 PASID TLP 字首中設定了 Privileged Mode Requested 位的 PASID 發出的請求。
-
struct iommu_hwpt_pgfault¶
iommu 頁錯誤資料
定義:
struct iommu_hwpt_pgfault {
__u32 flags;
__u32 dev_id;
__u32 pasid;
__u32 grpid;
__u32 perm;
__u32 __reserved;
__aligned_u64 addr;
__u32 length;
__u32 cookie;
};
成員
flagsdev_id發起裝置的 ID
pasid程序地址空間 ID
grpid頁面請求組索引
perm__reserved必須為 0。
addr錯誤地址
length請求者希望提取多少資料的提示。 例如,如果 PRI 發起者知道它將進行 10MB 的傳輸,則它可以填寫 10MB,並且 OS 可以預先錯誤地讀取 10MB 的 IOVA。 如果沒有這樣的提示,則預設為 0。
cookie核心管理的 cookie,用於標識一組故障訊息。 應在響應訊息中回顯該組的最後一個頁面錯誤中編碼的 cookie 編號。
-
enum iommufd_page_response_code¶
故障處理程式的返回狀態
常量
IOMMUFD_PAGE_RESP_SUCCESS已處理故障並填充了頁表,請重試訪問。 這是 PCI 10.4.2.1 中定義的“成功”。
IOMMUFD_PAGE_RESP_INVALID無法處理此故障,請勿重試訪問。 這是 PCI 10.4.2.1 中的“無效請求”。
-
struct iommu_hwpt_page_response¶
IOMMU 頁錯誤響應
定義:
struct iommu_hwpt_page_response {
__u32 cookie;
__u32 code;
};
成員
cookie在故障訊息中報告的核心管理的 cookie。
codeenum iommufd_page_response_code中的響應程式碼之一。
-
struct iommu_fault_alloc¶
ioctl(IOMMU_FAULT_QUEUE_ALLOC)
定義:
struct iommu_fault_alloc {
__u32 size;
__u32 flags;
__u32 out_fault_id;
__u32 out_fault_fd;
};
成員
sizesizeof(
struct iommu_fault_alloc)flags必須為 0
out_fault_id新 FAULT 的 ID
out_fault_fd新 FAULT 的 fd
描述
顯式分配故障處理物件。
-
enum iommu_viommu_type¶
虛擬 IOMMU 型別
常量
IOMMU_VIOMMU_TYPE_DEFAULT保留供將來使用
IOMMU_VIOMMU_TYPE_ARM_SMMUV3ARM SMMUv3 驅動程式特定型別
-
struct iommu_viommu_alloc¶
ioctl(IOMMU_VIOMMU_ALLOC)
定義:
struct iommu_viommu_alloc {
__u32 size;
__u32 flags;
__u32 type;
__u32 dev_id;
__u32 hwpt_id;
__u32 out_viommu_id;
};
成員
sizesizeof(
struct iommu_viommu_alloc)flags必須為 0
type虛擬 IOMMU 的型別。 必須在
enum iommu_viommu_type中定義dev_id裝置的物理 IOMMU 將用於支援虛擬 IOMMU
hwpt_id要關聯的巢狀父 HWPT 的 ID
out_viommu_id已分配物件的輸出虛擬 IOMMU ID
描述
分配一個虛擬 IOMMU 物件,表示底層物理 IOMMU 的虛擬化支援,該支援是真實 IOMMU HW 的安全隔離切片,對於特定的 VM 是唯一的。 全域性到 IOMMU 的操作連線到 vIOMMU,例如: - 訪客擁有的 ID 的安全名稱空間,例如訪客控制的快取標記 - 非裝置關聯的事件報告,例如無效化佇列錯誤 - 跨物理 IOMMU 訪問可共享的巢狀父頁表 - 各種平臺 ID 的虛擬化,例如 RID 等 - 提供準虛擬化無效 - 直接分配的無效化佇列 - 直接分配的中斷
-
struct iommu_vdevice_alloc¶
ioctl(IOMMU_VDEVICE_ALLOC)
定義:
struct iommu_vdevice_alloc {
__u32 size;
__u32 viommu_id;
__u32 dev_id;
__u32 out_vdevice_id;
__aligned_u64 virt_id;
};
成員
sizesizeof(
struct iommu_vdevice_alloc)viommu_id要與虛擬裝置關聯的 vIOMMU ID
dev_id要在 vIOMMU 上分配虛擬例項的物理裝置
out_vdevice_idvDevice 的物件控制代碼。 傳遞給 IOMMU_DESTORY
virt_id每個 vIOMMU 的虛擬裝置 ID,例如 ARM SMMUv3 的 vSID、AMD IOMMU 的 vDeviceID 以及巢狀的 Intel VT-d 到上下文表的 vRID
描述
針對 vIOMMU 分配一個虛擬裝置例項(對於物理裝置)。 此例項在 VM 中儲存裝置的資訊(與其 vIOMMU 相關)。
-
struct iommu_ioas_change_process¶
ioctl(VFIO_IOAS_CHANGE_PROCESS)
定義:
struct iommu_ioas_change_process {
__u32 size;
__u32 __reserved;
};
成員
sizesizeof(
struct iommu_ioas_change_process)__reserved必須為 0
描述
這將上下文中每個 IOAS 中每個記憶體對映的固定記憶體計數轉移到當前程序。 這僅支援使用 IOMMU_IOAS_MAP_FILE 建立的對映,如果存在其他對映,則返回 EINVAL。 如果 ioctl 返回失敗狀態,則不會進行任何更改。
此 API 對於將裝置的操作從一個程序轉移到另一個程序很有用,例如在使用者空間即時更新期間。
-
enum iommu_veventq_flag¶
常量
IOMMU_VEVENTQ_FLAG_LOST_EVENTSvEVENTQ 已丟失 vEVENT
-
struct iommufd_vevent_header¶
vEVENTQ 狀態的虛擬事件標頭
定義:
struct iommufd_vevent_header {
__u32 flags;
__u32 sequence;
};
成員
flagssequencevEVENTQ 中 vEVENT 的序列索引,範圍為 [0, INT_MAX],其中 INT_MAX 的下一個索引為 0
描述
每個 iommufd_vevent_header 報告以下 vEVENT 的序列索引
header0 {sequence=0} |
data0 |
header1 {sequence=1} |
data1 |
... |
dataN |
並且此序列索引預計對於前一個 vEVENT 的序列索引是單調的。 如果兩個相鄰的序列索引的增量大於 1,則表示已丟失增量 - 1 個 vEVENT,例如,丟失了兩個 vEVENT
... |
header3 {sequence=3} |
data3 |
header6 {sequence=6} |
data6 |
... |
如果 vEVENT 在 vEVENTQ 的尾部丟失,並且沒有後續 vEVENT 提供下一個序列索引,則會將 IOMMU_VEVENTQ_FLAG_LOST_EVENTS 標頭新增到尾部,並且此標頭後不會跟隨任何資料
header3 {sequence=3} |
data3 |
header4 {flags=LOST_EVENTS, sequence=4} |
-
enum iommu_veventq_type¶
虛擬事件佇列型別
常量
IOMMU_VEVENTQ_TYPE_DEFAULT保留供將來使用
IOMMU_VEVENTQ_TYPE_ARM_SMMUV3ARM SMMUv3 虛擬事件佇列
-
struct iommu_vevent_arm_smmuv3¶
ARM SMMUv3 虛擬事件 (IOMMU_VEVENTQ_TYPE_ARM_SMMUV3)
定義:
struct iommu_vevent_arm_smmuv3 {
__aligned_le64 evt[4];
};
成員
evt256 位 ARM SMMUv3 事件記錄,小端位元組序。 報告的事件記錄:(請參閱 SMMUv3 HW Spec 中的“7.3 Event records”) - 0x04 C_BAD_STE - 0x06 F_STREAM_DISABLED - 0x08 C_BAD_SUBSTREAMID - 0x0a C_BAD_CD - 0x10 F_TRANSLATION - 0x11 F_ADDR_SIZE - 0x12 F_ACCESS - 0x13 F_PERMISSION
描述
StreamID 欄位報告虛擬裝置 ID。 要接收裝置的虛擬事件,必須透過 IOMMU_VDEVICE_ALLOC 分配 vDEVICE。
-
struct iommu_veventq_alloc¶
ioctl(IOMMU_VEVENTQ_ALLOC)
定義:
struct iommu_veventq_alloc {
__u32 size;
__u32 flags;
__u32 viommu_id;
__u32 type;
__u32 veventq_depth;
__u32 out_veventq_id;
__u32 out_veventq_fd;
__u32 __reserved;
};
成員
sizesizeof(
struct iommu_veventq_alloc)flags必須為 0
viommu_id要與 vEVENTQ 關聯的虛擬 IOMMU ID
typevEVENTQ 的型別。 必須在
enum iommu_veventq_type中定義veventq_depthvEVENTQ 中的最大事件數
out_veventq_id新 vEVENTQ 的 ID
out_veventq_fd新 vEVENTQ 的 fd。 使用者空間在使用後必須關閉成功返回的 fd
__reserved必須為 0
描述
顯式分配 vIOMMU 的虛擬事件佇列介面。 vIOMMU 可以具有不同型別的多個 FD,但每個 type 僅限於一個。 使用者空間應開啟 out_veventq_fd 以從 vEVENTQ 中讀取 vEVENT,如果存在可用的 vEVENT。 如果 vEVENT 的數量達到 veventq_depth,則 vEVENTQ 將因溢位而丟失事件。
在 vEVENTQ 中的每個 vEVENT 包含一個 struct iommufd_vevent_header,後跟一個特定型別的資料結構,在正常情況下
header0 |
data0 |
header1 |
data1 |
... |
headerN |
dataN |
除非記錄了尾部的 IOMMU_VEVENTQ_FLAG_LOST_EVENTS 頭部 (參考 struct iommufd_vevent_header)。
IOMMUFD 核心 API¶
IOMMUFD kAPI 以裝置為中心,組相關技巧在幕後管理。這允許呼叫此 kAPI 的外部驅動程式實現一個簡單的以裝置為中心的 uAPI,用於將其裝置連線到 iommufd,而不是像 VFIO 那樣在其 uAPI 中顯式強制組語義。
-
struct iommufd_device *iommufd_device_bind(struct iommufd_ctx *ictx, struct device *dev, u32 *id)¶
將物理裝置繫結到 iommu fd
引數
struct iommufd_ctx *ictxiommufd 檔案描述符
struct device *dev指向物理裝置結構的指標
u32 *id要返回給使用者空間的此裝置的輸出 ID 號
描述
成功的繫結會建立裝置的所有權並返回 struct iommufd_device 指標,否則返回錯誤指標。
使用此 API 的驅動程式必須設定 driver_managed_dma 並且在此例程成功並建立所有權之前不得觸碰裝置。
繫結 PCI 裝置會將整個 RID 置於 iommufd 控制之下。
呼叫者必須使用 iommufd_device_unbind() 來撤消此操作。
-
bool iommufd_ctx_has_group(struct iommufd_ctx *ictx, struct iommu_group *group)¶
如果組中的任何裝置繫結到 ictx,則為 True
引數
struct iommufd_ctx *ictxiommufd 檔案描述符
struct iommu_group *group指向物理 iommu_group 結構的指標
描述
如果組中的任何裝置已繫結到此 ictx,例如透過 iommufd_device_bind(),則表示 ictx 擁有該組。
-
void iommufd_device_unbind(struct iommufd_device *idev)¶
引數
struct iommufd_device *idev由
iommufd_device_bind()返回的裝置
描述
從 iommufd 控制中釋放裝置。DMA 所有權將返回到未擁有的狀態,DMA 由 DMA API 控制。這會使 iommufd_device 指標失效,不得併發呼叫使用它的其他 API。
-
int iommufd_device_attach(struct iommufd_device *idev, ioasid_t pasid, u32 *pt_id)¶
將裝置/pasid 連線到 iommu_domain
引數
struct iommufd_device *idev要附加的裝置
ioasid_t pasid要附加的 pasid
u32 *pt_id輸入一個 IOMMUFD_OBJ_IOAS 或 IOMMUFD_OBJ_HWPT_PAGING 輸出 IOMMUFD_OBJ_HWPT_PAGING ID
描述
這會將裝置/pasid 連線到 iommu_domain,自動或手動選擇。 完成此操作後,裝置可以使用 **pasid** 執行 DMA。 如果此附件不用於 pasid,則 **pasid** 為 IOMMU_NO_PASID。
呼叫者應將結果 pt_id 返回給使用者空間。 此函式透過呼叫 iommufd_device_detach() 來撤消。
-
int iommufd_device_replace(struct iommufd_device *idev, ioasid_t pasid, u32 *pt_id)¶
更改裝置/pasid 的 iommu_domain
引數
struct iommufd_device *idev要更改的裝置
ioasid_t pasid要更改的 pasid
u32 *pt_id輸入一個 IOMMUFD_OBJ_IOAS 或 IOMMUFD_OBJ_HWPT_PAGING 輸出 IOMMUFD_OBJ_HWPT_PAGING ID
描述
這和
iommufd_device_detach();
iommufd_device_attach();
如果失敗,則不會對附件進行任何更改。 iommu 驅動程式可以實現此功能,因此翻譯中沒有中斷。 只有在 iommufd_device_attach() 已經成功後才能呼叫此函式。 對於沒有 pasid 的情況,**pasid** 為 IOMMU_NO_PASID。
-
void iommufd_device_detach(struct iommufd_device *idev, ioasid_t pasid)¶
斷開裝置/裝置與 iommu_domain 的連線
引數
struct iommufd_device *idev要分離的裝置
ioasid_t pasid要分離的 pasid
描述
撤消 iommufd_device_attach()。 這會將 idev 從先前連線的 pt_id 斷開連線。 該裝置返回到阻止的 DMA 轉換。 對於沒有 pasid 的情況,**pasid** 為 IOMMU_NO_PASID。
-
struct iommufd_access *iommufd_access_create(struct iommufd_ctx *ictx, const struct iommufd_access_ops *ops, void *data, u32 *id)¶
建立一個 iommufd_access
引數
struct iommufd_ctx *ictxiommufd 檔案描述符
const struct iommufd_access_ops *ops驅動程式的 ops 與訪問相關聯
void *data要傳遞到 ops 函式中的不透明資料
u32 *id要返回給使用者空間的此訪問的輸出 ID 號
描述
iommufd_access 允許驅動程式在不使用 DMA 的情況下讀取/寫入 IOAS。 可以使用 iommufd_access_pin_pages() 或 iommufd_access_rw() 函式訪問底層 CPU 記憶體。
提供的 ops 需要使用 iommufd_access_pin_pages()。
-
void iommufd_access_destroy(struct iommufd_access *access)¶
銷燬 iommufd_access
引數
struct iommufd_access *access要銷燬的訪問
描述
呼叫者必須先停止使用訪問,然後再銷燬它。
-
void iommufd_access_unpin_pages(struct iommufd_access *access, unsigned long iova, unsigned long length)¶
撤消 iommufd_access_pin_pages
引數
struct iommufd_access *access要操作的 IOAS 訪問
unsigned long iova起始 IOVA
unsigned long length要訪問的位元組數
描述
返回 struct page。 呼叫者必須在呼叫此函式之前停止訪問它們。 iova/length 必須與提供給 access_pages 的完全匹配。
-
int iommufd_access_pin_pages(struct iommufd_access *access, unsigned long iova, unsigned long length, struct page **out_pages, unsigned int flags)¶
返回 iova 下的頁面列表
引數
struct iommufd_access *access要操作的 IOAS 訪問
unsigned long iova起始 IOVA
unsigned long length要訪問的位元組數
struct page **out_pages輸出頁面列表
unsigned int flagsIOPMMUFD_ACCESS_RW_* 標誌
描述
讀取從 iova 開始的 **length** 個位元組,並返回 struct page * 指標。 這些可以由呼叫者進行 kmap 以進行 CPU 訪問。
呼叫者必須在完成時執行 iommufd_access_unpin_pages() 以平衡此操作。
此 API 始終需要頁面對齊的 iova。 如果 ioas 對齊 >= PAGE_SIZE 並且 iova 是 PAGE_SIZE 對齊的,則會自然發生這種情況。 但是,較小的對齊方式存在一些極端情況,否則此 API 可能會在對齊的 iova 上失敗。
-
int iommufd_access_rw(struct iommufd_access *access, unsigned long iova, void *data, size_t length, unsigned int flags)¶
讀取或寫入 iova 下的資料
引數
struct iommufd_access *access要操作的 IOAS 訪問
unsigned long iova起始 IOVA
void *data要複製到/從複製的核心緩衝區
size_t length要訪問的位元組數
unsigned int flagsIOMMUFD_ACCESS_RW_* 標誌
描述
將核心資料複製到/從 IOVA/length 給定的範圍內。 如果標誌指示 IOMMUFD_ACCESS_RW_KTHREAD,則可以透過將其更改為 copy_to/from_user() 來最佳化大型副本。
-
void iommufd_ctx_get(struct iommufd_ctx *ictx)¶
獲取上下文引用
引數
struct iommufd_ctx *ictx要獲取的上下文
描述
呼叫者必須已經擁有對 ictx 的有效引用。
引數
struct file *file從中獲取引用的檔案
描述
返回指向 iommufd_ctx 的指標,否則返回 ERR_PTR。 struct file 仍歸呼叫者所有,呼叫者仍必須執行 fput。 成功後,呼叫者有責任呼叫 iommufd_ctx_put()。
-
struct iommufd_ctx *iommufd_ctx_from_fd(int fd)¶
獲取 iommufd 上下文的引用
-
void iommufd_ctx_put(struct iommufd_ctx *ictx)¶
放回引用
引數
struct iommufd_ctx *ictx要放回的上下文
VFIO 和 IOMMUFD¶
可以透過兩種方式將 VFIO 裝置連線到 iommufd。
第一種是 VFIO 相容方式,透過直接實現 /dev/vfio/vfio 容器 IOCTL,將其對映到 io_pagetable 操作中。 這樣做允許透過將 /dev/vfio/vfio 符號連結到 /dev/iommufd 或擴充套件 VFIO 來使用 iommufd 在傳統的 VFIO 應用程式中,使用 iommufd 而不是容器 fd 來 SET_CONTAINER。
第二種方法直接擴充套件 VFIO 以支援一組新的基於裝置的使用者 API,這些 API 基於前面提到的 IOMMUFD 核心 API。 它需要使用者空間更改,但更好地匹配了 IOMMUFD API 語義,並且與第一種方法相比,更容易支援新的 iommufd 功能。
目前,這兩種方法仍在進行中。
正如 iommufd_vfio_check_extension() 中記錄的那樣,要趕上 VFIO type1,仍然有一些差距需要解決。
未來的待辦事項¶
目前,IOMMUFD 僅支援核心管理的 I/O 頁表,類似於 VFIO type1。 雷達上的新功能包括
將 iommu_domain 繫結到 PASID/SSID
使用者空間頁表,適用於 ARM、x86 和 S390
繞過核心的使用者頁表失效
在 IOMMU 中重用 KVM 頁表
在 IOMMU 中跟蹤髒頁
執行時增加/減少 IOPTE 大小
在使用者空間解決錯誤的 PRI 支援