STRUCT IOMMU_DOMAIN_OPS(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… struct iommu_domain_ops(9) β€” the kernel API manual, but make it make sense πŸŽ€

okay bestie, so this is a page from the Kernel API Manual, and honestly? it's giving "the plugin interface for your IOMMU domain." it's the struct that says what your domain can actually do β€” domain specific operations, periodt. ✨


🌸 NAME 🌸

struct iommu_domain_ops β€” domain specific operations πŸ’–


⭐ SYNOPSIS ⭐

struct iommu_domain_ops {
    int (*attach_dev)(struct iommu_domain *domain, struct device *dev,
struct iommu_domain *old);
    int (*set_dev_pasid)(struct iommu_domain *domain, struct device
*dev, ioasid_t pasid, struct iommu_domain *old);
    int (*map_pages)(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t pgsize, size_t pgcount, int prot, gfp_t gfp,
size_t *mapped);
    size_t (*unmap_pages)(struct iommu_domain *domain, unsigned long
iova, size_t pgsize, size_t pgcount, struct iommu_iotlb_gather
*iotlb_gather);
    void (*flush_iotlb_all)(struct iommu_domain *domain);
    int (*iotlb_sync_map)(struct iommu_domain *domain, unsigned long
iova, size_t size);
    void (*iotlb_sync)(struct iommu_domain *domain, struct
iommu_iotlb_gather *iotlb_gather);
    int (*cache_invalidate_user)(struct iommu_domain *domain, struct
iommu_user_data_array *array);
    phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t
iova);
    bool (*enforce_cache_coherency)(struct iommu_domain *domain);
    int (*set_pgtable_quirks)(struct iommu_domain *domain, unsigned long
quirks);
    void (*free)(struct iommu_domain *domain);
 };

like, twelve function pointers, all vibing in one struct. it's a whole squad 🫢


πŸ¦‹ Members πŸ¦‹

  • attach_dev β€” attaches an iommu domain to a device. matching-making, but for hardware πŸ’…
  • set_dev_pasid β€” sets or replaces an iommu domain on a pasid of a device. one (1) important rule, no cap: if it errors out, the pasid of the device should be left in the old config. don't leave it in a half-changed limbo state, that's not the vibe 😭
  • map_pages β€” maps a physically contiguous set of pages, all the same size, onto an iommu domain. iconic.
  • unmap_pages β€” unmaps a number (could be many!) of pages of the same size from an iommu domain. the reverse slay.
  • flush_iotlb_all β€” Synchronously flushes all the hardware TLBs for this domain. capital-S Synchronously, bestie, it waits.
  • iotlb_sync_map β€” syncs mappings you created recently using map over to the hardware. 🧚
  • iotlb_sync β€” flushes all the queued ranges from the hardware TLBs and empties the flush queue. clearing the group chat energy.
  • cache_invalidate_user β€” flushes the hardware cache for the user space IO page table. ok so the deets:
    • the domain must be IOMMU_DOMAIN_NESTED (this is not optional, it's a requirement πŸ’€)
    • the array passes in the cache invalidation requests, in the form of a driver data structure
    • the driver must update array->entry_num to report the number of handled invalidation requests
    • the driver data structure must be defined in include/uapi/linux/iommufd.h
  • iova_to_phys β€” translates iova to a physical address. glow-up but for addresses ✨
  • enforce_cache_coherency β€” prevents any kind of DMA from bypassing IOMMU_CACHE. that includes no-snoop TLPs on PCIe, or any other platform specific mechanisms. it's a strict bouncer at the door πŸ‘‘
  • set_pgtable_quirks β€” sets io page table quirks (IO_PGTABLE_QUIRK_*). quirky on purpose.
  • free β€” releases the domain after use. clean up your room after the party πŸŽ€

🌈 Return 🌈

these are the return vibes, bestie β€” memorize them iykyk:

  • 0 β€” success πŸŽ‰
  • EINVAL β€” can indicate that the device and domain are incompatible because of some previous configuration of the domain. and in that case the driver shouldn't log an error, because it's totally legitimate for a caller to test reuse of existing domains (testing the waters is valid πŸ’…). otherwise, it may still represent some other fundamental problem
  • ENOMEM β€” out of memory 😭
  • ENOSPC β€” non-ENOMEM type of resource allocation failures
  • EBUSY β€” the device is attached to a domain and cannot be changed. locked in, literally.
  • ENODEV β€” device specific errors, not able to be attached πŸ™ˆ
  • <others> β€” treated as ENODEV by the caller. Use is discouraged. like, don't. fr fr.
πŸ’€ real talk: if you're returning something random and hoping the caller figures it out β€” it won't. it just becomes ENODEV. use the documented codes.

πŸ”₯ SEE ALSO πŸ”₯

Kernel file ./include/linux/iommu.h, plus the whole extended friend group:

struct iommu_fault_page_request(9), struct iommu_fault(9), enum iommu_page_response_code(9), struct iommu_page_response(9), struct iopf_queue(9), struct iommu_resv_region(9), struct iommu_iotlb_gather(9), struct iommu_dirty_bitmap(9), struct iommu_dirty_ops(9), struct iommu_user_data(9), struct iommu_user_data_array(9), __iommu_copy_struct_from_user(9), iommu_copy_struct_from_user(9), __iommu_copy_struct_from_user_array(9), iommu_copy_struct_from_user_array(9), iommu_copy_struct_from_full_user_array(9), __iommu_copy_struct_to_user(9), iommu_copy_struct_to_user(9), struct iommu_ops(9), struct iommu_device(9), struct iommu_fault_param(9), struct dev_iommu(9), iommu_iotlb_gather_is_disjoint(9), iommu_iotlb_gather_add_range(9), iommu_iotlb_gather_add_page(9), struct iommu_fwspec(9), struct iommu_sva(9), iommu_map_sgtable(9)


okay that's the whole page, you ate that πŸ“ mwah πŸ’‹ β€” this one lives in ./include/linux, dated October 2026, from the Kernel API Manual. go forth and attach your devices correctly, bestie. πŸ¦‹πŸ’œ

πŸ“¦ where this page comes from