]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.9.169/powerpc-64s-add-support-for-ori-barrier_nospec-patch.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.9.169 / powerpc-64s-add-support-for-ori-barrier_nospec-patch.patch
CommitLineData
45d80ddf
SL
1From 4e7c5f670b90566d2a24e0d694c7f8b2a25afc61 Mon Sep 17 00:00:00 2001
2From: Michal Suchanek <msuchanek@suse.de>
3Date: Thu, 11 Apr 2019 21:45:58 +1000
4Subject: powerpc/64s: Add support for ori barrier_nospec patching
5
6commit 2eea7f067f495e33b8b116b35b5988ab2b8aec55 upstream.
7
8Based on the RFI patching. This is required to be able to disable the
9speculation barrier.
10
11Only one barrier type is supported and it does nothing when the
12firmware does not enable it. Also re-patching modules is not supported
13So the only meaningful thing that can be done is patching out the
14speculation barrier at boot when the user says it is not wanted.
15
16Signed-off-by: Michal Suchanek <msuchanek@suse.de>
17Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
18Signed-off-by: Sasha Levin <sashal@kernel.org>
19---
20 arch/powerpc/include/asm/barrier.h | 2 +-
21 arch/powerpc/include/asm/feature-fixups.h | 9 ++++++++
22 arch/powerpc/include/asm/setup.h | 1 +
23 arch/powerpc/kernel/security.c | 9 ++++++++
24 arch/powerpc/kernel/vmlinux.lds.S | 7 ++++++
25 arch/powerpc/lib/feature-fixups.c | 27 +++++++++++++++++++++++
26 6 files changed, 54 insertions(+), 1 deletion(-)
27
28diff --git a/arch/powerpc/include/asm/barrier.h b/arch/powerpc/include/asm/barrier.h
29index 352ea3e3cc05..a8131162104f 100644
30--- a/arch/powerpc/include/asm/barrier.h
31+++ b/arch/powerpc/include/asm/barrier.h
32@@ -82,7 +82,7 @@ do { \
33 * Prevent execution of subsequent instructions until preceding branches have
34 * been fully resolved and are no longer executing speculatively.
35 */
36-#define barrier_nospec_asm ori 31,31,0
37+#define barrier_nospec_asm NOSPEC_BARRIER_FIXUP_SECTION; nop
38
39 // This also acts as a compiler barrier due to the memory clobber.
40 #define barrier_nospec() asm (stringify_in_c(barrier_nospec_asm) ::: "memory")
41diff --git a/arch/powerpc/include/asm/feature-fixups.h b/arch/powerpc/include/asm/feature-fixups.h
42index 0bf8202feca6..afd3efd38938 100644
43--- a/arch/powerpc/include/asm/feature-fixups.h
44+++ b/arch/powerpc/include/asm/feature-fixups.h
45@@ -213,6 +213,14 @@ void setup_feature_keys(void);
46 FTR_ENTRY_OFFSET 951b-952b; \
47 .popsection;
48
49+#define NOSPEC_BARRIER_FIXUP_SECTION \
50+953: \
51+ .pushsection __barrier_nospec_fixup,"a"; \
52+ .align 2; \
53+954: \
54+ FTR_ENTRY_OFFSET 953b-954b; \
55+ .popsection;
56+
57
58 #ifndef __ASSEMBLY__
59
60@@ -220,6 +228,7 @@ extern long stf_barrier_fallback;
61 extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup;
62 extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup;
63 extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;
64+extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup;
65
66 #endif
67
68diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
69index 3f160cd20107..703ddf752516 100644
70--- a/arch/powerpc/include/asm/setup.h
71+++ b/arch/powerpc/include/asm/setup.h
72@@ -50,6 +50,7 @@ enum l1d_flush_type {
73
74 void setup_rfi_flush(enum l1d_flush_type, bool enable);
75 void do_rfi_flush_fixups(enum l1d_flush_type types);
76+void do_barrier_nospec_fixups(bool enable);
77
78 #endif /* !__ASSEMBLY__ */
79
80diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c
81index 2277df84ef6e..8b1cf9c81b82 100644
82--- a/arch/powerpc/kernel/security.c
83+++ b/arch/powerpc/kernel/security.c
84@@ -10,10 +10,19 @@
85 #include <linux/seq_buf.h>
86
87 #include <asm/security_features.h>
88+#include <asm/setup.h>
89
90
91 unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT;
92
93+static bool barrier_nospec_enabled;
94+
95+static void enable_barrier_nospec(bool enable)
96+{
97+ barrier_nospec_enabled = enable;
98+ do_barrier_nospec_fixups(enable);
99+}
100+
101 ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
102 {
103 bool thread_priv;
104diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
105index c16fddbb6ab8..61def0be6914 100644
106--- a/arch/powerpc/kernel/vmlinux.lds.S
107+++ b/arch/powerpc/kernel/vmlinux.lds.S
108@@ -153,6 +153,13 @@ SECTIONS
109 *(__rfi_flush_fixup)
110 __stop___rfi_flush_fixup = .;
111 }
112+
113+ . = ALIGN(8);
114+ __spec_barrier_fixup : AT(ADDR(__spec_barrier_fixup) - LOAD_OFFSET) {
115+ __start___barrier_nospec_fixup = .;
116+ *(__barrier_nospec_fixup)
117+ __stop___barrier_nospec_fixup = .;
118+ }
119 #endif
120
121 EXCEPTION_TABLE(0)
122diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
123index cf1398e3c2e0..f82ae6bb2365 100644
124--- a/arch/powerpc/lib/feature-fixups.c
125+++ b/arch/powerpc/lib/feature-fixups.c
126@@ -277,6 +277,33 @@ void do_rfi_flush_fixups(enum l1d_flush_type types)
127 (types & L1D_FLUSH_MTTRIG) ? "mttrig type"
128 : "unknown");
129 }
130+
131+void do_barrier_nospec_fixups(bool enable)
132+{
133+ unsigned int instr, *dest;
134+ long *start, *end;
135+ int i;
136+
137+ start = PTRRELOC(&__start___barrier_nospec_fixup),
138+ end = PTRRELOC(&__stop___barrier_nospec_fixup);
139+
140+ instr = 0x60000000; /* nop */
141+
142+ if (enable) {
143+ pr_info("barrier-nospec: using ORI speculation barrier\n");
144+ instr = 0x63ff0000; /* ori 31,31,0 speculation barrier */
145+ }
146+
147+ for (i = 0; start < end; start++, i++) {
148+ dest = (void *)start + *start;
149+
150+ pr_devel("patching dest %lx\n", (unsigned long)dest);
151+ patch_instruction(dest, instr);
152+ }
153+
154+ printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
155+}
156+
157 #endif /* CONFIG_PPC_BOOK3S_64 */
158
159 void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
160--
1612.19.1
162