Hello,

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

> From: Michal Suchanek <msucha...@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 <msucha...@suse.de>
> Signed-off-by: Michael Ellerman <m...@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)

Reply via email to