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 <jgebben@codeaurora.org>
This commit is contained in:
Jeremy Gebben 2015-07-10 16:43:22 -06:00 committed by David Keitel
parent ee954ddc28
commit 930d3bcb94

View file

@ -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;
}