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