Commit 880e9284 authored by Zhang Zekun's avatar Zhang Zekun
Browse files

iommu/arm-smmu-v3: Add a SYNC command to avoid broken page table prefetch

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8QSLV


CVE: NA

-----------------------------------------------

On Hisilicon LINXICORE9100 cores, SMMU pagetable prefetch features may
prefetch and use a invalid PTE even the PTE is valid at that time. This
will cause the device trigger fake pagefaults. If the SMMU works in
terminate mode, transactions which occur fake pagefaults will be aborted,
and could result in unexpected errors.

To fix this problem, we need to add a SYNC command after smmu has map a
iova, then smmu will always try to get the newest PTE.

Signed-off-by: default avatarZhang Zekun <zhangzekun11@huawei.com>
parent 4eb5a1ca
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -1180,6 +1180,19 @@ config HISILICON_ERRATUM_1980005

	  If unsure, say N.

config HISILICON_ERRATUM_162100602
	bool "Hisilicon erratum 162100602"
	depends on ARM_SMMU_V3
	default y
	help
	  On Hisilicon LINXICORE9100 cores, SMMU pagetable prefetch features may
	  prefetch and use a invalid PTE even the PTE is valid at that time. This
	  will cause the device trigger fake pagefaults. If the SMMU works in
	  terminate mode, transactions which occur fake pagefaults will be aborted,
	  and could result in unexpected errors.

	  If unsure, say Y.

config QCOM_FALKOR_ERRATUM_1003
	bool "Falkor E1003: Incorrect translation due to ASID change"
	default y
+1 −0
Original line number Diff line number Diff line
@@ -401,6 +401,7 @@ CONFIG_CAVIUM_TX2_ERRATUM_219=y
CONFIG_FUJITSU_ERRATUM_010001=y
CONFIG_HISILICON_ERRATUM_161600802=y
CONFIG_HISILICON_ERRATUM_162100125=y
CONFIG_HISILICON_ERRATUM_162100602=y
CONFIG_QCOM_FALKOR_ERRATUM_1003=y
CONFIG_QCOM_FALKOR_ERRATUM_1009=y
CONFIG_QCOM_QDF2400_ERRATUM_0065=y
+14 −0
Original line number Diff line number Diff line
@@ -360,6 +360,13 @@ static const struct midr_range hisilicon_erratum_162100125_cpus[] = {
};
#endif

#ifdef CONFIG_HISILICON_ERRATUM_162100602
static const struct midr_range hisilicon_erratum_162100602_cpus[] = {
	MIDR_REV(MIDR_HISI_LINXICORE9100, 0, 0),
	{},
};
#endif

#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
static const struct arm64_cpu_capabilities qcom_erratum_1003_list[] = {
	{
@@ -591,6 +598,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
		ERRATA_MIDR_RANGE_LIST(hisilicon_erratum_162100125_cpus),
	},
#endif
#ifdef CONFIG_HISILICON_ERRATUM_162100602
	{
		.desc = "Hisilicon erratum 162100602",
		.capability = ARM64_WORKAROUND_HISILICON_ERRATUM_162100602,
		ERRATA_MIDR_RANGE_LIST(hisilicon_erratum_162100602_cpus),
	},
#endif
#ifdef CONFIG_HISILICON_ERRATUM_1980005
	{
		.desc = "Hisilicon erratum 1980005 (IDC)",
+1 −0
Original line number Diff line number Diff line
@@ -103,3 +103,4 @@ WORKAROUND_SPECULATIVE_AT
WORKAROUND_HISILICON_ERRATUM_162100125
WORKAROUND_HISI_HIP08_RU_PREFETCH
WORKAROUND_HISILICON_1980005
WORKAROUND_HISILICON_ERRATUM_162100602
+20 −0
Original line number Diff line number Diff line
@@ -2528,6 +2528,23 @@ static void arm_smmu_iotlb_sync(struct iommu_domain *domain,
				      gather->pgsize, true, smmu_domain);
}

#ifdef CONFIG_HISILICON_ERRATUM_162100602
static void arm_smmu_iotlb_sync_map(struct iommu_domain *domain,
				unsigned long iova, size_t size)
{
	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
	size_t granule_size;

	if (!cpus_have_const_cap(ARM64_WORKAROUND_HISILICON_ERRATUM_162100602))
		return;

	granule_size = 1 <<  __ffs(smmu_domain->domain.pgsize_bitmap);

	/* Add a SYNC command to sync io-pgtale to avoid errors in pgtable prefetch*/
	arm_smmu_tlb_inv_range_domain(iova, granule_size, granule_size, true, smmu_domain);
}
#endif

static phys_addr_t
arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
{
@@ -2883,6 +2900,9 @@ static struct iommu_ops arm_smmu_ops = {
		.unmap_pages		= arm_smmu_unmap_pages,
		.flush_iotlb_all	= arm_smmu_flush_iotlb_all,
		.iotlb_sync		= arm_smmu_iotlb_sync,
#ifdef CONFIG_HISILICON_ERRATUM_162100602
		.iotlb_sync_map		= arm_smmu_iotlb_sync_map,
#endif
		.iova_to_phys		= arm_smmu_iova_to_phys,
		.enable_nesting		= arm_smmu_enable_nesting,
		.free			= arm_smmu_domain_free,