]>
Commit | Line | Data |
---|---|---|
88c4f4d9 GKH |
1 | From 4e4abae311e4b44aaf61f18a826fd7136037f199 Mon Sep 17 00:00:00 2001 |
2 | From: Robin Murphy <robin.murphy@arm.com> | |
3 | Date: Mon, 3 Jun 2019 14:15:37 +0200 | |
4 | Subject: iommu/arm-smmu: Avoid constant zero in TLBI writes | |
5 | ||
6 | From: Robin Murphy <robin.murphy@arm.com> | |
7 | ||
8 | commit 4e4abae311e4b44aaf61f18a826fd7136037f199 upstream. | |
9 | ||
10 | Apparently, some Qualcomm arm64 platforms which appear to expose their | |
11 | SMMU global register space are still, in fact, using a hypervisor to | |
12 | mediate it by trapping and emulating register accesses. Sadly, some | |
13 | deployed versions of said trapping code have bugs wherein they go | |
14 | horribly wrong for stores using r31 (i.e. XZR/WZR) as the source | |
15 | register. | |
16 | ||
17 | While this can be mitigated for GCC today by tweaking the constraints | |
18 | for the implementation of writel_relaxed(), to avoid any potential | |
19 | arms race with future compilers more aggressively optimising register | |
20 | allocation, the simple way is to just remove all the problematic | |
21 | constant zeros. For the write-only TLB operations, the actual value is | |
22 | irrelevant anyway and any old nearby variable will provide a suitable | |
23 | GPR to encode. The one point at which we really do need a zero to clear | |
24 | a context bank happens before any of the TLB maintenance where crashes | |
25 | have been reported, so is apparently not a problem... :/ | |
26 | ||
27 | Reported-by: AngeloGioacchino Del Regno <kholk11@gmail.com> | |
28 | Tested-by: Marc Gonzalez <marc.w.gonzalez@free.fr> | |
29 | Signed-off-by: Robin Murphy <robin.murphy@arm.com> | |
30 | Signed-off-by: Marc Gonzalez <marc.w.gonzalez@free.fr> | |
31 | Acked-by: Will Deacon <will.deacon@arm.com> | |
32 | Cc: stable@vger.kernel.org | |
33 | Signed-off-by: Joerg Roedel <jroedel@suse.de> | |
34 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
35 | ||
36 | --- | |
37 | drivers/iommu/arm-smmu.c | 15 ++++++++++++--- | |
38 | 1 file changed, 12 insertions(+), 3 deletions(-) | |
39 | ||
40 | --- a/drivers/iommu/arm-smmu.c | |
41 | +++ b/drivers/iommu/arm-smmu.c | |
42 | @@ -56,6 +56,15 @@ | |
43 | #include "io-pgtable.h" | |
44 | #include "arm-smmu-regs.h" | |
45 | ||
46 | +/* | |
47 | + * Apparently, some Qualcomm arm64 platforms which appear to expose their SMMU | |
48 | + * global register space are still, in fact, using a hypervisor to mediate it | |
49 | + * by trapping and emulating register accesses. Sadly, some deployed versions | |
50 | + * of said trapping code have bugs wherein they go horribly wrong for stores | |
51 | + * using r31 (i.e. XZR/WZR) as the source register. | |
52 | + */ | |
53 | +#define QCOM_DUMMY_VAL -1 | |
54 | + | |
55 | #define ARM_MMU500_ACTLR_CPRE (1 << 1) | |
56 | ||
57 | #define ARM_MMU500_ACR_CACHE_LOCK (1 << 26) | |
58 | @@ -398,7 +407,7 @@ static void __arm_smmu_tlb_sync(struct a | |
59 | { | |
60 | unsigned int spin_cnt, delay; | |
61 | ||
62 | - writel_relaxed(0, sync); | |
63 | + writel_relaxed(QCOM_DUMMY_VAL, sync); | |
64 | for (delay = 1; delay < TLB_LOOP_TIMEOUT; delay *= 2) { | |
65 | for (spin_cnt = TLB_SPIN_COUNT; spin_cnt > 0; spin_cnt--) { | |
66 | if (!(readl_relaxed(status) & sTLBGSTATUS_GSACTIVE)) | |
67 | @@ -1637,8 +1646,8 @@ static void arm_smmu_device_reset(struct | |
68 | } | |
69 | ||
70 | /* Invalidate the TLB, just in case */ | |
71 | - writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLH); | |
72 | - writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH); | |
73 | + writel_relaxed(QCOM_DUMMY_VAL, gr0_base + ARM_SMMU_GR0_TLBIALLH); | |
74 | + writel_relaxed(QCOM_DUMMY_VAL, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH); | |
75 | ||
76 | reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0); | |
77 |