iommu/arm-smmu: Implement .trigger_fault
In order to facilitate debugging and development, implement the
.trigger_fault method from iommu_ops. This can be done on ARM SMMUv2 by
writing to the FSRRESTORE register. Do it.
Change-Id: Ia8339b54fbb9263d8cf23ff61c4615122316729a
Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 28a1737..3d4a812 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -225,6 +225,7 @@
#define ARM_SMMU_CB_S1_MAIR1 0x3c
#define ARM_SMMU_CB_PAR 0x50
#define ARM_SMMU_CB_FSR 0x58
+#define ARM_SMMU_CB_FSRRESTORE 0x5c
#define ARM_SMMU_CB_FAR 0x60
#define ARM_SMMU_CB_FSYNR0 0x68
#define ARM_SMMU_CB_S1_TLBIVA 0x600
@@ -1973,6 +1974,27 @@
return ret;
}
+static void arm_smmu_trigger_fault(struct iommu_domain *domain,
+ unsigned long flags)
+{
+ struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
+ struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+ struct arm_smmu_device *smmu;
+ void __iomem *cb_base;
+
+ if (!smmu_domain->smmu) {
+ pr_err("Can't trigger faults on non-attached domains\n");
+ return;
+ }
+
+ smmu = smmu_domain->smmu;
+
+ cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
+ dev_err(smmu->dev, "Writing 0x%lx to FSRRESTORE on cb %d\n",
+ flags, cfg->cbndx);
+ writel_relaxed(flags, cb_base + ARM_SMMU_CB_FSRRESTORE);
+}
+
static struct iommu_ops arm_smmu_ops = {
.capable = arm_smmu_capable,
.domain_alloc = arm_smmu_domain_alloc,
@@ -1990,6 +2012,7 @@
.domain_get_attr = arm_smmu_domain_get_attr,
.domain_set_attr = arm_smmu_domain_set_attr,
.pgsize_bitmap = -1UL, /* Restricted during device attach */
+ .trigger_fault = arm_smmu_trigger_fault,
};
static int arm_smmu_wait_for_halt(struct arm_smmu_device *smmu)