]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-4.4/powerpc-64s-enable-barrier_nospec-based-on-firmware-settings.patch
4.4-stable patches
[thirdparty/kernel/stable-queue.git] / queue-4.4 / powerpc-64s-enable-barrier_nospec-based-on-firmware-settings.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:13 +1000
4Subject: powerpc/64s: Enable barrier_nospec based on firmware settings
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-29-mpe@ellerman.id.au>
8
9From: Michal Suchanek <msuchanek@suse.de>
10
11commit cb3d6759a93c6d0aea1c10deb6d00e111c29c19c upstream.
12
13Check what firmware told us and enable/disable the barrier_nospec as
14appropriate.
15
16We err on the side of enabling the barrier, as it's no-op on older
17systems, see the comment for more detail.
18
19Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
20Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
21---
22 arch/powerpc/include/asm/setup.h | 1
23 arch/powerpc/kernel/security.c | 59 +++++++++++++++++++++++++++++++++
24 arch/powerpc/platforms/powernv/setup.c | 1
25 arch/powerpc/platforms/pseries/setup.c | 1
26 4 files changed, 62 insertions(+)
27
28--- a/arch/powerpc/include/asm/setup.h
29+++ b/arch/powerpc/include/asm/setup.h
30@@ -38,6 +38,7 @@ enum l1d_flush_type {
31
32 void setup_rfi_flush(enum l1d_flush_type, bool enable);
33 void do_rfi_flush_fixups(enum l1d_flush_type types);
34+void setup_barrier_nospec(void);
35 void do_barrier_nospec_fixups(bool enable);
36 extern bool barrier_nospec_enabled;
37
38--- a/arch/powerpc/kernel/security.c
39+++ b/arch/powerpc/kernel/security.c
40@@ -24,6 +24,65 @@ static void enable_barrier_nospec(bool e
41 do_barrier_nospec_fixups(enable);
42 }
43
44+void setup_barrier_nospec(void)
45+{
46+ bool enable;
47+
48+ /*
49+ * It would make sense to check SEC_FTR_SPEC_BAR_ORI31 below as well.
50+ * But there's a good reason not to. The two flags we check below are
51+ * both are enabled by default in the kernel, so if the hcall is not
52+ * functional they will be enabled.
53+ * On a system where the host firmware has been updated (so the ori
54+ * functions as a barrier), but on which the hypervisor (KVM/Qemu) has
55+ * not been updated, we would like to enable the barrier. Dropping the
56+ * check for SEC_FTR_SPEC_BAR_ORI31 achieves that. The only downside is
57+ * we potentially enable the barrier on systems where the host firmware
58+ * is not updated, but that's harmless as it's a no-op.
59+ */
60+ enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
61+ security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR);
62+
63+ enable_barrier_nospec(enable);
64+}
65+
66+#ifdef CONFIG_DEBUG_FS
67+static int barrier_nospec_set(void *data, u64 val)
68+{
69+ switch (val) {
70+ case 0:
71+ case 1:
72+ break;
73+ default:
74+ return -EINVAL;
75+ }
76+
77+ if (!!val == !!barrier_nospec_enabled)
78+ return 0;
79+
80+ enable_barrier_nospec(!!val);
81+
82+ return 0;
83+}
84+
85+static int barrier_nospec_get(void *data, u64 *val)
86+{
87+ *val = barrier_nospec_enabled ? 1 : 0;
88+ return 0;
89+}
90+
91+DEFINE_SIMPLE_ATTRIBUTE(fops_barrier_nospec,
92+ barrier_nospec_get, barrier_nospec_set, "%llu\n");
93+
94+static __init int barrier_nospec_debugfs_init(void)
95+{
96+ debugfs_create_file("barrier_nospec", 0600, powerpc_debugfs_root, NULL,
97+ &fops_barrier_nospec);
98+ return 0;
99+}
100+device_initcall(barrier_nospec_debugfs_init);
101+#endif /* CONFIG_DEBUG_FS */
102+
103 ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
104 {
105 bool thread_priv;
106--- a/arch/powerpc/platforms/powernv/setup.c
107+++ b/arch/powerpc/platforms/powernv/setup.c
108@@ -123,6 +123,7 @@ static void pnv_setup_rfi_flush(void)
109 security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV));
110
111 setup_rfi_flush(type, enable);
112+ setup_barrier_nospec();
113 }
114
115 static void __init pnv_setup_arch(void)
116--- a/arch/powerpc/platforms/pseries/setup.c
117+++ b/arch/powerpc/platforms/pseries/setup.c
118@@ -574,6 +574,7 @@ void pseries_setup_rfi_flush(void)
119 security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR);
120
121 setup_rfi_flush(types, enable);
122+ setup_barrier_nospec();
123 }
124
125 static void __init pSeries_setup_arch(void)