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>
9 From: Michal Suchanek <msuchanek@suse.de>
11 commit cb3d6759a93c6d0aea1c10deb6d00e111c29c19c upstream.
13 Check what firmware told us and enable/disable the barrier_nospec as
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.
19 Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
20 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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(+)
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 {
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;
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);
44 +void setup_barrier_nospec(void)
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.
60 + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
61 + security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR);
63 + enable_barrier_nospec(enable);
66 +#ifdef CONFIG_DEBUG_FS
67 +static int barrier_nospec_set(void *data, u64 val)
77 + if (!!val == !!barrier_nospec_enabled)
80 + enable_barrier_nospec(!!val);
85 +static int barrier_nospec_get(void *data, u64 *val)
87 + *val = barrier_nospec_enabled ? 1 : 0;
91 +DEFINE_SIMPLE_ATTRIBUTE(fops_barrier_nospec,
92 + barrier_nospec_get, barrier_nospec_set, "%llu\n");
94 +static __init int barrier_nospec_debugfs_init(void)
96 + debugfs_create_file("barrier_nospec", 0600, powerpc_debugfs_root, NULL,
97 + &fops_barrier_nospec);
100 +device_initcall(barrier_nospec_debugfs_init);
101 +#endif /* CONFIG_DEBUG_FS */
103 ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
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));
111 setup_rfi_flush(type, enable);
112 + setup_barrier_nospec();
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);
121 setup_rfi_flush(types, enable);
122 + setup_barrier_nospec();
125 static void __init pSeries_setup_arch(void)