Skip to content

Commit 12dacfb

Browse files
jgunthorpewilldeacon
authored andcommitted
iommu/arm-smmu-v3: Add a global static IDENTITY domain
Move to the new static global for identity domains. Move all the logic out of arm_smmu_attach_dev into an identity only function. Reviewed-by: Michael Shavit <[email protected]> Reviewed-by: Nicolin Chen <[email protected]> Tested-by: Shameer Kolothum <[email protected]> Tested-by: Nicolin Chen <[email protected]> Tested-by: Moritz Fischer <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent ae91f65 commit 12dacfb

File tree

2 files changed

+58
-25
lines changed

2 files changed

+58
-25
lines changed

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

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,8 +2200,7 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
22002200
return arm_smmu_sva_domain_alloc();
22012201

22022202
if (type != IOMMU_DOMAIN_UNMANAGED &&
2203-
type != IOMMU_DOMAIN_DMA &&
2204-
type != IOMMU_DOMAIN_IDENTITY)
2203+
type != IOMMU_DOMAIN_DMA)
22052204
return NULL;
22062205

22072206
/*
@@ -2309,11 +2308,6 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
23092308
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
23102309
struct arm_smmu_device *smmu = smmu_domain->smmu;
23112310

2312-
if (domain->type == IOMMU_DOMAIN_IDENTITY) {
2313-
smmu_domain->stage = ARM_SMMU_DOMAIN_BYPASS;
2314-
return 0;
2315-
}
2316-
23172311
/* Restrict the stage to what we can actually support */
23182312
if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S1))
23192313
smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
@@ -2511,7 +2505,7 @@ static void arm_smmu_detach_dev(struct arm_smmu_master *master)
25112505
struct arm_smmu_domain *smmu_domain;
25122506
unsigned long flags;
25132507

2514-
if (!domain)
2508+
if (!domain || !(domain->type & __IOMMU_DOMAIN_PAGING))
25152509
return;
25162510

25172511
smmu_domain = to_smmu_domain(domain);
@@ -2574,15 +2568,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
25742568

25752569
arm_smmu_detach_dev(master);
25762570

2577-
/*
2578-
* The SMMU does not support enabling ATS with bypass. When the STE is
2579-
* in bypass (STE.Config[2:0] == 0b100), ATS Translation Requests and
2580-
* Translated transactions are denied as though ATS is disabled for the
2581-
* stream (STE.EATS == 0b00), causing F_BAD_ATS_TREQ and
2582-
* F_TRANSL_FORBIDDEN events (IHI0070Ea 5.2 Stream Table Entry).
2583-
*/
2584-
if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS)
2585-
master->ats_enabled = arm_smmu_ats_supported(master);
2571+
master->ats_enabled = arm_smmu_ats_supported(master);
25862572

25872573
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
25882574
list_add(&master->domain_head, &smmu_domain->devices);
@@ -2619,13 +2605,6 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
26192605
arm_smmu_write_ctx_desc(master, IOMMU_NO_PASID,
26202606
NULL);
26212607
break;
2622-
case ARM_SMMU_DOMAIN_BYPASS:
2623-
arm_smmu_make_bypass_ste(&target);
2624-
arm_smmu_install_ste_for_dev(master, &target);
2625-
if (master->cd_table.cdtab)
2626-
arm_smmu_write_ctx_desc(master, IOMMU_NO_PASID,
2627-
NULL);
2628-
break;
26292608
}
26302609

26312610
arm_smmu_enable_ats(master, smmu_domain);
@@ -2641,6 +2620,60 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
26412620
return ret;
26422621
}
26432622

2623+
static int arm_smmu_attach_dev_ste(struct device *dev,
2624+
struct arm_smmu_ste *ste)
2625+
{
2626+
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
2627+
2628+
if (arm_smmu_master_sva_enabled(master))
2629+
return -EBUSY;
2630+
2631+
/*
2632+
* Do not allow any ASID to be changed while are working on the STE,
2633+
* otherwise we could miss invalidations.
2634+
*/
2635+
mutex_lock(&arm_smmu_asid_lock);
2636+
2637+
/*
2638+
* The SMMU does not support enabling ATS with bypass/abort. When the
2639+
* STE is in bypass (STE.Config[2:0] == 0b100), ATS Translation Requests
2640+
* and Translated transactions are denied as though ATS is disabled for
2641+
* the stream (STE.EATS == 0b00), causing F_BAD_ATS_TREQ and
2642+
* F_TRANSL_FORBIDDEN events (IHI0070Ea 5.2 Stream Table Entry).
2643+
*/
2644+
arm_smmu_detach_dev(master);
2645+
2646+
arm_smmu_install_ste_for_dev(master, ste);
2647+
mutex_unlock(&arm_smmu_asid_lock);
2648+
2649+
/*
2650+
* This has to be done after removing the master from the
2651+
* arm_smmu_domain->devices to avoid races updating the same context
2652+
* descriptor from arm_smmu_share_asid().
2653+
*/
2654+
if (master->cd_table.cdtab)
2655+
arm_smmu_write_ctx_desc(master, IOMMU_NO_PASID, NULL);
2656+
return 0;
2657+
}
2658+
2659+
static int arm_smmu_attach_dev_identity(struct iommu_domain *domain,
2660+
struct device *dev)
2661+
{
2662+
struct arm_smmu_ste ste;
2663+
2664+
arm_smmu_make_bypass_ste(&ste);
2665+
return arm_smmu_attach_dev_ste(dev, &ste);
2666+
}
2667+
2668+
static const struct iommu_domain_ops arm_smmu_identity_ops = {
2669+
.attach_dev = arm_smmu_attach_dev_identity,
2670+
};
2671+
2672+
static struct iommu_domain arm_smmu_identity_domain = {
2673+
.type = IOMMU_DOMAIN_IDENTITY,
2674+
.ops = &arm_smmu_identity_ops,
2675+
};
2676+
26442677
static int arm_smmu_map_pages(struct iommu_domain *domain, unsigned long iova,
26452678
phys_addr_t paddr, size_t pgsize, size_t pgcount,
26462679
int prot, gfp_t gfp, size_t *mapped)
@@ -3030,6 +3063,7 @@ static void arm_smmu_remove_dev_pasid(struct device *dev, ioasid_t pasid)
30303063
}
30313064

30323065
static struct iommu_ops arm_smmu_ops = {
3066+
.identity_domain = &arm_smmu_identity_domain,
30333067
.capable = arm_smmu_capable,
30343068
.domain_alloc = arm_smmu_domain_alloc,
30353069
.probe_device = arm_smmu_probe_device,

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,6 @@ struct arm_smmu_master {
712712
enum arm_smmu_domain_stage {
713713
ARM_SMMU_DOMAIN_S1 = 0,
714714
ARM_SMMU_DOMAIN_S2,
715-
ARM_SMMU_DOMAIN_BYPASS,
716715
};
717716

718717
struct arm_smmu_domain {

0 commit comments

Comments
 (0)