iommu/arm-smmu: add option to enable static context bank allocation
To implement slave side protection, programming of global registers as well as secure context bank registers is handed over to TZ. Now, instead of dynamically allocating context banks, TZ allocates CBs once in pre defined static manner during boot and this allocation is maintained throughout the life of system. Add an option to enable use of this pre-defined context bank allocation. We would be reading through SMR and S2CR registers at run time to identify CB allocated for a particular sid. CRs-Fixed: 959535 Change-Id: I782470a2e4d2a66be17ed2b965ba52b7917592f6 Signed-off-by: Susheel Khiani <skhiani@codeaurora.org>
This commit is contained in:
parent
c4db2e1dec
commit
b3d402012c
2 changed files with 71 additions and 6 deletions
|
@ -124,6 +124,15 @@ conditions.
|
|||
a call back notifier on regulators in whcih SMMU can be halted
|
||||
or resumed when regulator is powered down/up.
|
||||
|
||||
- qcom,enable-static-cb : Enables option to use pre-defined static context bank
|
||||
allocation programmed by TZ. Global register including SMR and
|
||||
S2CR registers are configured by TZ before kernel comes up and
|
||||
this programming is not altered throughout the life of system.
|
||||
We would be reading through these registers at run time to
|
||||
identify CB allocated for a particular sid. SID masking isn't
|
||||
supported as we are directly comparing client SID with ID bits
|
||||
of SMR registers.
|
||||
|
||||
- clocks : List of clocks to be used during SMMU register access. See
|
||||
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
for information about the format. For each clock specified
|
||||
|
|
|
@ -363,6 +363,7 @@ struct arm_smmu_device {
|
|||
#define ARM_SMMU_OPT_NO_SMR_CHECK (1 << 9)
|
||||
#define ARM_SMMU_OPT_DYNAMIC (1 << 10)
|
||||
#define ARM_SMMU_OPT_HALT (1 << 11)
|
||||
#define ARM_SMMU_OPT_STATIC_CB (1 << 12)
|
||||
u32 options;
|
||||
enum arm_smmu_arch_version version;
|
||||
|
||||
|
@ -481,6 +482,7 @@ static struct arm_smmu_option_prop arm_smmu_options[] = {
|
|||
{ ARM_SMMU_OPT_NO_SMR_CHECK, "qcom,no-smr-check" },
|
||||
{ ARM_SMMU_OPT_DYNAMIC, "qcom,dynamic" },
|
||||
{ ARM_SMMU_OPT_HALT, "qcom,enable-smmu-halt"},
|
||||
{ ARM_SMMU_OPT_STATIC_CB, "qcom,enable-static-cb"},
|
||||
{ 0, NULL},
|
||||
};
|
||||
|
||||
|
@ -504,7 +506,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu);
|
|||
static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
|
||||
size_t size);
|
||||
static bool arm_smmu_is_master_side_secure(struct arm_smmu_domain *smmu_domain);
|
||||
|
||||
static bool arm_smmu_is_static_cb(struct arm_smmu_device *smmu);
|
||||
|
||||
static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
|
||||
{
|
||||
|
@ -1453,6 +1455,11 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
|
|||
writel_relaxed(reg, cb_base + ARM_SMMU_CB_SCTLR);
|
||||
}
|
||||
|
||||
static bool arm_smmu_is_static_cb(struct arm_smmu_device *smmu)
|
||||
{
|
||||
return smmu->options & ARM_SMMU_OPT_STATIC_CB;
|
||||
}
|
||||
|
||||
static bool arm_smmu_is_master_side_secure(struct arm_smmu_domain *smmu_domain)
|
||||
{
|
||||
return smmu_domain->secure_vmid != VMID_INVAL;
|
||||
|
@ -1537,12 +1544,17 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
|
||||
smmu->num_context_banks);
|
||||
if (IS_ERR_VALUE(ret))
|
||||
goto out;
|
||||
if (cfg->cbndx == INVALID_CBNDX) {
|
||||
ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
|
||||
smmu->num_context_banks);
|
||||
if (IS_ERR_VALUE(ret))
|
||||
goto out;
|
||||
cfg->cbndx = ret;
|
||||
} else {
|
||||
if (test_and_set_bit(cfg->cbndx, smmu->context_map))
|
||||
goto out;
|
||||
}
|
||||
|
||||
cfg->cbndx = ret;
|
||||
if (smmu->version == ARM_SMMU_V1) {
|
||||
cfg->irptndx = atomic_inc_return(&smmu->irptndx);
|
||||
cfg->irptndx %= smmu->num_context_irqs;
|
||||
|
@ -1917,6 +1929,40 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int arm_smmu_populate_cb(struct arm_smmu_device *smmu,
|
||||
struct arm_smmu_domain *smmu_domain, struct device *dev)
|
||||
{
|
||||
void __iomem *gr0_base;
|
||||
struct arm_smmu_master_cfg *cfg;
|
||||
struct arm_smmu_cfg *smmu_cfg = &smmu_domain->cfg;
|
||||
int i;
|
||||
u32 sid;
|
||||
|
||||
gr0_base = ARM_SMMU_GR0(smmu);
|
||||
cfg = find_smmu_master_cfg(dev);
|
||||
|
||||
if (!cfg)
|
||||
return -ENODEV;
|
||||
|
||||
sid = cfg->streamids[0];
|
||||
|
||||
for (i = 0; i < smmu->num_mapping_groups; i++) {
|
||||
u32 smr, s2cr;
|
||||
u8 cbndx;
|
||||
|
||||
smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(i));
|
||||
|
||||
if (sid == ((smr >> SMR_ID_SHIFT) & SMR_ID_MASK)) {
|
||||
s2cr = readl_relaxed(gr0_base + ARM_SMMU_GR0_S2CR(i));
|
||||
cbndx = (s2cr >> S2CR_CBNDX_SHIFT) & S2CR_CBNDX_MASK;
|
||||
smmu_cfg->cbndx = cbndx;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
@ -1975,6 +2021,16 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
|
|||
}
|
||||
smmu->attach_count++;
|
||||
|
||||
if (arm_smmu_is_static_cb(smmu)) {
|
||||
ret = arm_smmu_populate_cb(smmu, smmu_domain, dev);
|
||||
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get valid context bank\n");
|
||||
goto err_disable_clocks;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Ensure that the domain is finalised */
|
||||
ret = arm_smmu_init_domain_context(domain, smmu);
|
||||
if (IS_ERR_VALUE(ret))
|
||||
|
|
Loading…
Add table
Reference in a new issue