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

Commit f715a4c1 authored by Isaac J. Manjarres's avatar Isaac J. Manjarres
Browse files

iommu/arm-smmu: Add support for implementation specific debugging



Certain SMMU implementation, such as the QSMMUV500 model, have
hardware that can be used to collect information that is useful
for debugging adversarial scenarios, such as TLB sync timeouts.

Add support for collecting information for debugging TLB sync
timeouts, as well as triggering the SMMU HW to perform a
translation for verification purpose, and wire up the QSMMUV500
implementations of these hooks. In doing so, there are no
users of the iova_to_phys_hard() and tlb_sync_timeout() hooks
in the arm_smmu_arch_ops structure, so remove these fields.

Change-Id: I61df57e82f3058a7e8a09f4df1fe147a71ae2fc3
Signed-off-by: default avatarIsaac J. Manjarres <isaacm@codeaurora.org>
parent 1189ad27
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -851,15 +851,15 @@ static int qsmmuv500_cfg_probe(struct arm_smmu_device *smmu)
}

struct arm_smmu_arch_ops qsmmuv500_arch_ops = {
	.iova_to_phys_hard = qsmmuv500_iova_to_phys_hard,
	.device_group = qsmmuv500_device_group,
	.tlb_sync_timeout = qsmmuv500_tlb_sync_timeout,
	.device_remove = qsmmuv500_device_remove,
};

static const struct arm_smmu_impl qsmmuv500_impl = {
	.cfg_probe = qsmmuv500_cfg_probe,
	.init_context_bank = qsmmuv500_init_cb,
	.iova_to_phys_hard = qsmmuv500_iova_to_phys_hard,
	.tlb_sync_timeout = qsmmuv500_tlb_sync_timeout,
};

struct arm_smmu_device *qsmmuv500_impl_init(struct arm_smmu_device *smmu)
+5 −15
Original line number Diff line number Diff line
@@ -363,15 +363,6 @@ static int arm_smmu_arch_device_group(struct device *dev,
	return smmu->arch_ops->device_group(dev, group);
}

static void arm_smmu_arch_tlb_sync_timeout(struct arm_smmu_device *smmu)
{
	if (!smmu->arch_ops || !smmu->arch_ops->tlb_sync_timeout)
		return;

	smmu->arch_ops->tlb_sync_timeout(smmu);
}


static void arm_smmu_arch_device_remove(struct arm_smmu_device *smmu)
{
	if (!smmu->arch_ops)
@@ -854,8 +845,8 @@ static int __arm_smmu_tlb_sync(struct arm_smmu_device *smmu, int page,
		goto out;

	trace_tlbsync_timeout(smmu->dev, 0);
	arm_smmu_arch_tlb_sync_timeout(smmu);

	if (smmu->impl && smmu->impl->tlb_sync_timeout)
		smmu->impl->tlb_sync_timeout(smmu);
out:
	return -EINVAL;
}
@@ -3150,10 +3141,9 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
	if (arm_smmu_power_on(smmu_domain->smmu->pwr))
		return 0;

	if (smmu_domain->smmu->arch_ops &&
	    smmu_domain->smmu->arch_ops->iova_to_phys_hard) {
		ret = smmu_domain->smmu->arch_ops->iova_to_phys_hard(
						smmu_domain, iova, trans_flags);
	if (smmu->impl && smmu->impl->iova_to_phys_hard) {
		ret = smmu->impl->iova_to_phys_hard(smmu_domain, iova,
						    trans_flags);
		goto out;
	}

+4 −13
Original line number Diff line number Diff line
@@ -504,6 +504,10 @@ struct arm_smmu_impl {
	int (*init_context)(struct arm_smmu_domain *smmu_domain);
	void (*init_context_bank)(struct arm_smmu_domain *smmu_domain,
				  struct device *dev);
	phys_addr_t (*iova_to_phys_hard)(struct arm_smmu_domain *smmu_domain,
					 dma_addr_t iova,
					 unsigned long trans_flags);
	void (*tlb_sync_timeout)(struct arm_smmu_device *smmu);
};

static inline void __iomem *arm_smmu_page(struct arm_smmu_device *smmu, int n)
@@ -568,28 +572,15 @@ static inline void arm_smmu_writeq(struct arm_smmu_device *smmu, int page,
	arm_smmu_writeq((s), ARM_SMMU_CB((s), (n)), (o), (v))

/*
 * iova_to_phys_hard()
 * Provides debug information. May be called from the context fault irq handler.
 *
 * device_group()
 * Hook for checking whether a device is compatible with a said group.
 *
 * tlb_sync_timeout()
 * Hook for performing architecture-specific procedures to collect additional
 * debugging information on a TLB sync timeout.
 *
 * device_remove()
 * Hook for performing architecture-specific procedures prior to powering off
 * the SMMU.
 */
struct arm_smmu_arch_ops {
	int (*init)(struct arm_smmu_device *smmu);
	void (*device_reset)(struct arm_smmu_device *smmu);
	phys_addr_t (*iova_to_phys_hard)(struct arm_smmu_domain *domain,
					 dma_addr_t iova,
					 unsigned long trans_flags);
	int (*device_group)(struct device *dev, struct iommu_group *group);
	void (*tlb_sync_timeout)(struct arm_smmu_device *smmu);
	void (*device_remove)(struct arm_smmu_device *smmu);
};