Skip to content

Commit cfea71a

Browse files
jgunthorpejoergroedel
authored andcommitted
iommu/arm-smmu-v3: Put iopf enablement in the domain attach path
SMMUv3 co-mingles FEAT_IOPF and FEAT_SVA behaviors so that fault reporting doesn't work unless both are enabled. This is not correct and causes problems for iommufd which does not enable FEAT_SVA for it's fault capable domains. These APIs are both obsolete, update SMMUv3 to use the new method like AMD implements. A driver should enable iopf support when a domain with an iopf_handler is attached, and disable iopf support when the domain is removed. Move the fault support logic to sva domain allocation and to domain attach, refusing to create or attach fault capable domains if the HW doesn't support it. Move all the logic for controlling the iopf queue under arm_smmu_attach_prepare(). Keep track of the number of domains on the master (over all the SSIDs) that require iopf. When the first domain requiring iopf is attached create the iopf queue, when the last domain is detached destroy it. Turn FEAT_IOPF and FEAT_SVA into no ops. Remove the sva_lock, this is all protected by the group mutex. Signed-off-by: Jason Gunthorpe <[email protected]> Signed-off-by: Lu Baolu <[email protected]> Tested-by: Zhangfei Gao <[email protected]> Acked-by: Will Deacon <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 0da188c commit cfea71a

File tree

3 files changed

+90
-139
lines changed

3 files changed

+90
-139
lines changed

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c

Lines changed: 6 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
#include "arm-smmu-v3.h"
1414
#include "../../io-pgtable-arm.h"
1515

16-
static DEFINE_MUTEX(sva_lock);
17-
1816
static void __maybe_unused
1917
arm_smmu_update_s1_domain_cd_entry(struct arm_smmu_domain *smmu_domain)
2018
{
@@ -257,84 +255,6 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
257255
return true;
258256
}
259257

