iommu/arm-smmu: Avoid constant zero in TLBI writes [Linux 4.14.128]

iommu/arm-smmu: Avoid constant zero in TLBI writes [Linux 4.14.128]

This Linux kernel change "iommu/arm-smmu: Avoid constant zero in TLBI writes" is included in the Linux 4.14.128 release. This change is authored by Robin Murphy <robin.murphy [at] arm.com> on Mon Jun 3 14:15:37 2019 +0200. The commit for this change in Linux stable tree is d0365cb (patch) which is from upstream commit 4e4abae. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 4e4abae.

iommu/arm-smmu: Avoid constant zero in TLBI writes

commit 4e4abae311e4b44aaf61f18a826fd7136037f199 upstream.

Apparently, some Qualcomm arm64 platforms which appear to expose their
SMMU global register space are still, in fact, using a hypervisor to
mediate it by trapping and emulating register accesses. Sadly, some
deployed versions of said trapping code have bugs wherein they go
horribly wrong for stores using r31 (i.e. XZR/WZR) as the source
register.

While this can be mitigated for GCC today by tweaking the constraints
for the implementation of writel_relaxed(), to avoid any potential
arms race with future compilers more aggressively optimising register
allocation, the simple way is to just remove all the problematic
constant zeros. For the write-only TLB operations, the actual value is
irrelevant anyway and any old nearby variable will provide a suitable
GPR to encode. The one point at which we really do need a zero to clear
a context bank happens before any of the TLB maintenance where crashes
have been reported, so is apparently not a problem... :/

Reported-by: AngeloGioacchino Del Regno <kholk11@gmail.com>
Tested-by: Marc Gonzalez <marc.w.gonzalez@free.fr>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Marc Gonzalez <marc.w.gonzalez@free.fr>
Acked-by: Will Deacon <will.deacon@arm.com>
Cc: stable@vger.kernel.org
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

There are 15 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/iommu/arm-smmu.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 01a6a0e..c38cf03 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -56,6 +56,15 @@
 #include "io-pgtable.h"
 #include "arm-smmu-regs.h"

+/*
+ * Apparently, some Qualcomm arm64 platforms which appear to expose their SMMU
+ * global register space are still, in fact, using a hypervisor to mediate it
+ * by trapping and emulating register accesses. Sadly, some deployed versions
+ * of said trapping code have bugs wherein they go horribly wrong for stores
+ * using r31 (i.e. XZR/WZR) as the source register.
+ */
+#define QCOM_DUMMY_VAL -1
+
 #define ARM_MMU500_ACTLR_CPRE      (1 << 1)

 #define ARM_MMU500_ACR_CACHE_LOCK  (1 << 26)
@@ -404,7 +413,7 @@ static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu,
 {
    unsigned int spin_cnt, delay;

-   writel_relaxed(0, sync);
+   writel_relaxed(QCOM_DUMMY_VAL, sync);
    for (delay = 1; delay < TLB_LOOP_TIMEOUT; delay *= 2) {
        for (spin_cnt = TLB_SPIN_COUNT; spin_cnt > 0; spin_cnt--) {
            if (!(readl_relaxed(status) & sTLBGSTATUS_GSACTIVE))
@@ -1635,8 +1644,8 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
    }

    /* Invalidate the TLB, just in case */
-   writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLH);
-   writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH);
+   writel_relaxed(QCOM_DUMMY_VAL, gr0_base + ARM_SMMU_GR0_TLBIALLH);
+   writel_relaxed(QCOM_DUMMY_VAL, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH);

    reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);

Leave a Reply

Your email address will not be published. Required fields are marked *