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:
parent
ee954ddc28
commit
930d3bcb94
1 changed files with 51 additions and 2 deletions
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue