Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cb53a68d authored by Prakash Gupta's avatar Prakash Gupta
Browse files

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: ff4f3466 ("iommu/arm-smmu: Add support for split page table domains")
Change-Id: Iced0b7a518dbc27b2770fdae47bedce4e72cc3c1
Signed-off-by: default avatarPrakash Gupta <guptap@codeaurora.org>
parent 2bbcc098
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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);