| From foo@baz Fri Mar 29 15:53:50 CET 2019 |
| From: Michael Ellerman <mpe@ellerman.id.au> |
| Date: Fri, 29 Mar 2019 22:26:08 +1100 |
| Subject: powerpc/fsl: Add infrastructure to fixup branch predictor flush |
| To: stable@vger.kernel.org, gregkh@linuxfoundation.org |
| Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, christophe.leroy@c-s.fr |
| Message-ID: <20190329112620.14489-21-mpe@ellerman.id.au> |
| |
| From: Diana Craciun <diana.craciun@nxp.com> |
| |
| commit 76a5eaa38b15dda92cd6964248c39b5a6f3a4e9d upstream. |
| |
| In order to protect against speculation attacks (Spectre |
| variant 2) on NXP PowerPC platforms, the branch predictor |
| should be flushed when the privillege level is changed. |
| This patch is adding the infrastructure to fixup at runtime |
| the code sections that are performing the branch predictor flush |
| depending on a boot arg parameter which is added later in a |
| separate patch. |
| |
| Signed-off-by: Diana Craciun <diana.craciun@nxp.com> |
| Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/powerpc/include/asm/feature-fixups.h | 12 ++++++++++++ |
| arch/powerpc/include/asm/setup.h | 2 ++ |
| arch/powerpc/kernel/vmlinux.lds.S | 8 ++++++++ |
| arch/powerpc/lib/feature-fixups.c | 23 +++++++++++++++++++++++ |
| 4 files changed, 45 insertions(+) |
| |
| --- a/arch/powerpc/include/asm/feature-fixups.h |
| +++ b/arch/powerpc/include/asm/feature-fixups.h |
| @@ -219,6 +219,17 @@ label##3: \ |
| FTR_ENTRY_OFFSET 953b-954b; \ |
| .popsection; |
| |
| +#define START_BTB_FLUSH_SECTION \ |
| +955: \ |
| + |
| +#define END_BTB_FLUSH_SECTION \ |
| +956: \ |
| + .pushsection __btb_flush_fixup,"a"; \ |
| + .align 2; \ |
| +957: \ |
| + FTR_ENTRY_OFFSET 955b-957b; \ |
| + FTR_ENTRY_OFFSET 956b-957b; \ |
| + .popsection; |
| |
| #ifndef __ASSEMBLY__ |
| #include <linux/types.h> |
| @@ -228,6 +239,7 @@ extern long __start___stf_entry_barrier_ |
| extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup; |
| extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup; |
| extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup; |
| +extern long __start__btb_flush_fixup, __stop__btb_flush_fixup; |
| |
| void apply_feature_fixups(void); |
| void setup_feature_keys(void); |
| --- a/arch/powerpc/include/asm/setup.h |
| +++ b/arch/powerpc/include/asm/setup.h |
| @@ -66,6 +66,8 @@ void do_barrier_nospec_fixups_range(bool |
| static inline void do_barrier_nospec_fixups_range(bool enable, void *start, void *end) { }; |
| #endif |
| |
| +void do_btb_flush_fixups(void); |
| + |
| #endif /* !__ASSEMBLY__ */ |
| |
| #endif /* _ASM_POWERPC_SETUP_H */ |
| --- a/arch/powerpc/kernel/vmlinux.lds.S |
| +++ b/arch/powerpc/kernel/vmlinux.lds.S |
| @@ -164,6 +164,14 @@ SECTIONS |
| } |
| #endif /* CONFIG_PPC_BARRIER_NOSPEC */ |
| |
| +#ifdef CONFIG_PPC_FSL_BOOK3E |
| + . = ALIGN(8); |
| + __spec_btb_flush_fixup : AT(ADDR(__spec_btb_flush_fixup) - LOAD_OFFSET) { |
| + __start__btb_flush_fixup = .; |
| + *(__btb_flush_fixup) |
| + __stop__btb_flush_fixup = .; |
| + } |
| +#endif |
| EXCEPTION_TABLE(0) |
| |
| NOTES :kernel :notes |
| --- a/arch/powerpc/lib/feature-fixups.c |
| +++ b/arch/powerpc/lib/feature-fixups.c |
| @@ -347,6 +347,29 @@ void do_barrier_nospec_fixups_range(bool |
| |
| printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i); |
| } |
| + |
| +static void patch_btb_flush_section(long *curr) |
| +{ |
| + unsigned int *start, *end; |
| + |
| + start = (void *)curr + *curr; |
| + end = (void *)curr + *(curr + 1); |
| + for (; start < end; start++) { |
| + pr_devel("patching dest %lx\n", (unsigned long)start); |
| + patch_instruction(start, PPC_INST_NOP); |
| + } |
| +} |
| + |
| +void do_btb_flush_fixups(void) |
| +{ |
| + long *start, *end; |
| + |
| + start = PTRRELOC(&__start__btb_flush_fixup); |
| + end = PTRRELOC(&__stop__btb_flush_fixup); |
| + |
| + for (; start < end; start += 2) |
| + patch_btb_flush_section(start); |
| +} |
| #endif /* CONFIG_PPC_FSL_BOOK3E */ |
| |
| void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end) |