Skip to content

Commit 1467821

Browse files
LuBaoluwilldeacon
authored andcommitted
iommu: Introduce domain attachment handle
Currently, when attaching a domain to a device or its PASID, domain is stored within the iommu group. It could be retrieved for use during the window between attachment and detachment. With new features introduced, there's a need to store more information than just a domain pointer. This information essentially represents the association between a domain and a device. For example, the SVA code already has a custom struct iommu_sva which represents a bond between sva domain and a PASID of a device. Looking forward, the IOMMUFD needs a place to store the iommufd_device pointer in the core, so that the device object ID could be quickly retrieved in the critical fault handling path. Introduce domain attachment handle that explicitly represents the attachment relationship between a domain and a device or its PASID. Co-developed-by: Jason Gunthorpe <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Signed-off-by: Lu Baolu <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 83a7eef commit 1467821

File tree

4 files changed

+40
-19
lines changed

4 files changed

+40
-19
lines changed

drivers/dma/idxd/init.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ static int idxd_enable_system_pasid(struct idxd_device *idxd)
584584
* DMA domain is owned by the driver, it should support all valid
585585
* types such as DMA-FQ, identity, etc.
586586
*/
587-
ret = iommu_attach_device_pasid(domain, dev, pasid);
587+
ret = iommu_attach_device_pasid(domain, dev, pasid, NULL);
588588
if (ret) {
589589
dev_err(dev, "failed to attach device pasid %d, domain type %d",
590590
pasid, domain->type);

drivers/iommu/iommu-sva.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
9999

100100
/* Search for an existing domain. */
101101
list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next) {
102-
ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid);
102+
handle->handle.domain = domain;
103+
ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
104+
&handle->handle);
103105
if (!ret) {
104106
domain->users++;
105107
goto out;
@@ -113,7 +115,9 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
113115
goto out_free_handle;
114116
}
115117

116-
ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid);
118+
handle->handle.domain = domain;
119+
ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
120+
&handle->handle);
117121
if (ret)
118122
goto out_free_domain;
119123
domain->users = 1;
@@ -124,7 +128,6 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
124128
list_add(&handle->handle_item, &mm->iommu_mm->sva_handles);
125129
mutex_unlock(&iommu_sva_lock);
126130
handle->dev = dev;
127-
handle->domain = domain;
128131
return handle;
129132

130133
out_free_domain:
@@ -147,7 +150,7 @@ EXPORT_SYMBOL_GPL(iommu_sva_bind_device);
147150
*/
148151
void iommu_sva_unbind_device(struct iommu_sva *handle)
149152
{
150-
struct iommu_domain *domain = handle->domain;
153+
struct iommu_domain *domain = handle->handle.domain;
151154
struct iommu_mm_data *iommu_mm = domain->mm->iommu_mm;
152155
struct device *dev = handle->dev;
153156

@@ -170,7 +173,7 @@ EXPORT_SYMBOL_GPL(iommu_sva_unbind_device);
170173

171174
u32 iommu_sva_get_pasid(struct iommu_sva *handle)
172175
{
173-
struct iommu_domain *domain = handle->domain;
176+
struct iommu_domain *domain = handle->handle.domain;
174177

175178
return mm_get_enqcmd_pasid(domain->mm);
176179
}

drivers/iommu/iommu.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3352,16 +3352,17 @@ static void __iommu_remove_group_pasid(struct iommu_group *group,
33523352
* @domain: the iommu domain.
33533353
* @dev: the attached device.
33543354
* @pasid: the pasid of the device.
3355+
* @handle: the attach handle.
33553356
*
33563357
* Return: 0 on success, or an error.
33573358
*/
33583359
int iommu_attach_device_pasid(struct iommu_domain *domain,
3359-
struct device *dev, ioasid_t pasid)
3360+
struct device *dev, ioasid_t pasid,
3361+
struct iommu_attach_handle *handle)
33603362
{
33613363
/* Caller must be a probed driver on dev */
33623364
struct iommu_group *group = dev->iommu_group;
33633365
struct group_device *device;
3364-
void *curr;
33653366
int ret;
33663367

33673368
if (!domain->ops->set_dev_pasid)
@@ -3382,11 +3383,12 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
33823383
}
33833384
}
33843385

