[PATCH 2/6] powerpc/64s: Add support for ori barrier_nospec patching

Michal Suchánek msuchanek at suse.de
Fri Apr 27 02:10:42 AEST 2018


Hello,

On Tue, 24 Apr 2018 14:15:55 +1000
Michael Ellerman <mpe at ellerman.id.au> wrote:

> From: Michal Suchanek <msuchanek at suse.de>
> 
> Based on the RFI patching. This is required to be able to disable the
> speculation barrier.

why do you not patch the nospec barrier which is included as part of
the RFI flush code?

I think when debugging the code it would make more sense if RFI is
patched by RFI patcher and nospec by nospec patcher.

A separate question is if the RFI flush would break without the nospec
barrier.

Thanks

Michal


> 
> Only one barrier type is supported and it does nothing when the
> firmware does not enable it. Also re-patching modules is not supported
> So the only meaningful thing that can be done is patching out the
> speculation barrier at boot when the user says it is not wanted.
> 
> Signed-off-by: Michal Suchanek <msuchanek at suse.de>
> Signed-off-by: Michael Ellerman <mpe at ellerman.id.au>
> ---
>  arch/powerpc/include/asm/barrier.h        |  2 +-
>  arch/powerpc/include/asm/feature-fixups.h |  9 +++++++++
>  arch/powerpc/include/asm/setup.h          |  1 +
>  arch/powerpc/kernel/security.c            |  9 +++++++++
>  arch/powerpc/kernel/vmlinux.lds.S         |  7 +++++++
>  arch/powerpc/lib/feature-fixups.c         | 27
> +++++++++++++++++++++++++++ 6 files changed, 54 insertions(+), 1
> deletion(-)
> 
> diff --git a/arch/powerpc/include/asm/barrier.h
> b/arch/powerpc/include/asm/barrier.h index e582d2c88092..f67b3f6e36be
> 100644 --- a/arch/powerpc/include/asm/barrier.h
> +++ b/arch/powerpc/include/asm/barrier.h
> @@ -81,7 +81,7 @@ do
> {
> \
>   * Prevent execution of subsequent instructions until preceding
> branches have
>   * been fully resolved and are no longer executing speculatively.
>   */
> -#define barrier_nospec_asm ori 31,31,0
> +#define barrier_nospec_asm NOSPEC_BARRIER_FIXUP_SECTION; nop
>  
>  // This also acts as a compiler barrier due to the memory clobber.
>  #define barrier_nospec() asm (stringify_in_c(barrier_nospec_asm) :::
> "memory") diff --git a/arch/powerpc/include/asm/feature-fixups.h
> b/arch/powerpc/include/asm/feature-fixups.h index
> 1e82eb3caabd..86ac59e75f36 100644 ---
> a/arch/powerpc/include/asm/feature-fixups.h +++
> b/arch/powerpc/include/asm/feature-fixups.h @@ -195,11 +195,20 @@
> label##3:					       	\
> FTR_ENTRY_OFFSET 951b-952b;			\ .popsection;
>  
> +#define NOSPEC_BARRIER_FIXUP_SECTION			\
> +953:							\
> +	.pushsection __barrier_nospec_fixup,"a";	\
> +	.align 2;					\
> +954:							\
> +	FTR_ENTRY_OFFSET 953b-954b;			\
> +	.popsection;
> +
>  
>  #ifndef __ASSEMBLY__
>  #include <linux/types.h>
>  
>  extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;
> +extern long __start___barrier_nospec_fixup,
> __stop___barrier_nospec_fixup; 
>  void apply_feature_fixups(void);
>  void setup_feature_keys(void);
> diff --git a/arch/powerpc/include/asm/setup.h
> b/arch/powerpc/include/asm/setup.h index 27fa52ed6d00..afc7280cce3b
> 100644 --- a/arch/powerpc/include/asm/setup.h
> +++ b/arch/powerpc/include/asm/setup.h
> @@ -52,6 +52,7 @@ enum l1d_flush_type {
>  
>  void setup_rfi_flush(enum l1d_flush_type, bool enable);
>  void do_rfi_flush_fixups(enum l1d_flush_type types);
> +void do_barrier_nospec_fixups(bool enable);
>  
>  #endif /* !__ASSEMBLY__ */
>  
> diff --git a/arch/powerpc/kernel/security.c
> b/arch/powerpc/kernel/security.c index bab5a27ea805..b963eae0b0a0
> 100644 --- a/arch/powerpc/kernel/security.c
> +++ b/arch/powerpc/kernel/security.c
> @@ -9,10 +9,19 @@
>  #include <linux/seq_buf.h>
>  
>  #include <asm/security_features.h>
> +#include <asm/setup.h>
>  
>  
>  unsigned long powerpc_security_features __read_mostly =
> SEC_FTR_DEFAULT; 
> +static bool barrier_nospec_enabled;
> +
> +static void enable_barrier_nospec(bool enable)
> +{
> +	barrier_nospec_enabled = enable;
> +	do_barrier_nospec_fixups(enable);
> +}
> +
>  ssize_t cpu_show_meltdown(struct device *dev, struct
> device_attribute *attr, char *buf) {
>  	bool thread_priv;
> diff --git a/arch/powerpc/kernel/vmlinux.lds.S
> b/arch/powerpc/kernel/vmlinux.lds.S index c8af90ff49f0..ff73f498568c
> 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S
> +++ b/arch/powerpc/kernel/vmlinux.lds.S
> @@ -139,6 +139,13 @@ SECTIONS
>  		*(__rfi_flush_fixup)
>  		__stop___rfi_flush_fixup = .;
>  	}
> +
> +	. = ALIGN(8);
> +	__spec_barrier_fixup : AT(ADDR(__spec_barrier_fixup) -
> LOAD_OFFSET) {
> +		__start___barrier_nospec_fixup = .;
> +		*(__barrier_nospec_fixup)
> +		__stop___barrier_nospec_fixup = .;
> +	}
>  #endif
>  
>  	EXCEPTION_TABLE(0)
> diff --git a/arch/powerpc/lib/feature-fixups.c
> b/arch/powerpc/lib/feature-fixups.c index 288fe4f0db4e..093c1d2ea5fd
> 100644 --- a/arch/powerpc/lib/feature-fixups.c
> +++ b/arch/powerpc/lib/feature-fixups.c
> @@ -162,6 +162,33 @@ void do_rfi_flush_fixups(enum l1d_flush_type
> types) (types &  L1D_FLUSH_MTTRIG)     ? "mttrig type"
>  						: "unknown");
>  }
> +
> +void do_barrier_nospec_fixups(bool enable)
> +{
> +	unsigned int instr, *dest;
> +	long *start, *end;
> +	int i;
> +
> +	start = PTRRELOC(&__start___barrier_nospec_fixup),
> +	end = PTRRELOC(&__stop___barrier_nospec_fixup);
> +
> +	instr = 0x60000000; /* nop */
> +
> +	if (enable) {
> +		pr_info("barrier-nospec: using ORI speculation
> barrier\n");
> +		instr = 0x63ff0000; /* ori 31,31,0 speculation
> barrier */
> +	}
> +
> +	for (i = 0; start < end; start++, i++) {
> +		dest = (void *)start + *start;
> +
> +		pr_devel("patching dest %lx\n", (unsigned long)dest);
> +		patch_instruction(dest, instr);
> +	}
> +
> +	printk(KERN_DEBUG "barrier-nospec: patched %d locations\n",
> i); +}
> +
>  #endif /* CONFIG_PPC_BOOK3S_64 */
>  
>  void do_lwsync_fixups(unsigned long value, void *fixup_start, void
> *fixup_end)



More information about the Linuxppc-dev mailing list