iommu/arm-smmu-v3: Move ctx_desc out of s1_cfg
authorMichael Shavit <mshavit@google.com>
Fri, 15 Sep 2023 13:17:32 +0000 (21:17 +0800)
committerWill Deacon <will@kernel.org>
Thu, 12 Oct 2023 16:08:16 +0000 (17:08 +0100)
arm_smmu_s1_cfg (and by extension arm_smmu_domain) owns both a CD table
and the CD inserted into that table's non-pasid CD entry. This limits
arm_smmu_domain's ability to represent non-pasid domains, where multiple
domains need to be inserted into a common CD table. Rather than describing
an STE entry (which may have multiple domains installed into it with
PASID), a domain should describe a single CD entry instead. This is
precisely the role of arm_smmu_ctx_desc. A subsequent commit will also
move the CD table outside of arm_smmu_domain.

Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Michael Shavit <mshavit@google.com>
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Link: https://lore.kernel.org/r/20230915211705.v8.1.I67ab103c18d882aedc8a08985af1fba70bca084e@changeid
Signed-off-by: Will Deacon <will@kernel.org>
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

index 8a16cd3ef487cad4d63e8ebfae6f775b7bef3825..9b27fffe2ab95973e044fa614086b225dbd27d9e 100644 (file)
@@ -62,7 +62,7 @@ arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
                return cd;
        }
 
-       smmu_domain = container_of(cd, struct arm_smmu_domain, s1_cfg.cd);
+       smmu_domain = container_of(cd, struct arm_smmu_domain, cd);
        smmu = smmu_domain->smmu;
 
        ret = xa_alloc(&arm_smmu_asid_xa, &new_asid, cd,
index bd0a596f9863a32eb11316822d424ec6349de0ef..b10333d44f9d68a6637ff236479834c31bb2eb9e 100644 (file)
@@ -1869,7 +1869,7 @@ static void arm_smmu_tlb_inv_context(void *cookie)
         * careful, 007.
         */
        if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
-               arm_smmu_tlb_inv_asid(smmu, smmu_domain->s1_cfg.cd.asid);
+               arm_smmu_tlb_inv_asid(smmu, smmu_domain->cd.asid);
        } else {
                cmd.opcode      = CMDQ_OP_TLBI_S12_VMALL;
                cmd.tlbi.vmid   = smmu_domain->s2_cfg.vmid;
@@ -1962,7 +1962,7 @@ static void arm_smmu_tlb_inv_range_domain(unsigned long iova, size_t size,
        if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
                cmd.opcode      = smmu_domain->smmu->features & ARM_SMMU_FEAT_E2H ?
                                  CMDQ_OP_TLBI_EL2_VA : CMDQ_OP_TLBI_NH_VA;
-               cmd.tlbi.asid   = smmu_domain->s1_cfg.cd.asid;
+               cmd.tlbi.asid   = smmu_domain->cd.asid;
        } else {
                cmd.opcode      = CMDQ_OP_TLBI_S2_IPA;
                cmd.tlbi.vmid   = smmu_domain->s2_cfg.vmid;
@@ -2075,7 +2075,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
                mutex_lock(&arm_smmu_asid_lock);
                if (cfg->cdcfg.cdtab)
                        arm_smmu_free_cd_tables(smmu_domain);
-               arm_smmu_free_asid(&cfg->cd);
+               arm_smmu_free_asid(&smmu_domain->cd);
                mutex_unlock(&arm_smmu_asid_lock);
        } else {
                struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg;
@@ -2094,13 +2094,14 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
        u32 asid;
        struct arm_smmu_device *smmu = smmu_domain->smmu;
        struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
+       struct arm_smmu_ctx_desc *cd = &smmu_domain->cd;
        typeof(&pgtbl_cfg->arm_lpae_s1_cfg.tcr) tcr = &pgtbl_cfg->arm_lpae_s1_cfg.tcr;
 
-       refcount_set(&cfg->cd.refs, 1);
+       refcount_set(&cd->refs, 1);
 
        /* Prevent SVA from modifying the ASID until it is written to the CD */
        mutex_lock(&arm_smmu_asid_lock);
-       ret = xa_alloc(&arm_smmu_asid_xa, &asid, &cfg->cd,
+       ret = xa_alloc(&arm_smmu_asid_xa, &asid, cd,
                       XA_LIMIT(1, (1 << smmu->asid_bits) - 1), GFP_KERNEL);
        if (ret)
                goto out_unlock;
@@ -2113,23 +2114,23 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
        if (ret)
                goto out_free_asid;
 
-       cfg->cd.asid    = (u16)asid;
-       cfg->cd.ttbr    = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
-       cfg->cd.tcr     = FIELD_PREP(CTXDESC_CD_0_TCR_T0SZ, tcr->tsz) |
+       cd->asid        = (u16)asid;
+       cd->ttbr        = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
+       cd->tcr         = FIELD_PREP(CTXDESC_CD_0_TCR_T0SZ, tcr->tsz) |
                          FIELD_PREP(CTXDESC_CD_0_TCR_TG0, tcr->tg) |
                          FIELD_PREP(CTXDESC_CD_0_TCR_IRGN0, tcr->irgn) |
                          FIELD_PREP(CTXDESC_CD_0_TCR_ORGN0, tcr->orgn) |
                          FIELD_PREP(CTXDESC_CD_0_TCR_SH0, tcr->sh) |
                          FIELD_PREP(CTXDESC_CD_0_TCR_IPS, tcr->ips) |
                          CTXDESC_CD_0_TCR_EPD1 | CTXDESC_CD_0_AA64;
-       cfg->cd.mair    = pgtbl_cfg->arm_lpae_s1_cfg.mair;
+       cd->mair        = pgtbl_cfg->arm_lpae_s1_cfg.mair;
 
        /*
         * Note that this will end up calling arm_smmu_sync_cd() before
         * the master has been added to the devices list for this domain.
         * This isn't an issue because the STE hasn't been installed yet.
         */
-       ret = arm_smmu_write_ctx_desc(smmu_domain, IOMMU_NO_PASID, &cfg->cd);
+       ret = arm_smmu_write_ctx_desc(smmu_domain, IOMMU_NO_PASID, cd);
        if (ret)
                goto out_free_cd_tables;
 
@@ -2139,7 +2140,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
 out_free_cd_tables:
        arm_smmu_free_cd_tables(smmu_domain);
 out_free_asid:
-       arm_smmu_free_asid(&cfg->cd);
+       arm_smmu_free_asid(cd);
 out_unlock:
        mutex_unlock(&arm_smmu_asid_lock);
        return ret;
index 9915850dd4dbf771981cb378155ef8fee47ab4d6..9389780db1f3484c5e49b05f8ad3928d918be43c 100644 (file)
@@ -599,7 +599,6 @@ struct arm_smmu_ctx_desc_cfg {
 
 struct arm_smmu_s1_cfg {
        struct arm_smmu_ctx_desc_cfg    cdcfg;
-       struct arm_smmu_ctx_desc        cd;
        u8                              s1fmt;
        u8                              s1cdmax;
 };
@@ -724,7 +723,10 @@ struct arm_smmu_domain {
 
        enum arm_smmu_domain_stage      stage;
        union {
-               struct arm_smmu_s1_cfg  s1_cfg;
+               struct {
+               struct arm_smmu_ctx_desc        cd;
+               struct arm_smmu_s1_cfg          s1_cfg;
+               };
                struct arm_smmu_s2_cfg  s2_cfg;
        };