260-
bool arm_smmu_master_iopf_supported(struct arm_smmu_master *master)
261-
{
262-
/* We're not keeping track of SIDs in fault events */
263-
if (master->num_streams != 1)
264-
return false;
265-
266-
return master->stall_enabled;
267-
}
268-
269-
bool arm_smmu_master_sva_supported(struct arm_smmu_master *master)
270-
{
271-
if (!(master->smmu->features & ARM_SMMU_FEAT_SVA))
272-
return false;
273-
274-
/* SSID support is mandatory for the moment */
275-
return master->ssid_bits;
276-
}
277-
278-
bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master)
279-
{
280-
bool enabled;
281-
282-
mutex_lock(&sva_lock);
283-
enabled = master->sva_enabled;
284-
mutex_unlock(&sva_lock);
285-
return enabled;
286-
}
287-
288-
static int arm_smmu_master_sva_enable_iopf(struct arm_smmu_master *master)
289-
{
290-
struct device *dev = master->dev;
291-
292-
/*
293-
* Drivers for devices supporting PRI or stall should enable IOPF first.
294-
* Others have device-specific fault handlers and don't need IOPF.
295-
*/
296-
if (!arm_smmu_master_iopf_supported(master))
297-
return 0;
298-
299-
if (!master->iopf_enabled)
300-
return -EINVAL;
301-
302-
return iopf_queue_add_device(master->smmu->evtq.iopf, dev);
303-
}
304-
305-
static void arm_smmu_master_sva_disable_iopf(struct arm_smmu_master *master)
306-
{
307-
struct device *dev = master->dev;
308-
309-
if (!master->iopf_enabled)
310-
return;
311-
312-
iopf_queue_remove_device(master->smmu->evtq.iopf, dev);
313-
}
314-
315-
int arm_smmu_master_enable_sva(struct arm_smmu_master *master)
316-
{
317-
int ret;
318-
319-
mutex_lock(&sva_lock);
320-
ret = arm_smmu_master_sva_enable_iopf(master);
321-
if (!ret)
322-
master->sva_enabled = true;
323-
mutex_unlock(&sva_lock);
324-
325-
return ret;
326-
}
327-
328-
int arm_smmu_master_disable_sva(struct arm_smmu_master *master)
329-
{
330-
mutex_lock(&sva_lock);
331-
arm_smmu_master_sva_disable_iopf(master);
332-
master->sva_enabled = false;
333-
mutex_unlock(&sva_lock);
334-
335-
return 0;
336-
}
337-
338258
void arm_smmu_sva_notifier_synchronize(void)
339259
{
340260
/*
@@ -353,6 +273,9 @@ static int arm_smmu_sva_set_dev_pasid(struct iommu_domain *domain,
353273
struct arm_smmu_cd target;
354274
int ret;
355275

276+
if (!(master->smmu->features & ARM_SMMU_FEAT_SVA))
277+
return -EOPNOTSUPP;
278+
356279
/* Prevent arm_smmu_mm_release from being called while we are attaching */
357280
if (!mmget_not_zero(domain->mm))
358281
return -EINVAL;
@@ -406,6 +329,9 @@ struct iommu_domain *arm_smmu_sva_domain_alloc(struct device *dev,
406329
u32 asid;
407330
int ret;
408331

332+
if (!(master->smmu->features & ARM_SMMU_FEAT_SVA))
333+
return ERR_PTR(-EOPNOTSUPP);
334+
409335
smmu_domain = arm_smmu_domain_alloc();
410336
if (IS_ERR(smmu_domain))
411337
return ERR_CAST(smmu_domain);

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 77 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2720,6 +2720,7 @@ static void arm_smmu_disable_pasid(struct arm_smmu_master *master)
27202720

27212721
static struct arm_smmu_master_domain *
27222722
arm_smmu_find_master_domain(struct arm_smmu_domain *smmu_domain,
2723+
struct iommu_domain *domain,
27232724
struct arm_smmu_master *master,
27242725
ioasid_t ssid, bool nested_ats_flush)
27252726
{
@@ -2730,6 +2731,7 @@ arm_smmu_find_master_domain(struct arm_smmu_domain *smmu_domain,
27302731
list_for_each_entry(master_domain, &smmu_domain->devices,
27312732
devices_elm) {
27322733
if (master_domain->master == master &&
2734+
master_domain->domain == domain &&
27332735
master_domain->ssid == ssid &&
27342736
master_domain->nested_ats_flush == nested_ats_flush)
27352737
return master_domain;
@@ -2756,6 +2758,58 @@ to_smmu_domain_devices(struct iommu_domain *domain)
27562758
return NULL;
27572759
}
27582760

2761+
static int arm_smmu_enable_iopf(struct arm_smmu_master *master,
2762+
struct arm_smmu_master_domain *master_domain)
2763+
{
2764+
int ret;
2765+
2766+
iommu_group_mutex_assert(master->dev);
2767+
2768+
if (!IS_ENABLED(CONFIG_ARM_SMMU_V3_SVA))
2769+
return -EOPNOTSUPP;
2770+
2771+
/*
2772+
* Drivers for devices supporting PRI or stall require iopf others have
2773+
* device-specific fault handlers and don't need IOPF, so this is not a
2774+
* failure.
2775+
*/
2776+
if (!master->stall_enabled)
2777+
return 0;
2778+
2779+
/* We're not keeping track of SIDs in fault events */
2780+
if (master->num_streams != 1)
2781+
return -EOPNOTSUPP;
2782+
2783+
if (master->iopf_refcount) {
2784+
master->iopf_refcount++;
2785+
master_domain->using_iopf = true;
2786+
return 0;
2787+
}
2788+
2789+
ret = iopf_queue_add_device(master->smmu->evtq.iopf, master->dev);
2790+
if (ret)
2791+
return ret;
2792+
master->iopf_refcount = 1;
2793+
master_domain->using_iopf = true;
2794+
return 0;
2795+
}
2796+
2797+
static void arm_smmu_disable_iopf(struct arm_smmu_master *master,
2798+
struct arm_smmu_master_domain *master_domain)
2799+
{
2800+
iommu_group_mutex_assert(master->dev);
2801+
2802+
if (!IS_ENABLED(CONFIG_ARM_SMMU_V3_SVA))
2803+
return;
2804+
2805+
if (!master_domain || !master_domain->using_iopf)
2806+
return;
2807+
2808+
master->iopf_refcount--;
2809+
if (master->iopf_refcount == 0)
2810+
iopf_queue_remove_device(master->smmu->evtq.iopf, master->dev);
2811+
}
2812+
27592813
static void arm_smmu_remove_master_domain(struct arm_smmu_master *master,
27602814
struct iommu_domain *domain,
27612815
ioasid_t ssid)
@@ -2772,15 +2826,17 @@ static void arm_smmu_remove_master_domain(struct arm_smmu_master *master,
27722826
nested_ats_flush = to_smmu_nested_domain(domain)->enable_ats;
27732827

27742828
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
2775-
master_domain = arm_smmu_find_master_domain(smmu_domain, master, ssid,
2776-
nested_ats_flush);
2829+
master_domain = arm_smmu_find_master_domain(smmu_domain, domain, master,
2830+
ssid, nested_ats_flush);
27772831
if (master_domain) {
27782832
list_del(&master_domain->devices_elm);
2779-
kfree(master_domain);
27802833
if (master->ats_enabled)
27812834
atomic_dec(&smmu_domain->nr_ats_masters);
27822835
}
27832836
spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
2837+
2838+
arm_smmu_disable_iopf(master, master_domain);
2839+
kfree(master_domain);
27842840
}
27852841

27862842
/*
@@ -2853,12 +2909,19 @@ int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
28532909
kfree(state->vmaster);
28542910
return -ENOMEM;
28552911
}
2912+
master_domain->domain = new_domain;
28562913
master_domain->master = master;
28572914
master_domain->ssid = state->ssid;
28582915
if (new_domain->type == IOMMU_DOMAIN_NESTED)
28592916
master_domain->nested_ats_flush =
28602917
to_smmu_nested_domain(new_domain)->enable_ats;
28612918

2919+
if (new_domain->iopf_handler) {
2920+
ret = arm_smmu_enable_iopf(master, master_domain);
2921+
if (ret)
2922+
goto err_free_master_domain;
2923+
}
2924+
28622925
/*
28632926
* During prepare we want the current smmu_domain and new
28642927
* smmu_domain to be in the devices list before we change any
@@ -2878,9 +2941,9 @@ int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
28782941
!arm_smmu_master_canwbs(master)) {
28792942
spin_unlock_irqrestore(&smmu_domain->devices_lock,
28802943
flags);
2881-
kfree(master_domain);
28822944
kfree(state->vmaster);
2883-
return -EINVAL;
2945+
ret = -EINVAL;
2946+
goto err_iopf;
28842947
}
28852948

28862949
if (state->ats_enabled)
@@ -2899,6 +2962,12 @@ int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
28992962
wmb();
29002963
}
29012964
return 0;
2965+
2966+
err_iopf:
2967+
arm_smmu_disable_iopf(master, master_domain);
2968+
err_free_master_domain:
2969+
kfree(master_domain);
2970+
return ret;
29022971
}
29032972

29042973
/*
@@ -3499,8 +3568,7 @@ static void arm_smmu_release_device(struct device *dev)
34993568
{
35003569
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
35013570

3502-
if (WARN_ON(arm_smmu_master_sva_enabled(master)))
3503-
iopf_queue_remove_device(master->smmu->evtq.iopf, dev);
3571+
WARN_ON(master->iopf_refcount);
35043572

35053573
/* Put the STE back to what arm_smmu_init_strtab() sets */
35063574
if (dev->iommu->require_direct)
@@ -3585,18 +3653,8 @@ static int arm_smmu_dev_enable_feature(struct device *dev,
35853653

35863654
switch (feat) {
35873655
case IOMMU_DEV_FEAT_IOPF:
3588-
if (!arm_smmu_master_iopf_supported(master))
3589-
return -EINVAL;
3590-
if (master->iopf_enabled)
3591-
return -EBUSY;
3592-
master->iopf_enabled = true;
3593-
return 0;
35943656
case IOMMU_DEV_FEAT_SVA:
3595-
if (!arm_smmu_master_sva_supported(master))
3596-
return -EINVAL;
3597-
if (arm_smmu_master_sva_enabled(master))
3598-
return -EBUSY;
3599-
return arm_smmu_master_enable_sva(master);
3657+
return 0;
36003658
default:
36013659
return -EINVAL;
36023660
}
@@ -3612,16 +3670,8 @@ static int arm_smmu_dev_disable_feature(struct device *dev,
36123670

36133671
switch (feat) {
36143672
case IOMMU_DEV_FEAT_IOPF:
3615-
if (!master->iopf_enabled)
3616-
return -EINVAL;
3617-
if (master->sva_enabled)
3618-
return -EBUSY;
3619-
master->iopf_enabled = false;
3620-
return 0;
36213673
case IOMMU_DEV_FEAT_SVA:
3622-
if (!arm_smmu_master_sva_enabled(master))
3623-
return -EINVAL;
3624-
return arm_smmu_master_disable_sva(master);
3674+
return 0;
36253675
default:
36263676
return -EINVAL;
36273677
}

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -837,9 +837,8 @@ struct arm_smmu_master {
837837
bool ats_enabled : 1;
838838
bool ste_ats_enabled : 1;
839839
bool stall_enabled;
840-
bool sva_enabled;
841-
bool iopf_enabled;
842840
unsigned int ssid_bits;
841+
unsigned int iopf_refcount;
843842
};
844843

845844
/* SMMU private data for an IOMMU domain */
@@ -915,8 +914,14 @@ void arm_smmu_make_sva_cd(struct arm_smmu_cd *target,
915914
struct arm_smmu_master_domain {
916915
struct list_head devices_elm;
917916
struct arm_smmu_master *master;
917+
/*
918+
* For nested domains the master_domain is threaded onto the S2 parent,
919+
* this points to the IOMMU_DOMAIN_NESTED to disambiguate the masters.
920+
*/
921+
struct iommu_domain *domain;
918922
ioasid_t ssid;
919923
bool nested_ats_flush : 1;
924+
bool using_iopf : 1;
920925
};
921926

922927
static inline struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
@@ -995,11 +1000,6 @@ int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
9951000

9961001
#ifdef CONFIG_ARM_SMMU_V3_SVA
9971002
bool arm_smmu_sva_supported(struct arm_smmu_device *smmu);
998-
bool arm_smmu_master_sva_supported(struct arm_smmu_master *master);
999-
bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master);
1000-
int arm_smmu_master_enable_sva(struct arm_smmu_master *master);
1001-
int arm_smmu_master_disable_sva(struct arm_smmu_master *master);
1002-
bool arm_smmu_master_iopf_supported(struct arm_smmu_master *master);
10031003
void arm_smmu_sva_notifier_synchronize(void);
10041004
struct iommu_domain *arm_smmu_sva_domain_alloc(struct device *dev,
10051005
struct mm_struct *mm);
@@ -1009,31 +1009,6 @@ static inline bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
10091009
return false;
10101010
}
10111011

1012-
static inline bool arm_smmu_master_sva_supported(struct arm_smmu_master *master)
1013-
{
1014-
return false;
1015-
}
1016-
1017-
static inline bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master)
1018-
{
1019-
return false;
1020-
}
1021-
1022-
static inline int arm_smmu_master_enable_sva(struct arm_smmu_master *master)
1023-
{
1024-
return -ENODEV;
1025-
}
1026-
1027-
static inline int arm_smmu_master_disable_sva(struct arm_smmu_master *master)
1028-
{
1029-
return -ENODEV;
1030-
}
1031-
1032-
static inline bool arm_smmu_master_iopf_supported(struct arm_smmu_master *master)
1033-
{
1034-
return false;
1035-
}
1036-
10371012
static inline void arm_smmu_sva_notifier_synchronize(void) {}
10381013

10391014
#define arm_smmu_sva_domain_alloc NULL

0 commit comments

Comments
 (0)