Skip to content

Commit 1ea2a07

Browse files
LuBaolujoergroedel
authored andcommitted
iommu: Add DMA ownership management interfaces
Multiple devices may be placed in the same IOMMU group because they cannot be isolated from each other. These devices must either be entirely under kernel control or userspace control, never a mixture. This adds dma ownership management in iommu core and exposes several interfaces for the device drivers and the device userspace assignment framework (i.e. VFIO), so that any conflict between user and kernel controlled dma could be detected at the beginning. The device driver oriented interfaces are, int iommu_device_use_default_domain(struct device *dev); void iommu_device_unuse_default_domain(struct device *dev); By calling iommu_device_use_default_domain(), the device driver tells the iommu layer that the device dma is handled through the kernel DMA APIs. The iommu layer will manage the IOVA and use the default domain for DMA address translation. The device user-space assignment framework oriented interfaces are, int iommu_group_claim_dma_owner(struct iommu_group *group, void *owner); void iommu_group_release_dma_owner(struct iommu_group *group); bool iommu_group_dma_owner_claimed(struct iommu_group *group); The device userspace assignment must be disallowed if the DMA owner claiming interface returns failure. Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Kevin Tian <kevin.tian@intel.com> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Link: https://lore.kernel.org/r/20220418005000.897664-2-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent af2d861 commit 1ea2a07

2 files changed

Lines changed: 181 additions & 3 deletions

File tree

drivers/iommu/iommu.c

Lines changed: 150 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ struct iommu_group {
4848
struct iommu_domain *default_domain;
4949
struct iommu_domain *domain;
5050
struct list_head entry;
51+
unsigned int owner_cnt;
52+
void *owner;
5153
};
5254

