
From: Zhang Zekun <zhangzekun11@huawei.com> hulk inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I913T5 CVE: NA --------------------------------------------------- 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: Zhang Zekun <zhangzekun11@huawei.com> Signed-off-by: Qi Xi <xiqi2@huawei.com> --- Documentation/arch/arm64/silicon-errata.rst | 1 + arch/arm64/Kconfig | 12 +++++++++ config.aarch64 | 1 + drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 28 +++++++++++++++++++++ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 + 5 files changed, 43 insertions(+) diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst index baf31a3108d1..03d12015cef5 100644 --- a/Documentation/arch/arm64/silicon-errata.rst +++ b/Documentation/arch/arm64/silicon-errata.rst @@ -253,6 +253,7 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | Hisilicon | LINXICORE9100 | #162100125 | HISILICON_ERRATUM_162100125 | +----------------+-----------------+-----------------+-----------------------------+ +| Hisilicon | SMMUv3 | #162100602 | HISILICON_ERRATUM_162100602 | +----------------+-----------------+-----------------+-----------------------------+ | Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 | +----------------+-----------------+-----------------+-----------------------------+ diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 01ff2a969539..8d4eb7ce8a7f 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1245,6 +1245,18 @@ config HISILICON_ERRATUM_162100125 If unsure, say Y. +config HISILICON_ERRATUM_162100602 + bool "Hisilicon erratum 162100602" + depends on ARM_SMMU_V3 && ARCH_HISI + default y + help + 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 diff --git a/config.aarch64 b/config.aarch64 index e89c80a4850f..32c16a9e87bb 100644 --- a/config.aarch64 +++ b/config.aarch64 @@ -390,6 +390,7 @@ CONFIG_CAVIUM_ERRATUM_30115=y CONFIG_CAVIUM_TX2_ERRATUM_219=y CONFIG_FUJITSU_ERRATUM_010001=y CONFIG_HISILICON_ERRATUM_161600802=y +CONFIG_HISILICON_ERRATUM_162100602=y CONFIG_QCOM_FALKOR_ERRATUM_1003=y CONFIG_QCOM_FALKOR_ERRATUM_1009=y CONFIG_QCOM_QDF2400_ERRATUM_0065=y diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index 68b81f9c2f4b..166982b67cd0 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -2525,6 +2525,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 (!(smmu_domain->smmu->options & ARM_SMMU_OPT_SYNC_MAP)) + 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) { @@ -2880,6 +2897,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, @@ -3661,6 +3681,14 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) smmu->oas = 48; } +#ifdef CONFIG_HISILICON_ERRATUM_162100602 + /* IIDR */ + reg = readl_relaxed(smmu->base + ARM_SMMU_IIDR); + if (FIELD_GET(IIDR_VARIANT, reg) == 0x3 && + FIELD_GET(IIDR_REVISION, reg) == 0x2) + smmu->options |= ARM_SMMU_OPT_SYNC_MAP; +#endif + if (arm_smmu_ops.pgsize_bitmap == -1UL) arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap; else diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h index 9915850dd4db..33c81035021c 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -652,6 +652,7 @@ struct arm_smmu_device { #define ARM_SMMU_OPT_PAGE0_REGS_ONLY (1 << 1) #define ARM_SMMU_OPT_MSIPOLL (1 << 2) #define ARM_SMMU_OPT_CMDQ_FORCE_SYNC (1 << 3) +#define ARM_SMMU_OPT_SYNC_MAP (1 << 4) u32 options; struct arm_smmu_cmdq cmdq; -- 2.25.1