]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.14/powerpc-64s-enable-barrier_nospec-based-on-firmware-settings.patch
Linux 4.9.167
[thirdparty/kernel/stable-queue.git] / queue-4.14 / powerpc-64s-enable-barrier_nospec-based-on-firmware-settings.patch
1 From foo@baz Fri Mar 29 15:53:50 CET 2019
2 From: Michael Ellerman <mpe@ellerman.id.au>
3 Date: Fri, 29 Mar 2019 22:25:51 +1100
4 Subject: powerpc/64s: Enable barrier_nospec based on firmware settings
5 To: stable@vger.kernel.org, gregkh@linuxfoundation.org
6 Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, christophe.leroy@c-s.fr
7 Message-ID: <20190329112620.14489-4-mpe@ellerman.id.au>
8
9 From: Michal Suchanek <msuchanek@suse.de>
10
11 commit cb3d6759a93c6d0aea1c10deb6d00e111c29c19c upstream.
12
13 Check what firmware told us and enable/disable the barrier_nospec as
14 appropriate.
15
16 We err on the side of enabling the barrier, as it's no-op on older
17 systems, see the comment for more detail.
18
19 Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
20 Signed-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 @@ -52,6 +52,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 @@ -23,6 +23,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 @@ -534,6 +534,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)