[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