5355
struct group_device {
@@ -294,7 +296,11 @@ int iommu_probe_device(struct device *dev)
294296
mutex_lock(&group->mutex);
295297
iommu_alloc_default_domain(group, dev);
296298

297-
if (group->default_domain) {
299+
/*
300+
* If device joined an existing group which has been claimed, don't
301+
* attach the default domain.
302+
*/
303+
if (group->default_domain && !group->owner) {
298304
ret = __iommu_attach_device(group->default_domain, dev);
299305
if (ret) {
300306
mutex_unlock(&group->mutex);
@@ -2109,7 +2115,7 @@ static int __iommu_attach_group(struct iommu_domain *domain,
21092115
{
21102116
int ret;
21112117

2112-
if (group->default_domain && group->domain != group->default_domain)
2118+
if (group->domain && group->domain != group->default_domain)
21132119
return -EBUSY;
21142120

21152121
ret = __iommu_group_for_each_dev(group, domain,
@@ -2146,7 +2152,11 @@ static void __iommu_detach_group(struct iommu_domain *domain,
21462152
{
21472153
int ret;
21482154

2149-
if (!group->default_domain) {
2155+
/*
2156+
* If the group has been claimed already, do not re-attach the default
2157+
* domain.
2158+
*/
2159+
if (!group->default_domain || group->owner) {
21502160
__iommu_group_for_each_dev(group, domain,
21512161
iommu_group_do_detach_device);
21522162
group->domain = NULL;
@@ -3095,3 +3105,140 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
30953105

30963106
return ret;
30973107
}
3108+
3109+
/**
3110+
* iommu_device_use_default_domain() - Device driver wants to handle device
3111+
* DMA through the kernel DMA API.
3112+
* @dev: The device.
3113+
*
3114+
* The device driver about to bind @dev wants to do DMA through the kernel
3115+
* DMA API. Return 0 if it is allowed, otherwise an error.
3116+
*/
3117+
int iommu_device_use_default_domain(struct device *dev)
3118+
{
3119+
struct iommu_group *group = iommu_group_get(dev);
3120+
int ret = 0;
3121+
3122+
if (!group)
3123+
return 0;
3124+
3125+
mutex_lock(&group->mutex);
3126+
if (group->owner_cnt) {
3127+
if (group->domain != group->default_domain ||
3128+
group->owner) {
3129+
ret = -EBUSY;
3130+
goto unlock_out;
3131+
}
3132+
}
3133+
3134+
group->owner_cnt++;
3135+
3136+
unlock_out:
3137+
mutex_unlock(&group->mutex);
3138+
iommu_group_put(group);
3139+
3140+
return ret;
3141+
}
3142+
3143+
/**
3144+
* iommu_device_unuse_default_domain() - Device driver stops handling device
3145+
* DMA through the kernel DMA API.
3146+
* @dev: The device.
3147+
*
3148+
* The device driver doesn't want to do DMA through kernel DMA API anymore.
3149+
* It must be called after iommu_device_use_default_domain().
3150+
*/
3151+
void iommu_device_unuse_default_domain(struct device *dev)
3152+
{
3153+
struct iommu_group *group = iommu_group_get(dev);
3154+
3155+
if (!group)
3156+
return;
3157+
3158+
mutex_lock(&group->mutex);
3159+
if (!WARN_ON(!group->owner_cnt))
3160+
group->owner_cnt--;
3161+
3162+
mutex_unlock(&group->mutex);
3163+
iommu_group_put(group);
3164+
}
3165+
3166+
/**
3167+
* iommu_group_claim_dma_owner() - Set DMA ownership of a group
3168+
* @group: The group.
3169+
* @owner: Caller specified pointer. Used for exclusive ownership.
3170+
*
3171+
* This is to support backward compatibility for vfio which manages
3172+
* the dma ownership in iommu_group level. New invocations on this
3173+
* interface should be prohibited.
3174+
*/
3175+
int iommu_group_claim_dma_owner(struct iommu_group *group, void *owner)
3176+
{
3177+
int ret = 0;
3178+
3179+
mutex_lock(&group->mutex);
3180+
if (group->owner_cnt) {
3181+
ret = -EPERM;
3182+
goto unlock_out;
3183+
} else {
3184+
if (group->domain && group->domain != group->default_domain) {
3185+
ret = -EBUSY;
3186+
goto unlock_out;
3187+
}
3188+
3189+
group->owner = owner;
3190+
if (group->domain)
3191+
__iommu_detach_group(group->domain, group);
3192+
}
3193+
3194+
group->owner_cnt++;
3195+
unlock_out:
3196+
mutex_unlock(&group->mutex);
3197+
3198+
return ret;
3199+
}
3200+
EXPORT_SYMBOL_GPL(iommu_group_claim_dma_owner);
3201+
3202+
/**
3203+
* iommu_group_release_dma_owner() - Release DMA ownership of a group
3204+
* @group: The group.
3205+
*
3206+
* Release the DMA ownership claimed by iommu_group_claim_dma_owner().
3207+
*/
3208+
void iommu_group_release_dma_owner(struct iommu_group *group)
3209+
{
3210+
mutex_lock(&group->mutex);
3211+
if (WARN_ON(!group->owner_cnt || !group->owner))
3212+
goto unlock_out;
3213+
3214+
group->owner_cnt = 0;
3215+
/*
3216+
* The UNMANAGED domain should be detached before all USER
3217+
* owners have been released.
3218+
*/
3219+
if (!WARN_ON(group->domain) && group->default_domain)
3220+
__iommu_attach_group(group->default_domain, group);
3221+
group->owner = NULL;
3222+
unlock_out:
3223+
mutex_unlock(&group->mutex);
3224+
}
3225+
EXPORT_SYMBOL_GPL(iommu_group_release_dma_owner);
3226+
3227+
/**
3228+
* iommu_group_dma_owner_claimed() - Query group dma ownership status
3229+
* @group: The group.
3230+
*
3231+
* This provides status query on a given group. It is racy and only for
3232+
* non-binding status reporting.
3233+
*/
3234+
bool iommu_group_dma_owner_claimed(struct iommu_group *group)
3235+
{
3236+
unsigned int user;
3237+
3238+
mutex_lock(&group->mutex);
3239+
user = group->owner_cnt;
3240+
mutex_unlock(&group->mutex);
3241+
3242+
return user;
3243+
}
3244+
EXPORT_SYMBOL_GPL(iommu_group_dma_owner_claimed);

include/linux/iommu.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,13 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev,
675675
void iommu_sva_unbind_device(struct iommu_sva *handle);
676676
u32 iommu_sva_get_pasid(struct iommu_sva *handle);
677677

678+
int iommu_device_use_default_domain(struct device *dev);
679+
void iommu_device_unuse_default_domain(struct device *dev);
680+
681+
int iommu_group_claim_dma_owner(struct iommu_group *group, void *owner);
682+
void iommu_group_release_dma_owner(struct iommu_group *group);
683+
bool iommu_group_dma_owner_claimed(struct iommu_group *group);
684+
678685
#else /* CONFIG_IOMMU_API */
679686

680687
struct iommu_ops {};
@@ -1031,6 +1038,30 @@ static inline struct iommu_fwspec *dev_iommu_fwspec_get(struct device *dev)
10311038
{
10321039
return NULL;
10331040
}
1041+
1042+
static inline int iommu_device_use_default_domain(struct device *dev)
1043+
{
1044+
return 0;
1045+
}
1046+
1047+
static inline void iommu_device_unuse_default_domain(struct device *dev)
1048+
{
1049+
}
1050+
1051+
static inline int
1052+
iommu_group_claim_dma_owner(struct iommu_group *group, void *owner)
1053+
{
1054+
return -ENODEV;
1055+
}
1056+
1057+
static inline void iommu_group_release_dma_owner(struct iommu_group *group)
1058+
{
1059+
}
1060+
1061+
static inline bool iommu_group_dma_owner_claimed(struct iommu_group *group)
1062+
{
1063+
return false;
1064+
}
10341065
#endif /* CONFIG_IOMMU_API */
10351066

10361067
/**

0 commit comments

Comments
 (0)