요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0+
=======
IOMMUFD
=======
:Author: Jason Gunthorpe
:Author: Kevin Tian
Overview
========
IOMMUFD is the user API to control the IOMMU subsystem as it relates to managing
IO page tables from userspace using file descriptors. It intends to be general
and consumable by any driver that wants to expose DMA to userspace. These
drivers are eventually expected to deprecate any internal IOMMU logic
they may already/historically implement (e.g. vfio_iommu_type1.c).
At minimum iommufd provides universal support of managing I/O address spaces and
I/O page tables for all IOMMUs, with room in the design to add non-generic
features to cater to specific hardware functionality.
In this context the capital letter (IOMMUFD) refers to the subsystem while the
small letter (iommufd) refers to the file descriptors created via /dev/iommu for
use by userspace.
Key Concepts
============
User Visible Objects
--------------------
Following IOMMUFD objects are exposed to userspace:
- IOMMUFD_OBJ_IOAS, representing an I/O address space (IOAS), allowing map/unmap
of user space memory into ranges of I/O Virtual Address (IOVA).
The IOAS is a functional replacement for the VFIO container, and like the VFIO
container it copies an IOVA map to a list of iommu_domains held within it.
- IOMMUFD_OBJ_DEVICE, representing a device that is bound to iommufd by an
external driver.
- IOMMUFD_OBJ_HWPT_PAGING, representing an actual hardware I/O page table
(i.e. a single struct iommu_domain) managed by the iommu driver. "PAGING"
primarily indicates this type of HWPT should be linked to an IOAS. It also
indicates that it is backed by an iommu_domain with __IOMMU_DOMAIN_PAGING
feature flag. This can be either an UNMANAGED stage-1 domain for a device
running in the user space, or a nesting parent stage-2 domain for mappings
from guest-level physical addresses to host-level physical addresses.
The IOAS has a list of HWPT_PAGINGs that share the same IOVA mapping and
it will synchronize its mapping with each member HWPT_PAGING.
- IOMMUFD_OBJ_HWPT_NESTED, representing an actual hardware I/O page table
(i.e. a single struct iommu_domain) managed by user space (e.g. guest OS).
"NESTED" indicates that this type of HWPT should be linked to an HWPT_PAGING.
It also indicates that it is backed by an iommu_domain that has a type of
IOMMU_DOMAIN_NESTED. This must be a stage-1 domain for a device running in
the user space (e.g. in a guest VM enabling the IOMMU nested translation
feature.) As such, it must be created with a given nesting parent stage-2
domain to associate to. This nested stage-1 page table managed by the user
space usually has mappings from guest-level I/O virtual addresses to guest-
level physical addresses.
- IOMMUFD_FAULT, representing a software queue for an HWPT reporting IO page
faults using the IOMMU HW's PRI (Page Request Interface). This queue object
provides user space an FD to poll the page fault events and also to respond
to those events. A FAULT object must be created first to get a fault_id that
could be then used to allocate a fault-enabled HWPT via the IOMMU_HWPT_ALLOC
command by setting the IOMMU_HWPT_FAULT_ID_VALID bit in its flags field.
- IOMMUFD_OBJ_VIOMMU, representing a slice of the physical IOMMU instance,
passed to or shared with a VM. It may be some HW-accelerated virtualization
features and some SW resources used by the VM. For examples:
* Security namespace for guest owned ID, e.g. guest-controlled cache tags
* Non-device-affiliated event reporting, e.g. invalidation queue errors
* Access to a shareable nesting parent pagetable across physical IOMMUs
* Virtualization of various platforms IDs, e.g. RIDs and others
* Delivery of paravirtualized invalidation
* Direct assigned invalidation queues
* Direct assigned interrupts
Such a vIOMMU object generally has the access to a nesting parent pagetable
to support some HW-accelerated virtualization features. So, a vIOMMU object
must be created given a nesting parent HWPT_PAGING object, and then it would
encapsulate that HWPT_PAGING object. Therefore, a vIOMMU object can be used
to allocate an HWPT_NESTED object in place of the encapsulated HWPT_PAGING.
.. note::
The name "vIOMMU" isn't necessarily identical to a virtualized IOMMU in a
VM. A VM can have one giant virtualized IOMMU running on a machine having
multiple physical IOMMUs, in which case the VMM will dispatch the requests
or configurations from this single virtualized IOMMU instance to multiple
vIOMMU objects created for individual slices of different physical IOMMUs.
In other words, a vIOMMU object is always a representation of one physical
IOMMU, not necessarily of a virtualized IOMMU. For VMMs that want the full
virtualization features from physical IOMMUs, it is suggested to build the
same number of virtualized IOMMUs as the number of physical IOMMUs, so the
passed-through devices would be connected to their own virtualized IOMMUs
backed by corresponding vIOMMU objects, in which case a guest OS would do
the "dispatch" naturally instead of VMM trappings.
- IOMMUFD_OBJ_VDEVICE, representing a virtual device for an IOMMUFD_OBJ_DEVICE
against an IOMMUFD_OBJ_VIOMMU. This virtual device holds the device's virtual
information or attributes (related to the vIOMMU) in a VM. An immediate vDATA
example can be the virtual ID of the device on a vIOMMU, which is a unique ID
that VMM assigns to the device for a translation channel/port of the vIOMMU,
e.g. vSID of ARM SMMUv3, vDeviceID of AMD IOMMU, and vRID of Intel VT-d to a
Context Table. Potential use cases of some advanced security information can
be forwarded via this object too, such as security level or realm information
in a Confidential Compute Architecture. A VMM should create a vDEVICE object
to forward all the device information in a VM, when it connects a device to a
vIOMMU, which is a separate ioctl call from attaching the same device to an
HWPT_PAGING that the vIOMMU holds.
- IOMMUFD_OBJ_VEVENTQ, representing a software queue for a vIOMMU to report its
events such as translation faults occurred to a nested stage-1 (excluding I/O
page faults that should go through IOMMUFD_OBJ_FAULT) and HW-specific events.
This queue object provides user space an FD to poll/read the vIOMMU events. A
vIOMMU object must be created first to get its viommu_id, which could be then
used to allocate a vEVENTQ. Each vIOMMU can support multiple types of vEVENTS,
but is confined to one vEVENTQ per vEVENTQ type.
- IOMMUFD_OBJ_HW_QUEUE, representing a hardware accelerated queue, as a subset
of IOMMU's virtualization features, for the IOMMU HW to directly read or write
the virtual queue memory owned by a guest OS. This HW-acceleration feature can
allow VM to work with the IOMMU HW directly without a VM Exit, so as to reduce
overhead from the hypercalls. Along with the HW QUEUE object, iommufd provides
user space an mmap interface for VMM to mmap a physical MMIO region from the
host physical address space to the guest physical address space, allowing the
guest OS to directly control the allocated HW QUEUE. Thus, when allocating a
HW QUEUE, the VMM must request a pair of mmap info (offset/length) and pass in
exactly to an mmap syscall via its offset and length arguments.
All user-visible objects are destroyed via the IOMMU_DESTROY uAPI.
The diagrams below show relationships between user-visible objects and kernel
datastructures (external to iommufd), with numbers referred to operations
creating the objects and links::
_______________________________________________________________________
| 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|____________| |____________| |______|
1. IOMMUFD_OBJ_IOAS is created via the IOMMU_IOAS_ALLOC uAPI. An iommufd can
hold multiple IOAS objects. IOAS is the most generic object and does not
expose interfaces that are specific to single IOMMU drivers. All operations
on the IOAS must operate equally on each of the iommu_domains inside of it.
2. IOMMUFD_OBJ_DEVICE is created when an external driver calls the IOMMUFD kAPI
to bind a device to an iommufd. The driver is expected to implement a set of
ioctls to allow userspace to initiate the binding operation. Successful
completion of this operation establishes the desired DMA ownership over the
device. The driver must also set the driver_managed_dma flag and must not
touch the device until this operation succeeds.
3. IOMMUFD_OBJ_HWPT_PAGING can be created in two ways:
* IOMMUFD_OBJ_HWPT_PAGING is automatically created when an external driver
calls the IOMMUFD kAPI to attach a bound device to an IOAS. Similarly the
external driver uAPI allows userspace to initiate the attaching operation.
If a compatible member HWPT_PAGING object exists in the IOAS's HWPT_PAGING
list, then it will be reused. Otherwise a new HWPT_PAGING that represents
an iommu_domain to userspace will be created, and then added to the list.
Successful completion of this operation sets up the linkages among IOAS,
device and iommu_domain. Once this completes the device could do DMA.
* IOMMUFD_OBJ_HWPT_PAGING can be manually created via the IOMMU_HWPT_ALLOC
uAPI, provided an ioas_id via @pt_id to associate the new HWPT_PAGING to
the corresponding IOAS object. The benefit of this manual allocation is to
allow allocation flags (defined in enum iommufd_hwpt_alloc_flags), e.g. it
allocates a nesting parent HWPT_PAGING if the IOMMU_HWPT_ALLOC_NEST_PARENT
flag is set.
4. IOMMUFD_OBJ_HWPT_NESTED can be only manually created via the IOMMU_HWPT_ALLOC
uAPI, provided an hwpt_id or a viommu_id of a vIOMMU object encapsulating a
nesting parent HWPT_PAGING via @pt_id to associate the new HWPT_NESTED object
to the corresponding HWPT_PAGING object. The associating HWPT_PAGING object
must be a nesting parent manually allocated via the same uAPI previously with
an IOMMU_HWPT_ALLOC_NEST_PARENT flag, otherwise the allocation will fail. The
allocation will be further validated by the IOMMU driver to ensure that the
nesting parent domain and the nested domain being allocated are compatible.
Successful completion of this operation sets up linkages among IOAS, device,
and iommu_domains. Once this completes the device could do DMA via a 2-stage
translation, a.k.a nested translation. Note that multiple HWPT_NESTED objects
can be allocated by (and then associated to) the same nesting parent.
.. note::
Either a manual IOMMUFD_OBJ_HWPT_PAGING or an IOMMUFD_OBJ_HWPT_NESTED is
created via the same IOMMU_HWPT_ALLOC uAPI. The difference is at the type
of the object passed in via the @pt_id field of struct iommufd_hwpt_alloc.
5. IOMMUFD_OBJ_VIOMMU can be only manually created via the IOMMU_VIOMMU_ALLOC
uAPI, provided a dev_id (for the device's physical IOMMU to back the vIOMMU)
and an hwpt_id (to associate the vIOMMU to a nesting parent HWPT_PAGING). The
iommufd core will link the vIOMMU object to the struct iommu_device that the
struct device is behind. And an IOMMU driver can implement a viommu_alloc op
to allocate its own vIOMMU data structure embedding the core-level structure
iommufd_viommu and some driver-specific data. If necessary, the driver can
also configure its HW virtualization feature for that vIOMMU (and thus for
the VM). Successful completion of this operation sets up the linkages between
the vIOMMU object and the HWPT_PAGING, then this vIOMMU object can be used
as a nesting parent object to allocate an HWPT_NESTED object described above.
6. IOMMUFD_OBJ_VDEVICE can be only manually created via the IOMMU_VDEVICE_ALLOC
uAPI, provided a viommu_id for an iommufd_viommu object and a dev_id for an
iommufd_device object. The vDEVICE object will be the binding between these
two parent objects. Another @virt_id will be also set via the uAPI providing
the iommufd core an index to store the vDEVICE object to a vDEVICE array per
vIOMMU. If necessary, the IOMMU driver may choose to implement a vdevce_alloc
op to init its HW for virtualization feature related to a vDEVICE. Successful
completion of this operation sets up the linkages between vIOMMU and device.
A device can only bind to an iommufd due to DMA ownership claim and attach to at
most one IOAS object (no support of PASID yet).
Kernel Datastructure
--------------------
User visible objects are backed by following datastructures:
- iommufd_ioas for IOMMUFD_OBJ_IOAS.
- iommufd_device for IOMMUFD_OBJ_DEVICE.
- iommufd_hwpt_paging for IOMMUFD_OBJ_HWPT_PAGING.
- iommufd_hwpt_nested for IOMMUFD_OBJ_HWPT_NESTED.
- iommufd_fault for IOMMUFD_OBJ_FAULT.
- iommufd_viommu for IOMMUFD_OBJ_VIOMMU.
- iommufd_vdevice for IOMMUFD_OBJ_VDEVICE.
- iommufd_veventq for IOMMUFD_OBJ_VEVENTQ.
- iommufd_hw_queue for IOMMUFD_OBJ_HW_QUEUE.
Several terminologies when looking at these datastructures:
- Automatic domain - refers to an iommu domain created automatically when
attaching a device to an IOAS object. This is compatible to the semantics of
VFIO type1.
- Manual domain - refers to an iommu domain designated by the user as the
target pagetable to be attached to by a device. Though currently there are
no uAPIs to directly create such domain, the datastructure and algorithms
are ready for handling that use case.
- In-kernel user - refers to something like a VFIO mdev that is using the
IOMMUFD access interface to access the IOAS. This starts by creating an
iommufd_access object that is similar to the domain binding a physical device
would do. The access object will then allow converting IOVA ranges into struct
page * lists, or doing direct read/write to an IOVA.
iommufd_ioas serves as the metadata datastructure to manage how IOVA ranges are
mapped to memory pages, composed of:
- struct io_pagetable holding the IOVA map
- struct iopt_area's representing populated portions of IOVA
- struct iopt_pages representing the storage of PFNs
- struct iommu_domain representing the IO page table in the IOMMU
- struct iopt_pages_access representing in-kernel users of PFNs
- struct xarray pinned_pfns holding a list of pages pinned by in-kernel users
Each iopt_pages represents a logical linear array of full PFNs. The PFNs are
ultimately derived from userspace VAs via an mm_struct. Once they have been
pinned the PFNs are stored in IOPTEs of an iommu_domain or inside the pinned_pfns
xarray if they have been pinned through an iommufd_access.
PFN have to be copied between all combinations of storage locations, depending
on what domains are present and what kinds of in-kernel "software access" users
exist. The mechanism ensures that a page is pinned only once.
An io_pagetable is composed of iopt_areas pointing at iopt_pages, along with a
list of iommu_domains that mirror the IOVA to PFN map.
Multiple io_pagetable-s, through their iopt_area-s, can share a single
iopt_pages which avoids multi-pinning and double accounting of page
consumption.
iommufd_ioas is shareable between subsystems, e.g. VFIO and VDPA, as long as
devices managed by different subsystems are bound to a same iommufd.
IOMMUFD User API
================
.. kernel-doc:: include/uapi/linux/iommufd.h
IOMMUFD Kernel API
==================
The IOMMUFD kAPI is device-centric with group-related tricks managed behind the
scene. This allows the external drivers calling such kAPI to implement a simple
device-centric uAPI for connecting its device to an iommufd, instead of
explicitly imposing the group semantics in its uAPI as VFIO does.
.. kernel-doc:: drivers/iommu/iommufd/device.c
:export:
.. kernel-doc:: drivers/iommu/iommufd/main.c
:export:
VFIO and IOMMUFD
----------------
Connecting a VFIO device to iommufd can be done in two ways.
First is a VFIO compatible way by directly implementing the /dev/vfio/vfio
container IOCTLs by mapping them into io_pagetable operations. Doing so allows
the use of iommufd in legacy VFIO applications by symlinking /dev/vfio/vfio to
/dev/iommufd or extending VFIO to SET_CONTAINER using an iommufd instead of a
container fd.
The second approach directly extends VFIO to support a new set of device-centric
user API based on aforementioned IOMMUFD kernel API. It requires userspace
change but better matches the IOMMUFD API semantics and easier to support new
iommufd features when comparing it to the first approach.
Currently both approaches are still work-in-progress.
There are still a few gaps to be resolved to catch up with VFIO type1, as
documented in iommufd_vfio_check_extension().
Future TODOs
============
Currently IOMMUFD supports only kernel-managed I/O page table, similar to VFIO
type1. New features on the radar include:
- Binding iommu_domain's to PASID/SSID
- Userspace page tables, for ARM, x86 and S390
- Kernel bypass'd invalidation of user page tables
- Re-use of the KVM page table in the IOMMU
- Dirty page tracking in the IOMMU
- Runtime Increase/Decrease of IOPTE size
- PRI support with faults resolved in userspace
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
개요
1-26IOMMUFD는 파일 디스크립터를 통해 사용자 공간에서 I/O 페이지 테이블을 관리하는 관점으로 IOMMU 서브시스템을 제어하는 사용자 API입니다. DMA를 사용자 공간에 공개하려는 모든 드라이버가 공통으로 사용할 수 있도록 설계되었습니다.
이 API를 채택하는 드라이버는 기존 또는 과거에 자체 구현했던 IOMMU 로직, 예를 들어 `vfio_iommu_type1.c`를 장기적으로 폐기할 것으로 예상됩니다.
최소 기능으로 모든 IOMMU의 I/O 주소 공간과 I/O 페이지 테이블 관리를 보편적으로 지원하며, 특정 하드웨어 기능을 위한 비범용 기능도 확장할 수 있는 구조입니다.
대문자 `IOMMUFD`는 서브시스템을 뜻하고, 소문자 `iommufd`는 사용자 공간이 `/dev/iommu`를 통해 만든 파일 디스크립터를 뜻합니다. 문서 작성자는 Jason Gunthorpe와 Kevin Tian이며 라이선스는 GPL-2.0+입니다.
서브시스템과 사용자 파일 디스크립터 표기를 구분합니다.
.. SPDX-License-Identifier: GPL-2.0+
=======
IOMMUFD
=======
:Author: Jason Gunthorpe
:Author: Kevin Tian
Overview
========
IOMMUFD is the user API to control the IOMMU subsystem as it relates to managing
IO page tables from userspace using file descriptors. It intends to be general
and consumable by any driver that wants to expose DMA to userspace. These
drivers are eventually expected to deprecate any internal IOMMU logic
they may already/historically implement (e.g. vfio_iommu_type1.c).
At minimum iommufd provides universal support of managing I/O address spaces and
I/O page tables for all IOMMUs, with room in the design to add non-generic
features to cater to specific hardware functionality.
In this context the capital letter (IOMMUFD) refers to the subsystem while the
small letter (iommufd) refers to the file descriptors created via /dev/iommu for
use by userspace.
IOAS, DEVICE와 하드웨어 페이지 테이블 객체
27-65`IOMMUFD_OBJ_IOAS`는 I/O 주소 공간(IOAS)을 나타내며 사용자 메모리를 IOVA 범위에 map/unmap할 수 있습니다. VFIO container의 기능적 대체물이고, VFIO container처럼 IOVA 매핑을 내부의 `iommu_domain` 목록에 복제합니다.
`IOMMUFD_OBJ_DEVICE`는 외부 드라이버가 iommufd에 bind한 장치를 나타냅니다.
`IOMMUFD_OBJ_HWPT_PAGING`은 IOMMU 드라이버가 관리하는 실제 하드웨어 I/O 페이지 테이블 하나, 즉 `struct iommu_domain` 하나를 나타냅니다. `PAGING`은 이 HWPT가 IOAS에 연결되어야 하고 `__IOMMU_DOMAIN_PAGING` 기능 플래그를 가진 `iommu_domain`이 기반임을 뜻합니다.
HWPT_PAGING은 사용자 공간에서 동작하는 장치를 위한 UNMANAGED stage-1 domain일 수도 있고, guest 물리 주소를 host 물리 주소로 변환하는 nesting parent stage-2 domain일 수도 있습니다. IOAS는 동일 IOVA 매핑을 공유하는 HWPT_PAGING 목록을 가지며 모든 구성원과 매핑을 동기화합니다.
`IOMMUFD_OBJ_HWPT_NESTED`는 사용자 공간, 예를 들어 guest OS가 관리하는 실제 하드웨어 I/O 페이지 테이블입니다. `IOMMU_DOMAIN_NESTED` 유형의 `iommu_domain`이 기반이며 HWPT_PAGING에 연결해야 합니다.
HWPT_NESTED는 사용자 공간 장치의 stage-1 domain이어야 하고, 생성할 때 연결할 nesting parent stage-2 domain을 지정해야 합니다. 이 사용자 관리 nested stage-1 페이지 테이블은 보통 guest IOVA를 guest 물리 주소로 매핑합니다.
객체가 소유하는 주소 공간과 관리 주체를 구분합니다.
Key Concepts
============
User Visible Objects
--------------------
Following IOMMUFD objects are exposed to userspace:
- IOMMUFD_OBJ_IOAS, representing an I/O address space (IOAS), allowing map/unmap
of user space memory into ranges of I/O Virtual Address (IOVA).
The IOAS is a functional replacement for the VFIO container, and like the VFIO
container it copies an IOVA map to a list of iommu_domains held within it.
- IOMMUFD_OBJ_DEVICE, representing a device that is bound to iommufd by an
external driver.
- IOMMUFD_OBJ_HWPT_PAGING, representing an actual hardware I/O page table
(i.e. a single struct iommu_domain) managed by the iommu driver. "PAGING"
primarily indicates this type of HWPT should be linked to an IOAS. It also
indicates that it is backed by an iommu_domain with __IOMMU_DOMAIN_PAGING
feature flag. This can be either an UNMANAGED stage-1 domain for a device
running in the user space, or a nesting parent stage-2 domain for mappings
from guest-level physical addresses to host-level physical addresses.
The IOAS has a list of HWPT_PAGINGs that share the same IOVA mapping and
it will synchronize its mapping with each member HWPT_PAGING.
- IOMMUFD_OBJ_HWPT_NESTED, representing an actual hardware I/O page table
(i.e. a single struct iommu_domain) managed by user space (e.g. guest OS).
"NESTED" indicates that this type of HWPT should be linked to an HWPT_PAGING.
It also indicates that it is backed by an iommu_domain that has a type of
IOMMU_DOMAIN_NESTED. This must be a stage-1 domain for a device running in
the user space (e.g. in a guest VM enabling the IOMMU nested translation
feature.) As such, it must be created with a given nesting parent stage-2
domain to associate to. This nested stage-1 page table managed by the user
space usually has mappings from guest-level I/O virtual addresses to guest-
level physical addresses.
FAULT와 vIOMMU 객체
66-105`IOMMUFD_FAULT`는 IOMMU 하드웨어의 PRI(Page Request Interface)를 사용해 HWPT가 보고한 I/O 페이지 폴트를 담는 소프트웨어 큐입니다. 사용자 공간은 이 객체의 FD를 poll하여 폴트 이벤트를 받고 응답할 수 있습니다.
폴트 지원 HWPT를 만들려면 먼저 FAULT 객체를 생성해 `fault_id`를 얻고, `IOMMU_HWPT_ALLOC`의 flags에 `IOMMU_HWPT_FAULT_ID_VALID`를 설정하여 그 ID를 전달해야 합니다.
`IOMMUFD_OBJ_VIOMMU`는 VM에 전달하거나 공유하는 물리 IOMMU 인스턴스의 한 slice입니다. 하드웨어 가속 가상화 기능과 VM이 사용하는 소프트웨어 자원을 포함할 수 있습니다.
플랫폼별 물리 IOMMU slice의 가상화 자원을 묶습니다.
vIOMMU는 보통 하드웨어 가속 가상화를 위해 nesting parent 페이지 테이블에 접근합니다. 따라서 nesting parent HWPT_PAGING을 지정해 만들고 그 객체를 캡슐화합니다. 이후 캡슐화된 HWPT_PAGING 대신 vIOMMU를 parent로 사용해 HWPT_NESTED를 할당할 수 있습니다.
이름이 vIOMMU라고 해서 VM 안의 가상 IOMMU 하나와 반드시 일대일인 것은 아닙니다. 여러 물리 IOMMU가 있는 시스템에서 VM은 하나의 거대한 가상 IOMMU를 가질 수 있고, VMM은 요청을 물리 IOMMU별 vIOMMU 객체로 분배할 수 있습니다.
즉 vIOMMU는 항상 물리 IOMMU 하나의 표현이지 가상 IOMMU 자체의 표현은 아닙니다. 물리 IOMMU의 전체 가상화 기능을 원하는 VMM은 물리 IOMMU 수와 같은 수의 가상 IOMMU를 만들어 pass-through 장치를 대응 vIOMMU가 뒷받침하는 가상 IOMMU에 연결하는 것이 권장됩니다. 그러면 VMM trap 대신 guest OS가 자연스럽게 분배합니다.
FAULT 객체를 먼저 만들고 그 ID를 HWPT 할당에 사용합니다.
- IOMMUFD_FAULT, representing a software queue for an HWPT reporting IO page
faults using the IOMMU HW's PRI (Page Request Interface). This queue object
provides user space an FD to poll the page fault events and also to respond
to those events. A FAULT object must be created first to get a fault_id that
could be then used to allocate a fault-enabled HWPT via the IOMMU_HWPT_ALLOC
command by setting the IOMMU_HWPT_FAULT_ID_VALID bit in its flags field.
- IOMMUFD_OBJ_VIOMMU, representing a slice of the physical IOMMU instance,
passed to or shared with a VM. It may be some HW-accelerated virtualization
features and some SW resources used by the VM. For examples:
* Security namespace for guest owned ID, e.g. guest-controlled cache tags
* Non-device-affiliated event reporting, e.g. invalidation queue errors
* Access to a shareable nesting parent pagetable across physical IOMMUs
* Virtualization of various platforms IDs, e.g. RIDs and others
* Delivery of paravirtualized invalidation
* Direct assigned invalidation queues
* Direct assigned interrupts
Such a vIOMMU object generally has the access to a nesting parent pagetable
to support some HW-accelerated virtualization features. So, a vIOMMU object
must be created given a nesting parent HWPT_PAGING object, and then it would
encapsulate that HWPT_PAGING object. Therefore, a vIOMMU object can be used
to allocate an HWPT_NESTED object in place of the encapsulated HWPT_PAGING.
.. note::
The name "vIOMMU" isn't necessarily identical to a virtualized IOMMU in a
VM. A VM can have one giant virtualized IOMMU running on a machine having
multiple physical IOMMUs, in which case the VMM will dispatch the requests
or configurations from this single virtualized IOMMU instance to multiple
vIOMMU objects created for individual slices of different physical IOMMUs.
In other words, a vIOMMU object is always a representation of one physical
IOMMU, not necessarily of a virtualized IOMMU. For VMMs that want the full
virtualization features from physical IOMMUs, it is suggested to build the
same number of virtualized IOMMUs as the number of physical IOMMUs, so the
passed-through devices would be connected to their own virtualized IOMMUs
backed by corresponding vIOMMU objects, in which case a guest OS would do
the "dispatch" naturally instead of VMM trappings.
vDEVICE, vEVENTQ와 HW_QUEUE
106-143`IOMMUFD_OBJ_VDEVICE`는 `IOMMUFD_OBJ_VIOMMU`에 대한 `IOMMUFD_OBJ_DEVICE`의 가상 장치입니다. VM 안에서 vIOMMU와 관련된 장치의 가상 정보와 속성을 보관합니다.
즉시 사용할 수 있는 vDATA의 예는 vIOMMU 변환 channel/port에 대해 VMM이 장치에 부여하는 고유 가상 ID입니다. ARM SMMUv3의 vSID, AMD IOMMU의 vDeviceID, Intel VT-d Context Table의 vRID가 여기에 해당합니다. Confidential Compute Architecture의 보안 수준이나 realm 정보 같은 고급 보안 속성도 전달할 수 있습니다.
VMM이 장치를 vIOMMU에 연결할 때는 VM의 모든 장치 정보를 전달하기 위해 vDEVICE를 만들어야 합니다. 이는 같은 장치를 vIOMMU가 보유한 HWPT_PAGING에 attach하는 호출과는 별도의 ioctl입니다.
`IOMMUFD_OBJ_VEVENTQ`는 nested stage-1에서 발생한 translation fault와 하드웨어별 이벤트를 vIOMMU가 보고하는 소프트웨어 큐입니다. I/O page fault는 제외되며 그것은 `IOMMUFD_OBJ_FAULT`를 통해 전달해야 합니다.
사용자 공간은 vEVENTQ FD를 poll/read합니다. 먼저 vIOMMU를 만들어 `viommu_id`를 얻은 뒤 vEVENTQ를 할당합니다. vIOMMU 하나가 여러 vEVENT 유형을 지원할 수 있지만 각 vEVENTQ 유형마다 큐는 하나만 허용됩니다.
`IOMMUFD_OBJ_HW_QUEUE`는 guest OS가 소유한 가상 큐 메모리를 IOMMU 하드웨어가 직접 읽고 쓰는 하드웨어 가속 큐입니다. VM exit와 hypercall 오버헤드를 줄이기 위해 VM이 IOMMU 하드웨어와 직접 동작하게 합니다.
iommufd는 VMM이 host 물리 주소 공간의 MMIO 영역을 guest 물리 주소 공간에 mmap할 인터페이스를 함께 제공합니다. HW_QUEUE를 할당할 때 VMM은 mmap 정보의 offset/length 쌍을 요청하고, 정확히 그 값을 `mmap` 시스템 호출의 인자로 전달해야 합니다.
모든 사용자 가시 객체는 `IOMMU_DESTROY` uAPI로 파괴합니다.
이벤트 종류와 FD 사용 방식을 구분합니다.
- IOMMUFD_OBJ_VDEVICE, representing a virtual device for an IOMMUFD_OBJ_DEVICE
against an IOMMUFD_OBJ_VIOMMU. This virtual device holds the device's virtual
information or attributes (related to the vIOMMU) in a VM. An immediate vDATA
example can be the virtual ID of the device on a vIOMMU, which is a unique ID
that VMM assigns to the device for a translation channel/port of the vIOMMU,
e.g. vSID of ARM SMMUv3, vDeviceID of AMD IOMMU, and vRID of Intel VT-d to a
Context Table. Potential use cases of some advanced security information can
be forwarded via this object too, such as security level or realm information
in a Confidential Compute Architecture. A VMM should create a vDEVICE object
to forward all the device information in a VM, when it connects a device to a
vIOMMU, which is a separate ioctl call from attaching the same device to an
HWPT_PAGING that the vIOMMU holds.
- IOMMUFD_OBJ_VEVENTQ, representing a software queue for a vIOMMU to report its
events such as translation faults occurred to a nested stage-1 (excluding I/O
page faults that should go through IOMMUFD_OBJ_FAULT) and HW-specific events.
This queue object provides user space an FD to poll/read the vIOMMU events. A
vIOMMU object must be created first to get its viommu_id, which could be then
used to allocate a vEVENTQ. Each vIOMMU can support multiple types of vEVENTS,
but is confined to one vEVENTQ per vEVENTQ type.
- IOMMUFD_OBJ_HW_QUEUE, representing a hardware accelerated queue, as a subset
of IOMMU's virtualization features, for the IOMMU HW to directly read or write
the virtual queue memory owned by a guest OS. This HW-acceleration feature can
allow VM to work with the IOMMU HW directly without a VM Exit, so as to reduce
overhead from the hypercalls. Along with the HW QUEUE object, iommufd provides
user space an mmap interface for VMM to mmap a physical MMIO region from the
host physical address space to the guest physical address space, allowing the
guest OS to directly control the allocated HW QUEUE. Thus, when allocating a
HW QUEUE, the VMM must request a pair of mmap info (offset/length) and pass in
exactly to an mmap syscall via its offset and length arguments.
All user-visible objects are destroyed via the IOMMU_DESTROY uAPI.
The diagrams below show relationships between user-visible objects and kernel
datastructures (external to iommufd), with numbers referred to operations
creating the objects and links::
사용자 객체와 커널 구조체 관계
144-197원문의 세 ASCII 그림은 객체 생성 순서 번호와 iommufd 외부 커널 구조체의 연결을 보여 줍니다. 아래 흐름도는 같은 관계를 구조화하여 표현합니다.
IOAS의 PFN 저장소가 paging iommu_domain을 채우고 DEVICE가 그 domain에 연결됩니다.
nested stage-1이 paging stage-2 parent에 연결되어 2단계 변환을 구성합니다.
vIOMMU는 물리 iommu_device slice와 parent HWPT_PAGING을 캡슐화합니다.
뒤의 번호별 설명과 일치합니다.
_______________________________________________________________________
| 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|____________| |____________| |______|
작업 1·2: IOAS 생성과 DEVICE bind
198-2091. `IOMMUFD_OBJ_IOAS`는 `IOMMU_IOAS_ALLOC` uAPI로 생성합니다. iommufd 하나가 여러 IOAS를 보유할 수 있습니다. IOAS는 가장 범용적인 객체이며 개별 IOMMU 드라이버 전용 인터페이스를 공개하지 않습니다. IOAS의 모든 작업은 내부의 각 `iommu_domain`에 동일하게 적용되어야 합니다.
2. 외부 드라이버가 IOMMUFD kAPI를 호출하여 장치를 iommufd에 bind하면 `IOMMUFD_OBJ_DEVICE`가 생성됩니다. 드라이버는 사용자 공간이 bind를 시작할 수 있는 ioctl 집합을 구현해야 합니다.
bind가 성공하면 장치의 DMA 소유권을 확보합니다. 드라이버는 `driver_managed_dma` 플래그를 설정해야 하고 bind 작업이 성공하기 전에는 장치를 건드려서는 안 됩니다.
객체 생성 주체와 성공 후 효과입니다.
1. IOMMUFD_OBJ_IOAS is created via the IOMMU_IOAS_ALLOC uAPI. An iommufd can
hold multiple IOAS objects. IOAS is the most generic object and does not
expose interfaces that are specific to single IOMMU drivers. All operations
on the IOAS must operate equally on each of the iommu_domains inside of it.
2. IOMMUFD_OBJ_DEVICE is created when an external driver calls the IOMMUFD kAPI
to bind a device to an iommufd. The driver is expected to implement a set of
ioctls to allow userspace to initiate the binding operation. Successful
completion of this operation establishes the desired DMA ownership over the
device. The driver must also set the driver_managed_dma flag and must not
touch the device until this operation succeeds.
작업 3: HWPT_PAGING 자동·수동 생성
210-2273. `IOMMUFD_OBJ_HWPT_PAGING`은 자동 또는 수동으로 만들 수 있습니다.
자동 경로에서는 외부 드라이버가 bind된 장치를 IOAS에 attach하는 IOMMUFD kAPI를 호출합니다. 사용자 공간은 외부 드라이버 uAPI를 통해 이 작업을 시작합니다. IOAS의 HWPT_PAGING 목록에 호환되는 객체가 있으면 재사용하고, 없으면 `iommu_domain`을 나타내는 새 HWPT_PAGING을 만들어 목록에 추가합니다.
자동 attach가 성공하면 IOAS, device, `iommu_domain` 사이 연결이 완성되고 장치가 DMA를 수행할 수 있습니다.
수동 경로는 `IOMMU_HWPT_ALLOC` uAPI에 `@pt_id`로 `ioas_id`를 제공하여 새 HWPT_PAGING을 해당 IOAS와 연결합니다. 수동 할당은 `enum iommufd_hwpt_alloc_flags`의 플래그를 지정할 수 있다는 장점이 있습니다. 예를 들어 `IOMMU_HWPT_ALLOC_NEST_PARENT`를 설정하면 nesting parent HWPT_PAGING을 할당합니다.
호환 객체 재사용이 가능한 자동 경로와 플래그를 지정하는 수동 경로입니다.
3. IOMMUFD_OBJ_HWPT_PAGING can be created in two ways:
* IOMMUFD_OBJ_HWPT_PAGING is automatically created when an external driver
calls the IOMMUFD kAPI to attach a bound device to an IOAS. Similarly the
external driver uAPI allows userspace to initiate the attaching operation.
If a compatible member HWPT_PAGING object exists in the IOAS's HWPT_PAGING
list, then it will be reused. Otherwise a new HWPT_PAGING that represents
an iommu_domain to userspace will be created, and then added to the list.
Successful completion of this operation sets up the linkages among IOAS,
device and iommu_domain. Once this completes the device could do DMA.
* IOMMUFD_OBJ_HWPT_PAGING can be manually created via the IOMMU_HWPT_ALLOC
uAPI, provided an ioas_id via @pt_id to associate the new HWPT_PAGING to
the corresponding IOAS object. The benefit of this manual allocation is to
allow allocation flags (defined in enum iommufd_hwpt_alloc_flags), e.g. it
allocates a nesting parent HWPT_PAGING if the IOMMU_HWPT_ALLOC_NEST_PARENT
flag is set.
작업 4: HWPT_NESTED 생성
228-2464. `IOMMUFD_OBJ_HWPT_NESTED`는 `IOMMU_HWPT_ALLOC` uAPI로만 수동 생성합니다. `@pt_id`에는 nesting parent HWPT_PAGING의 `hwpt_id` 또는 그 parent를 캡슐화한 vIOMMU의 `viommu_id`를 전달합니다.
연결 대상 HWPT_PAGING은 앞서 같은 uAPI에서 `IOMMU_HWPT_ALLOC_NEST_PARENT` 플래그로 수동 할당한 nesting parent여야 하며, 그렇지 않으면 할당이 실패합니다. IOMMU 드라이버는 parent domain과 새 nested domain의 호환성도 추가 검증합니다.
성공하면 IOAS, device, 여러 `iommu_domain` 사이 연결이 설정되고 장치는 nested translation이라 부르는 2단계 변환으로 DMA를 수행할 수 있습니다. 하나의 nesting parent에 여러 HWPT_NESTED를 할당하고 연결할 수 있습니다.
수동 HWPT_PAGING과 HWPT_NESTED는 같은 `IOMMU_HWPT_ALLOC`을 사용합니다. 둘의 차이는 `struct iommufd_hwpt_alloc`의 `@pt_id`로 전달한 객체 유형입니다.
parent 지정과 드라이버 호환성 검사가 모두 성공해야 합니다.
4. IOMMUFD_OBJ_HWPT_NESTED can be only manually created via the IOMMU_HWPT_ALLOC
uAPI, provided an hwpt_id or a viommu_id of a vIOMMU object encapsulating a
nesting parent HWPT_PAGING via @pt_id to associate the new HWPT_NESTED object
to the corresponding HWPT_PAGING object. The associating HWPT_PAGING object
must be a nesting parent manually allocated via the same uAPI previously with
an IOMMU_HWPT_ALLOC_NEST_PARENT flag, otherwise the allocation will fail. The
allocation will be further validated by the IOMMU driver to ensure that the
nesting parent domain and the nested domain being allocated are compatible.
Successful completion of this operation sets up linkages among IOAS, device,
and iommu_domains. Once this completes the device could do DMA via a 2-stage
translation, a.k.a nested translation. Note that multiple HWPT_NESTED objects
can be allocated by (and then associated to) the same nesting parent.
.. note::
Either a manual IOMMUFD_OBJ_HWPT_PAGING or an IOMMUFD_OBJ_HWPT_NESTED is
created via the same IOMMU_HWPT_ALLOC uAPI. The difference is at the type
of the object passed in via the @pt_id field of struct iommufd_hwpt_alloc.
작업 5·6: vIOMMU와 vDEVICE 생성
247-2705. `IOMMUFD_OBJ_VIOMMU`는 `IOMMU_VIOMMU_ALLOC` uAPI로만 수동 생성합니다. 물리 IOMMU를 정하기 위한 `dev_id`와 nesting parent HWPT_PAGING에 연결할 `hwpt_id`를 제공합니다.
iommufd core는 vIOMMU를 `struct device` 뒤의 `struct iommu_device`에 연결합니다. IOMMU 드라이버는 `viommu_alloc` op를 구현해 core 구조체 `iommufd_viommu`와 driver 전용 데이터를 포함하는 자체 구조체를 할당하고, 필요하면 VM을 위한 하드웨어 가상화 기능을 설정할 수 있습니다.
성공하면 vIOMMU와 HWPT_PAGING이 연결되며 이 vIOMMU를 parent로 사용해 HWPT_NESTED를 할당할 수 있습니다.
6. `IOMMUFD_OBJ_VDEVICE`는 `IOMMU_VDEVICE_ALLOC` uAPI로만 수동 생성합니다. `iommufd_viommu`의 `viommu_id`, `iommufd_device`의 `dev_id`를 제공하며 vDEVICE가 두 parent 객체의 binding이 됩니다.
uAPI의 `@virt_id`는 vIOMMU별 vDEVICE 배열에 객체를 저장할 index입니다. IOMMU 드라이버는 필요하면 원문 표기의 `vdevce_alloc` op를 구현해 vDEVICE 관련 가상화 하드웨어를 초기화할 수 있습니다. 성공하면 vIOMMU와 device 연결이 완성됩니다.
DMA ownership claim 때문에 장치는 iommufd 하나에만 bind할 수 있고, 최대 IOAS 하나에만 attach할 수 있습니다. PASID는 아직 지원하지 않습니다.
수동 할당에 필요한 ID와 연결 결과입니다.
5. IOMMUFD_OBJ_VIOMMU can be only manually created via the IOMMU_VIOMMU_ALLOC
uAPI, provided a dev_id (for the device's physical IOMMU to back the vIOMMU)
and an hwpt_id (to associate the vIOMMU to a nesting parent HWPT_PAGING). The
iommufd core will link the vIOMMU object to the struct iommu_device that the
struct device is behind. And an IOMMU driver can implement a viommu_alloc op
to allocate its own vIOMMU data structure embedding the core-level structure
iommufd_viommu and some driver-specific data. If necessary, the driver can
also configure its HW virtualization feature for that vIOMMU (and thus for
the VM). Successful completion of this operation sets up the linkages between
the vIOMMU object and the HWPT_PAGING, then this vIOMMU object can be used
as a nesting parent object to allocate an HWPT_NESTED object described above.
6. IOMMUFD_OBJ_VDEVICE can be only manually created via the IOMMU_VDEVICE_ALLOC
uAPI, provided a viommu_id for an iommufd_viommu object and a dev_id for an
iommufd_device object. The vDEVICE object will be the binding between these
two parent objects. Another @virt_id will be also set via the uAPI providing
the iommufd core an index to store the vDEVICE object to a vDEVICE array per
vIOMMU. If necessary, the IOMMU driver may choose to implement a vdevce_alloc
op to init its HW for virtualization feature related to a vDEVICE. Successful
completion of this operation sets up the linkages between vIOMMU and device.
A device can only bind to an iommufd due to DMA ownership claim and attach to at
most one IOAS object (no support of PASID yet).
커널 자료구조와 용어
271-302사용자 가시 객체는 대응 커널 자료구조가 뒷받침합니다.
객체별 core 자료구조 이름을 보존합니다.
Automatic domain은 장치를 IOAS에 attach할 때 자동으로 생성되는 iommu domain이며 VFIO type1 의미론과 호환됩니다.
Manual domain은 사용자가 장치가 attach할 대상 page table로 지정한 iommu domain입니다. 현재 이런 domain을 직접 만드는 uAPI는 없지만 자료구조와 알고리즘은 이 사용 사례를 처리할 준비가 되어 있습니다.
In-kernel user는 VFIO mdev처럼 IOMMUFD access interface로 IOAS에 접근하는 커널 내부 사용자를 뜻합니다. 물리 장치의 domain bind와 비슷한 `iommufd_access` 객체를 먼저 만듭니다.
access 객체는 IOVA 범위를 `struct page *` 목록으로 변환하거나 IOVA를 직접 read/write할 수 있게 합니다.
domain 생성 주체와 IOAS 접근 방식을 구분합니다.
Kernel Datastructure
--------------------
User visible objects are backed by following datastructures:
- iommufd_ioas for IOMMUFD_OBJ_IOAS.
- iommufd_device for IOMMUFD_OBJ_DEVICE.
- iommufd_hwpt_paging for IOMMUFD_OBJ_HWPT_PAGING.
- iommufd_hwpt_nested for IOMMUFD_OBJ_HWPT_NESTED.
- iommufd_fault for IOMMUFD_OBJ_FAULT.
- iommufd_viommu for IOMMUFD_OBJ_VIOMMU.
- iommufd_vdevice for IOMMUFD_OBJ_VDEVICE.
- iommufd_veventq for IOMMUFD_OBJ_VEVENTQ.
- iommufd_hw_queue for IOMMUFD_OBJ_HW_QUEUE.
Several terminologies when looking at these datastructures:
- Automatic domain - refers to an iommu domain created automatically when
attaching a device to an IOAS object. This is compatible to the semantics of
VFIO type1.
- Manual domain - refers to an iommu domain designated by the user as the
target pagetable to be attached to by a device. Though currently there are
no uAPIs to directly create such domain, the datastructure and algorithms
are ready for handling that use case.
- In-kernel user - refers to something like a VFIO mdev that is using the
IOMMUFD access interface to access the IOAS. This starts by creating an
iommufd_access object that is similar to the domain binding a physical device
would do. The access object will then allow converting IOVA ranges into struct
page * lists, or doing direct read/write to an IOVA.
iommufd_ioas 내부와 PFN 저장
303-331`iommufd_ioas`는 IOVA 범위를 메모리 페이지에 매핑하는 방식을 관리하는 metadata 자료구조입니다.
IOVA map, PFN 저장소, domain과 커널 내부 접근자를 함께 관리합니다.
각 `iopt_pages`는 완전한 PFN의 논리적 선형 배열입니다. PFN은 최종적으로 `mm_struct`를 통해 사용자 VA에서 얻습니다. pin한 PFN은 `iommu_domain`의 IOPTE에 저장하거나, `iommufd_access`를 통해 pin한 경우 `pinned_pfns` xarray에 저장합니다.
존재하는 domain과 커널 내부 software access 사용자 종류에 따라 모든 저장 위치 조합 사이에서 PFN을 복사해야 합니다. 이 메커니즘은 페이지 하나가 한 번만 pin되도록 보장합니다.
`io_pagetable`은 `iopt_pages`를 가리키는 `iopt_area`와 IOVA-to-PFN map을 mirror하는 `iommu_domain` 목록으로 구성됩니다.
여러 `io_pagetable`은 각자의 `iopt_area`를 통해 하나의 `iopt_pages`를 공유할 수 있습니다. 이로써 다중 pin과 페이지 소비량 중복 계상을 피합니다.
서로 다른 서브시스템이 관리하는 장치가 같은 iommufd에 bind되어 있다면 `iommufd_ioas`를 VFIO와 VDPA 같은 서브시스템 사이에서 공유할 수 있습니다.
사용자 VA에서 얻은 PFN을 한 번만 pin해 필요한 저장 위치에서 공유합니다.
iommufd_ioas serves as the metadata datastructure to manage how IOVA ranges are
mapped to memory pages, composed of:
- struct io_pagetable holding the IOVA map
- struct iopt_area's representing populated portions of IOVA
- struct iopt_pages representing the storage of PFNs
- struct iommu_domain representing the IO page table in the IOMMU
- struct iopt_pages_access representing in-kernel users of PFNs
- struct xarray pinned_pfns holding a list of pages pinned by in-kernel users
Each iopt_pages represents a logical linear array of full PFNs. The PFNs are
ultimately derived from userspace VAs via an mm_struct. Once they have been
pinned the PFNs are stored in IOPTEs of an iommu_domain or inside the pinned_pfns
xarray if they have been pinned through an iommufd_access.
PFN have to be copied between all combinations of storage locations, depending
on what domains are present and what kinds of in-kernel "software access" users
exist. The mechanism ensures that a page is pinned only once.
An io_pagetable is composed of iopt_areas pointing at iopt_pages, along with a
list of iommu_domains that mirror the IOVA to PFN map.
Multiple io_pagetable-s, through their iopt_area-s, can share a single
iopt_pages which avoids multi-pinning and double accounting of page
consumption.
iommufd_ioas is shareable between subsystems, e.g. VFIO and VDPA, as long as
devices managed by different subsystems are bound to a same iommufd.
IOMMUFD 사용자·커널 API
332-350IOMMUFD 사용자 API의 kernel-doc 원본은 `include/uapi/linux/iommufd.h`입니다.
IOMMUFD kAPI는 device 중심이며 group 관련 처리는 내부에서 숨깁니다. 따라서 외부 드라이버는 VFIO처럼 uAPI에 group 의미론을 명시적으로 강제하지 않고, 장치를 iommufd에 연결하는 단순한 device 중심 uAPI를 구현할 수 있습니다.
커널 API 문서는 `drivers/iommu/iommufd/device.c`와 `drivers/iommu/iommufd/main.c`의 exported kernel-doc에서 생성됩니다.
Sphinx kernel-doc 지시문이 참조하는 경로입니다.
IOMMUFD User API
================
.. kernel-doc:: include/uapi/linux/iommufd.h
IOMMUFD Kernel API
==================
The IOMMUFD kAPI is device-centric with group-related tricks managed behind the
scene. This allows the external drivers calling such kAPI to implement a simple
device-centric uAPI for connecting its device to an iommufd, instead of
explicitly imposing the group semantics in its uAPI as VFIO does.
.. kernel-doc:: drivers/iommu/iommufd/device.c
:export:
.. kernel-doc:: drivers/iommu/iommufd/main.c
:export:
VFIO와 IOMMUFD
351-371VFIO 장치를 iommufd에 연결하는 방법은 두 가지입니다.
첫 번째는 `/dev/vfio/vfio` container ioctl을 `io_pagetable` 작업에 매핑해 직접 구현하는 VFIO 호환 방식입니다. `/dev/vfio/vfio`를 `/dev/iommufd`에 symlink하거나, VFIO의 `SET_CONTAINER`가 container fd 대신 iommufd를 받게 확장하면 기존 VFIO 애플리케이션에서도 iommufd를 사용할 수 있습니다.
두 번째는 앞서 설명한 IOMMUFD kernel API를 기반으로 새로운 device 중심 사용자 API를 VFIO에 직접 추가하는 방법입니다. 사용자 공간 변경이 필요하지만 IOMMUFD 의미론에 더 잘 맞고 첫 번째 방식보다 새로운 iommufd 기능을 지원하기 쉽습니다.
현재 두 방식 모두 개발 중입니다. VFIO type1을 따라잡기 위해 해결해야 할 차이는 `iommufd_vfio_check_extension()`에 문서화되어 있습니다.
호환성과 장기 확장성의 차이입니다.
VFIO and IOMMUFD
----------------
Connecting a VFIO device to iommufd can be done in two ways.
First is a VFIO compatible way by directly implementing the /dev/vfio/vfio
container IOCTLs by mapping them into io_pagetable operations. Doing so allows
the use of iommufd in legacy VFIO applications by symlinking /dev/vfio/vfio to
/dev/iommufd or extending VFIO to SET_CONTAINER using an iommufd instead of a
container fd.
The second approach directly extends VFIO to support a new set of device-centric
user API based on aforementioned IOMMUFD kernel API. It requires userspace
change but better matches the IOMMUFD API semantics and easier to support new
iommufd features when comparing it to the first approach.
Currently both approaches are still work-in-progress.
There are still a few gaps to be resolved to catch up with VFIO type1, as
documented in iommufd_vfio_check_extension().
향후 작업
372-384현재 IOMMUFD는 VFIO type1과 비슷하게 kernel 관리 I/O 페이지 테이블만 지원합니다. 향후 검토 중인 기능은 다음과 같습니다.
PASID·사용자 페이지 테이블·무효화·dirty tracking과 PRI가 주요 확장 축입니다.
Future TODOs
============
Currently IOMMUFD supports only kernel-managed I/O page table, similar to VFIO
type1. New features on the radar include:
- Binding iommu_domain's to PASID/SSID
- Userspace page tables, for ARM, x86 and S390
- Kernel bypass'd invalidation of user page tables
- Re-use of the KVM page table in the IOMMU
- Dirty page tracking in the IOMMU
- Runtime Increase/Decrease of IOPTE size
- PRI support with faults resolved in userspace
요약·해설
iommufd.rst:1-384IOMMUFD는 `/dev/iommu` 파일 디스크립터를 중심으로 IOAS, 장치, paging·nested HWPT와 가상 IOMMU 객체를 연결해 사용자 공간 DMA를 관리하는 공통 API입니다.
문서는 객체 생성 순서, 자동·수동 domain, PFN 저장과 공유, device 중심 kernel API, VFIO 호환 경로와 향후 PASID·dirty tracking·PRI 계획을 함께 설명합니다.
한국어 전문 번역은 원문 384줄 전체와 세 ASCII 객체 관계도를 연속 좌표로 대조하고, 도식은 동일한 관계를 갖는 구조화 흐름도로 다시 구성했습니다.