mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-12 15:49:17 -04:00
iommu: arm-smmu: Fail device attach when SMR write fails
On systems with Hypervisor support, writes to SMR registers are trapped by Hypervisor where the value is vetted and gets written to the SMR register only if valid. If such SMR writes fails, the SID value doesn't get populated to the stream mapping table, and any device transaction would lead to USF which would crash the system. Hence, to avoid any USF fault, fail the device attach sequence. Change-Id: I1435c7aa8290d7c2916cc86cc30cfa1cefae3910 Signed-off-by: Sudarshan Rajagopalan <sudaraja@codeaurora.org> Signed-off-by: Prakash Gupta <guptap@codeaurora.org>
This commit is contained in:
parent
4cf5de7504
commit
e49e9c98bd
1 changed files with 26 additions and 4 deletions
|
|
@ -2392,14 +2392,30 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
|
|||
kfree(smmu_domain);
|
||||
}
|
||||
|
||||
static void arm_smmu_write_smr(struct arm_smmu_device *smmu, int idx)
|
||||
static int arm_smmu_write_smr(struct arm_smmu_device *smmu, int idx)
|
||||
{
|
||||
struct arm_smmu_smr *smr = smmu->smrs + idx;
|
||||
u32 reg = FIELD_PREP(SMR_ID, smr->id) | FIELD_PREP(SMR_MASK, smr->mask);
|
||||
u32 val;
|
||||
|
||||
if (!(smmu->features & ARM_SMMU_FEAT_EXIDS) && smr->valid)
|
||||
reg |= SMR_VALID;
|
||||
arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_SMR(idx), reg);
|
||||
|
||||
/*
|
||||
* Check if the write went properly. If failed, we would have to fail
|
||||
* the attach sequence to avoid any USF faults being generated in the
|
||||
* future due to device transactions, since this SID entry would not
|
||||
* be present in the stream mapping table.
|
||||
*/
|
||||
val = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(idx));
|
||||
if (val != reg) {
|
||||
dev_err(smmu->dev, "SMR[%d] write err write:0x%lx, read:0x%lx\n",
|
||||
idx, reg, val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void arm_smmu_write_s2cr(struct arm_smmu_device *smmu, int idx)
|
||||
|
|
@ -2416,11 +2432,14 @@ static void arm_smmu_write_s2cr(struct arm_smmu_device *smmu, int idx)
|
|||
arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_S2CR(idx), reg);
|
||||
}
|
||||
|
||||
static void arm_smmu_write_sme(struct arm_smmu_device *smmu, int idx)
|
||||
static int arm_smmu_write_sme(struct arm_smmu_device *smmu, int idx)
|
||||
{
|
||||
arm_smmu_write_s2cr(smmu, idx);
|
||||
if (smmu->smrs)
|
||||
arm_smmu_write_smr(smmu, idx);
|
||||
if (arm_smmu_write_smr(smmu, idx))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2674,7 +2693,10 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
|
|||
s2cr[idx].type = type;
|
||||
s2cr[idx].privcfg = S2CR_PRIVCFG_DEFAULT;
|
||||
s2cr[idx].cbndx = cbndx;
|
||||
arm_smmu_write_sme(smmu, idx);
|
||||
if (arm_smmu_write_sme(smmu, idx)) {
|
||||
mutex_unlock(&smmu->stream_map_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&smmu->stream_map_mutex);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue