From: Jeremy Gebben Date: Fri, 10 Jul 2015 22:43:22 +0000 (-0600) Subject: iommu/arm-smmu: add support for TTBR0, CONTEXTIDR and PROCID attributes X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=930d3bcb94eeff1773bccf221274b110d9517fb6;p=sagit-ice-cold%2Fkernel_xiaomi_msm8998.git iommu/arm-smmu: add support for TTBR0, CONTEXTIDR and PROCID attributes 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 --- diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index d669888b768c..945724dcdd0a 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -194,6 +194,7 @@ #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; }