iommu/arm-smmu: sign extend iova for fault handler

The address in the CB's FAR is not sign-extended. With split page tables,
this can cause software page table walk causing warning.

WARNING: CPU: 2 PID: 264 at drivers/iommu/arm-smmu.c:3161 arm_smmu_iova_to_phys+0xfc/0x128
kgsl kgsl-3d0: CP Illegal instruction error
kgsl kgsl-3d0: CP Illegal instruction error
kgsl kgsl-3d0: CP Illegal instruction error
kgsl kgsl-3d0: CP Illegal instruction error
pc : arm_smmu_iova_to_phys+0xfc/0x128
lr : arm_smmu_context_fault+0x188/0xea4

Perform the sign extension in fault handler, as arm_smmu_iova_to_phys()
expects the IOVA to be sign extended.

Fixes: ff4f34660e ("iommu/arm-smmu: Add support for split page table domains")
Change-Id: Iced0b7a518dbc27b2770fdae47bedce4e72cc3c1
Signed-off-by: Prakash Gupta <guptap@codeaurora.org>
This commit is contained in:
Prakash Gupta 2021-05-03 09:57:38 +05:30
commit cb53a68d6a

View file

@ -1361,6 +1361,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
bool fatal_asf = smmu->options & ARM_SMMU_OPT_FATAL_ASF;
phys_addr_t phys_soft;
uint64_t pte;
unsigned int ias = smmu_domain->pgtbl_info[0].pgtbl_cfg.ias;
bool non_fatal_fault = test_bit(DOMAIN_ATTR_NON_FATAL_FAULTS,
smmu_domain->attributes);
@ -1399,6 +1400,16 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
flags |= IOMMU_FAULT_TRANSACTION_STALLED;
iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
/*
* The address in the CB's FAR is not sign-extended, so lets perform the
* sign extension here, as arm_smmu_iova_to_phys() expects the
* IOVA to be sign extended.
*/
if ((iova & BIT_ULL(ias)) &&
(test_bit(DOMAIN_ATTR_SPLIT_TABLES, smmu_domain->attributes)))
iova |= GENMASK_ULL(63, ias + 1);
phys_soft = arm_smmu_iova_to_phys(domain, iova);
frsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx));
tmp = report_iommu_fault(domain, smmu->dev, iova, flags);