3385-
curr = xa_cmpxchg(&group->pasid_array, pasid, NULL, domain, GFP_KERNEL);
3386-
if (curr) {
3387-
ret = xa_err(curr) ? : -EBUSY;
3386+
if (handle)
3387+
handle->domain = domain;
3388+
3389+
ret = xa_insert(&group->pasid_array, pasid, handle, GFP_KERNEL);
3390+
if (ret)
33883391
goto out_unlock;
3389-
}
33903392

33913393
ret = __iommu_set_group_pasid(domain, group, pasid);
33923394
if (ret)
@@ -3414,7 +3416,7 @@ void iommu_detach_device_pasid(struct iommu_domain *domain, struct device *dev,
34143416

34153417
mutex_lock(&group->mutex);
34163418
__iommu_remove_group_pasid(group, pasid, domain);
3417-
WARN_ON(xa_erase(&group->pasid_array, pasid) != domain);
3419+
xa_erase(&group->pasid_array, pasid);
34183420
mutex_unlock(&group->mutex);
34193421
}
34203422
EXPORT_SYMBOL_GPL(iommu_detach_device_pasid);
@@ -3439,15 +3441,19 @@ struct iommu_domain *iommu_get_domain_for_dev_pasid(struct device *dev,
34393441
{
34403442
/* Caller must be a probed driver on dev */
34413443
struct iommu_group *group = dev->iommu_group;
3442-
struct iommu_domain *domain;
3444+
struct iommu_attach_handle *handle;
3445+
struct iommu_domain *domain = NULL;
34433446

34443447
if (!group)
34453448
return NULL;
34463449

34473450
xa_lock(&group->pasid_array);
3448-
domain = xa_load(&group->pasid_array, pasid);
3451+
handle = xa_load(&group->pasid_array, pasid);
3452+
if (handle)
3453+
domain = handle->domain;
3454+
34493455
if (type && domain && domain->type != type)
3450-
domain = ERR_PTR(-EBUSY);
3456+
domain = NULL;
34513457
xa_unlock(&group->pasid_array);
34523458

34533459
return domain;

include/linux/iommu.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -989,12 +989,22 @@ struct iommu_fwspec {
989989
/* ATS is supported */
990990
#define IOMMU_FWSPEC_PCI_RC_ATS (1 << 0)
991991

992+
/*
993+
* An iommu attach handle represents a relationship between an iommu domain
994+
* and a PASID or RID of a device. It is allocated and managed by the component
995+
* that manages the domain and is stored in the iommu group during the time the
996+
* domain is attached.
997+
*/
998+
struct iommu_attach_handle {
999+
struct iommu_domain *domain;
1000+
};
1001+
9921002
/**
9931003
* struct iommu_sva - handle to a device-mm bond
9941004
*/
9951005
struct iommu_sva {
1006+
struct iommu_attach_handle handle;
9961007
struct device *dev;
997-
struct iommu_domain *domain;
9981008
struct list_head handle_item;
9991009
refcount_t users;
10001010
};
@@ -1052,7 +1062,8 @@ int iommu_device_claim_dma_owner(struct device *dev, void *owner);
10521062
void iommu_device_release_dma_owner(struct device *dev);
10531063

10541064
int iommu_attach_device_pasid(struct iommu_domain *domain,
1055-
struct device *dev, ioasid_t pasid);
1065+
struct device *dev, ioasid_t pasid,
1066+
struct iommu_attach_handle *handle);
10561067
void iommu_detach_device_pasid(struct iommu_domain *domain,
10571068
struct device *dev, ioasid_t pasid);
10581069
struct iommu_domain *
@@ -1388,7 +1399,8 @@ static inline int iommu_device_claim_dma_owner(struct device *dev, void *owner)
13881399
}
13891400

13901401
static inline int iommu_attach_device_pasid(struct iommu_domain *domain,
1391-
struct device *dev, ioasid_t pasid)
1402+
struct device *dev, ioasid_t pasid,
1403+
struct iommu_attach_handle *handle)
13921404
{
13931405
return -ENODEV;
13941406
}

0 commit comments

Comments
 (0)