To allow nested stage support, we need to store both
stage 1 and stage 2 configurations (and remove the former
union).

arm_smmu_write_strtab_ent() is modified to write both stage
fields in the STE.

We add a bypass field to the S1 configuration as the first
stage can be bypassed.

Only S2 stage is "finalized" as the host does not configure
S1 CD, guest does.

Signed-off-by: Eric Auger <[email protected]>
---
 drivers/iommu/arm-smmu-v3.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 19c085d..3a33979 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -496,6 +496,7 @@ struct arm_smmu_strtab_l1_desc {
 struct arm_smmu_s1_cfg {
        __le64                          *cdptr;
        dma_addr_t                      cdptr_dma;
+       bool bypass;
 
        struct arm_smmu_ctx_desc {
                u16     asid;
@@ -617,10 +618,8 @@ struct arm_smmu_domain {
        struct io_pgtable_ops           *pgtbl_ops;
 
        enum arm_smmu_domain_stage      stage;
-       union {
-               struct arm_smmu_s1_cfg  s1_cfg;
-               struct arm_smmu_s2_cfg  s2_cfg;
-       };
+       struct arm_smmu_s1_cfg  s1_cfg;
+       struct arm_smmu_s2_cfg  s2_cfg;
 
        struct iommu_domain             domain;
 
@@ -1107,6 +1106,7 @@ static void arm_smmu_write_strtab_ent(struct 
arm_smmu_device *smmu, u32 sid,
                        break;
                case STRTAB_STE_0_CFG_S1_TRANS:
                case STRTAB_STE_0_CFG_S2_TRANS:
+               case STRTAB_STE_0_CFG_S1_TRANS | STRTAB_STE_0_CFG_S2_TRANS:
                        ste_live = true;
                        break;
                case STRTAB_STE_0_CFG_ABORT:
@@ -1141,7 +1141,6 @@ static void arm_smmu_write_strtab_ent(struct 
arm_smmu_device *smmu, u32 sid,
        }
 
        if (ste->s1_cfg) {
-               BUG_ON(ste_live);
                dst[1] = cpu_to_le64(
                         FIELD_PREP(STRTAB_STE_1_S1CIR, 
STRTAB_STE_1_S1C_CACHE_WBRA) |
                         FIELD_PREP(STRTAB_STE_1_S1COR, 
STRTAB_STE_1_S1C_CACHE_WBRA) |
@@ -1155,12 +1154,12 @@ static void arm_smmu_write_strtab_ent(struct 
arm_smmu_device *smmu, u32 sid,
                   !(smmu->features & ARM_SMMU_FEAT_STALL_FORCE))
                        dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD);
 
-               val |= (ste->s1_cfg->cdptr_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
-                       FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS);
+               if (!ste->s1_cfg->bypass)
+                       val |= (ste->s1_cfg->cdptr_dma & 
STRTAB_STE_0_S1CTXPTR_MASK) |
+                               FIELD_PREP(STRTAB_STE_0_CFG, 
STRTAB_STE_0_CFG_S1_TRANS);
        }
 
        if (ste->s2_cfg) {
-               BUG_ON(ste_live);
                dst[2] = cpu_to_le64(
                         FIELD_PREP(STRTAB_STE_2_S2VMID, ste->s2_cfg->vmid) |
                         FIELD_PREP(STRTAB_STE_2_VTCR, ste->s2_cfg->vtcr) |
@@ -1399,6 +1398,10 @@ static void arm_smmu_tlb_inv_context(void *cookie)
                cmd.opcode      = CMDQ_OP_TLBI_NH_ASID;
                cmd.tlbi.asid   = smmu_domain->s1_cfg.cd.asid;
                cmd.tlbi.vmid   = 0;
+       } else if (smmu_domain->stage == ARM_SMMU_DOMAIN_NESTED) {
+               cmd.opcode      = CMDQ_OP_TLBI_NH_ASID;
+               cmd.tlbi.asid   = smmu_domain->s1_cfg.cd.asid;
+               cmd.tlbi.vmid   = smmu_domain->s2_cfg.vmid;
        } else {
                cmd.opcode      = CMDQ_OP_TLBI_S12_VMALL;
                cmd.tlbi.vmid   = smmu_domain->s2_cfg.vmid;
@@ -1423,6 +1426,10 @@ static void arm_smmu_tlb_inv_range_nosync(unsigned long 
iova, size_t size,
        if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
                cmd.opcode      = CMDQ_OP_TLBI_NH_VA;
                cmd.tlbi.asid   = smmu_domain->s1_cfg.cd.asid;
+       } else if (smmu_domain->stage == ARM_SMMU_DOMAIN_NESTED) {
+               cmd.opcode      = CMDQ_OP_TLBI_NH_VA;
+               cmd.tlbi.asid   = smmu_domain->s1_cfg.cd.asid;
+               cmd.tlbi.vmid   = smmu_domain->s2_cfg.vmid;
        } else {
                cmd.opcode      = CMDQ_OP_TLBI_S2_IPA;
                cmd.tlbi.vmid   = smmu_domain->s2_cfg.vmid;
-- 
2.5.5

_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to