Messages in this thread Patch in this message | ![/](/images/icornerl.gif) | | Subject | Re: [PATCH] iommu/arm-smmu-qcom: Fix mask extraction for bootloader programmed SMRs | From | Robin Murphy <> | Date | Tue, 26 Jan 2021 10:34:31 +0000 |
| |
On 2021-01-25 21:52, Isaac J. Manjarres wrote: > When extracting the mask for a SMR that was programmed by the > bootloader, the SMR's valid bit is also extracted and is treated > as part of the mask, which is not correct. Consider the scenario > where an SMMU master whose context is determined by a bootloader > programmed SMR is removed (omitting parts of device/driver core): > > ->iommu_release_device() > -> arm_smmu_release_device() > -> arm_smmu_master_free_smes() > -> arm_smmu_free_sme() /* Assume that the SME is now free */ > -> arm_smmu_write_sme() > -> arm_smmu_write_smr() /* Construct SMR value using mask and SID */ > > Since the valid bit was considered as part of the mask, the SMR will > be programmed as valid.
Ah, right, because ARM_SMMU_SMR_{ID,MASK} are 16-bit fields to accommodate EXIDS, which doesn't matter normally when the IDs are strictly validated in arm_smmu_probe_device()...
> Fix the SMR mask extraction step for bootloader programmed SMRs > by masking out the valid bit when we know that we're already > working with a valid SMR.
This seems like the neatest approach to me.
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
> Fixes: 07a7f2caaa5a ("iommu/arm-smmu-qcom: Read back stream mappings") > Signed-off-by: Isaac J. Manjarres <isaacm@codeaurora.org> > Cc: stable@vger.kernel.org > --- > drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c > index bcda170..abb1d2f 100644 > --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c > @@ -206,6 +206,8 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu) > smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(i)); > > if (FIELD_GET(ARM_SMMU_SMR_VALID, smr)) { > + /* Ignore valid bit for SMR mask extraction. */ > + smr &= ~ARM_SMMU_SMR_VALID; > smmu->smrs[i].id = FIELD_GET(ARM_SMMU_SMR_ID, smr); > smmu->smrs[i].mask = FIELD_GET(ARM_SMMU_SMR_MASK, smr); > smmu->smrs[i].valid = true; >
| ![\](/images/icornerr.gif) |