OSDN Git Service

iommu/arm-smmu: add support for TTBR0, CONTEXTIDR and PROCID attributes
authorJeremy Gebben <jgebben@codeaurora.org>
Fri, 10 Jul 2015 22:43:22 +0000 (16:43 -0600)
committerDavid Keitel <dkeitel@codeaurora.org>
Tue, 22 Mar 2016 18:13:36 +0000 (11:13 -0700)
Add fields to arm_smmu_cfg to store asid, vmid, and procid so that they
can queried easily.

Program the CONTEXTIDR register during attach so that the PROCID
attribute functions as expected.

Change-Id: I2e2b3926fbf021754e89edda9a6857d2e3a7138b
Signed-off-by: Jeremy Gebben <jgebben@codeaurora.org>
drivers/iommu/arm-smmu.c

index d669888..945724d 100644 (file)
 #define ARM_SMMU_CB_TTBR1_LO           0x28
 #define ARM_SMMU_CB_TTBR1_HI           0x2c
 #define ARM_SMMU_CB_TTBCR              0x30
+#define ARM_SMMU_CB_CONTEXTIDR         0x34
 #define ARM_SMMU_CB_S1_MAIR0           0x38
 #define ARM_SMMU_CB_S1_MAIR1           0x3c
 #define ARM_SMMU_CB_PAR_LO             0x50
@@ -405,11 +406,17 @@ struct arm_smmu_cfg {
        u8                              cbndx;
        u8                              irptndx;
        u32                             cbar;
+       u32                             procid;
+       u16                             asid;
+       u8                              vmid;
 };
 #define INVALID_IRPTNDX                        0xff
+#define INVALID_CBNDX                  0xff
+#define INVALID_ASID                   0xffff
+#define INVALID_VMID                   0xff
 
-#define ARM_SMMU_CB_ASID(cfg)          ((cfg)->cbndx + 1)
-#define ARM_SMMU_CB_VMID(cfg)          ((cfg)->cbndx + 2)
+#define ARM_SMMU_CB_ASID(cfg)          ((cfg)->asid)
+#define ARM_SMMU_CB_VMID(cfg)          ((cfg)->vmid)
 
 enum arm_smmu_domain_stage {
        ARM_SMMU_DOMAIN_S1 = 0,
@@ -1378,6 +1385,8 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
                .tlb            = &arm_smmu_gather_ops,
        };
 
+       cfg->asid = cfg->cbndx + 1;
+       cfg->vmid = cfg->cbndx + 2;
        smmu_domain->smmu = smmu;
        pgtbl_ops = alloc_io_pgtable_ops(fmt, &smmu_domain->pgtbl_cfg,
                                         smmu_domain);
@@ -1463,6 +1472,11 @@ static int arm_smmu_domain_init(struct iommu_domain *domain)
        /* disable coherent htw by default */
        smmu_domain->attributes = (1 << DOMAIN_ATTR_COHERENT_HTW_DISABLE);
        INIT_LIST_HEAD(&smmu_domain->pte_info_list);
+       smmu_domain->cfg.cbndx = INVALID_CBNDX;
+       smmu_domain->cfg.irptndx = INVALID_IRPTNDX;
+       smmu_domain->cfg.asid = INVALID_ASID;
+       smmu_domain->cfg.vmid = INVALID_VMID;
+
        mutex_init(&smmu_domain->init_mutex);
        spin_lock_init(&smmu_domain->pgtbl_lock);
        domain->priv = smmu_domain;
@@ -2165,6 +2179,31 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain,
                *((unsigned int *) data) = smmu_domain->cfg.cbndx;
                ret = 0;
                break;
+       case DOMAIN_ATTR_TTBR0: {
+               u64 val;
+               /* not valid until we are attached */
+               if (smmu_domain->smmu == NULL)
+                       return -ENODEV;
+
+               val = smmu_domain->pgtbl_cfg.arm_lpae_s1_cfg.ttbr[0];
+               if (smmu_domain->cfg.cbar != CBAR_TYPE_S2_TRANS)
+                       val |= (u64)ARM_SMMU_CB_ASID(&smmu_domain->cfg)
+                                       << (32ULL + TTBRn_HI_ASID_SHIFT);
+               *((u64 *)data) = val;
+               ret = 0;
+               break;
+       }
+       case DOMAIN_ATTR_CONTEXTIDR:
+               /* not valid until attached */
+               if (smmu_domain->smmu == NULL)
+                       return -ENODEV;
+               *((u32 *)data) = smmu_domain->cfg.procid;
+               ret = 0;
+               break;
+       case DOMAIN_ATTR_PROCID:
+               *((u32 *)data) = smmu_domain->cfg.procid;
+               ret = 0;
+               break;
        default:
                ret = -ENODEV;
                break;
@@ -2229,6 +2268,16 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain,
                        smmu_domain->attributes &= ~(1 << DOMAIN_ATTR_ATOMIC);
                break;
        }
+       case DOMAIN_ATTR_PROCID:
+               if (smmu_domain->smmu != NULL) {
+                       dev_err(smmu_domain->smmu->dev,
+                         "cannot change procid attribute while attached\n");
+                       ret = -EBUSY;
+                       break;
+               }
+               smmu_domain->cfg.procid = *((u32 *)data);
+               ret = 0;
+               break;
        default:
                ret = -ENODEV;
        }