Skip to content

Commit 6b22d56

Browse files
nicolincjgunthorpe
authored andcommitted
iommufd: Introduce IOMMUFD_OBJ_VIOMMU and its related struct
Add a new IOMMUFD_OBJ_VIOMMU with an iommufd_viommu structure to represent a slice of physical IOMMU device passed to or shared with a user space VM. This slice, now a vIOMMU object, is a group of virtualization resources of a physical IOMMU's, such as: - 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 sharable 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 Add a new viommu_alloc op in iommu_ops, for drivers to allocate their own vIOMMU structures. And this allocation also needs a free(), so add struct iommufd_viommu_ops. To simplify a vIOMMU allocation, provide a iommufd_viommu_alloc() helper. It's suggested that a driver should embed a core-level viommu structure in its driver-level viommu struct and call the iommufd_viommu_alloc() helper, meanwhile the driver can also implement a viommu ops: struct my_driver_viommu { struct iommufd_viommu core; /* driver-owned properties/features */ .... }; static const struct iommufd_viommu_ops my_driver_viommu_ops = { .free = my_driver_viommu_free, /* future ops for virtualization features */ .... }; static struct iommufd_viommu my_driver_viommu_alloc(...) { struct my_driver_viommu *my_viommu = iommufd_viommu_alloc(ictx, my_driver_viommu, core, my_driver_viommu_ops); /* Init my_viommu and related HW feature */ .... return &my_viommu->core; } static struct iommu_domain_ops my_driver_domain_ops = { .... .viommu_alloc = my_driver_viommu_alloc, }; Link: https://patch.msgid.link/r/64685e2b79dea0f1dc56f6ede04809b72d578935.1730836219.git.nicolinc@nvidia.com Suggested-by: Jason Gunthorpe <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Signed-off-by: Nicolin Chen <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 7d4f46c commit 6b22d56

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

include/linux/iommu.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ struct notifier_block;
4242
struct iommu_sva;
4343
struct iommu_dma_cookie;
4444
struct iommu_fault_param;
45+
struct iommufd_ctx;
46+
struct iommufd_viommu;
4547

4648
#define IOMMU_FAULT_PERM_READ (1 << 0) /* read */
4749
#define IOMMU_FAULT_PERM_WRITE (1 << 1) /* write */
@@ -542,6 +544,14 @@ static inline int __iommu_copy_struct_from_user_array(
542544
* @remove_dev_pasid: Remove any translation configurations of a specific
543545
* pasid, so that any DMA transactions with this pasid
544546
* will be blocked by the hardware.
547+
* @viommu_alloc: Allocate an iommufd_viommu on a physical IOMMU instance behind
548+
* the @dev, as the set of virtualization resources shared/passed
549+
* to user space IOMMU instance. And associate it with a nesting
550+
* @parent_domain. The @viommu_type must be defined in the header
551+
* include/uapi/linux/iommufd.h
552+
* It is required to call iommufd_viommu_alloc() helper for
553+
* a bundled allocation of the core and the driver structures,
554+
* using the given @ictx pointer.
545555
* @pgsize_bitmap: bitmap of all possible supported page sizes
546556
* @owner: Driver module providing these ops
547557
* @identity_domain: An always available, always attachable identity
@@ -591,6 +601,10 @@ struct iommu_ops {
591601
void (*remove_dev_pasid)(struct device *dev, ioasid_t pasid,
592602
struct iommu_domain *domain);
593603

604+
struct iommufd_viommu *(*viommu_alloc)(
605+
struct device *dev, struct iommu_domain *parent_domain,
606+
struct iommufd_ctx *ictx, unsigned int viommu_type);
607+
594608
const struct iommu_domain_ops *default_domain_ops;
595609
unsigned long pgsize_bitmap;
596610
struct module *owner;

include/linux/iommufd.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ struct iommu_group;
1717
struct iommufd_access;
1818
struct iommufd_ctx;
1919
struct iommufd_device;
20+
struct iommufd_viommu_ops;
2021
struct page;
2122

2223
enum iommufd_object_type {
@@ -28,6 +29,7 @@ enum iommufd_object_type {
2829
IOMMUFD_OBJ_IOAS,
2930
IOMMUFD_OBJ_ACCESS,
3031
IOMMUFD_OBJ_FAULT,
32+
IOMMUFD_OBJ_VIOMMU,
3133
#ifdef CONFIG_IOMMUFD_TEST
3234
IOMMUFD_OBJ_SELFTEST,
3335
#endif
@@ -78,6 +80,26 @@ void iommufd_access_detach(struct iommufd_access *access);
7880

7981
void iommufd_ctx_get(struct iommufd_ctx *ictx);
8082

83+
struct iommufd_viommu {
84+
struct iommufd_object obj;
85+
struct iommufd_ctx *ictx;
86+
struct iommu_device *iommu_dev;
87+
struct iommufd_hwpt_paging *hwpt;
88+
89+
const struct iommufd_viommu_ops *ops;
90+
91+
unsigned int type;
92+
};
93+
94+
/**
95+
* struct iommufd_viommu_ops - vIOMMU specific operations
96+
* @destroy: Clean up all driver-specific parts of an iommufd_viommu. The memory
97+
* of the vIOMMU will be free-ed by iommufd core after calling this op
98+
*/
99+
struct iommufd_viommu_ops {
100+
void (*destroy)(struct iommufd_viommu *viommu);
101+
};
102+
81103
#if IS_ENABLED(CONFIG_IOMMUFD)
82104
struct iommufd_ctx *iommufd_ctx_from_file(struct file *file);
83105
struct iommufd_ctx *iommufd_ctx_from_fd(int fd);
@@ -148,4 +170,22 @@ _iommufd_object_alloc(struct iommufd_ctx *ictx, size_t size,
148170
return ERR_PTR(-EOPNOTSUPP);
149171
}
150172
#endif /* CONFIG_IOMMUFD_DRIVER_CORE */
173+
174+
/*
175+
* Helpers for IOMMU driver to allocate driver structures that will be freed by
176+
* the iommufd core. The free op will be called prior to freeing the memory.
177+
*/
178+
#define iommufd_viommu_alloc(ictx, drv_struct, member, viommu_ops) \
179+
({ \
180+
drv_struct *ret; \
181+
\
182+
static_assert(__same_type(struct iommufd_viommu, \
183+
((drv_struct *)NULL)->member)); \
184+
static_assert(offsetof(drv_struct, member.obj) == 0); \
185+
ret = (drv_struct *)_iommufd_object_alloc( \
186+
ictx, sizeof(drv_struct), IOMMUFD_OBJ_VIOMMU); \
187+
if (!IS_ERR(ret)) \
188+
ret->member.ops = viommu_ops; \
189+
ret; \
190+
})
151191
#endif

0 commit comments

Comments
 (0)