From: Greg Kroah-Hartman Date: Mon, 29 Apr 2019 09:51:21 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v4.9.172~38 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4fa5b95ee2e68fb35b7b759c87e50a72d06db153;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: ceph-ensure-d_name-stability-in-ceph_dentry_hash.patch ceph-fix-ci-i_head_snapc-leak.patch nfsd-don-t-release-the-callback-slot-unless-it-was-actually-held.patch powerpc-64-add-config_ppc_barrier_nospec.patch powerpc-64-call-setup_barrier_nospec-from-setup_arch.patch powerpc-64-disable-the-speculation-barrier-from-the-command-line.patch powerpc-64-make-meltdown-reporting-book3s-64-specific.patch powerpc-64-make-stf-barrier-ppc_book3s_64-specific.patch powerpc-64-use-barrier_nospec-in-syscall-entry.patch powerpc-64s-add-barrier_nospec.patch powerpc-64s-add-new-security-feature-flags-for-count-cache-flush.patch powerpc-64s-add-support-for-a-store-forwarding-barrier-at-kernel-entry-exit.patch powerpc-64s-add-support-for-ori-barrier_nospec-patching.patch powerpc-64s-add-support-for-software-count-cache-flush.patch powerpc-64s-enable-barrier_nospec-based-on-firmware-settings.patch powerpc-64s-enhance-the-information-in-cpu_show_meltdown.patch powerpc-64s-enhance-the-information-in-cpu_show_spectre_v1.patch powerpc-64s-fix-section-mismatch-warnings-from-setup_rfi_flush.patch powerpc-64s-improve-rfi-l1-d-cache-flush-fallback.patch powerpc-64s-move-cpu_show_meltdown.patch powerpc-64s-patch-barrier_nospec-in-modules.patch powerpc-64s-wire-up-cpu_show_spectre_v1.patch powerpc-64s-wire-up-cpu_show_spectre_v2.patch powerpc-add-security-feature-flags-for-spectre-meltdown.patch powerpc-asm-add-a-patch_site-macro-helpers-for-patching-instructions.patch powerpc-avoid-code-patching-freed-init-sections.patch powerpc-fsl-add-barrier_nospec-implementation-for-nxp-powerpc-book3e.patch powerpc-fsl-add-infrastructure-to-fixup-branch-predictor-flush.patch powerpc-fsl-add-macro-to-flush-the-branch-predictor.patch powerpc-fsl-add-nospectre_v2-command-line-argument.patch powerpc-fsl-fix-spectre_v2-mitigations-reporting.patch powerpc-fsl-fix-the-flush-of-branch-predictor.patch powerpc-fsl-flush-the-branch-predictor-at-each-kernel-entry-64bit.patch powerpc-fsl-update-spectre-v2-reporting.patch powerpc-move-default-security-feature-flags.patch powerpc-powernv-query-firmware-for-count-cache-flush-settings.patch powerpc-powernv-set-or-clear-security-feature-flags.patch powerpc-powernv-support-firmware-disable-of-rfi-flush.patch powerpc-powernv-use-the-security-flags-in-pnv_setup_rfi_flush.patch powerpc-pseries-add-new-h_get_cpu_characteristics-flags.patch powerpc-pseries-fix-clearing-of-security-feature-flags.patch powerpc-pseries-query-hypervisor-for-count-cache-flush-settings.patch powerpc-pseries-restore-default-security-feature-flags-on-setup.patch powerpc-pseries-set-or-clear-security-feature-flags.patch powerpc-pseries-support-firmware-disable-of-rfi-flush.patch powerpc-pseries-use-the-security-flags-in-pseries_setup_rfi_flush.patch powerpc-rfi-flush-always-enable-fallback-flush-on-pseries.patch powerpc-rfi-flush-call-setup_rfi_flush-after-lpm-migration.patch powerpc-rfi-flush-differentiate-enabled-and-patched-flush-types.patch powerpc-rfi-flush-make-it-possible-to-call-setup_rfi_flush-again.patch powerpc-rfi-flush-move-the-logic-to-avoid-a-redo-into-the-debugfs-code.patch powerpc-security-fix-spectre_v2-reporting.patch powerpc-use-barrier_nospec-in-copy_from_user.patch powerpc-xmon-add-rfi-flush-related-fields-to-paca-dump.patch powerpc64s-show-ori31-availability-in-spectre_v1-sysfs-file-not-v2.patch sunrpc-don-t-mark-uninitialised-items-as-valid.patch usb-add-new-usb-lpm-helpers.patch usb-consolidate-lpm-checks-to-avoid-enabling-lpm-twice.patch --- diff --git a/queue-4.4/ceph-ensure-d_name-stability-in-ceph_dentry_hash.patch b/queue-4.4/ceph-ensure-d_name-stability-in-ceph_dentry_hash.patch new file mode 100644 index 00000000000..06fcd50735d --- /dev/null +++ b/queue-4.4/ceph-ensure-d_name-stability-in-ceph_dentry_hash.patch @@ -0,0 +1,44 @@ +From 76a495d666e5043ffc315695f8241f5e94a98849 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Wed, 17 Apr 2019 12:58:28 -0400 +Subject: ceph: ensure d_name stability in ceph_dentry_hash() + +From: Jeff Layton + +commit 76a495d666e5043ffc315695f8241f5e94a98849 upstream. + +Take the d_lock here to ensure that d_name doesn't change. + +Cc: stable@vger.kernel.org +Signed-off-by: Jeff Layton +Reviewed-by: "Yan, Zheng" +Signed-off-by: Ilya Dryomov +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ceph/dir.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/fs/ceph/dir.c ++++ b/fs/ceph/dir.c +@@ -1288,6 +1288,7 @@ void ceph_dentry_lru_del(struct dentry * + unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn) + { + struct ceph_inode_info *dci = ceph_inode(dir); ++ unsigned hash; + + switch (dci->i_dir_layout.dl_dir_hash) { + case 0: /* for backward compat */ +@@ -1295,8 +1296,11 @@ unsigned ceph_dentry_hash(struct inode * + return dn->d_name.hash; + + default: +- return ceph_str_hash(dci->i_dir_layout.dl_dir_hash, ++ spin_lock(&dn->d_lock); ++ hash = ceph_str_hash(dci->i_dir_layout.dl_dir_hash, + dn->d_name.name, dn->d_name.len); ++ spin_unlock(&dn->d_lock); ++ return hash; + } + } + diff --git a/queue-4.4/ceph-fix-ci-i_head_snapc-leak.patch b/queue-4.4/ceph-fix-ci-i_head_snapc-leak.patch new file mode 100644 index 00000000000..fa0fd1da2ac --- /dev/null +++ b/queue-4.4/ceph-fix-ci-i_head_snapc-leak.patch @@ -0,0 +1,59 @@ +From 37659182bff1eeaaeadcfc8f853c6d2b6dbc3f47 Mon Sep 17 00:00:00 2001 +From: "Yan, Zheng" +Date: Thu, 18 Apr 2019 11:24:57 +0800 +Subject: ceph: fix ci->i_head_snapc leak + +From: Yan, Zheng + +commit 37659182bff1eeaaeadcfc8f853c6d2b6dbc3f47 upstream. + +We missed two places that i_wrbuffer_ref_head, i_wr_ref, i_dirty_caps +and i_flushing_caps may change. When they are all zeros, we should free +i_head_snapc. + +Cc: stable@vger.kernel.org +Link: https://tracker.ceph.com/issues/38224 +Reported-and-tested-by: Luis Henriques +Signed-off-by: "Yan, Zheng" +Signed-off-by: Ilya Dryomov +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ceph/mds_client.c | 9 +++++++++ + fs/ceph/snap.c | 7 ++++++- + 2 files changed, 15 insertions(+), 1 deletion(-) + +--- a/fs/ceph/mds_client.c ++++ b/fs/ceph/mds_client.c +@@ -1198,6 +1198,15 @@ static int remove_session_caps_cb(struct + list_add(&ci->i_prealloc_cap_flush->list, &to_remove); + ci->i_prealloc_cap_flush = NULL; + } ++ ++ if (drop && ++ ci->i_wrbuffer_ref_head == 0 && ++ ci->i_wr_ref == 0 && ++ ci->i_dirty_caps == 0 && ++ ci->i_flushing_caps == 0) { ++ ceph_put_snap_context(ci->i_head_snapc); ++ ci->i_head_snapc = NULL; ++ } + } + spin_unlock(&ci->i_ceph_lock); + while (!list_empty(&to_remove)) { +--- a/fs/ceph/snap.c ++++ b/fs/ceph/snap.c +@@ -567,7 +567,12 @@ void ceph_queue_cap_snap(struct ceph_ino + capsnap = NULL; + + update_snapc: +- if (ci->i_head_snapc) { ++ if (ci->i_wrbuffer_ref_head == 0 && ++ ci->i_wr_ref == 0 && ++ ci->i_dirty_caps == 0 && ++ ci->i_flushing_caps == 0) { ++ ci->i_head_snapc = NULL; ++ } else { + ci->i_head_snapc = ceph_get_snap_context(new_snapc); + dout(" new snapc is %p\n", new_snapc); + } diff --git a/queue-4.4/nfsd-don-t-release-the-callback-slot-unless-it-was-actually-held.patch b/queue-4.4/nfsd-don-t-release-the-callback-slot-unless-it-was-actually-held.patch new file mode 100644 index 00000000000..66a6fb41286 --- /dev/null +++ b/queue-4.4/nfsd-don-t-release-the-callback-slot-unless-it-was-actually-held.patch @@ -0,0 +1,82 @@ +From e6abc8caa6deb14be2a206253f7e1c5e37e9515b Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Fri, 5 Apr 2019 08:54:37 -0700 +Subject: nfsd: Don't release the callback slot unless it was actually held + +From: Trond Myklebust + +commit e6abc8caa6deb14be2a206253f7e1c5e37e9515b upstream. + +If there are multiple callbacks queued, waiting for the callback +slot when the callback gets shut down, then they all currently +end up acting as if they hold the slot, and call +nfsd4_cb_sequence_done() resulting in interesting side-effects. + +In addition, the 'retry_nowait' path in nfsd4_cb_sequence_done() +causes a loop back to nfsd4_cb_prepare() without first freeing the +slot, which causes a deadlock when nfsd41_cb_get_slot() gets called +a second time. + +This patch therefore adds a boolean to track whether or not the +callback did pick up the slot, so that it can do the right thing +in these 2 cases. + +Cc: stable@vger.kernel.org +Signed-off-by: Trond Myklebust +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfs4callback.c | 8 +++++++- + fs/nfsd/state.h | 1 + + 2 files changed, 8 insertions(+), 1 deletion(-) + +--- a/fs/nfsd/nfs4callback.c ++++ b/fs/nfsd/nfs4callback.c +@@ -874,8 +874,9 @@ static void nfsd4_cb_prepare(struct rpc_ + cb->cb_seq_status = 1; + cb->cb_status = 0; + if (minorversion) { +- if (!nfsd41_cb_get_slot(clp, task)) ++ if (!cb->cb_holds_slot && !nfsd41_cb_get_slot(clp, task)) + return; ++ cb->cb_holds_slot = true; + } + rpc_call_start(task); + } +@@ -902,6 +903,9 @@ static bool nfsd4_cb_sequence_done(struc + return true; + } + ++ if (!cb->cb_holds_slot) ++ goto need_restart; ++ + switch (cb->cb_seq_status) { + case 0: + /* +@@ -939,6 +943,7 @@ static bool nfsd4_cb_sequence_done(struc + cb->cb_seq_status); + } + ++ cb->cb_holds_slot = false; + clear_bit(0, &clp->cl_cb_slot_busy); + rpc_wake_up_next(&clp->cl_cb_waitq); + dprintk("%s: freed slot, new seqid=%d\n", __func__, +@@ -1146,6 +1151,7 @@ void nfsd4_init_cb(struct nfsd4_callback + cb->cb_seq_status = 1; + cb->cb_status = 0; + cb->cb_need_restart = false; ++ cb->cb_holds_slot = false; + } + + void nfsd4_run_cb(struct nfsd4_callback *cb) +--- a/fs/nfsd/state.h ++++ b/fs/nfsd/state.h +@@ -70,6 +70,7 @@ struct nfsd4_callback { + int cb_seq_status; + int cb_status; + bool cb_need_restart; ++ bool cb_holds_slot; + }; + + struct nfsd4_callback_ops { diff --git a/queue-4.4/powerpc-64-add-config_ppc_barrier_nospec.patch b/queue-4.4/powerpc-64-add-config_ppc_barrier_nospec.patch new file mode 100644 index 00000000000..9467477550d --- /dev/null +++ b/queue-4.4/powerpc-64-add-config_ppc_barrier_nospec.patch @@ -0,0 +1,162 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:20 +1000 +Subject: powerpc/64: Add CONFIG_PPC_BARRIER_NOSPEC +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-36-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 179ab1cbf883575c3a585bcfc0f2160f1d22a149 upstream. + +Add a config symbol to encode which platforms support the +barrier_nospec speculation barrier. Currently this is just Book3S 64 +but we will add Book3E in a future patch. + +Signed-off-by: Diana Craciun +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/Kconfig | 7 ++++++- + arch/powerpc/include/asm/barrier.h | 6 +++--- + arch/powerpc/include/asm/setup.h | 2 +- + arch/powerpc/kernel/Makefile | 3 ++- + arch/powerpc/kernel/module.c | 4 +++- + arch/powerpc/kernel/vmlinux.lds.S | 4 +++- + arch/powerpc/lib/feature-fixups.c | 6 ++++-- + 7 files changed, 22 insertions(+), 10 deletions(-) + +--- a/arch/powerpc/Kconfig ++++ b/arch/powerpc/Kconfig +@@ -136,7 +136,7 @@ config PPC + select GENERIC_SMP_IDLE_THREAD + select GENERIC_CMOS_UPDATE + select GENERIC_TIME_VSYSCALL_OLD +- select GENERIC_CPU_VULNERABILITIES if PPC_BOOK3S_64 ++ select GENERIC_CPU_VULNERABILITIES if PPC_BARRIER_NOSPEC + select GENERIC_CLOCKEVENTS + select GENERIC_CLOCKEVENTS_BROADCAST if SMP + select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST +@@ -162,6 +162,11 @@ config PPC + select ARCH_HAS_DMA_SET_COHERENT_MASK + select HAVE_ARCH_SECCOMP_FILTER + ++config PPC_BARRIER_NOSPEC ++ bool ++ default y ++ depends on PPC_BOOK3S_64 ++ + config GENERIC_CSUM + def_bool CPU_LITTLE_ENDIAN + +--- a/arch/powerpc/include/asm/barrier.h ++++ b/arch/powerpc/include/asm/barrier.h +@@ -92,7 +92,7 @@ do { \ + #define smp_mb__after_atomic() smp_mb() + #define smp_mb__before_spinlock() smp_mb() + +-#ifdef CONFIG_PPC_BOOK3S_64 ++#ifdef CONFIG_PPC_BARRIER_NOSPEC + /* + * Prevent execution of subsequent instructions until preceding branches have + * been fully resolved and are no longer executing speculatively. +@@ -102,9 +102,9 @@ do { \ + // This also acts as a compiler barrier due to the memory clobber. + #define barrier_nospec() asm (stringify_in_c(barrier_nospec_asm) ::: "memory") + +-#else /* !CONFIG_PPC_BOOK3S_64 */ ++#else /* !CONFIG_PPC_BARRIER_NOSPEC */ + #define barrier_nospec_asm + #define barrier_nospec() +-#endif ++#endif /* CONFIG_PPC_BARRIER_NOSPEC */ + + #endif /* _ASM_POWERPC_BARRIER_H */ +--- a/arch/powerpc/include/asm/setup.h ++++ b/arch/powerpc/include/asm/setup.h +@@ -42,7 +42,7 @@ void setup_barrier_nospec(void); + void do_barrier_nospec_fixups(bool enable); + extern bool barrier_nospec_enabled; + +-#ifdef CONFIG_PPC_BOOK3S_64 ++#ifdef CONFIG_PPC_BARRIER_NOSPEC + void do_barrier_nospec_fixups_range(bool enable, void *start, void *end); + #else + static inline void do_barrier_nospec_fixups_range(bool enable, void *start, void *end) { }; +--- a/arch/powerpc/kernel/Makefile ++++ b/arch/powerpc/kernel/Makefile +@@ -40,10 +40,11 @@ obj-$(CONFIG_PPC64) += setup_64.o sys_p + obj-$(CONFIG_VDSO32) += vdso32/ + obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o + obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_ppc970.o cpu_setup_pa6t.o +-obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_power.o security.o ++obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_power.o + obj-$(CONFIG_PPC_BOOK3S_64) += mce.o mce_power.o + obj64-$(CONFIG_RELOCATABLE) += reloc_64.o + obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o idle_book3e.o ++obj-$(CONFIG_PPC_BARRIER_NOSPEC) += security.o + obj-$(CONFIG_PPC64) += vdso64/ + obj-$(CONFIG_ALTIVEC) += vecemu.o + obj-$(CONFIG_PPC_970_NAP) += idle_power4.o +--- a/arch/powerpc/kernel/module.c ++++ b/arch/powerpc/kernel/module.c +@@ -67,13 +67,15 @@ int module_finalize(const Elf_Ehdr *hdr, + do_feature_fixups(powerpc_firmware_features, + (void *)sect->sh_addr, + (void *)sect->sh_addr + sect->sh_size); ++#endif /* CONFIG_PPC64 */ + ++#ifdef CONFIG_PPC_BARRIER_NOSPEC + sect = find_section(hdr, sechdrs, "__spec_barrier_fixup"); + if (sect != NULL) + do_barrier_nospec_fixups_range(barrier_nospec_enabled, + (void *)sect->sh_addr, + (void *)sect->sh_addr + sect->sh_size); +-#endif ++#endif /* CONFIG_PPC_BARRIER_NOSPEC */ + + sect = find_section(hdr, sechdrs, "__lwsync_fixup"); + if (sect != NULL) +--- a/arch/powerpc/kernel/vmlinux.lds.S ++++ b/arch/powerpc/kernel/vmlinux.lds.S +@@ -93,14 +93,16 @@ SECTIONS + *(__rfi_flush_fixup) + __stop___rfi_flush_fixup = .; + } ++#endif /* CONFIG_PPC64 */ + ++#ifdef CONFIG_PPC_BARRIER_NOSPEC + . = ALIGN(8); + __spec_barrier_fixup : AT(ADDR(__spec_barrier_fixup) - LOAD_OFFSET) { + __start___barrier_nospec_fixup = .; + *(__barrier_nospec_fixup) + __stop___barrier_nospec_fixup = .; + } +-#endif ++#endif /* CONFIG_PPC_BARRIER_NOSPEC */ + + EXCEPTION_TABLE(0) + +--- a/arch/powerpc/lib/feature-fixups.c ++++ b/arch/powerpc/lib/feature-fixups.c +@@ -301,6 +301,9 @@ void do_barrier_nospec_fixups_range(bool + printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i); + } + ++#endif /* CONFIG_PPC_BOOK3S_64 */ ++ ++#ifdef CONFIG_PPC_BARRIER_NOSPEC + void do_barrier_nospec_fixups(bool enable) + { + void *start, *end; +@@ -310,8 +313,7 @@ void do_barrier_nospec_fixups(bool enabl + + do_barrier_nospec_fixups_range(enable, start, end); + } +- +-#endif /* CONFIG_PPC_BOOK3S_64 */ ++#endif /* CONFIG_PPC_BARRIER_NOSPEC */ + + void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end) + { diff --git a/queue-4.4/powerpc-64-call-setup_barrier_nospec-from-setup_arch.patch b/queue-4.4/powerpc-64-call-setup_barrier_nospec-from-setup_arch.patch new file mode 100644 index 00000000000..ee9ca1c7600 --- /dev/null +++ b/queue-4.4/powerpc-64-call-setup_barrier_nospec-from-setup_arch.patch @@ -0,0 +1,83 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:21 +1000 +Subject: powerpc/64: Call setup_barrier_nospec() from setup_arch() +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-37-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit af375eefbfb27cbb5b831984e66d724a40d26b5c upstream. + +Currently we require platform code to call setup_barrier_nospec(). But +if we add an empty definition for the !CONFIG_PPC_BARRIER_NOSPEC case +then we can call it in setup_arch(). + +Signed-off-by: Diana Craciun +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/setup.h | 4 ++++ + arch/powerpc/kernel/setup_32.c | 2 ++ + arch/powerpc/kernel/setup_64.c | 2 ++ + arch/powerpc/platforms/powernv/setup.c | 1 - + arch/powerpc/platforms/pseries/setup.c | 1 - + 5 files changed, 8 insertions(+), 2 deletions(-) + +--- a/arch/powerpc/include/asm/setup.h ++++ b/arch/powerpc/include/asm/setup.h +@@ -38,7 +38,11 @@ enum l1d_flush_type { + + void setup_rfi_flush(enum l1d_flush_type, bool enable); + void do_rfi_flush_fixups(enum l1d_flush_type types); ++#ifdef CONFIG_PPC_BARRIER_NOSPEC + void setup_barrier_nospec(void); ++#else ++static inline void setup_barrier_nospec(void) { }; ++#endif + void do_barrier_nospec_fixups(bool enable); + extern bool barrier_nospec_enabled; + +--- a/arch/powerpc/kernel/setup_32.c ++++ b/arch/powerpc/kernel/setup_32.c +@@ -322,6 +322,8 @@ void __init setup_arch(char **cmdline_p) + ppc_md.setup_arch(); + if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); + ++ setup_barrier_nospec(); ++ + paging_init(); + + /* Initialize the MMU context management stuff */ +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -736,6 +736,8 @@ void __init setup_arch(char **cmdline_p) + if (ppc_md.setup_arch) + ppc_md.setup_arch(); + ++ setup_barrier_nospec(); ++ + paging_init(); + + /* Initialize the MMU context management stuff */ +--- a/arch/powerpc/platforms/powernv/setup.c ++++ b/arch/powerpc/platforms/powernv/setup.c +@@ -123,7 +123,6 @@ static void pnv_setup_rfi_flush(void) + security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV)); + + setup_rfi_flush(type, enable); +- setup_barrier_nospec(); + } + + static void __init pnv_setup_arch(void) +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -574,7 +574,6 @@ void pseries_setup_rfi_flush(void) + security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR); + + setup_rfi_flush(types, enable); +- setup_barrier_nospec(); + } + + static void __init pSeries_setup_arch(void) diff --git a/queue-4.4/powerpc-64-disable-the-speculation-barrier-from-the-command-line.patch b/queue-4.4/powerpc-64-disable-the-speculation-barrier-from-the-command-line.patch new file mode 100644 index 00000000000..afcc496ea9b --- /dev/null +++ b/queue-4.4/powerpc-64-disable-the-speculation-barrier-from-the-command-line.patch @@ -0,0 +1,52 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:18 +1000 +Subject: powerpc/64: Disable the speculation barrier from the command line +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-34-mpe@ellerman.id.au> + +From: Diana Craciun + +commit cf175dc315f90185128fb061dc05b6fbb211aa2f upstream. + +The speculation barrier can be disabled from the command line +with the parameter: "nospectre_v1". + +Signed-off-by: Diana Craciun +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/security.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -17,6 +17,7 @@ + unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT; + + bool barrier_nospec_enabled; ++static bool no_nospec; + + static void enable_barrier_nospec(bool enable) + { +@@ -43,9 +44,18 @@ void setup_barrier_nospec(void) + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && + security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR); + +- enable_barrier_nospec(enable); ++ if (!no_nospec) ++ enable_barrier_nospec(enable); + } + ++static int __init handle_nospectre_v1(char *p) ++{ ++ no_nospec = true; ++ ++ return 0; ++} ++early_param("nospectre_v1", handle_nospectre_v1); ++ + #ifdef CONFIG_DEBUG_FS + static int barrier_nospec_set(void *data, u64 val) + { diff --git a/queue-4.4/powerpc-64-make-meltdown-reporting-book3s-64-specific.patch b/queue-4.4/powerpc-64-make-meltdown-reporting-book3s-64-specific.patch new file mode 100644 index 00000000000..0968c3f677b --- /dev/null +++ b/queue-4.4/powerpc-64-make-meltdown-reporting-book3s-64-specific.patch @@ -0,0 +1,42 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:22 +1000 +Subject: powerpc/64: Make meltdown reporting Book3S 64 specific +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-38-mpe@ellerman.id.au> + +From: Diana Craciun + +commit 406d2b6ae3420f5bb2b3db6986dc6f0b6dbb637b upstream. + +In a subsequent patch we will enable building security.c for Book3E. +However the NXP platforms are not vulnerable to Meltdown, so make the +Meltdown vulnerability reporting PPC_BOOK3S_64 specific. + +Signed-off-by: Diana Craciun +[mpe: Split out of larger patch] +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/security.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -93,6 +93,7 @@ static __init int barrier_nospec_debugfs + device_initcall(barrier_nospec_debugfs_init); + #endif /* CONFIG_DEBUG_FS */ + ++#ifdef CONFIG_PPC_BOOK3S_64 + ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) + { + bool thread_priv; +@@ -125,6 +126,7 @@ ssize_t cpu_show_meltdown(struct device + + return sprintf(buf, "Vulnerable\n"); + } ++#endif + + ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf) + { diff --git a/queue-4.4/powerpc-64-make-stf-barrier-ppc_book3s_64-specific.patch b/queue-4.4/powerpc-64-make-stf-barrier-ppc_book3s_64-specific.patch new file mode 100644 index 00000000000..fa591c532ab --- /dev/null +++ b/queue-4.4/powerpc-64-make-stf-barrier-ppc_book3s_64-specific.patch @@ -0,0 +1,37 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:19 +1000 +Subject: powerpc/64: Make stf barrier PPC_BOOK3S_64 specific. +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-35-mpe@ellerman.id.au> + +From: Diana Craciun + +commit 6453b532f2c8856a80381e6b9a1f5ea2f12294df upstream. + +NXP Book3E platforms are not vulnerable to speculative store +bypass, so make the mitigations PPC_BOOK3S_64 specific. + +Signed-off-by: Diana Craciun +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/security.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -177,6 +177,7 @@ ssize_t cpu_show_spectre_v2(struct devic + return s.len; + } + ++#ifdef CONFIG_PPC_BOOK3S_64 + /* + * Store-forwarding barrier support. + */ +@@ -322,3 +323,4 @@ static __init int stf_barrier_debugfs_in + } + device_initcall(stf_barrier_debugfs_init); + #endif /* CONFIG_DEBUG_FS */ ++#endif /* CONFIG_PPC_BOOK3S_64 */ diff --git a/queue-4.4/powerpc-64-use-barrier_nospec-in-syscall-entry.patch b/queue-4.4/powerpc-64-use-barrier_nospec-in-syscall-entry.patch new file mode 100644 index 00000000000..90d04520063 --- /dev/null +++ b/queue-4.4/powerpc-64-use-barrier_nospec-in-syscall-entry.patch @@ -0,0 +1,50 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:14 +1000 +Subject: powerpc/64: Use barrier_nospec in syscall entry +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-30-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 51973a815c6b46d7b23b68d6af371ad1c9d503ca upstream. + +Our syscall entry is done in assembly so patch in an explicit +barrier_nospec. + +Based on a patch by Michal Suchanek. + +Signed-off-by: Michal Suchanek +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/entry_64.S | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/arch/powerpc/kernel/entry_64.S ++++ b/arch/powerpc/kernel/entry_64.S +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + #ifdef CONFIG_PPC_BOOK3S + #include + #else +@@ -177,6 +178,15 @@ system_call: /* label this so stack tr + clrldi r8,r8,32 + 15: + slwi r0,r0,4 ++ ++ barrier_nospec_asm ++ /* ++ * Prevent the load of the handler below (based on the user-passed ++ * system call number) being speculatively executed until the test ++ * against NR_syscalls and branch to .Lsyscall_enosys above has ++ * committed. ++ */ ++ + ldx r12,r11,r0 /* Fetch system call handler [ptr] */ + mtctr r12 + bctrl /* Call handler */ diff --git a/queue-4.4/powerpc-64s-add-barrier_nospec.patch b/queue-4.4/powerpc-64s-add-barrier_nospec.patch new file mode 100644 index 00000000000..20278541ea2 --- /dev/null +++ b/queue-4.4/powerpc-64s-add-barrier_nospec.patch @@ -0,0 +1,53 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:10 +1000 +Subject: powerpc/64s: Add barrier_nospec +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-26-mpe@ellerman.id.au> + +From: Michal Suchanek + +commit a6b3964ad71a61bb7c61d80a60bea7d42187b2eb upstream. + +A no-op form of ori (or immediate of 0 into r31 and the result stored +in r31) has been re-tasked as a speculation barrier. The instruction +only acts as a barrier on newer machines with appropriate firmware +support. On older CPUs it remains a harmless no-op. + +Implement barrier_nospec using this instruction. + +mpe: The semantics of the instruction are believed to be that it +prevents execution of subsequent instructions until preceding branches +have been fully resolved and are no longer executing speculatively. +There is no further documentation available at this time. + +Signed-off-by: Michal Suchanek +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/barrier.h | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/arch/powerpc/include/asm/barrier.h ++++ b/arch/powerpc/include/asm/barrier.h +@@ -92,4 +92,19 @@ do { \ + #define smp_mb__after_atomic() smp_mb() + #define smp_mb__before_spinlock() smp_mb() + ++#ifdef CONFIG_PPC_BOOK3S_64 ++/* ++ * 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 ++ ++// This also acts as a compiler barrier due to the memory clobber. ++#define barrier_nospec() asm (stringify_in_c(barrier_nospec_asm) ::: "memory") ++ ++#else /* !CONFIG_PPC_BOOK3S_64 */ ++#define barrier_nospec_asm ++#define barrier_nospec() ++#endif ++ + #endif /* _ASM_POWERPC_BARRIER_H */ diff --git a/queue-4.4/powerpc-64s-add-new-security-feature-flags-for-count-cache-flush.patch b/queue-4.4/powerpc-64s-add-new-security-feature-flags-for-count-cache-flush.patch new file mode 100644 index 00000000000..0f51c12cdaf --- /dev/null +++ b/queue-4.4/powerpc-64s-add-new-security-feature-flags-for-count-cache-flush.patch @@ -0,0 +1,44 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:25 +1000 +Subject: powerpc/64s: Add new security feature flags for count cache flush +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-41-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit dc8c6cce9a26a51fc19961accb978217a3ba8c75 upstream. + +Add security feature flags to indicate the need for software to flush +the count cache on context switch, and for the presence of a hardware +assisted count cache flush. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/security_features.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/arch/powerpc/include/asm/security_features.h ++++ b/arch/powerpc/include/asm/security_features.h +@@ -59,6 +59,9 @@ static inline bool security_ftr_enabled( + // Indirect branch prediction cache disabled + #define SEC_FTR_COUNT_CACHE_DISABLED 0x0000000000000020ull + ++// bcctr 2,0,0 triggers a hardware assisted count cache flush ++#define SEC_FTR_BCCTR_FLUSH_ASSIST 0x0000000000000800ull ++ + + // Features indicating need for Spectre/Meltdown mitigations + +@@ -74,6 +77,9 @@ static inline bool security_ftr_enabled( + // Firmware configuration indicates user favours security over performance + #define SEC_FTR_FAVOUR_SECURITY 0x0000000000000200ull + ++// Software required to flush count cache on context switch ++#define SEC_FTR_FLUSH_COUNT_CACHE 0x0000000000000400ull ++ + + // Features enabled by default + #define SEC_FTR_DEFAULT \ diff --git a/queue-4.4/powerpc-64s-add-support-for-a-store-forwarding-barrier-at-kernel-entry-exit.patch b/queue-4.4/powerpc-64s-add-support-for-a-store-forwarding-barrier-at-kernel-entry-exit.patch new file mode 100644 index 00000000000..810a46d4a9b --- /dev/null +++ b/queue-4.4/powerpc-64s-add-support-for-a-store-forwarding-barrier-at-kernel-entry-exit.patch @@ -0,0 +1,602 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:09 +1000 +Subject: powerpc/64s: Add support for a store forwarding barrier at kernel entry/exit +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-25-mpe@ellerman.id.au> + +From: Nicholas Piggin + +commit a048a07d7f4535baa4cbad6bc024f175317ab938 upstream. + +On some CPUs we can prevent a vulnerability related to store-to-load +forwarding by preventing store forwarding between privilege domains, +by inserting a barrier in kernel entry and exit paths. + +This is known to be the case on at least Power7, Power8 and Power9 +powerpc CPUs. + +Barriers must be inserted generally before the first load after moving +to a higher privilege, and after the last store before moving to a +lower privilege, HV and PR privilege transitions must be protected. + +Barriers are added as patch sections, with all kernel/hypervisor entry +points patched, and the exit points to lower privilge levels patched +similarly to the RFI flush patching. + +Firmware advertisement is not implemented yet, so CPU flush types +are hard coded. + +Thanks to Michal Suchánek for bug fixes and review. + +Signed-off-by: Nicholas Piggin +Signed-off-by: Mauricio Faria de Oliveira +Signed-off-by: Michael Neuling +Signed-off-by: Michal Suchánek +[mpe: 4.4 doesn't have EXC_REAL_OOL_MASKABLE, so do it manually] +Signed-off-by: Michael Ellerman +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/exception-64s.h | 35 ++++++ + arch/powerpc/include/asm/feature-fixups.h | 19 +++ + arch/powerpc/include/asm/security_features.h | 11 ++ + arch/powerpc/kernel/exceptions-64s.S | 22 +++- + arch/powerpc/kernel/security.c | 148 +++++++++++++++++++++++++++ + arch/powerpc/kernel/vmlinux.lds.S | 14 ++ + arch/powerpc/lib/feature-fixups.c | 116 ++++++++++++++++++++- + arch/powerpc/platforms/powernv/setup.c | 1 + arch/powerpc/platforms/pseries/setup.c | 1 + 9 files changed, 365 insertions(+), 2 deletions(-) + +--- a/arch/powerpc/include/asm/exception-64s.h ++++ b/arch/powerpc/include/asm/exception-64s.h +@@ -50,6 +50,27 @@ + #define EX_PPR 88 /* SMT thread status register (priority) */ + #define EX_CTR 96 + ++#define STF_ENTRY_BARRIER_SLOT \ ++ STF_ENTRY_BARRIER_FIXUP_SECTION; \ ++ nop; \ ++ nop; \ ++ nop ++ ++#define STF_EXIT_BARRIER_SLOT \ ++ STF_EXIT_BARRIER_FIXUP_SECTION; \ ++ nop; \ ++ nop; \ ++ nop; \ ++ nop; \ ++ nop; \ ++ nop ++ ++/* ++ * r10 must be free to use, r13 must be paca ++ */ ++#define INTERRUPT_TO_KERNEL \ ++ STF_ENTRY_BARRIER_SLOT ++ + /* + * Macros for annotating the expected destination of (h)rfid + * +@@ -66,16 +87,19 @@ + rfid + + #define RFI_TO_USER \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + rfid; \ + b rfi_flush_fallback + + #define RFI_TO_USER_OR_KERNEL \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + rfid; \ + b rfi_flush_fallback + + #define RFI_TO_GUEST \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + rfid; \ + b rfi_flush_fallback +@@ -84,21 +108,25 @@ + hrfid + + #define HRFI_TO_USER \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + hrfid; \ + b hrfi_flush_fallback + + #define HRFI_TO_USER_OR_KERNEL \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + hrfid; \ + b hrfi_flush_fallback + + #define HRFI_TO_GUEST \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + hrfid; \ + b hrfi_flush_fallback + + #define HRFI_TO_UNKNOWN \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + hrfid; \ + b hrfi_flush_fallback +@@ -226,6 +254,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) + #define __EXCEPTION_PROLOG_1(area, extra, vec) \ + OPT_SAVE_REG_TO_PACA(area+EX_PPR, r9, CPU_FTR_HAS_PPR); \ + OPT_SAVE_REG_TO_PACA(area+EX_CFAR, r10, CPU_FTR_CFAR); \ ++ INTERRUPT_TO_KERNEL; \ + SAVE_CTR(r10, area); \ + mfcr r9; \ + extra(vec); \ +@@ -512,6 +541,12 @@ label##_relon_hv: \ + #define _MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ + __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) + ++#define MASKABLE_EXCEPTION_OOL(vec, label) \ ++ .globl label##_ool; \ ++label##_ool: \ ++ EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_PR, vec); \ ++ EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_STD); ++ + #define MASKABLE_EXCEPTION_PSERIES(loc, vec, label) \ + . = loc; \ + .globl label##_pSeries; \ +--- a/arch/powerpc/include/asm/feature-fixups.h ++++ b/arch/powerpc/include/asm/feature-fixups.h +@@ -184,6 +184,22 @@ label##3: \ + FTR_ENTRY_OFFSET label##1b-label##3b; \ + .popsection; + ++#define STF_ENTRY_BARRIER_FIXUP_SECTION \ ++953: \ ++ .pushsection __stf_entry_barrier_fixup,"a"; \ ++ .align 2; \ ++954: \ ++ FTR_ENTRY_OFFSET 953b-954b; \ ++ .popsection; ++ ++#define STF_EXIT_BARRIER_FIXUP_SECTION \ ++955: \ ++ .pushsection __stf_exit_barrier_fixup,"a"; \ ++ .align 2; \ ++956: \ ++ FTR_ENTRY_OFFSET 955b-956b; \ ++ .popsection; ++ + #define RFI_FLUSH_FIXUP_SECTION \ + 951: \ + .pushsection __rfi_flush_fixup,"a"; \ +@@ -195,6 +211,9 @@ label##3: \ + + #ifndef __ASSEMBLY__ + ++extern long stf_barrier_fallback; ++extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup; ++extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup; + extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup; + + #endif +--- a/arch/powerpc/include/asm/security_features.h ++++ b/arch/powerpc/include/asm/security_features.h +@@ -12,6 +12,17 @@ + extern unsigned long powerpc_security_features; + extern bool rfi_flush; + ++/* These are bit flags */ ++enum stf_barrier_type { ++ STF_BARRIER_NONE = 0x1, ++ STF_BARRIER_FALLBACK = 0x2, ++ STF_BARRIER_EIEIO = 0x4, ++ STF_BARRIER_SYNC_ORI = 0x8, ++}; ++ ++void setup_stf_barrier(void); ++void do_stf_barrier_fixups(enum stf_barrier_type types); ++ + static inline void security_ftr_set(unsigned long feature) + { + powerpc_security_features |= feature; +--- a/arch/powerpc/kernel/exceptions-64s.S ++++ b/arch/powerpc/kernel/exceptions-64s.S +@@ -36,6 +36,7 @@ BEGIN_FTR_SECTION \ + END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \ + mr r9,r13 ; \ + GET_PACA(r13) ; \ ++ INTERRUPT_TO_KERNEL ; \ + mfspr r11,SPRN_SRR0 ; \ + 0: + +@@ -292,7 +293,9 @@ hardware_interrupt_hv: + . = 0x900 + .globl decrementer_pSeries + decrementer_pSeries: +- _MASKABLE_EXCEPTION_PSERIES(0x900, decrementer, EXC_STD, SOFTEN_TEST_PR) ++ SET_SCRATCH0(r13) ++ EXCEPTION_PROLOG_0(PACA_EXGEN) ++ b decrementer_ool + + STD_EXCEPTION_HV(0x980, 0x982, hdecrementer) + +@@ -319,6 +322,7 @@ system_call_pSeries: + OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR); + HMT_MEDIUM; + std r10,PACA_EXGEN+EX_R10(r13) ++ INTERRUPT_TO_KERNEL + OPT_SAVE_REG_TO_PACA(PACA_EXGEN+EX_PPR, r9, CPU_FTR_HAS_PPR); + mfcr r9 + KVMTEST(0xc00) +@@ -607,6 +611,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) + + .align 7 + /* moved from 0xe00 */ ++ MASKABLE_EXCEPTION_OOL(0x900, decrementer) + STD_EXCEPTION_HV_OOL(0xe02, h_data_storage) + KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0xe02) + STD_EXCEPTION_HV_OOL(0xe22, h_instr_storage) +@@ -1564,6 +1569,21 @@ power4_fixup_nap: + blr + #endif + ++ .balign 16 ++ .globl stf_barrier_fallback ++stf_barrier_fallback: ++ std r9,PACA_EXRFI+EX_R9(r13) ++ std r10,PACA_EXRFI+EX_R10(r13) ++ sync ++ ld r9,PACA_EXRFI+EX_R9(r13) ++ ld r10,PACA_EXRFI+EX_R10(r13) ++ ori 31,31,0 ++ .rept 14 ++ b 1f ++1: ++ .endr ++ blr ++ + .globl rfi_flush_fallback + rfi_flush_fallback: + SET_SCRATCH0(r13); +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -5,9 +5,11 @@ + // Copyright 2018, Michael Ellerman, IBM Corporation. + + #include ++#include + #include + #include + ++#include + #include + + +@@ -86,3 +88,149 @@ ssize_t cpu_show_spectre_v2(struct devic + + return s.len; + } ++ ++/* ++ * Store-forwarding barrier support. ++ */ ++ ++static enum stf_barrier_type stf_enabled_flush_types; ++static bool no_stf_barrier; ++bool stf_barrier; ++ ++static int __init handle_no_stf_barrier(char *p) ++{ ++ pr_info("stf-barrier: disabled on command line."); ++ no_stf_barrier = true; ++ return 0; ++} ++ ++early_param("no_stf_barrier", handle_no_stf_barrier); ++ ++/* This is the generic flag used by other architectures */ ++static int __init handle_ssbd(char *p) ++{ ++ if (!p || strncmp(p, "auto", 5) == 0 || strncmp(p, "on", 2) == 0 ) { ++ /* Until firmware tells us, we have the barrier with auto */ ++ return 0; ++ } else if (strncmp(p, "off", 3) == 0) { ++ handle_no_stf_barrier(NULL); ++ return 0; ++ } else ++ return 1; ++ ++ return 0; ++} ++early_param("spec_store_bypass_disable", handle_ssbd); ++ ++/* This is the generic flag used by other architectures */ ++static int __init handle_no_ssbd(char *p) ++{ ++ handle_no_stf_barrier(NULL); ++ return 0; ++} ++early_param("nospec_store_bypass_disable", handle_no_ssbd); ++ ++static void stf_barrier_enable(bool enable) ++{ ++ if (enable) ++ do_stf_barrier_fixups(stf_enabled_flush_types); ++ else ++ do_stf_barrier_fixups(STF_BARRIER_NONE); ++ ++ stf_barrier = enable; ++} ++ ++void setup_stf_barrier(void) ++{ ++ enum stf_barrier_type type; ++ bool enable, hv; ++ ++ hv = cpu_has_feature(CPU_FTR_HVMODE); ++ ++ /* Default to fallback in case fw-features are not available */ ++ if (cpu_has_feature(CPU_FTR_ARCH_207S)) ++ type = STF_BARRIER_SYNC_ORI; ++ else if (cpu_has_feature(CPU_FTR_ARCH_206)) ++ type = STF_BARRIER_FALLBACK; ++ else ++ type = STF_BARRIER_NONE; ++ ++ enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && ++ (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) || ++ (security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) && hv)); ++ ++ if (type == STF_BARRIER_FALLBACK) { ++ pr_info("stf-barrier: fallback barrier available\n"); ++ } else if (type == STF_BARRIER_SYNC_ORI) { ++ pr_info("stf-barrier: hwsync barrier available\n"); ++ } else if (type == STF_BARRIER_EIEIO) { ++ pr_info("stf-barrier: eieio barrier available\n"); ++ } ++ ++ stf_enabled_flush_types = type; ++ ++ if (!no_stf_barrier) ++ stf_barrier_enable(enable); ++} ++ ++ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ if (stf_barrier && stf_enabled_flush_types != STF_BARRIER_NONE) { ++ const char *type; ++ switch (stf_enabled_flush_types) { ++ case STF_BARRIER_EIEIO: ++ type = "eieio"; ++ break; ++ case STF_BARRIER_SYNC_ORI: ++ type = "hwsync"; ++ break; ++ case STF_BARRIER_FALLBACK: ++ type = "fallback"; ++ break; ++ default: ++ type = "unknown"; ++ } ++ return sprintf(buf, "Mitigation: Kernel entry/exit barrier (%s)\n", type); ++ } ++ ++ if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) && ++ !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR)) ++ return sprintf(buf, "Not affected\n"); ++ ++ return sprintf(buf, "Vulnerable\n"); ++} ++ ++#ifdef CONFIG_DEBUG_FS ++static int stf_barrier_set(void *data, u64 val) ++{ ++ bool enable; ++ ++ if (val == 1) ++ enable = true; ++ else if (val == 0) ++ enable = false; ++ else ++ return -EINVAL; ++ ++ /* Only do anything if we're changing state */ ++ if (enable != stf_barrier) ++ stf_barrier_enable(enable); ++ ++ return 0; ++} ++ ++static int stf_barrier_get(void *data, u64 *val) ++{ ++ *val = stf_barrier ? 1 : 0; ++ return 0; ++} ++ ++DEFINE_SIMPLE_ATTRIBUTE(fops_stf_barrier, stf_barrier_get, stf_barrier_set, "%llu\n"); ++ ++static __init int stf_barrier_debugfs_init(void) ++{ ++ debugfs_create_file("stf_barrier", 0600, powerpc_debugfs_root, NULL, &fops_stf_barrier); ++ return 0; ++} ++device_initcall(stf_barrier_debugfs_init); ++#endif /* CONFIG_DEBUG_FS */ +--- a/arch/powerpc/kernel/vmlinux.lds.S ++++ b/arch/powerpc/kernel/vmlinux.lds.S +@@ -74,6 +74,20 @@ SECTIONS + + #ifdef CONFIG_PPC64 + . = ALIGN(8); ++ __stf_entry_barrier_fixup : AT(ADDR(__stf_entry_barrier_fixup) - LOAD_OFFSET) { ++ __start___stf_entry_barrier_fixup = .; ++ *(__stf_entry_barrier_fixup) ++ __stop___stf_entry_barrier_fixup = .; ++ } ++ ++ . = ALIGN(8); ++ __stf_exit_barrier_fixup : AT(ADDR(__stf_exit_barrier_fixup) - LOAD_OFFSET) { ++ __start___stf_exit_barrier_fixup = .; ++ *(__stf_exit_barrier_fixup) ++ __stop___stf_exit_barrier_fixup = .; ++ } ++ ++ . = ALIGN(8); + __rfi_flush_fixup : AT(ADDR(__rfi_flush_fixup) - LOAD_OFFSET) { + __start___rfi_flush_fixup = .; + *(__rfi_flush_fixup) +--- a/arch/powerpc/lib/feature-fixups.c ++++ b/arch/powerpc/lib/feature-fixups.c +@@ -21,7 +21,7 @@ + #include + #include + #include +- ++#include + + struct fixup_entry { + unsigned long mask; +@@ -115,6 +115,120 @@ void do_feature_fixups(unsigned long val + } + + #ifdef CONFIG_PPC_BOOK3S_64 ++void do_stf_entry_barrier_fixups(enum stf_barrier_type types) ++{ ++ unsigned int instrs[3], *dest; ++ long *start, *end; ++ int i; ++ ++ start = PTRRELOC(&__start___stf_entry_barrier_fixup), ++ end = PTRRELOC(&__stop___stf_entry_barrier_fixup); ++ ++ instrs[0] = 0x60000000; /* nop */ ++ instrs[1] = 0x60000000; /* nop */ ++ instrs[2] = 0x60000000; /* nop */ ++ ++ i = 0; ++ if (types & STF_BARRIER_FALLBACK) { ++ instrs[i++] = 0x7d4802a6; /* mflr r10 */ ++ instrs[i++] = 0x60000000; /* branch patched below */ ++ instrs[i++] = 0x7d4803a6; /* mtlr r10 */ ++ } else if (types & STF_BARRIER_EIEIO) { ++ instrs[i++] = 0x7e0006ac; /* eieio + bit 6 hint */ ++ } else if (types & STF_BARRIER_SYNC_ORI) { ++ instrs[i++] = 0x7c0004ac; /* hwsync */ ++ instrs[i++] = 0xe94d0000; /* ld r10,0(r13) */ ++ instrs[i++] = 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, instrs[0]); ++ ++ if (types & STF_BARRIER_FALLBACK) ++ patch_branch(dest + 1, (unsigned long)&stf_barrier_fallback, ++ BRANCH_SET_LINK); ++ else ++ patch_instruction(dest + 1, instrs[1]); ++ ++ patch_instruction(dest + 2, instrs[2]); ++ } ++ ++ printk(KERN_DEBUG "stf-barrier: patched %d entry locations (%s barrier)\n", i, ++ (types == STF_BARRIER_NONE) ? "no" : ++ (types == STF_BARRIER_FALLBACK) ? "fallback" : ++ (types == STF_BARRIER_EIEIO) ? "eieio" : ++ (types == (STF_BARRIER_SYNC_ORI)) ? "hwsync" ++ : "unknown"); ++} ++ ++void do_stf_exit_barrier_fixups(enum stf_barrier_type types) ++{ ++ unsigned int instrs[6], *dest; ++ long *start, *end; ++ int i; ++ ++ start = PTRRELOC(&__start___stf_exit_barrier_fixup), ++ end = PTRRELOC(&__stop___stf_exit_barrier_fixup); ++ ++ instrs[0] = 0x60000000; /* nop */ ++ instrs[1] = 0x60000000; /* nop */ ++ instrs[2] = 0x60000000; /* nop */ ++ instrs[3] = 0x60000000; /* nop */ ++ instrs[4] = 0x60000000; /* nop */ ++ instrs[5] = 0x60000000; /* nop */ ++ ++ i = 0; ++ if (types & STF_BARRIER_FALLBACK || types & STF_BARRIER_SYNC_ORI) { ++ if (cpu_has_feature(CPU_FTR_HVMODE)) { ++ instrs[i++] = 0x7db14ba6; /* mtspr 0x131, r13 (HSPRG1) */ ++ instrs[i++] = 0x7db04aa6; /* mfspr r13, 0x130 (HSPRG0) */ ++ } else { ++ instrs[i++] = 0x7db243a6; /* mtsprg 2,r13 */ ++ instrs[i++] = 0x7db142a6; /* mfsprg r13,1 */ ++ } ++ instrs[i++] = 0x7c0004ac; /* hwsync */ ++ instrs[i++] = 0xe9ad0000; /* ld r13,0(r13) */ ++ instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */ ++ if (cpu_has_feature(CPU_FTR_HVMODE)) { ++ instrs[i++] = 0x7db14aa6; /* mfspr r13, 0x131 (HSPRG1) */ ++ } else { ++ instrs[i++] = 0x7db242a6; /* mfsprg r13,2 */ ++ } ++ } else if (types & STF_BARRIER_EIEIO) { ++ instrs[i++] = 0x7e0006ac; /* eieio + bit 6 hint */ ++ } ++ ++ for (i = 0; start < end; start++, i++) { ++ dest = (void *)start + *start; ++ ++ pr_devel("patching dest %lx\n", (unsigned long)dest); ++ ++ patch_instruction(dest, instrs[0]); ++ patch_instruction(dest + 1, instrs[1]); ++ patch_instruction(dest + 2, instrs[2]); ++ patch_instruction(dest + 3, instrs[3]); ++ patch_instruction(dest + 4, instrs[4]); ++ patch_instruction(dest + 5, instrs[5]); ++ } ++ printk(KERN_DEBUG "stf-barrier: patched %d exit locations (%s barrier)\n", i, ++ (types == STF_BARRIER_NONE) ? "no" : ++ (types == STF_BARRIER_FALLBACK) ? "fallback" : ++ (types == STF_BARRIER_EIEIO) ? "eieio" : ++ (types == (STF_BARRIER_SYNC_ORI)) ? "hwsync" ++ : "unknown"); ++} ++ ++ ++void do_stf_barrier_fixups(enum stf_barrier_type types) ++{ ++ do_stf_entry_barrier_fixups(types); ++ do_stf_exit_barrier_fixups(types); ++} ++ + void do_rfi_flush_fixups(enum l1d_flush_type types) + { + unsigned int instrs[3], *dest; +--- a/arch/powerpc/platforms/powernv/setup.c ++++ b/arch/powerpc/platforms/powernv/setup.c +@@ -130,6 +130,7 @@ static void __init pnv_setup_arch(void) + set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT); + + pnv_setup_rfi_flush(); ++ setup_stf_barrier(); + + /* Initialize SMP */ + pnv_smp_init(); +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -593,6 +593,7 @@ static void __init pSeries_setup_arch(vo + fwnmi_init(); + + pseries_setup_rfi_flush(); ++ setup_stf_barrier(); + + /* By default, only probe PCI (can be overridden by rtas_pci) */ + pci_add_flags(PCI_PROBE_ONLY); diff --git a/queue-4.4/powerpc-64s-add-support-for-ori-barrier_nospec-patching.patch b/queue-4.4/powerpc-64s-add-support-for-ori-barrier_nospec-patching.patch new file mode 100644 index 00000000000..8a71c859cdd --- /dev/null +++ b/queue-4.4/powerpc-64s-add-support-for-ori-barrier_nospec-patching.patch @@ -0,0 +1,152 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:11 +1000 +Subject: powerpc/64s: Add support for ori barrier_nospec patching +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-27-mpe@ellerman.id.au> + +From: Michal Suchanek + +commit 2eea7f067f495e33b8b116b35b5988ab2b8aec55 upstream. + +Based on the RFI patching. This is required to be able to disable the +speculation barrier. + +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 +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + 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(-) + +--- a/arch/powerpc/include/asm/barrier.h ++++ b/arch/powerpc/include/asm/barrier.h +@@ -97,7 +97,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") +--- a/arch/powerpc/include/asm/feature-fixups.h ++++ b/arch/powerpc/include/asm/feature-fixups.h +@@ -208,6 +208,14 @@ 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__ + +@@ -215,6 +223,7 @@ extern long stf_barrier_fallback; + extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup; + 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; + + #endif + +--- a/arch/powerpc/include/asm/setup.h ++++ b/arch/powerpc/include/asm/setup.h +@@ -38,6 +38,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__ */ + +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -11,10 +11,19 @@ + + #include + #include ++#include + + + 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; +--- a/arch/powerpc/kernel/vmlinux.lds.S ++++ b/arch/powerpc/kernel/vmlinux.lds.S +@@ -93,6 +93,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) +--- a/arch/powerpc/lib/feature-fixups.c ++++ b/arch/powerpc/lib/feature-fixups.c +@@ -274,6 +274,33 @@ void do_rfi_flush_fixups(enum l1d_flush_ + (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) diff --git a/queue-4.4/powerpc-64s-add-support-for-software-count-cache-flush.patch b/queue-4.4/powerpc-64s-add-support-for-software-count-cache-flush.patch new file mode 100644 index 00000000000..6ca135d7689 --- /dev/null +++ b/queue-4.4/powerpc-64s-add-support-for-software-count-cache-flush.patch @@ -0,0 +1,281 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:26 +1000 +Subject: powerpc/64s: Add support for software count cache flush +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-42-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit ee13cb249fabdff8b90aaff61add347749280087 upstream. + +Some CPU revisions support a mode where the count cache needs to be +flushed by software on context switch. Additionally some revisions may +have a hardware accelerated flush, in which case the software flush +sequence can be shortened. + +If we detect the appropriate flag from firmware we patch a branch +into _switch() which takes us to a count cache flush sequence. + +That sequence in turn may be patched to return early if we detect that +the CPU supports accelerating the flush sequence in hardware. + +Add debugfs support for reporting the state of the flush, as well as +runtime disabling it. + +And modify the spectre_v2 sysfs file to report the state of the +software flush. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/asm-prototypes.h | 21 +++++ + arch/powerpc/include/asm/security_features.h | 1 + arch/powerpc/kernel/entry_64.S | 54 ++++++++++++++ + arch/powerpc/kernel/security.c | 98 +++++++++++++++++++++++++-- + 4 files changed, 169 insertions(+), 5 deletions(-) + create mode 100644 arch/powerpc/include/asm/asm-prototypes.h + +--- /dev/null ++++ b/arch/powerpc/include/asm/asm-prototypes.h +@@ -0,0 +1,21 @@ ++#ifndef _ASM_POWERPC_ASM_PROTOTYPES_H ++#define _ASM_POWERPC_ASM_PROTOTYPES_H ++/* ++ * This file is for prototypes of C functions that are only called ++ * from asm, and any associated variables. ++ * ++ * Copyright 2016, Daniel Axtens, IBM Corporation. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ */ ++ ++/* Patch sites */ ++extern s32 patch__call_flush_count_cache; ++extern s32 patch__flush_count_cache_return; ++ ++extern long flush_count_cache; ++ ++#endif /* _ASM_POWERPC_ASM_PROTOTYPES_H */ +--- a/arch/powerpc/include/asm/security_features.h ++++ b/arch/powerpc/include/asm/security_features.h +@@ -22,6 +22,7 @@ enum stf_barrier_type { + + void setup_stf_barrier(void); + void do_stf_barrier_fixups(enum stf_barrier_type types); ++void setup_count_cache_flush(void); + + static inline void security_ftr_set(unsigned long feature) + { +--- a/arch/powerpc/kernel/entry_64.S ++++ b/arch/powerpc/kernel/entry_64.S +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -450,6 +451,57 @@ _GLOBAL(ret_from_kernel_thread) + li r3,0 + b .Lsyscall_exit + ++#ifdef CONFIG_PPC_BOOK3S_64 ++ ++#define FLUSH_COUNT_CACHE \ ++1: nop; \ ++ patch_site 1b, patch__call_flush_count_cache ++ ++ ++#define BCCTR_FLUSH .long 0x4c400420 ++ ++.macro nops number ++ .rept \number ++ nop ++ .endr ++.endm ++ ++.balign 32 ++.global flush_count_cache ++flush_count_cache: ++ /* Save LR into r9 */ ++ mflr r9 ++ ++ .rept 64 ++ bl .+4 ++ .endr ++ b 1f ++ nops 6 ++ ++ .balign 32 ++ /* Restore LR */ ++1: mtlr r9 ++ li r9,0x7fff ++ mtctr r9 ++ ++ BCCTR_FLUSH ++ ++2: nop ++ patch_site 2b patch__flush_count_cache_return ++ ++ nops 3 ++ ++ .rept 278 ++ .balign 32 ++ BCCTR_FLUSH ++ nops 7 ++ .endr ++ ++ blr ++#else ++#define FLUSH_COUNT_CACHE ++#endif /* CONFIG_PPC_BOOK3S_64 */ ++ + /* + * This routine switches between two different tasks. The process + * state of one is saved on its kernel stack. Then the state +@@ -513,6 +565,8 @@ BEGIN_FTR_SECTION + END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) + #endif + ++ FLUSH_COUNT_CACHE ++ + #ifdef CONFIG_SMP + /* We need a sync somewhere here to make sure that if the + * previous task gets rescheduled on another CPU, it sees all +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -10,12 +10,21 @@ + #include + + #include ++#include ++#include + #include + #include + + + unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT; + ++enum count_cache_flush_type { ++ COUNT_CACHE_FLUSH_NONE = 0x1, ++ COUNT_CACHE_FLUSH_SW = 0x2, ++ COUNT_CACHE_FLUSH_HW = 0x4, ++}; ++static enum count_cache_flush_type count_cache_flush_type; ++ + bool barrier_nospec_enabled; + static bool no_nospec; + +@@ -160,17 +169,29 @@ ssize_t cpu_show_spectre_v2(struct devic + bcs = security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED); + ccd = security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED); + +- if (bcs || ccd) { ++ if (bcs || ccd || count_cache_flush_type != COUNT_CACHE_FLUSH_NONE) { ++ bool comma = false; + seq_buf_printf(&s, "Mitigation: "); + +- if (bcs) ++ if (bcs) { + seq_buf_printf(&s, "Indirect branch serialisation (kernel only)"); ++ comma = true; ++ } ++ ++ if (ccd) { ++ if (comma) ++ seq_buf_printf(&s, ", "); ++ seq_buf_printf(&s, "Indirect branch cache disabled"); ++ comma = true; ++ } + +- if (bcs && ccd) ++ if (comma) + seq_buf_printf(&s, ", "); + +- if (ccd) +- seq_buf_printf(&s, "Indirect branch cache disabled"); ++ seq_buf_printf(&s, "Software count cache flush"); ++ ++ if (count_cache_flush_type == COUNT_CACHE_FLUSH_HW) ++ seq_buf_printf(&s, "(hardware accelerated)"); + } else + seq_buf_printf(&s, "Vulnerable"); + +@@ -325,4 +346,71 @@ static __init int stf_barrier_debugfs_in + } + device_initcall(stf_barrier_debugfs_init); + #endif /* CONFIG_DEBUG_FS */ ++ ++static void toggle_count_cache_flush(bool enable) ++{ ++ if (!enable || !security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) { ++ patch_instruction_site(&patch__call_flush_count_cache, PPC_INST_NOP); ++ count_cache_flush_type = COUNT_CACHE_FLUSH_NONE; ++ pr_info("count-cache-flush: software flush disabled.\n"); ++ return; ++ } ++ ++ patch_branch_site(&patch__call_flush_count_cache, ++ (u64)&flush_count_cache, BRANCH_SET_LINK); ++ ++ if (!security_ftr_enabled(SEC_FTR_BCCTR_FLUSH_ASSIST)) { ++ count_cache_flush_type = COUNT_CACHE_FLUSH_SW; ++ pr_info("count-cache-flush: full software flush sequence enabled.\n"); ++ return; ++ } ++ ++ patch_instruction_site(&patch__flush_count_cache_return, PPC_INST_BLR); ++ count_cache_flush_type = COUNT_CACHE_FLUSH_HW; ++ pr_info("count-cache-flush: hardware assisted flush sequence enabled\n"); ++} ++ ++void setup_count_cache_flush(void) ++{ ++ toggle_count_cache_flush(true); ++} ++ ++#ifdef CONFIG_DEBUG_FS ++static int count_cache_flush_set(void *data, u64 val) ++{ ++ bool enable; ++ ++ if (val == 1) ++ enable = true; ++ else if (val == 0) ++ enable = false; ++ else ++ return -EINVAL; ++ ++ toggle_count_cache_flush(enable); ++ ++ return 0; ++} ++ ++static int count_cache_flush_get(void *data, u64 *val) ++{ ++ if (count_cache_flush_type == COUNT_CACHE_FLUSH_NONE) ++ *val = 0; ++ else ++ *val = 1; ++ ++ return 0; ++} ++ ++DEFINE_SIMPLE_ATTRIBUTE(fops_count_cache_flush, count_cache_flush_get, ++ count_cache_flush_set, "%llu\n"); ++ ++static __init int count_cache_flush_debugfs_init(void) ++{ ++ debugfs_create_file("count_cache_flush", 0600, powerpc_debugfs_root, ++ NULL, &fops_count_cache_flush); ++ return 0; ++} ++device_initcall(count_cache_flush_debugfs_init); ++#endif /* CONFIG_DEBUG_FS */ + #endif /* CONFIG_PPC_BOOK3S_64 */ diff --git a/queue-4.4/powerpc-64s-enable-barrier_nospec-based-on-firmware-settings.patch b/queue-4.4/powerpc-64s-enable-barrier_nospec-based-on-firmware-settings.patch new file mode 100644 index 00000000000..4096fedaada --- /dev/null +++ b/queue-4.4/powerpc-64s-enable-barrier_nospec-based-on-firmware-settings.patch @@ -0,0 +1,125 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:13 +1000 +Subject: powerpc/64s: Enable barrier_nospec based on firmware settings +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-29-mpe@ellerman.id.au> + +From: Michal Suchanek + +commit cb3d6759a93c6d0aea1c10deb6d00e111c29c19c upstream. + +Check what firmware told us and enable/disable the barrier_nospec as +appropriate. + +We err on the side of enabling the barrier, as it's no-op on older +systems, see the comment for more detail. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/setup.h | 1 + arch/powerpc/kernel/security.c | 59 +++++++++++++++++++++++++++++++++ + arch/powerpc/platforms/powernv/setup.c | 1 + arch/powerpc/platforms/pseries/setup.c | 1 + 4 files changed, 62 insertions(+) + +--- a/arch/powerpc/include/asm/setup.h ++++ b/arch/powerpc/include/asm/setup.h +@@ -38,6 +38,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 setup_barrier_nospec(void); + void do_barrier_nospec_fixups(bool enable); + extern bool barrier_nospec_enabled; + +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -24,6 +24,65 @@ static void enable_barrier_nospec(bool e + do_barrier_nospec_fixups(enable); + } + ++void setup_barrier_nospec(void) ++{ ++ bool enable; ++ ++ /* ++ * It would make sense to check SEC_FTR_SPEC_BAR_ORI31 below as well. ++ * But there's a good reason not to. The two flags we check below are ++ * both are enabled by default in the kernel, so if the hcall is not ++ * functional they will be enabled. ++ * On a system where the host firmware has been updated (so the ori ++ * functions as a barrier), but on which the hypervisor (KVM/Qemu) has ++ * not been updated, we would like to enable the barrier. Dropping the ++ * check for SEC_FTR_SPEC_BAR_ORI31 achieves that. The only downside is ++ * we potentially enable the barrier on systems where the host firmware ++ * is not updated, but that's harmless as it's a no-op. ++ */ ++ enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && ++ security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR); ++ ++ enable_barrier_nospec(enable); ++} ++ ++#ifdef CONFIG_DEBUG_FS ++static int barrier_nospec_set(void *data, u64 val) ++{ ++ switch (val) { ++ case 0: ++ case 1: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (!!val == !!barrier_nospec_enabled) ++ return 0; ++ ++ enable_barrier_nospec(!!val); ++ ++ return 0; ++} ++ ++static int barrier_nospec_get(void *data, u64 *val) ++{ ++ *val = barrier_nospec_enabled ? 1 : 0; ++ return 0; ++} ++ ++DEFINE_SIMPLE_ATTRIBUTE(fops_barrier_nospec, ++ barrier_nospec_get, barrier_nospec_set, "%llu\n"); ++ ++static __init int barrier_nospec_debugfs_init(void) ++{ ++ debugfs_create_file("barrier_nospec", 0600, powerpc_debugfs_root, NULL, ++ &fops_barrier_nospec); ++ return 0; ++} ++device_initcall(barrier_nospec_debugfs_init); ++#endif /* CONFIG_DEBUG_FS */ ++ + ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) + { + bool thread_priv; +--- a/arch/powerpc/platforms/powernv/setup.c ++++ b/arch/powerpc/platforms/powernv/setup.c +@@ -123,6 +123,7 @@ static void pnv_setup_rfi_flush(void) + security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV)); + + setup_rfi_flush(type, enable); ++ setup_barrier_nospec(); + } + + static void __init pnv_setup_arch(void) +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -574,6 +574,7 @@ void pseries_setup_rfi_flush(void) + security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR); + + setup_rfi_flush(types, enable); ++ setup_barrier_nospec(); + } + + static void __init pSeries_setup_arch(void) diff --git a/queue-4.4/powerpc-64s-enhance-the-information-in-cpu_show_meltdown.patch b/queue-4.4/powerpc-64s-enhance-the-information-in-cpu_show_meltdown.patch new file mode 100644 index 00000000000..ce3dba159cf --- /dev/null +++ b/queue-4.4/powerpc-64s-enhance-the-information-in-cpu_show_meltdown.patch @@ -0,0 +1,78 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:00 +1000 +Subject: powerpc/64s: Enhance the information in cpu_show_meltdown() +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-16-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit ff348355e9c72493947be337bb4fae4fc1a41eba upstream. + +Now that we have the security feature flags we can make the +information displayed in the "meltdown" file more informative. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/security_features.h | 1 + arch/powerpc/kernel/security.c | 30 +++++++++++++++++++++++++-- + 2 files changed, 29 insertions(+), 2 deletions(-) + +--- a/arch/powerpc/include/asm/security_features.h ++++ b/arch/powerpc/include/asm/security_features.h +@@ -10,6 +10,7 @@ + + + extern unsigned long powerpc_security_features; ++extern bool rfi_flush; + + static inline void security_ftr_set(unsigned long feature) + { +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -6,6 +6,7 @@ + + #include + #include ++#include + + #include + +@@ -19,8 +20,33 @@ unsigned long powerpc_security_features + + ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) + { +- if (rfi_flush) +- return sprintf(buf, "Mitigation: RFI Flush\n"); ++ bool thread_priv; ++ ++ thread_priv = security_ftr_enabled(SEC_FTR_L1D_THREAD_PRIV); ++ ++ if (rfi_flush || thread_priv) { ++ struct seq_buf s; ++ seq_buf_init(&s, buf, PAGE_SIZE - 1); ++ ++ seq_buf_printf(&s, "Mitigation: "); ++ ++ if (rfi_flush) ++ seq_buf_printf(&s, "RFI Flush"); ++ ++ if (rfi_flush && thread_priv) ++ seq_buf_printf(&s, ", "); ++ ++ if (thread_priv) ++ seq_buf_printf(&s, "L1D private per thread"); ++ ++ seq_buf_printf(&s, "\n"); ++ ++ return s.len; ++ } ++ ++ if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) && ++ !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR)) ++ return sprintf(buf, "Not affected\n"); + + return sprintf(buf, "Vulnerable\n"); + } diff --git a/queue-4.4/powerpc-64s-enhance-the-information-in-cpu_show_spectre_v1.patch b/queue-4.4/powerpc-64s-enhance-the-information-in-cpu_show_spectre_v1.patch new file mode 100644 index 00000000000..301bee43a86 --- /dev/null +++ b/queue-4.4/powerpc-64s-enhance-the-information-in-cpu_show_spectre_v1.patch @@ -0,0 +1,34 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:16 +1000 +Subject: powerpc/64s: Enhance the information in cpu_show_spectre_v1() +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-32-mpe@ellerman.id.au> + +From: Michal Suchanek + +commit a377514519b9a20fa1ea9adddbb4129573129cef upstream. + +We now have barrier_nospec as mitigation so print it in +cpu_show_spectre_v1() when enabled. + +Signed-off-by: Michal Suchanek +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/security.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -121,6 +121,9 @@ ssize_t cpu_show_spectre_v1(struct devic + if (!security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR)) + return sprintf(buf, "Not affected\n"); + ++ if (barrier_nospec_enabled) ++ return sprintf(buf, "Mitigation: __user pointer sanitization\n"); ++ + return sprintf(buf, "Vulnerable\n"); + } + diff --git a/queue-4.4/powerpc-64s-fix-section-mismatch-warnings-from-setup_rfi_flush.patch b/queue-4.4/powerpc-64s-fix-section-mismatch-warnings-from-setup_rfi_flush.patch new file mode 100644 index 00000000000..53d9e30679f --- /dev/null +++ b/queue-4.4/powerpc-64s-fix-section-mismatch-warnings-from-setup_rfi_flush.patch @@ -0,0 +1,56 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:08 +1000 +Subject: powerpc/64s: Fix section mismatch warnings from setup_rfi_flush() +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-24-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 501a78cbc17c329fabf8e9750a1e9ab810c88a0e upstream. + +The recent LPM changes to setup_rfi_flush() are causing some section +mismatch warnings because we removed the __init annotation on +setup_rfi_flush(): + + The function setup_rfi_flush() references + the function __init ppc64_bolted_size(). + the function __init memblock_alloc_base(). + +The references are actually in init_fallback_flush(), but that is +inlined into setup_rfi_flush(). + +These references are safe because: + - only pseries calls setup_rfi_flush() at runtime + - pseries always passes L1D_FLUSH_FALLBACK at boot + - so the fallback flush area will always be allocated + - so the check in init_fallback_flush() will always return early: + /* Only allocate the fallback flush area once (at boot time). */ + if (l1d_flush_fallback_area) + return; + + - and therefore we won't actually call the freed init routines. + +We should rework the code to make it safer by default rather than +relying on the above, but for now as a quick-fix just add a __ref +annotation to squash the warning. + +Fixes: abf110f3e1ce ("powerpc/rfi-flush: Make it possible to call setup_rfi_flush() again") +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/setup_64.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -882,7 +882,7 @@ void rfi_flush_enable(bool enable) + rfi_flush = enable; + } + +-static void init_fallback_flush(void) ++static void __ref init_fallback_flush(void) + { + u64 l1d_size, limit; + int cpu; diff --git a/queue-4.4/powerpc-64s-improve-rfi-l1-d-cache-flush-fallback.patch b/queue-4.4/powerpc-64s-improve-rfi-l1-d-cache-flush-fallback.patch new file mode 100644 index 00000000000..a00e84862ee --- /dev/null +++ b/queue-4.4/powerpc-64s-improve-rfi-l1-d-cache-flush-fallback.patch @@ -0,0 +1,219 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:47 +1000 +Subject: powerpc/64s: Improve RFI L1-D cache flush fallback +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-3-mpe@ellerman.id.au> + +From: Nicholas Piggin + +commit bdcb1aefc5b3f7d0f1dc8b02673602bca2ff7a4b upstream. + +The fallback RFI flush is used when firmware does not provide a way +to flush the cache. It's a "displacement flush" that evicts useful +data by displacing it with an uninteresting buffer. + +The flush has to take care to work with implementation specific cache +replacment policies, so the recipe has been in flux. The initial +slow but conservative approach is to touch all lines of a congruence +class, with dependencies between each load. It has since been +determined that a linear pattern of loads without dependencies is +sufficient, and is significantly faster. + +Measuring the speed of a null syscall with RFI fallback flush enabled +gives the relative improvement: + +P8 - 1.83x +P9 - 1.75x + +The flush also becomes simpler and more adaptable to different cache +geometries. + +Signed-off-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/paca.h | 3 - + arch/powerpc/kernel/asm-offsets.c | 3 - + arch/powerpc/kernel/exceptions-64s.S | 76 ++++++++++++++++------------------- + arch/powerpc/kernel/setup_64.c | 13 ----- + arch/powerpc/xmon/xmon.c | 2 + 5 files changed, 39 insertions(+), 58 deletions(-) + +--- a/arch/powerpc/include/asm/paca.h ++++ b/arch/powerpc/include/asm/paca.h +@@ -199,8 +199,7 @@ struct paca_struct { + */ + u64 exrfi[13] __aligned(0x80); + void *rfi_flush_fallback_area; +- u64 l1d_flush_congruence; +- u64 l1d_flush_sets; ++ u64 l1d_flush_size; + #endif + }; + +--- a/arch/powerpc/kernel/asm-offsets.c ++++ b/arch/powerpc/kernel/asm-offsets.c +@@ -245,8 +245,7 @@ int main(void) + DEFINE(PACA_IN_MCE, offsetof(struct paca_struct, in_mce)); + DEFINE(PACA_RFI_FLUSH_FALLBACK_AREA, offsetof(struct paca_struct, rfi_flush_fallback_area)); + DEFINE(PACA_EXRFI, offsetof(struct paca_struct, exrfi)); +- DEFINE(PACA_L1D_FLUSH_CONGRUENCE, offsetof(struct paca_struct, l1d_flush_congruence)); +- DEFINE(PACA_L1D_FLUSH_SETS, offsetof(struct paca_struct, l1d_flush_sets)); ++ DEFINE(PACA_L1D_FLUSH_SIZE, offsetof(struct paca_struct, l1d_flush_size)); + #endif + DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); + DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state)); +--- a/arch/powerpc/kernel/exceptions-64s.S ++++ b/arch/powerpc/kernel/exceptions-64s.S +@@ -1571,39 +1571,37 @@ rfi_flush_fallback: + std r9,PACA_EXRFI+EX_R9(r13) + std r10,PACA_EXRFI+EX_R10(r13) + std r11,PACA_EXRFI+EX_R11(r13) +- std r12,PACA_EXRFI+EX_R12(r13) +- std r8,PACA_EXRFI+EX_R13(r13) + mfctr r9 + ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13) +- ld r11,PACA_L1D_FLUSH_SETS(r13) +- ld r12,PACA_L1D_FLUSH_CONGRUENCE(r13) +- /* +- * The load adresses are at staggered offsets within cachelines, +- * which suits some pipelines better (on others it should not +- * hurt). +- */ +- addi r12,r12,8 ++ ld r11,PACA_L1D_FLUSH_SIZE(r13) ++ srdi r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */ + mtctr r11 + DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */ + + /* order ld/st prior to dcbt stop all streams with flushing */ + sync +-1: li r8,0 +- .rept 8 /* 8-way set associative */ +- ldx r11,r10,r8 +- add r8,r8,r12 +- xor r11,r11,r11 // Ensure r11 is 0 even if fallback area is not +- add r8,r8,r11 // Add 0, this creates a dependency on the ldx +- .endr +- addi r10,r10,128 /* 128 byte cache line */ ++ ++ /* ++ * The load adresses are at staggered offsets within cachelines, ++ * which suits some pipelines better (on others it should not ++ * hurt). ++ */ ++1: ++ ld r11,(0x80 + 8)*0(r10) ++ ld r11,(0x80 + 8)*1(r10) ++ ld r11,(0x80 + 8)*2(r10) ++ ld r11,(0x80 + 8)*3(r10) ++ ld r11,(0x80 + 8)*4(r10) ++ ld r11,(0x80 + 8)*5(r10) ++ ld r11,(0x80 + 8)*6(r10) ++ ld r11,(0x80 + 8)*7(r10) ++ addi r10,r10,0x80*8 + bdnz 1b + + mtctr r9 + ld r9,PACA_EXRFI+EX_R9(r13) + ld r10,PACA_EXRFI+EX_R10(r13) + ld r11,PACA_EXRFI+EX_R11(r13) +- ld r12,PACA_EXRFI+EX_R12(r13) +- ld r8,PACA_EXRFI+EX_R13(r13) + GET_SCRATCH0(r13); + rfid + +@@ -1614,39 +1612,37 @@ hrfi_flush_fallback: + std r9,PACA_EXRFI+EX_R9(r13) + std r10,PACA_EXRFI+EX_R10(r13) + std r11,PACA_EXRFI+EX_R11(r13) +- std r12,PACA_EXRFI+EX_R12(r13) +- std r8,PACA_EXRFI+EX_R13(r13) + mfctr r9 + ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13) +- ld r11,PACA_L1D_FLUSH_SETS(r13) +- ld r12,PACA_L1D_FLUSH_CONGRUENCE(r13) +- /* +- * The load adresses are at staggered offsets within cachelines, +- * which suits some pipelines better (on others it should not +- * hurt). +- */ +- addi r12,r12,8 ++ ld r11,PACA_L1D_FLUSH_SIZE(r13) ++ srdi r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */ + mtctr r11 + DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */ + + /* order ld/st prior to dcbt stop all streams with flushing */ + sync +-1: li r8,0 +- .rept 8 /* 8-way set associative */ +- ldx r11,r10,r8 +- add r8,r8,r12 +- xor r11,r11,r11 // Ensure r11 is 0 even if fallback area is not +- add r8,r8,r11 // Add 0, this creates a dependency on the ldx +- .endr +- addi r10,r10,128 /* 128 byte cache line */ ++ ++ /* ++ * The load adresses are at staggered offsets within cachelines, ++ * which suits some pipelines better (on others it should not ++ * hurt). ++ */ ++1: ++ ld r11,(0x80 + 8)*0(r10) ++ ld r11,(0x80 + 8)*1(r10) ++ ld r11,(0x80 + 8)*2(r10) ++ ld r11,(0x80 + 8)*3(r10) ++ ld r11,(0x80 + 8)*4(r10) ++ ld r11,(0x80 + 8)*5(r10) ++ ld r11,(0x80 + 8)*6(r10) ++ ld r11,(0x80 + 8)*7(r10) ++ addi r10,r10,0x80*8 + bdnz 1b + + mtctr r9 + ld r9,PACA_EXRFI+EX_R9(r13) + ld r10,PACA_EXRFI+EX_R10(r13) + ld r11,PACA_EXRFI+EX_R11(r13) +- ld r12,PACA_EXRFI+EX_R12(r13) +- ld r8,PACA_EXRFI+EX_R13(r13) + GET_SCRATCH0(r13); + hrfid + +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -902,19 +902,8 @@ static void init_fallback_flush(void) + memset(l1d_flush_fallback_area, 0, l1d_size * 2); + + for_each_possible_cpu(cpu) { +- /* +- * The fallback flush is currently coded for 8-way +- * associativity. Different associativity is possible, but it +- * will be treated as 8-way and may not evict the lines as +- * effectively. +- * +- * 128 byte lines are mandatory. +- */ +- u64 c = l1d_size / 8; +- + paca[cpu].rfi_flush_fallback_area = l1d_flush_fallback_area; +- paca[cpu].l1d_flush_congruence = c; +- paca[cpu].l1d_flush_sets = c / 128; ++ paca[cpu].l1d_flush_size = l1d_size; + } + } + +--- a/arch/powerpc/xmon/xmon.c ++++ b/arch/powerpc/xmon/xmon.c +@@ -2146,8 +2146,6 @@ static void dump_one_paca(int cpu) + printf(" slb_cache[%d]: = 0x%016lx\n", i, p->slb_cache[i]); + + DUMP(p, rfi_flush_fallback_area, "px"); +- DUMP(p, l1d_flush_congruence, "llx"); +- DUMP(p, l1d_flush_sets, "llx"); + #endif + DUMP(p, dscr_default, "llx"); + #ifdef CONFIG_PPC_BOOK3E diff --git a/queue-4.4/powerpc-64s-move-cpu_show_meltdown.patch b/queue-4.4/powerpc-64s-move-cpu_show_meltdown.patch new file mode 100644 index 00000000000..be0b2d4eb31 --- /dev/null +++ b/queue-4.4/powerpc-64s-move-cpu_show_meltdown.patch @@ -0,0 +1,62 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:59 +1000 +Subject: powerpc/64s: Move cpu_show_meltdown() +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-15-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 8ad33041563a10b34988800c682ada14b2612533 upstream. + +This landed in setup_64.c for no good reason other than we had nowhere +else to put it. Now that we have a security-related file, that is a +better place for it so move it. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/security.c | 11 +++++++++++ + arch/powerpc/kernel/setup_64.c | 8 -------- + 2 files changed, 11 insertions(+), 8 deletions(-) + +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -5,6 +5,8 @@ + // Copyright 2018, Michael Ellerman, IBM Corporation. + + #include ++#include ++ + #include + + +@@ -13,3 +15,12 @@ unsigned long powerpc_security_features + SEC_FTR_L1D_FLUSH_PR | \ + SEC_FTR_BNDS_CHK_SPEC_BAR | \ + SEC_FTR_FAVOUR_SECURITY; ++ ++ ++ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ if (rfi_flush) ++ return sprintf(buf, "Mitigation: RFI Flush\n"); ++ ++ return sprintf(buf, "Vulnerable\n"); ++} +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -961,12 +961,4 @@ static __init int rfi_flush_debugfs_init + } + device_initcall(rfi_flush_debugfs_init); + #endif +- +-ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) +-{ +- if (rfi_flush) +- return sprintf(buf, "Mitigation: RFI Flush\n"); +- +- return sprintf(buf, "Vulnerable\n"); +-} + #endif /* CONFIG_PPC_BOOK3S_64 */ diff --git a/queue-4.4/powerpc-64s-patch-barrier_nospec-in-modules.patch b/queue-4.4/powerpc-64s-patch-barrier_nospec-in-modules.patch new file mode 100644 index 00000000000..f8ff9fb7178 --- /dev/null +++ b/queue-4.4/powerpc-64s-patch-barrier_nospec-in-modules.patch @@ -0,0 +1,109 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:12 +1000 +Subject: powerpc/64s: Patch barrier_nospec in modules +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-28-mpe@ellerman.id.au> + +From: Michal Suchanek + +commit 815069ca57c142eb71d27439bc27f41a433a67b3 upstream. + +Note that unlike RFI which is patched only in kernel the nospec state +reflects settings at the time the module was loaded. + +Iterating all modules and re-patching every time the settings change +is not implemented. + +Based on lwsync patching. + +Signed-off-by: Michal Suchanek +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/setup.h | 7 +++++++ + arch/powerpc/kernel/module.c | 6 ++++++ + arch/powerpc/kernel/security.c | 2 +- + arch/powerpc/lib/feature-fixups.c | 16 +++++++++++++--- + 4 files changed, 27 insertions(+), 4 deletions(-) + +--- a/arch/powerpc/include/asm/setup.h ++++ b/arch/powerpc/include/asm/setup.h +@@ -39,6 +39,13 @@ 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); ++extern bool barrier_nospec_enabled; ++ ++#ifdef CONFIG_PPC_BOOK3S_64 ++void do_barrier_nospec_fixups_range(bool enable, void *start, void *end); ++#else ++static inline void do_barrier_nospec_fixups_range(bool enable, void *start, void *end) { }; ++#endif + + #endif /* !__ASSEMBLY__ */ + +--- a/arch/powerpc/kernel/module.c ++++ b/arch/powerpc/kernel/module.c +@@ -67,6 +67,12 @@ int module_finalize(const Elf_Ehdr *hdr, + do_feature_fixups(powerpc_firmware_features, + (void *)sect->sh_addr, + (void *)sect->sh_addr + sect->sh_size); ++ ++ sect = find_section(hdr, sechdrs, "__spec_barrier_fixup"); ++ if (sect != NULL) ++ do_barrier_nospec_fixups_range(barrier_nospec_enabled, ++ (void *)sect->sh_addr, ++ (void *)sect->sh_addr + sect->sh_size); + #endif + + sect = find_section(hdr, sechdrs, "__lwsync_fixup"); +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -16,7 +16,7 @@ + + unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT; + +-static bool barrier_nospec_enabled; ++bool barrier_nospec_enabled; + + static void enable_barrier_nospec(bool enable) + { +--- a/arch/powerpc/lib/feature-fixups.c ++++ b/arch/powerpc/lib/feature-fixups.c +@@ -275,14 +275,14 @@ void do_rfi_flush_fixups(enum l1d_flush_ + : "unknown"); + } + +-void do_barrier_nospec_fixups(bool enable) ++void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_end) + { + unsigned int instr, *dest; + long *start, *end; + int i; + +- start = PTRRELOC(&__start___barrier_nospec_fixup), +- end = PTRRELOC(&__stop___barrier_nospec_fixup); ++ start = fixup_start; ++ end = fixup_end; + + instr = 0x60000000; /* nop */ + +@@ -301,6 +301,16 @@ void do_barrier_nospec_fixups(bool enabl + printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i); + } + ++void do_barrier_nospec_fixups(bool enable) ++{ ++ void *start, *end; ++ ++ start = PTRRELOC(&__start___barrier_nospec_fixup), ++ end = PTRRELOC(&__stop___barrier_nospec_fixup); ++ ++ do_barrier_nospec_fixups_range(enable, start, end); ++} ++ + #endif /* CONFIG_PPC_BOOK3S_64 */ + + void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end) diff --git a/queue-4.4/powerpc-64s-wire-up-cpu_show_spectre_v1.patch b/queue-4.4/powerpc-64s-wire-up-cpu_show_spectre_v1.patch new file mode 100644 index 00000000000..e7e443a31d6 --- /dev/null +++ b/queue-4.4/powerpc-64s-wire-up-cpu_show_spectre_v1.patch @@ -0,0 +1,40 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:03 +1000 +Subject: powerpc/64s: Wire up cpu_show_spectre_v1() +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-19-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 56986016cb8cd9050e601831fe89f332b4e3c46e upstream. + +Add a definition for cpu_show_spectre_v1() to override the generic +version. Currently this just prints "Not affected" or "Vulnerable" +based on the firmware flag. + +Although the kernel does have array_index_nospec() in a few places, we +haven't yet audited all the powerpc code to see where it's necessary, +so for now we don't list that as a mitigation. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/security.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -50,3 +50,11 @@ ssize_t cpu_show_meltdown(struct device + + return sprintf(buf, "Vulnerable\n"); + } ++ ++ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ if (!security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR)) ++ return sprintf(buf, "Not affected\n"); ++ ++ return sprintf(buf, "Vulnerable\n"); ++} diff --git a/queue-4.4/powerpc-64s-wire-up-cpu_show_spectre_v2.patch b/queue-4.4/powerpc-64s-wire-up-cpu_show_spectre_v2.patch new file mode 100644 index 00000000000..aa04e14a569 --- /dev/null +++ b/queue-4.4/powerpc-64s-wire-up-cpu_show_spectre_v2.patch @@ -0,0 +1,73 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:04 +1000 +Subject: powerpc/64s: Wire up cpu_show_spectre_v2() +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-20-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit d6fbe1c55c55c6937cbea3531af7da84ab7473c3 upstream. + +Add a definition for cpu_show_spectre_v2() to override the generic +version. This has several permuations, though in practice some may not +occur we cater for any combination. + +The most verbose is: + + Mitigation: Indirect branch serialisation (kernel only), Indirect + branch cache disabled, ori31 speculation barrier enabled + +We don't treat the ori31 speculation barrier as a mitigation on its +own, because it has to be *used* by code in order to be a mitigation +and we don't know if userspace is doing that. So if that's all we see +we say: + + Vulnerable, ori31 speculation barrier enabled + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/security.c | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -58,3 +58,36 @@ ssize_t cpu_show_spectre_v1(struct devic + + return sprintf(buf, "Vulnerable\n"); + } ++ ++ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ bool bcs, ccd, ori; ++ struct seq_buf s; ++ ++ seq_buf_init(&s, buf, PAGE_SIZE - 1); ++ ++ bcs = security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED); ++ ccd = security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED); ++ ori = security_ftr_enabled(SEC_FTR_SPEC_BAR_ORI31); ++ ++ if (bcs || ccd) { ++ seq_buf_printf(&s, "Mitigation: "); ++ ++ if (bcs) ++ seq_buf_printf(&s, "Indirect branch serialisation (kernel only)"); ++ ++ if (bcs && ccd) ++ seq_buf_printf(&s, ", "); ++ ++ if (ccd) ++ seq_buf_printf(&s, "Indirect branch cache disabled"); ++ } else ++ seq_buf_printf(&s, "Vulnerable"); ++ ++ if (ori) ++ seq_buf_printf(&s, ", ori31 speculation barrier enabled"); ++ ++ seq_buf_printf(&s, "\n"); ++ ++ return s.len; ++} diff --git a/queue-4.4/powerpc-add-security-feature-flags-for-spectre-meltdown.patch b/queue-4.4/powerpc-add-security-feature-flags-for-spectre-meltdown.patch new file mode 100644 index 00000000000..5a822e35e53 --- /dev/null +++ b/queue-4.4/powerpc-add-security-feature-flags-for-spectre-meltdown.patch @@ -0,0 +1,132 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:56 +1000 +Subject: powerpc: Add security feature flags for Spectre/Meltdown +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-12-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 9a868f634349e62922c226834aa23e3d1329ae7f upstream. + +This commit adds security feature flags to reflect the settings we +receive from firmware regarding Spectre/Meltdown mitigations. + +The feature names reflect the names we are given by firmware on bare +metal machines. See the hostboot source for details. + +Arguably these could be firmware features, but that then requires them +to be read early in boot so they're available prior to asm feature +patching, but we don't actually want to use them for patching. We may +also want to dynamically update them in future, which would be +incompatible with the way firmware features work (at the moment at +least). So for now just make them separate flags. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/security_features.h | 65 +++++++++++++++++++++++++++ + arch/powerpc/kernel/Makefile | 2 + arch/powerpc/kernel/security.c | 15 ++++++ + 3 files changed, 81 insertions(+), 1 deletion(-) + create mode 100644 arch/powerpc/include/asm/security_features.h + create mode 100644 arch/powerpc/kernel/security.c + +--- /dev/null ++++ b/arch/powerpc/include/asm/security_features.h +@@ -0,0 +1,65 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Security related feature bit definitions. ++ * ++ * Copyright 2018, Michael Ellerman, IBM Corporation. ++ */ ++ ++#ifndef _ASM_POWERPC_SECURITY_FEATURES_H ++#define _ASM_POWERPC_SECURITY_FEATURES_H ++ ++ ++extern unsigned long powerpc_security_features; ++ ++static inline void security_ftr_set(unsigned long feature) ++{ ++ powerpc_security_features |= feature; ++} ++ ++static inline void security_ftr_clear(unsigned long feature) ++{ ++ powerpc_security_features &= ~feature; ++} ++ ++static inline bool security_ftr_enabled(unsigned long feature) ++{ ++ return !!(powerpc_security_features & feature); ++} ++ ++ ++// Features indicating support for Spectre/Meltdown mitigations ++ ++// The L1-D cache can be flushed with ori r30,r30,0 ++#define SEC_FTR_L1D_FLUSH_ORI30 0x0000000000000001ull ++ ++// The L1-D cache can be flushed with mtspr 882,r0 (aka SPRN_TRIG2) ++#define SEC_FTR_L1D_FLUSH_TRIG2 0x0000000000000002ull ++ ++// ori r31,r31,0 acts as a speculation barrier ++#define SEC_FTR_SPEC_BAR_ORI31 0x0000000000000004ull ++ ++// Speculation past bctr is disabled ++#define SEC_FTR_BCCTRL_SERIALISED 0x0000000000000008ull ++ ++// Entries in L1-D are private to a SMT thread ++#define SEC_FTR_L1D_THREAD_PRIV 0x0000000000000010ull ++ ++// Indirect branch prediction cache disabled ++#define SEC_FTR_COUNT_CACHE_DISABLED 0x0000000000000020ull ++ ++ ++// Features indicating need for Spectre/Meltdown mitigations ++ ++// The L1-D cache should be flushed on MSR[HV] 1->0 transition (hypervisor to guest) ++#define SEC_FTR_L1D_FLUSH_HV 0x0000000000000040ull ++ ++// The L1-D cache should be flushed on MSR[PR] 0->1 transition (kernel to userspace) ++#define SEC_FTR_L1D_FLUSH_PR 0x0000000000000080ull ++ ++// A speculation barrier should be used for bounds checks (Spectre variant 1) ++#define SEC_FTR_BNDS_CHK_SPEC_BAR 0x0000000000000100ull ++ ++// Firmware configuration indicates user favours security over performance ++#define SEC_FTR_FAVOUR_SECURITY 0x0000000000000200ull ++ ++#endif /* _ASM_POWERPC_SECURITY_FEATURES_H */ +--- a/arch/powerpc/kernel/Makefile ++++ b/arch/powerpc/kernel/Makefile +@@ -40,7 +40,7 @@ obj-$(CONFIG_PPC64) += setup_64.o sys_p + obj-$(CONFIG_VDSO32) += vdso32/ + obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o + obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_ppc970.o cpu_setup_pa6t.o +-obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_power.o ++obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_power.o security.o + obj-$(CONFIG_PPC_BOOK3S_64) += mce.o mce_power.o + obj64-$(CONFIG_RELOCATABLE) += reloc_64.o + obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o idle_book3e.o +--- /dev/null ++++ b/arch/powerpc/kernel/security.c +@@ -0,0 +1,15 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++// ++// Security related flags and so on. ++// ++// Copyright 2018, Michael Ellerman, IBM Corporation. ++ ++#include ++#include ++ ++ ++unsigned long powerpc_security_features __read_mostly = \ ++ SEC_FTR_L1D_FLUSH_HV | \ ++ SEC_FTR_L1D_FLUSH_PR | \ ++ SEC_FTR_BNDS_CHK_SPEC_BAR | \ ++ SEC_FTR_FAVOUR_SECURITY; diff --git a/queue-4.4/powerpc-asm-add-a-patch_site-macro-helpers-for-patching-instructions.patch b/queue-4.4/powerpc-asm-add-a-patch_site-macro-helpers-for-patching-instructions.patch new file mode 100644 index 00000000000..2b380a9311c --- /dev/null +++ b/queue-4.4/powerpc-asm-add-a-patch_site-macro-helpers-for-patching-instructions.patch @@ -0,0 +1,93 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:24 +1000 +Subject: powerpc/asm: Add a patch_site macro & helpers for patching instructions +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-40-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 06d0bbc6d0f56dacac3a79900e9a9a0d5972d818 upstream. + +Add a macro and some helper C functions for patching single asm +instructions. + +The gas macro means we can do something like: + + 1: nop + patch_site 1b, patch__foo + +Which is less visually distracting than defining a GLOBAL symbol at 1, +and also doesn't pollute the symbol table which can confuse eg. perf. + +These are obviously similar to our existing feature sections, but are +not automatically patched based on CPU/MMU features, rather they are +designed to be manually patched by C code at some arbitrary point. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/code-patching-asm.h | 18 ++++++++++++++++++ + arch/powerpc/include/asm/code-patching.h | 2 ++ + arch/powerpc/lib/code-patching.c | 16 ++++++++++++++++ + 3 files changed, 36 insertions(+) + create mode 100644 arch/powerpc/include/asm/code-patching-asm.h + +--- /dev/null ++++ b/arch/powerpc/include/asm/code-patching-asm.h +@@ -0,0 +1,18 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2018, Michael Ellerman, IBM Corporation. ++ */ ++#ifndef _ASM_POWERPC_CODE_PATCHING_ASM_H ++#define _ASM_POWERPC_CODE_PATCHING_ASM_H ++ ++/* Define a "site" that can be patched */ ++.macro patch_site label name ++ .pushsection ".rodata" ++ .balign 4 ++ .global \name ++\name: ++ .4byte \label - . ++ .popsection ++.endm ++ ++#endif /* _ASM_POWERPC_CODE_PATCHING_ASM_H */ +--- a/arch/powerpc/include/asm/code-patching.h ++++ b/arch/powerpc/include/asm/code-patching.h +@@ -28,6 +28,8 @@ unsigned int create_cond_branch(const un + unsigned long target, int flags); + int patch_branch(unsigned int *addr, unsigned long target, int flags); + int patch_instruction(unsigned int *addr, unsigned int instr); ++int patch_instruction_site(s32 *addr, unsigned int instr); ++int patch_branch_site(s32 *site, unsigned long target, int flags); + + int instr_is_relative_branch(unsigned int instr); + int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr); +--- a/arch/powerpc/lib/code-patching.c ++++ b/arch/powerpc/lib/code-patching.c +@@ -32,6 +32,22 @@ int patch_branch(unsigned int *addr, uns + return patch_instruction(addr, create_branch(addr, target, flags)); + } + ++int patch_branch_site(s32 *site, unsigned long target, int flags) ++{ ++ unsigned int *addr; ++ ++ addr = (unsigned int *)((unsigned long)site + *site); ++ return patch_instruction(addr, create_branch(addr, target, flags)); ++} ++ ++int patch_instruction_site(s32 *site, unsigned int instr) ++{ ++ unsigned int *addr; ++ ++ addr = (unsigned int *)((unsigned long)site + *site); ++ return patch_instruction(addr, instr); ++} ++ + unsigned int create_branch(const unsigned int *addr, + unsigned long target, int flags) + { diff --git a/queue-4.4/powerpc-avoid-code-patching-freed-init-sections.patch b/queue-4.4/powerpc-avoid-code-patching-freed-init-sections.patch new file mode 100644 index 00000000000..b8c8bba99c6 --- /dev/null +++ b/queue-4.4/powerpc-avoid-code-patching-freed-init-sections.patch @@ -0,0 +1,101 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:29 +1000 +Subject: powerpc: Avoid code patching freed init sections +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-45-mpe@ellerman.id.au> + +From: Michael Neuling + +commit 51c3c62b58b357e8d35e4cc32f7b4ec907426fe3 upstream. + +This stops us from doing code patching in init sections after they've +been freed. + +In this chain: + kvm_guest_init() -> + kvm_use_magic_page() -> + fault_in_pages_readable() -> + __get_user() -> + __get_user_nocheck() -> + barrier_nospec(); + +We have a code patching location at barrier_nospec() and +kvm_guest_init() is an init function. This whole chain gets inlined, +so when we free the init section (hence kvm_guest_init()), this code +goes away and hence should no longer be patched. + +We seen this as userspace memory corruption when using a memory +checker while doing partition migration testing on powervm (this +starts the code patching post migration via +/sys/kernel/mobility/migration). In theory, it could also happen when +using /sys/kernel/debug/powerpc/barrier_nospec. + +Signed-off-by: Michael Neuling +Reviewed-by: Nicholas Piggin +Reviewed-by: Christophe Leroy +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/setup.h | 1 + + arch/powerpc/lib/code-patching.c | 13 +++++++++++++ + arch/powerpc/mm/mem.c | 2 ++ + 3 files changed, 16 insertions(+) + +--- a/arch/powerpc/include/asm/setup.h ++++ b/arch/powerpc/include/asm/setup.h +@@ -8,6 +8,7 @@ extern void ppc_printk_progress(char *s, + + extern unsigned int rtas_data; + extern unsigned long long memory_limit; ++extern bool init_mem_is_free; + extern unsigned long klimit; + extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask); + +--- a/arch/powerpc/lib/code-patching.c ++++ b/arch/powerpc/lib/code-patching.c +@@ -14,12 +14,25 @@ + #include + #include + #include ++#include ++#include + + ++static inline bool is_init(unsigned int *addr) ++{ ++ return addr >= (unsigned int *)__init_begin && addr < (unsigned int *)__init_end; ++} ++ + int patch_instruction(unsigned int *addr, unsigned int instr) + { + int err; + ++ /* Make sure we aren't patching a freed init section */ ++ if (init_mem_is_free && is_init(addr)) { ++ pr_debug("Skipping init section patching addr: 0x%px\n", addr); ++ return 0; ++ } ++ + __put_user_size(instr, addr, 4, err); + if (err) + return err; +--- a/arch/powerpc/mm/mem.c ++++ b/arch/powerpc/mm/mem.c +@@ -62,6 +62,7 @@ + #endif + + unsigned long long memory_limit; ++bool init_mem_is_free; + + #ifdef CONFIG_HIGHMEM + pte_t *kmap_pte; +@@ -381,6 +382,7 @@ void __init mem_init(void) + void free_initmem(void) + { + ppc_md.progress = ppc_printk_progress; ++ init_mem_is_free = true; + free_initmem_default(POISON_FREE_INITMEM); + } + diff --git a/queue-4.4/powerpc-fsl-add-barrier_nospec-implementation-for-nxp-powerpc-book3e.patch b/queue-4.4/powerpc-fsl-add-barrier_nospec-implementation-for-nxp-powerpc-book3e.patch new file mode 100644 index 00000000000..5498de1052b --- /dev/null +++ b/queue-4.4/powerpc-fsl-add-barrier_nospec-implementation-for-nxp-powerpc-book3e.patch @@ -0,0 +1,109 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:23 +1000 +Subject: powerpc/fsl: Add barrier_nospec implementation for NXP PowerPC Book3E +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-39-mpe@ellerman.id.au> + +From: Diana Craciun + +commit ebcd1bfc33c7a90df941df68a6e5d4018c022fba upstream. + +Implement the barrier_nospec as a isync;sync instruction sequence. +The implementation uses the infrastructure built for BOOK3S 64. + +Signed-off-by: Diana Craciun +[mpe: Add PPC_INST_ISYNC for backport] +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/Kconfig | 2 +- + arch/powerpc/include/asm/barrier.h | 8 +++++++- + arch/powerpc/include/asm/ppc-opcode.h | 1 + + arch/powerpc/lib/feature-fixups.c | 31 +++++++++++++++++++++++++++++++ + 4 files changed, 40 insertions(+), 2 deletions(-) + +--- a/arch/powerpc/Kconfig ++++ b/arch/powerpc/Kconfig +@@ -165,7 +165,7 @@ config PPC + config PPC_BARRIER_NOSPEC + bool + default y +- depends on PPC_BOOK3S_64 ++ depends on PPC_BOOK3S_64 || PPC_FSL_BOOK3E + + config GENERIC_CSUM + def_bool CPU_LITTLE_ENDIAN +--- a/arch/powerpc/include/asm/barrier.h ++++ b/arch/powerpc/include/asm/barrier.h +@@ -92,12 +92,18 @@ do { \ + #define smp_mb__after_atomic() smp_mb() + #define smp_mb__before_spinlock() smp_mb() + ++#ifdef CONFIG_PPC_BOOK3S_64 ++#define NOSPEC_BARRIER_SLOT nop ++#elif defined(CONFIG_PPC_FSL_BOOK3E) ++#define NOSPEC_BARRIER_SLOT nop; nop ++#endif ++ + #ifdef CONFIG_PPC_BARRIER_NOSPEC + /* + * Prevent execution of subsequent instructions until preceding branches have + * been fully resolved and are no longer executing speculatively. + */ +-#define barrier_nospec_asm NOSPEC_BARRIER_FIXUP_SECTION; nop ++#define barrier_nospec_asm NOSPEC_BARRIER_FIXUP_SECTION; NOSPEC_BARRIER_SLOT + + // This also acts as a compiler barrier due to the memory clobber. + #define barrier_nospec() asm (stringify_in_c(barrier_nospec_asm) ::: "memory") +--- a/arch/powerpc/include/asm/ppc-opcode.h ++++ b/arch/powerpc/include/asm/ppc-opcode.h +@@ -147,6 +147,7 @@ + #define PPC_INST_LWSYNC 0x7c2004ac + #define PPC_INST_SYNC 0x7c0004ac + #define PPC_INST_SYNC_MASK 0xfc0007fe ++#define PPC_INST_ISYNC 0x4c00012c + #define PPC_INST_LXVD2X 0x7c000698 + #define PPC_INST_MCRXR 0x7c000400 + #define PPC_INST_MCRXR_MASK 0xfc0007fe +--- a/arch/powerpc/lib/feature-fixups.c ++++ b/arch/powerpc/lib/feature-fixups.c +@@ -315,6 +315,37 @@ void do_barrier_nospec_fixups(bool enabl + } + #endif /* CONFIG_PPC_BARRIER_NOSPEC */ + ++#ifdef CONFIG_PPC_FSL_BOOK3E ++void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_end) ++{ ++ unsigned int instr[2], *dest; ++ long *start, *end; ++ int i; ++ ++ start = fixup_start; ++ end = fixup_end; ++ ++ instr[0] = PPC_INST_NOP; ++ instr[1] = PPC_INST_NOP; ++ ++ if (enable) { ++ pr_info("barrier-nospec: using isync; sync as speculation barrier\n"); ++ instr[0] = PPC_INST_ISYNC; ++ instr[1] = PPC_INST_SYNC; ++ } ++ ++ for (i = 0; start < end; start++, i++) { ++ dest = (void *)start + *start; ++ ++ pr_devel("patching dest %lx\n", (unsigned long)dest); ++ patch_instruction(dest, instr[0]); ++ patch_instruction(dest + 1, instr[1]); ++ } ++ ++ printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i); ++} ++#endif /* CONFIG_PPC_FSL_BOOK3E */ ++ + void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end) + { + long *start, *end; diff --git a/queue-4.4/powerpc-fsl-add-infrastructure-to-fixup-branch-predictor-flush.patch b/queue-4.4/powerpc-fsl-add-infrastructure-to-fixup-branch-predictor-flush.patch new file mode 100644 index 00000000000..72a5e390a4c --- /dev/null +++ b/queue-4.4/powerpc-fsl-add-infrastructure-to-fixup-branch-predictor-flush.patch @@ -0,0 +1,118 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:30 +1000 +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, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-46-mpe@ellerman.id.au> + +From: Diana Craciun + +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 +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -216,6 +216,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__ + +@@ -224,6 +235,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; + + #endif + +--- a/arch/powerpc/include/asm/setup.h ++++ b/arch/powerpc/include/asm/setup.h +@@ -53,6 +53,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 +@@ -104,6 +104,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 +@@ -344,6 +344,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) diff --git a/queue-4.4/powerpc-fsl-add-macro-to-flush-the-branch-predictor.patch b/queue-4.4/powerpc-fsl-add-macro-to-flush-the-branch-predictor.patch new file mode 100644 index 00000000000..22c9ae2ec54 --- /dev/null +++ b/queue-4.4/powerpc-fsl-add-macro-to-flush-the-branch-predictor.patch @@ -0,0 +1,40 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:31 +1000 +Subject: powerpc/fsl: Add macro to flush the branch predictor +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-47-mpe@ellerman.id.au> + +From: Diana Craciun + +commit 1cbf8990d79ff69da8ad09e8a3df014e1494462b upstream. + +The BUCSR register can be used to invalidate the entries in the +branch prediction mechanisms. + +Signed-off-by: Diana Craciun +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/ppc_asm.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/arch/powerpc/include/asm/ppc_asm.h ++++ b/arch/powerpc/include/asm/ppc_asm.h +@@ -821,4 +821,15 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,C + .long 0x2400004c /* rfid */ + #endif /* !CONFIG_PPC_BOOK3E */ + #endif /* __ASSEMBLY__ */ ++ ++#ifdef CONFIG_PPC_FSL_BOOK3E ++#define BTB_FLUSH(reg) \ ++ lis reg,BUCSR_INIT@h; \ ++ ori reg,reg,BUCSR_INIT@l; \ ++ mtspr SPRN_BUCSR,reg; \ ++ isync; ++#else ++#define BTB_FLUSH(reg) ++#endif /* CONFIG_PPC_FSL_BOOK3E */ ++ + #endif /* _ASM_POWERPC_PPC_ASM_H */ diff --git a/queue-4.4/powerpc-fsl-add-nospectre_v2-command-line-argument.patch b/queue-4.4/powerpc-fsl-add-nospectre_v2-command-line-argument.patch new file mode 100644 index 00000000000..f1992d4f1a1 --- /dev/null +++ b/queue-4.4/powerpc-fsl-add-nospectre_v2-command-line-argument.patch @@ -0,0 +1,74 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:33 +1000 +Subject: powerpc/fsl: Add nospectre_v2 command line argument +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-49-mpe@ellerman.id.au> + +From: Diana Craciun + +commit f633a8ad636efb5d4bba1a047d4a0f1ef719aa06 upstream. + +When the command line argument is present, the Spectre variant 2 +mitigations are disabled. + +Signed-off-by: Diana Craciun +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/setup.h | 5 +++++ + arch/powerpc/kernel/security.c | 21 +++++++++++++++++++++ + 2 files changed, 26 insertions(+) + +--- a/arch/powerpc/include/asm/setup.h ++++ b/arch/powerpc/include/asm/setup.h +@@ -53,6 +53,11 @@ void do_barrier_nospec_fixups_range(bool + static inline void do_barrier_nospec_fixups_range(bool enable, void *start, void *end) { }; + #endif + ++#ifdef CONFIG_PPC_FSL_BOOK3E ++void setup_spectre_v2(void); ++#else ++static inline void setup_spectre_v2(void) {}; ++#endif + void do_btb_flush_fixups(void); + + #endif /* !__ASSEMBLY__ */ +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -27,6 +27,10 @@ static enum count_cache_flush_type count + + bool barrier_nospec_enabled; + static bool no_nospec; ++static bool btb_flush_enabled; ++#ifdef CONFIG_PPC_FSL_BOOK3E ++static bool no_spectrev2; ++#endif + + static void enable_barrier_nospec(bool enable) + { +@@ -102,6 +106,23 @@ static __init int barrier_nospec_debugfs + device_initcall(barrier_nospec_debugfs_init); + #endif /* CONFIG_DEBUG_FS */ + ++#ifdef CONFIG_PPC_FSL_BOOK3E ++static int __init handle_nospectre_v2(char *p) ++{ ++ no_spectrev2 = true; ++ ++ return 0; ++} ++early_param("nospectre_v2", handle_nospectre_v2); ++void setup_spectre_v2(void) ++{ ++ if (no_spectrev2) ++ do_btb_flush_fixups(); ++ else ++ btb_flush_enabled = true; ++} ++#endif /* CONFIG_PPC_FSL_BOOK3E */ ++ + #ifdef CONFIG_PPC_BOOK3S_64 + ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) + { diff --git a/queue-4.4/powerpc-fsl-fix-spectre_v2-mitigations-reporting.patch b/queue-4.4/powerpc-fsl-fix-spectre_v2-mitigations-reporting.patch new file mode 100644 index 00000000000..e98ae2db320 --- /dev/null +++ b/queue-4.4/powerpc-fsl-fix-spectre_v2-mitigations-reporting.patch @@ -0,0 +1,39 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:32 +1000 +Subject: powerpc/fsl: Fix spectre_v2 mitigations reporting +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-48-mpe@ellerman.id.au> + +From: Diana Craciun + +commit 7d8bad99ba5a22892f0cad6881289fdc3875a930 upstream. + +Currently for CONFIG_PPC_FSL_BOOK3E the spectre_v2 file is incorrect: + + $ cat /sys/devices/system/cpu/vulnerabilities/spectre_v2 + "Mitigation: Software count cache flush" + +Which is wrong. Fix it to report vulnerable for now. + +Fixes: ee13cb249fab ("powerpc/64s: Add support for software count cache flush") +Cc: stable@vger.kernel.org # v4.19+ +Signed-off-by: Diana Craciun +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/security.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -23,7 +23,7 @@ enum count_cache_flush_type { + COUNT_CACHE_FLUSH_SW = 0x2, + COUNT_CACHE_FLUSH_HW = 0x4, + }; +-static enum count_cache_flush_type count_cache_flush_type; ++static enum count_cache_flush_type count_cache_flush_type = COUNT_CACHE_FLUSH_NONE; + + bool barrier_nospec_enabled; + static bool no_nospec; diff --git a/queue-4.4/powerpc-fsl-fix-the-flush-of-branch-predictor.patch b/queue-4.4/powerpc-fsl-fix-the-flush-of-branch-predictor.patch new file mode 100644 index 00000000000..07465fac0ac --- /dev/null +++ b/queue-4.4/powerpc-fsl-fix-the-flush-of-branch-predictor.patch @@ -0,0 +1,45 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:37 +1000 +Subject: powerpc/fsl: Fix the flush of branch predictor. +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-53-mpe@ellerman.id.au> + +From: Christophe Leroy + +commit 27da80719ef132cf8c80eb406d5aeb37dddf78cc upstream. + +The commit identified below adds MC_BTB_FLUSH macro only when +CONFIG_PPC_FSL_BOOK3E is defined. This results in the following error +on some configs (seen several times with kisskb randconfig_defconfig) + +arch/powerpc/kernel/exceptions-64e.S:576: Error: Unrecognized opcode: `mc_btb_flush' +make[3]: *** [scripts/Makefile.build:367: arch/powerpc/kernel/exceptions-64e.o] Error 1 +make[2]: *** [scripts/Makefile.build:492: arch/powerpc/kernel] Error 2 +make[1]: *** [Makefile:1043: arch/powerpc] Error 2 +make: *** [Makefile:152: sub-make] Error 2 + +This patch adds a blank definition of MC_BTB_FLUSH for other cases. + +Fixes: 10c5e83afd4a ("powerpc/fsl: Flush the branch predictor at each kernel entry (64bit)") +Cc: Diana Craciun +Signed-off-by: Christophe Leroy +Reviewed-by: Daniel Axtens +Reviewed-by: Diana Craciun +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/exceptions-64e.S | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/powerpc/kernel/exceptions-64e.S ++++ b/arch/powerpc/kernel/exceptions-64e.S +@@ -348,6 +348,7 @@ ret_from_mc_except: + #define GEN_BTB_FLUSH + #define CRIT_BTB_FLUSH + #define DBG_BTB_FLUSH ++#define MC_BTB_FLUSH + #define GDBELL_BTB_FLUSH + #endif + diff --git a/queue-4.4/powerpc-fsl-flush-the-branch-predictor-at-each-kernel-entry-64bit.patch b/queue-4.4/powerpc-fsl-flush-the-branch-predictor-at-each-kernel-entry-64bit.patch new file mode 100644 index 00000000000..bf9bde297b6 --- /dev/null +++ b/queue-4.4/powerpc-fsl-flush-the-branch-predictor-at-each-kernel-entry-64bit.patch @@ -0,0 +1,101 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:34 +1000 +Subject: powerpc/fsl: Flush the branch predictor at each kernel entry (64bit) +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-50-mpe@ellerman.id.au> + +From: Diana Craciun + +commit 10c5e83afd4a3f01712d97d3bb1ae34d5b74a185 upstream. + +In order to protect against speculation attacks on +indirect branches, the branch predictor is flushed at +kernel entry to protect for the following situations: +- userspace process attacking another userspace process +- userspace process attacking the kernel +Basically when the privillege level change (i.e. the +kernel is entered), the branch predictor state is flushed. + +Signed-off-by: Diana Craciun +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/entry_64.S | 5 +++++ + arch/powerpc/kernel/exceptions-64e.S | 26 +++++++++++++++++++++++++- + arch/powerpc/mm/tlb_low_64e.S | 7 +++++++ + 3 files changed, 37 insertions(+), 1 deletion(-) + +--- a/arch/powerpc/kernel/entry_64.S ++++ b/arch/powerpc/kernel/entry_64.S +@@ -77,6 +77,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM) + std r0,GPR0(r1) + std r10,GPR1(r1) + beq 2f /* if from kernel mode */ ++#ifdef CONFIG_PPC_FSL_BOOK3E ++START_BTB_FLUSH_SECTION ++ BTB_FLUSH(r10) ++END_BTB_FLUSH_SECTION ++#endif + ACCOUNT_CPU_USER_ENTRY(r10, r11) + 2: std r2,GPR2(r1) + std r3,GPR3(r1) +--- a/arch/powerpc/kernel/exceptions-64e.S ++++ b/arch/powerpc/kernel/exceptions-64e.S +@@ -295,7 +295,8 @@ ret_from_mc_except: + andi. r10,r11,MSR_PR; /* save stack pointer */ \ + beq 1f; /* branch around if supervisor */ \ + ld r1,PACAKSAVE(r13); /* get kernel stack coming from usr */\ +-1: cmpdi cr1,r1,0; /* check if SP makes sense */ \ ++1: type##_BTB_FLUSH \ ++ cmpdi cr1,r1,0; /* check if SP makes sense */ \ + bge- cr1,exc_##n##_bad_stack;/* bad stack (TODO: out of line) */ \ + mfspr r10,SPRN_##type##_SRR0; /* read SRR0 before touching stack */ + +@@ -327,6 +328,29 @@ ret_from_mc_except: + #define SPRN_MC_SRR0 SPRN_MCSRR0 + #define SPRN_MC_SRR1 SPRN_MCSRR1 + ++#ifdef CONFIG_PPC_FSL_BOOK3E ++#define GEN_BTB_FLUSH \ ++ START_BTB_FLUSH_SECTION \ ++ beq 1f; \ ++ BTB_FLUSH(r10) \ ++ 1: \ ++ END_BTB_FLUSH_SECTION ++ ++#define CRIT_BTB_FLUSH \ ++ START_BTB_FLUSH_SECTION \ ++ BTB_FLUSH(r10) \ ++ END_BTB_FLUSH_SECTION ++ ++#define DBG_BTB_FLUSH CRIT_BTB_FLUSH ++#define MC_BTB_FLUSH CRIT_BTB_FLUSH ++#define GDBELL_BTB_FLUSH GEN_BTB_FLUSH ++#else ++#define GEN_BTB_FLUSH ++#define CRIT_BTB_FLUSH ++#define DBG_BTB_FLUSH ++#define GDBELL_BTB_FLUSH ++#endif ++ + #define NORMAL_EXCEPTION_PROLOG(n, intnum, addition) \ + EXCEPTION_PROLOG(n, intnum, GEN, addition##_GEN(n)) + +--- a/arch/powerpc/mm/tlb_low_64e.S ++++ b/arch/powerpc/mm/tlb_low_64e.S +@@ -69,6 +69,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV) + std r15,EX_TLB_R15(r12) + std r10,EX_TLB_CR(r12) + #ifdef CONFIG_PPC_FSL_BOOK3E ++START_BTB_FLUSH_SECTION ++ mfspr r11, SPRN_SRR1 ++ andi. r10,r11,MSR_PR ++ beq 1f ++ BTB_FLUSH(r10) ++1: ++END_BTB_FLUSH_SECTION + std r7,EX_TLB_R7(r12) + #endif + TLB_MISS_PROLOG_STATS diff --git a/queue-4.4/powerpc-fsl-update-spectre-v2-reporting.patch b/queue-4.4/powerpc-fsl-update-spectre-v2-reporting.patch new file mode 100644 index 00000000000..31fe0aa6f93 --- /dev/null +++ b/queue-4.4/powerpc-fsl-update-spectre-v2-reporting.patch @@ -0,0 +1,37 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:35 +1000 +Subject: powerpc/fsl: Update Spectre v2 reporting +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-51-mpe@ellerman.id.au> + +From: Diana Craciun + +commit dfa88658fb0583abb92e062c7a9cd5a5b94f2a46 upstream. + +Report branch predictor state flush as a mitigation for +Spectre variant 2. + +Signed-off-by: Diana Craciun +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/security.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -213,8 +213,11 @@ ssize_t cpu_show_spectre_v2(struct devic + + if (count_cache_flush_type == COUNT_CACHE_FLUSH_HW) + seq_buf_printf(&s, "(hardware accelerated)"); +- } else ++ } else if (btb_flush_enabled) { ++ seq_buf_printf(&s, "Mitigation: Branch predictor state flush"); ++ } else { + seq_buf_printf(&s, "Vulnerable"); ++ } + + seq_buf_printf(&s, "\n"); + diff --git a/queue-4.4/powerpc-move-default-security-feature-flags.patch b/queue-4.4/powerpc-move-default-security-feature-flags.patch new file mode 100644 index 00000000000..7095cbbc04d --- /dev/null +++ b/queue-4.4/powerpc-move-default-security-feature-flags.patch @@ -0,0 +1,56 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:06 +1000 +Subject: powerpc: Move default security feature flags +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-22-mpe@ellerman.id.au> + +From: Mauricio Faria de Oliveira + +commit e7347a86830f38dc3e40c8f7e28c04412b12a2e7 upstream. + +This moves the definition of the default security feature flags +(i.e., enabled by default) closer to the security feature flags. + +This can be used to restore current flags to the default flags. + +Signed-off-by: Mauricio Faria de Oliveira +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/security_features.h | 8 ++++++++ + arch/powerpc/kernel/security.c | 7 +------ + 2 files changed, 9 insertions(+), 6 deletions(-) + +--- a/arch/powerpc/include/asm/security_features.h ++++ b/arch/powerpc/include/asm/security_features.h +@@ -63,4 +63,12 @@ static inline bool security_ftr_enabled( + // Firmware configuration indicates user favours security over performance + #define SEC_FTR_FAVOUR_SECURITY 0x0000000000000200ull + ++ ++// Features enabled by default ++#define SEC_FTR_DEFAULT \ ++ (SEC_FTR_L1D_FLUSH_HV | \ ++ SEC_FTR_L1D_FLUSH_PR | \ ++ SEC_FTR_BNDS_CHK_SPEC_BAR | \ ++ SEC_FTR_FAVOUR_SECURITY) ++ + #endif /* _ASM_POWERPC_SECURITY_FEATURES_H */ +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -11,12 +11,7 @@ + #include + + +-unsigned long powerpc_security_features __read_mostly = \ +- SEC_FTR_L1D_FLUSH_HV | \ +- SEC_FTR_L1D_FLUSH_PR | \ +- SEC_FTR_BNDS_CHK_SPEC_BAR | \ +- SEC_FTR_FAVOUR_SECURITY; +- ++unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT; + + ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) + { diff --git a/queue-4.4/powerpc-powernv-query-firmware-for-count-cache-flush-settings.patch b/queue-4.4/powerpc-powernv-query-firmware-for-count-cache-flush-settings.patch new file mode 100644 index 00000000000..d5692ec8371 --- /dev/null +++ b/queue-4.4/powerpc-powernv-query-firmware-for-count-cache-flush-settings.patch @@ -0,0 +1,45 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:28 +1000 +Subject: powerpc/powernv: Query firmware for count cache flush settings +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-44-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 99d54754d3d5f896a8f616b0b6520662bc99d66b upstream. + +Look for fw-features properties to determine the appropriate settings +for the count cache flush, and then call the generic powerpc code to +set it up based on the security feature flags. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/powernv/setup.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/powerpc/platforms/powernv/setup.c ++++ b/arch/powerpc/platforms/powernv/setup.c +@@ -77,6 +77,12 @@ static void init_fw_feat_flags(struct de + if (fw_feature_is("enabled", "fw-count-cache-disabled", np)) + security_ftr_set(SEC_FTR_COUNT_CACHE_DISABLED); + ++ if (fw_feature_is("enabled", "fw-count-cache-flush-bcctr2,0,0", np)) ++ security_ftr_set(SEC_FTR_BCCTR_FLUSH_ASSIST); ++ ++ if (fw_feature_is("enabled", "needs-count-cache-flush-on-context-switch", np)) ++ security_ftr_set(SEC_FTR_FLUSH_COUNT_CACHE); ++ + /* + * The features below are enabled by default, so we instead look to see + * if firmware has *disabled* them, and clear them if so. +@@ -123,6 +129,7 @@ static void pnv_setup_rfi_flush(void) + security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV)); + + setup_rfi_flush(type, enable); ++ setup_count_cache_flush(); + } + + static void __init pnv_setup_arch(void) diff --git a/queue-4.4/powerpc-powernv-set-or-clear-security-feature-flags.patch b/queue-4.4/powerpc-powernv-set-or-clear-security-feature-flags.patch new file mode 100644 index 00000000000..7fc121e3392 --- /dev/null +++ b/queue-4.4/powerpc-powernv-set-or-clear-security-feature-flags.patch @@ -0,0 +1,97 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:58 +1000 +Subject: powerpc/powernv: Set or clear security feature flags +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-14-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 77addf6e95c8689e478d607176b399a6242a777e upstream. + +Now that we have feature flags for security related things, set or +clear them based on what we see in the device tree provided by +firmware. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/powernv/setup.c | 56 +++++++++++++++++++++++++++++++++ + 1 file changed, 56 insertions(+) + +--- a/arch/powerpc/platforms/powernv/setup.c ++++ b/arch/powerpc/platforms/powernv/setup.c +@@ -37,9 +37,63 @@ + #include + #include + #include ++#include + + #include "powernv.h" + ++ ++static bool fw_feature_is(const char *state, const char *name, ++ struct device_node *fw_features) ++{ ++ struct device_node *np; ++ bool rc = false; ++ ++ np = of_get_child_by_name(fw_features, name); ++ if (np) { ++ rc = of_property_read_bool(np, state); ++ of_node_put(np); ++ } ++ ++ return rc; ++} ++ ++static void init_fw_feat_flags(struct device_node *np) ++{ ++ if (fw_feature_is("enabled", "inst-spec-barrier-ori31,31,0", np)) ++ security_ftr_set(SEC_FTR_SPEC_BAR_ORI31); ++ ++ if (fw_feature_is("enabled", "fw-bcctrl-serialized", np)) ++ security_ftr_set(SEC_FTR_BCCTRL_SERIALISED); ++ ++ if (fw_feature_is("enabled", "inst-spec-barrier-ori31,31,0", np)) ++ security_ftr_set(SEC_FTR_L1D_FLUSH_ORI30); ++ ++ if (fw_feature_is("enabled", "inst-l1d-flush-trig2", np)) ++ security_ftr_set(SEC_FTR_L1D_FLUSH_TRIG2); ++ ++ if (fw_feature_is("enabled", "fw-l1d-thread-split", np)) ++ security_ftr_set(SEC_FTR_L1D_THREAD_PRIV); ++ ++ if (fw_feature_is("enabled", "fw-count-cache-disabled", np)) ++ security_ftr_set(SEC_FTR_COUNT_CACHE_DISABLED); ++ ++ /* ++ * The features below are enabled by default, so we instead look to see ++ * if firmware has *disabled* them, and clear them if so. ++ */ ++ if (fw_feature_is("disabled", "speculation-policy-favor-security", np)) ++ security_ftr_clear(SEC_FTR_FAVOUR_SECURITY); ++ ++ if (fw_feature_is("disabled", "needs-l1d-flush-msr-pr-0-to-1", np)) ++ security_ftr_clear(SEC_FTR_L1D_FLUSH_PR); ++ ++ if (fw_feature_is("disabled", "needs-l1d-flush-msr-hv-1-to-0", np)) ++ security_ftr_clear(SEC_FTR_L1D_FLUSH_HV); ++ ++ if (fw_feature_is("disabled", "needs-spec-barrier-for-bound-checks", np)) ++ security_ftr_clear(SEC_FTR_BNDS_CHK_SPEC_BAR); ++} ++ + static void pnv_setup_rfi_flush(void) + { + struct device_node *np, *fw_features; +@@ -55,6 +109,8 @@ static void pnv_setup_rfi_flush(void) + of_node_put(np); + + if (fw_features) { ++ init_fw_feat_flags(fw_features); ++ + np = of_get_child_by_name(fw_features, "inst-l1d-flush-trig2"); + if (np && of_property_read_bool(np, "enabled")) + type = L1D_FLUSH_MTTRIG; diff --git a/queue-4.4/powerpc-powernv-support-firmware-disable-of-rfi-flush.patch b/queue-4.4/powerpc-powernv-support-firmware-disable-of-rfi-flush.patch new file mode 100644 index 00000000000..a3d38946741 --- /dev/null +++ b/queue-4.4/powerpc-powernv-support-firmware-disable-of-rfi-flush.patch @@ -0,0 +1,35 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:49 +1000 +Subject: powerpc/powernv: Support firmware disable of RFI flush +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-5-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit eb0a2d2620ae431c543963c8c7f08f597366fc60 upstream. + +Some versions of firmware will have a setting that can be configured +to disable the RFI flush, add support for it. + +Fixes: 6e032b350cd1 ("powerpc/powernv: Check device-tree for RFI flush settings") +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/powernv/setup.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/powerpc/platforms/powernv/setup.c ++++ b/arch/powerpc/platforms/powernv/setup.c +@@ -79,6 +79,10 @@ static void pnv_setup_rfi_flush(void) + if (np && of_property_read_bool(np, "disabled")) + enable--; + ++ np = of_get_child_by_name(fw_features, "speculation-policy-favor-security"); ++ if (np && of_property_read_bool(np, "disabled")) ++ enable = 0; ++ + of_node_put(np); + of_node_put(fw_features); + } diff --git a/queue-4.4/powerpc-powernv-use-the-security-flags-in-pnv_setup_rfi_flush.patch b/queue-4.4/powerpc-powernv-use-the-security-flags-in-pnv_setup_rfi_flush.patch new file mode 100644 index 00000000000..c7acfe459ef --- /dev/null +++ b/queue-4.4/powerpc-powernv-use-the-security-flags-in-pnv_setup_rfi_flush.patch @@ -0,0 +1,96 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:01 +1000 +Subject: powerpc/powernv: Use the security flags in pnv_setup_rfi_flush() +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-17-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 37c0bdd00d3ae83369ab60a6712c28e11e6458d5 upstream. + +Now that we have the security flags we can significantly simplify the +code in pnv_setup_rfi_flush(), because we can use the flags instead of +checking device tree properties and because the security flags have +pessimistic defaults. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/powernv/setup.c | 41 ++++++++------------------------- + 1 file changed, 10 insertions(+), 31 deletions(-) + +--- a/arch/powerpc/platforms/powernv/setup.c ++++ b/arch/powerpc/platforms/powernv/setup.c +@@ -65,7 +65,7 @@ static void init_fw_feat_flags(struct de + if (fw_feature_is("enabled", "fw-bcctrl-serialized", np)) + security_ftr_set(SEC_FTR_BCCTRL_SERIALISED); + +- if (fw_feature_is("enabled", "inst-spec-barrier-ori31,31,0", np)) ++ if (fw_feature_is("enabled", "inst-l1d-flush-ori30,30,0", np)) + security_ftr_set(SEC_FTR_L1D_FLUSH_ORI30); + + if (fw_feature_is("enabled", "inst-l1d-flush-trig2", np)) +@@ -98,11 +98,10 @@ static void pnv_setup_rfi_flush(void) + { + struct device_node *np, *fw_features; + enum l1d_flush_type type; +- int enable; ++ bool enable; + + /* Default to fallback in case fw-features are not available */ + type = L1D_FLUSH_FALLBACK; +- enable = 1; + + np = of_find_node_by_name(NULL, "ibm,opal"); + fw_features = of_get_child_by_name(np, "fw-features"); +@@ -110,40 +109,20 @@ static void pnv_setup_rfi_flush(void) + + if (fw_features) { + init_fw_feat_flags(fw_features); ++ of_node_put(fw_features); + +- np = of_get_child_by_name(fw_features, "inst-l1d-flush-trig2"); +- if (np && of_property_read_bool(np, "enabled")) ++ if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_TRIG2)) + type = L1D_FLUSH_MTTRIG; + +- of_node_put(np); +- +- np = of_get_child_by_name(fw_features, "inst-l1d-flush-ori30,30,0"); +- if (np && of_property_read_bool(np, "enabled")) ++ if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_ORI30)) + type = L1D_FLUSH_ORI; +- +- of_node_put(np); +- +- /* Enable unless firmware says NOT to */ +- enable = 2; +- np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-hv-1-to-0"); +- if (np && of_property_read_bool(np, "disabled")) +- enable--; +- +- of_node_put(np); +- +- np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-pr-0-to-1"); +- if (np && of_property_read_bool(np, "disabled")) +- enable--; +- +- np = of_get_child_by_name(fw_features, "speculation-policy-favor-security"); +- if (np && of_property_read_bool(np, "disabled")) +- enable = 0; +- +- of_node_put(np); +- of_node_put(fw_features); + } + +- setup_rfi_flush(type, enable > 0); ++ enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && \ ++ (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) || \ ++ security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV)); ++ ++ setup_rfi_flush(type, enable); + } + + static void __init pnv_setup_arch(void) diff --git a/queue-4.4/powerpc-pseries-add-new-h_get_cpu_characteristics-flags.patch b/queue-4.4/powerpc-pseries-add-new-h_get_cpu_characteristics-flags.patch new file mode 100644 index 00000000000..f0488bd6a1b --- /dev/null +++ b/queue-4.4/powerpc-pseries-add-new-h_get_cpu_characteristics-flags.patch @@ -0,0 +1,33 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:54 +1000 +Subject: powerpc/pseries: Add new H_GET_CPU_CHARACTERISTICS flags +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-10-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit c4bc36628d7f8b664657d8bd6ad1c44c177880b7 upstream. + +Add some additional values which have been defined for the +H_GET_CPU_CHARACTERISTICS hypercall. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/hvcall.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/arch/powerpc/include/asm/hvcall.h ++++ b/arch/powerpc/include/asm/hvcall.h +@@ -292,6 +292,9 @@ + #define H_CPU_CHAR_L1D_FLUSH_ORI30 (1ull << 61) // IBM bit 2 + #define H_CPU_CHAR_L1D_FLUSH_TRIG2 (1ull << 60) // IBM bit 3 + #define H_CPU_CHAR_L1D_THREAD_PRIV (1ull << 59) // IBM bit 4 ++#define H_CPU_CHAR_BRANCH_HINTS_HONORED (1ull << 58) // IBM bit 5 ++#define H_CPU_CHAR_THREAD_RECONFIG_CTRL (1ull << 57) // IBM bit 6 ++#define H_CPU_CHAR_COUNT_CACHE_DISABLED (1ull << 56) // IBM bit 7 + + #define H_CPU_BEHAV_FAVOUR_SECURITY (1ull << 63) // IBM bit 0 + #define H_CPU_BEHAV_L1D_FLUSH_PR (1ull << 62) // IBM bit 1 diff --git a/queue-4.4/powerpc-pseries-fix-clearing-of-security-feature-flags.patch b/queue-4.4/powerpc-pseries-fix-clearing-of-security-feature-flags.patch new file mode 100644 index 00000000000..46659a8d07f --- /dev/null +++ b/queue-4.4/powerpc-pseries-fix-clearing-of-security-feature-flags.patch @@ -0,0 +1,81 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:05 +1000 +Subject: powerpc/pseries: Fix clearing of security feature flags +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-21-mpe@ellerman.id.au> + +From: Mauricio Faria de Oliveira + +commit 0f9bdfe3c77091e8704d2e510eb7c2c2c6cde524 upstream. + +The H_CPU_BEHAV_* flags should be checked for in the 'behaviour' field +of 'struct h_cpu_char_result' -- 'character' is for H_CPU_CHAR_* +flags. + +Found by playing around with QEMU's implementation of the hypercall: + + H_CPU_CHAR=0xf000000000000000 + H_CPU_BEHAV=0x0000000000000000 + + This clears H_CPU_BEHAV_FAVOUR_SECURITY and H_CPU_BEHAV_L1D_FLUSH_PR + so pseries_setup_rfi_flush() disables 'rfi_flush'; and it also + clears H_CPU_CHAR_L1D_THREAD_PRIV flag. So there is no RFI flush + mitigation at all for cpu_show_meltdown() to report; but currently + it does: + + Original kernel: + + # cat /sys/devices/system/cpu/vulnerabilities/meltdown + Mitigation: RFI Flush + + Patched kernel: + + # cat /sys/devices/system/cpu/vulnerabilities/meltdown + Not affected + + H_CPU_CHAR=0x0000000000000000 + H_CPU_BEHAV=0xf000000000000000 + + This sets H_CPU_BEHAV_BNDS_CHK_SPEC_BAR so cpu_show_spectre_v1() should + report vulnerable; but currently it doesn't: + + Original kernel: + + # cat /sys/devices/system/cpu/vulnerabilities/spectre_v1 + Not affected + + Patched kernel: + + # cat /sys/devices/system/cpu/vulnerabilities/spectre_v1 + Vulnerable + +Brown-paper-bag-by: Michael Ellerman +Fixes: f636c14790ea ("powerpc/pseries: Set or clear security feature flags") +Signed-off-by: Mauricio Faria de Oliveira +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/pseries/setup.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -524,13 +524,13 @@ static void init_cpu_char_feature_flags( + * The features below are enabled by default, so we instead look to see + * if firmware has *disabled* them, and clear them if so. + */ +- if (!(result->character & H_CPU_BEHAV_FAVOUR_SECURITY)) ++ if (!(result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY)) + security_ftr_clear(SEC_FTR_FAVOUR_SECURITY); + +- if (!(result->character & H_CPU_BEHAV_L1D_FLUSH_PR)) ++ if (!(result->behaviour & H_CPU_BEHAV_L1D_FLUSH_PR)) + security_ftr_clear(SEC_FTR_L1D_FLUSH_PR); + +- if (!(result->character & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR)) ++ if (!(result->behaviour & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR)) + security_ftr_clear(SEC_FTR_BNDS_CHK_SPEC_BAR); + } + diff --git a/queue-4.4/powerpc-pseries-query-hypervisor-for-count-cache-flush-settings.patch b/queue-4.4/powerpc-pseries-query-hypervisor-for-count-cache-flush-settings.patch new file mode 100644 index 00000000000..a2d95a94bfa --- /dev/null +++ b/queue-4.4/powerpc-pseries-query-hypervisor-for-count-cache-flush-settings.patch @@ -0,0 +1,61 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:27 +1000 +Subject: powerpc/pseries: Query hypervisor for count cache flush settings +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-43-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit ba72dc171954b782a79d25e0f4b3ed91090c3b1e upstream. + +Use the existing hypercall to determine the appropriate settings for +the count cache flush, and then call the generic powerpc code to set +it up based on the security feature flags. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/hvcall.h | 2 ++ + arch/powerpc/platforms/pseries/setup.c | 7 +++++++ + 2 files changed, 9 insertions(+) + +--- a/arch/powerpc/include/asm/hvcall.h ++++ b/arch/powerpc/include/asm/hvcall.h +@@ -295,10 +295,12 @@ + #define H_CPU_CHAR_BRANCH_HINTS_HONORED (1ull << 58) // IBM bit 5 + #define H_CPU_CHAR_THREAD_RECONFIG_CTRL (1ull << 57) // IBM bit 6 + #define H_CPU_CHAR_COUNT_CACHE_DISABLED (1ull << 56) // IBM bit 7 ++#define H_CPU_CHAR_BCCTR_FLUSH_ASSIST (1ull << 54) // IBM bit 9 + + #define H_CPU_BEHAV_FAVOUR_SECURITY (1ull << 63) // IBM bit 0 + #define H_CPU_BEHAV_L1D_FLUSH_PR (1ull << 62) // IBM bit 1 + #define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR (1ull << 61) // IBM bit 2 ++#define H_CPU_BEHAV_FLUSH_COUNT_CACHE (1ull << 58) // IBM bit 5 + + #ifndef __ASSEMBLY__ + #include +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -524,6 +524,12 @@ static void init_cpu_char_feature_flags( + if (result->character & H_CPU_CHAR_COUNT_CACHE_DISABLED) + security_ftr_set(SEC_FTR_COUNT_CACHE_DISABLED); + ++ if (result->character & H_CPU_CHAR_BCCTR_FLUSH_ASSIST) ++ security_ftr_set(SEC_FTR_BCCTR_FLUSH_ASSIST); ++ ++ if (result->behaviour & H_CPU_BEHAV_FLUSH_COUNT_CACHE) ++ security_ftr_set(SEC_FTR_FLUSH_COUNT_CACHE); ++ + /* + * The features below are enabled by default, so we instead look to see + * if firmware has *disabled* them, and clear them if so. +@@ -574,6 +580,7 @@ void pseries_setup_rfi_flush(void) + security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR); + + setup_rfi_flush(types, enable); ++ setup_count_cache_flush(); + } + + static void __init pSeries_setup_arch(void) diff --git a/queue-4.4/powerpc-pseries-restore-default-security-feature-flags-on-setup.patch b/queue-4.4/powerpc-pseries-restore-default-security-feature-flags-on-setup.patch new file mode 100644 index 00000000000..b4e1e07134f --- /dev/null +++ b/queue-4.4/powerpc-pseries-restore-default-security-feature-flags-on-setup.patch @@ -0,0 +1,61 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:07 +1000 +Subject: powerpc/pseries: Restore default security feature flags on setup +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-23-mpe@ellerman.id.au> + +From: Mauricio Faria de Oliveira + +commit 6232774f1599028a15418179d17f7df47ede770a upstream. + +After migration the security feature flags might have changed (e.g., +destination system with unpatched firmware), but some flags are not +set/clear again in init_cpu_char_feature_flags() because it assumes +the security flags to be the defaults. + +Additionally, if the H_GET_CPU_CHARACTERISTICS hypercall fails then +init_cpu_char_feature_flags() does not run again, which potentially +might leave the system in an insecure or sub-optimal configuration. + +So, just restore the security feature flags to the defaults assumed +by init_cpu_char_feature_flags() so it can set/clear them correctly, +and to ensure safe settings are in place in case the hypercall fail. + +Fixes: f636c14790ea ("powerpc/pseries: Set or clear security feature flags") +Depends-on: 19887d6a28e2 ("powerpc: Move default security feature flags") +Signed-off-by: Mauricio Faria de Oliveira +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/pseries/setup.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -502,6 +502,10 @@ static void __init find_and_init_phbs(vo + + static void init_cpu_char_feature_flags(struct h_cpu_char_result *result) + { ++ /* ++ * The features below are disabled by default, so we instead look to see ++ * if firmware has *enabled* them, and set them if so. ++ */ + if (result->character & H_CPU_CHAR_SPEC_BAR_ORI31) + security_ftr_set(SEC_FTR_SPEC_BAR_ORI31); + +@@ -541,6 +545,13 @@ void pseries_setup_rfi_flush(void) + bool enable; + long rc; + ++ /* ++ * Set features to the defaults assumed by init_cpu_char_feature_flags() ++ * so it can set/clear again any features that might have changed after ++ * migration, and in case the hypercall fails and it is not even called. ++ */ ++ powerpc_security_features = SEC_FTR_DEFAULT; ++ + rc = plpar_get_cpu_characteristics(&result); + if (rc == H_SUCCESS) + init_cpu_char_feature_flags(&result); diff --git a/queue-4.4/powerpc-pseries-set-or-clear-security-feature-flags.patch b/queue-4.4/powerpc-pseries-set-or-clear-security-feature-flags.patch new file mode 100644 index 00000000000..2fe53f2659e --- /dev/null +++ b/queue-4.4/powerpc-pseries-set-or-clear-security-feature-flags.patch @@ -0,0 +1,94 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:57 +1000 +Subject: powerpc/pseries: Set or clear security feature flags +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-13-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit f636c14790ead6cc22cf62279b1f8d7e11a67116 upstream. + +Now that we have feature flags for security related things, set or +clear them based on what we receive from the hypercall. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/pseries/setup.c | 43 +++++++++++++++++++++++++++++++++ + 1 file changed, 43 insertions(+) + +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -67,6 +67,7 @@ + #include + #include + #include ++#include + + #include "pseries.h" + +@@ -499,6 +500,40 @@ static void __init find_and_init_phbs(vo + of_pci_check_probe_only(); + } + ++static void init_cpu_char_feature_flags(struct h_cpu_char_result *result) ++{ ++ if (result->character & H_CPU_CHAR_SPEC_BAR_ORI31) ++ security_ftr_set(SEC_FTR_SPEC_BAR_ORI31); ++ ++ if (result->character & H_CPU_CHAR_BCCTRL_SERIALISED) ++ security_ftr_set(SEC_FTR_BCCTRL_SERIALISED); ++ ++ if (result->character & H_CPU_CHAR_L1D_FLUSH_ORI30) ++ security_ftr_set(SEC_FTR_L1D_FLUSH_ORI30); ++ ++ if (result->character & H_CPU_CHAR_L1D_FLUSH_TRIG2) ++ security_ftr_set(SEC_FTR_L1D_FLUSH_TRIG2); ++ ++ if (result->character & H_CPU_CHAR_L1D_THREAD_PRIV) ++ security_ftr_set(SEC_FTR_L1D_THREAD_PRIV); ++ ++ if (result->character & H_CPU_CHAR_COUNT_CACHE_DISABLED) ++ security_ftr_set(SEC_FTR_COUNT_CACHE_DISABLED); ++ ++ /* ++ * The features below are enabled by default, so we instead look to see ++ * if firmware has *disabled* them, and clear them if so. ++ */ ++ if (!(result->character & H_CPU_BEHAV_FAVOUR_SECURITY)) ++ security_ftr_clear(SEC_FTR_FAVOUR_SECURITY); ++ ++ if (!(result->character & H_CPU_BEHAV_L1D_FLUSH_PR)) ++ security_ftr_clear(SEC_FTR_L1D_FLUSH_PR); ++ ++ if (!(result->character & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR)) ++ security_ftr_clear(SEC_FTR_BNDS_CHK_SPEC_BAR); ++} ++ + void pseries_setup_rfi_flush(void) + { + struct h_cpu_char_result result; +@@ -512,6 +547,8 @@ void pseries_setup_rfi_flush(void) + + rc = plpar_get_cpu_characteristics(&result); + if (rc == H_SUCCESS) { ++ init_cpu_char_feature_flags(&result); ++ + if (result.character & H_CPU_CHAR_L1D_FLUSH_TRIG2) + types |= L1D_FLUSH_MTTRIG; + if (result.character & H_CPU_CHAR_L1D_FLUSH_ORI30) +@@ -522,6 +559,12 @@ void pseries_setup_rfi_flush(void) + enable = false; + } + ++ /* ++ * We're the guest so this doesn't apply to us, clear it to simplify ++ * handling of it elsewhere. ++ */ ++ security_ftr_clear(SEC_FTR_L1D_FLUSH_HV); ++ + setup_rfi_flush(types, enable); + } + diff --git a/queue-4.4/powerpc-pseries-support-firmware-disable-of-rfi-flush.patch b/queue-4.4/powerpc-pseries-support-firmware-disable-of-rfi-flush.patch new file mode 100644 index 00000000000..288a65b4e82 --- /dev/null +++ b/queue-4.4/powerpc-pseries-support-firmware-disable-of-rfi-flush.patch @@ -0,0 +1,34 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:48 +1000 +Subject: powerpc/pseries: Support firmware disable of RFI flush +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-4-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 582605a429e20ae68fd0b041b2e840af296edd08 upstream. + +Some versions of firmware will have a setting that can be configured +to disable the RFI flush, add support for it. + +Fixes: 8989d56878a7 ("powerpc/pseries: Query hypervisor for RFI flush settings") +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/pseries/setup.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -522,7 +522,8 @@ static void pseries_setup_rfi_flush(void + if (types == L1D_FLUSH_NONE) + types = L1D_FLUSH_FALLBACK; + +- if (!(result.behaviour & H_CPU_BEHAV_L1D_FLUSH_PR)) ++ if ((!(result.behaviour & H_CPU_BEHAV_L1D_FLUSH_PR)) || ++ (!(result.behaviour & H_CPU_BEHAV_FAVOUR_SECURITY))) + enable = false; + } else { + /* Default to fallback if case hcall is not available */ diff --git a/queue-4.4/powerpc-pseries-use-the-security-flags-in-pseries_setup_rfi_flush.patch b/queue-4.4/powerpc-pseries-use-the-security-flags-in-pseries_setup_rfi_flush.patch new file mode 100644 index 00000000000..300ad8bc99f --- /dev/null +++ b/queue-4.4/powerpc-pseries-use-the-security-flags-in-pseries_setup_rfi_flush.patch @@ -0,0 +1,67 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:02 +1000 +Subject: powerpc/pseries: Use the security flags in pseries_setup_rfi_flush() +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-18-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 2e4a16161fcd324b1f9bf6cb6856529f7eaf0689 upstream. + +Now that we have the security flags we can simplify the code in +pseries_setup_rfi_flush() because the security flags have pessimistic +defaults. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/pseries/setup.c | 27 ++++++++++++--------------- + 1 file changed, 12 insertions(+), 15 deletions(-) + +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -541,30 +541,27 @@ void pseries_setup_rfi_flush(void) + bool enable; + long rc; + +- /* Enable by default */ +- enable = true; +- types = L1D_FLUSH_FALLBACK; +- + rc = plpar_get_cpu_characteristics(&result); +- if (rc == H_SUCCESS) { ++ if (rc == H_SUCCESS) + init_cpu_char_feature_flags(&result); + +- if (result.character & H_CPU_CHAR_L1D_FLUSH_TRIG2) +- types |= L1D_FLUSH_MTTRIG; +- if (result.character & H_CPU_CHAR_L1D_FLUSH_ORI30) +- types |= L1D_FLUSH_ORI; +- +- if ((!(result.behaviour & H_CPU_BEHAV_L1D_FLUSH_PR)) || +- (!(result.behaviour & H_CPU_BEHAV_FAVOUR_SECURITY))) +- enable = false; +- } +- + /* + * We're the guest so this doesn't apply to us, clear it to simplify + * handling of it elsewhere. + */ + security_ftr_clear(SEC_FTR_L1D_FLUSH_HV); + ++ types = L1D_FLUSH_FALLBACK; ++ ++ if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_TRIG2)) ++ types |= L1D_FLUSH_MTTRIG; ++ ++ if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_ORI30)) ++ types |= L1D_FLUSH_ORI; ++ ++ enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && \ ++ security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR); ++ + setup_rfi_flush(types, enable); + } + diff --git a/queue-4.4/powerpc-rfi-flush-always-enable-fallback-flush-on-pseries.patch b/queue-4.4/powerpc-rfi-flush-always-enable-fallback-flush-on-pseries.patch new file mode 100644 index 00000000000..afdaa5265bb --- /dev/null +++ b/queue-4.4/powerpc-rfi-flush-always-enable-fallback-flush-on-pseries.patch @@ -0,0 +1,54 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:52 +1000 +Subject: powerpc/rfi-flush: Always enable fallback flush on pseries +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-8-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 84749a58b6e382f109abf1e734bc4dd43c2c25bb upstream. + +This ensures the fallback flush area is always allocated on pseries, +so in case a LPAR is migrated from a patched to an unpatched system, +it is possible to enable the fallback flush in the target system. + +Signed-off-by: Michael Ellerman +Signed-off-by: Mauricio Faria de Oliveira +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/pseries/setup.c | 10 +--------- + 1 file changed, 1 insertion(+), 9 deletions(-) + +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -508,26 +508,18 @@ static void pseries_setup_rfi_flush(void + + /* Enable by default */ + enable = true; ++ types = L1D_FLUSH_FALLBACK; + + rc = plpar_get_cpu_characteristics(&result); + if (rc == H_SUCCESS) { +- types = L1D_FLUSH_NONE; +- + if (result.character & H_CPU_CHAR_L1D_FLUSH_TRIG2) + types |= L1D_FLUSH_MTTRIG; + if (result.character & H_CPU_CHAR_L1D_FLUSH_ORI30) + types |= L1D_FLUSH_ORI; + +- /* Use fallback if nothing set in hcall */ +- if (types == L1D_FLUSH_NONE) +- types = L1D_FLUSH_FALLBACK; +- + if ((!(result.behaviour & H_CPU_BEHAV_L1D_FLUSH_PR)) || + (!(result.behaviour & H_CPU_BEHAV_FAVOUR_SECURITY))) + enable = false; +- } else { +- /* Default to fallback if case hcall is not available */ +- types = L1D_FLUSH_FALLBACK; + } + + setup_rfi_flush(types, enable); diff --git a/queue-4.4/powerpc-rfi-flush-call-setup_rfi_flush-after-lpm-migration.patch b/queue-4.4/powerpc-rfi-flush-call-setup_rfi_flush-after-lpm-migration.patch new file mode 100644 index 00000000000..c8736396b12 --- /dev/null +++ b/queue-4.4/powerpc-rfi-flush-call-setup_rfi_flush-after-lpm-migration.patch @@ -0,0 +1,57 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:55 +1000 +Subject: powerpc/rfi-flush: Call setup_rfi_flush() after LPM migration +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-11-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 921bc6cf807ceb2ab8005319cf39f33494d6b100 upstream. + +We might have migrated to a machine that uses a different flush type, +or doesn't need flushing at all. + +Signed-off-by: Michael Ellerman +Signed-off-by: Mauricio Faria de Oliveira +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/pseries/mobility.c | 3 +++ + arch/powerpc/platforms/pseries/pseries.h | 2 ++ + arch/powerpc/platforms/pseries/setup.c | 2 +- + 3 files changed, 6 insertions(+), 1 deletion(-) + +--- a/arch/powerpc/platforms/pseries/mobility.c ++++ b/arch/powerpc/platforms/pseries/mobility.c +@@ -314,6 +314,9 @@ void post_mobility_fixup(void) + printk(KERN_ERR "Post-mobility device tree update " + "failed: %d\n", rc); + ++ /* Possibly switch to a new RFI flush type */ ++ pseries_setup_rfi_flush(); ++ + return; + } + +--- a/arch/powerpc/platforms/pseries/pseries.h ++++ b/arch/powerpc/platforms/pseries/pseries.h +@@ -81,4 +81,6 @@ extern struct pci_controller_ops pseries + + unsigned long pseries_memory_block_size(void); + ++void pseries_setup_rfi_flush(void); ++ + #endif /* _PSERIES_PSERIES_H */ +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -499,7 +499,7 @@ static void __init find_and_init_phbs(vo + of_pci_check_probe_only(); + } + +-static void pseries_setup_rfi_flush(void) ++void pseries_setup_rfi_flush(void) + { + struct h_cpu_char_result result; + enum l1d_flush_type types; diff --git a/queue-4.4/powerpc-rfi-flush-differentiate-enabled-and-patched-flush-types.patch b/queue-4.4/powerpc-rfi-flush-differentiate-enabled-and-patched-flush-types.patch new file mode 100644 index 00000000000..863898e6fc1 --- /dev/null +++ b/queue-4.4/powerpc-rfi-flush-differentiate-enabled-and-patched-flush-types.patch @@ -0,0 +1,72 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:53 +1000 +Subject: powerpc/rfi-flush: Differentiate enabled and patched flush types +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-9-mpe@ellerman.id.au> + +From: Mauricio Faria de Oliveira + +commit 0063d61ccfc011f379a31acaeba6de7c926fed2c upstream. + +Currently the rfi-flush messages print 'Using flush' for all +enabled_flush_types, but that is not necessarily true -- as now the +fallback flush is always enabled on pseries, but the fixup function +overwrites its nop/branch slot with other flush types, if available. + +So, replace the 'Using flush' messages with ' flush is +available'. + +Also, print the patched flush types in the fixup function, so users +can know what is (not) being used (e.g., the slower, fallback flush, +or no flush type at all if flush is disabled via the debugfs switch). + +Suggested-by: Michael Ellerman +Signed-off-by: Mauricio Faria de Oliveira +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/setup_64.c | 6 +++--- + arch/powerpc/lib/feature-fixups.c | 9 ++++++++- + 2 files changed, 11 insertions(+), 4 deletions(-) + +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -911,15 +911,15 @@ static void init_fallback_flush(void) + void setup_rfi_flush(enum l1d_flush_type types, bool enable) + { + if (types & L1D_FLUSH_FALLBACK) { +- pr_info("rfi-flush: Using fallback displacement flush\n"); ++ pr_info("rfi-flush: fallback displacement flush available\n"); + init_fallback_flush(); + } + + if (types & L1D_FLUSH_ORI) +- pr_info("rfi-flush: Using ori type flush\n"); ++ pr_info("rfi-flush: ori type flush available\n"); + + if (types & L1D_FLUSH_MTTRIG) +- pr_info("rfi-flush: Using mttrig type flush\n"); ++ pr_info("rfi-flush: mttrig type flush available\n"); + + enabled_flush_types = types; + +--- a/arch/powerpc/lib/feature-fixups.c ++++ b/arch/powerpc/lib/feature-fixups.c +@@ -151,7 +151,14 @@ void do_rfi_flush_fixups(enum l1d_flush_ + patch_instruction(dest + 2, instrs[2]); + } + +- printk(KERN_DEBUG "rfi-flush: patched %d locations\n", i); ++ printk(KERN_DEBUG "rfi-flush: patched %d locations (%s flush)\n", i, ++ (types == L1D_FLUSH_NONE) ? "no" : ++ (types == L1D_FLUSH_FALLBACK) ? "fallback displacement" : ++ (types & L1D_FLUSH_ORI) ? (types & L1D_FLUSH_MTTRIG) ++ ? "ori+mttrig type" ++ : "ori type" : ++ (types & L1D_FLUSH_MTTRIG) ? "mttrig type" ++ : "unknown"); + } + #endif /* CONFIG_PPC_BOOK3S_64 */ + diff --git a/queue-4.4/powerpc-rfi-flush-make-it-possible-to-call-setup_rfi_flush-again.patch b/queue-4.4/powerpc-rfi-flush-make-it-possible-to-call-setup_rfi_flush-again.patch new file mode 100644 index 00000000000..31903003ff1 --- /dev/null +++ b/queue-4.4/powerpc-rfi-flush-make-it-possible-to-call-setup_rfi_flush-again.patch @@ -0,0 +1,60 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:51 +1000 +Subject: powerpc/rfi-flush: Make it possible to call setup_rfi_flush() again +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-7-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit abf110f3e1cea40f5ea15e85f5d67c39c14568a7 upstream. + +For PowerVM migration we want to be able to call setup_rfi_flush() +again after we've migrated the partition. + +To support that we need to check that we're not trying to allocate the +fallback flush area after memblock has gone away (i.e., boot-time only). + +Signed-off-by: Michael Ellerman +Signed-off-by: Mauricio Faria de Oliveira +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/setup.h | 2 +- + arch/powerpc/kernel/setup_64.c | 6 +++++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +--- a/arch/powerpc/include/asm/setup.h ++++ b/arch/powerpc/include/asm/setup.h +@@ -36,7 +36,7 @@ enum l1d_flush_type { + L1D_FLUSH_MTTRIG = 0x8, + }; + +-void __init setup_rfi_flush(enum l1d_flush_type, bool enable); ++void setup_rfi_flush(enum l1d_flush_type, bool enable); + void do_rfi_flush_fixups(enum l1d_flush_type types); + + #endif /* !__ASSEMBLY__ */ +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -887,6 +887,10 @@ static void init_fallback_flush(void) + u64 l1d_size, limit; + int cpu; + ++ /* Only allocate the fallback flush area once (at boot time). */ ++ if (l1d_flush_fallback_area) ++ return; ++ + l1d_size = ppc64_caches.dsize; + limit = min(safe_stack_limit(), ppc64_rma_size); + +@@ -904,7 +908,7 @@ static void init_fallback_flush(void) + } + } + +-void __init setup_rfi_flush(enum l1d_flush_type types, bool enable) ++void setup_rfi_flush(enum l1d_flush_type types, bool enable) + { + if (types & L1D_FLUSH_FALLBACK) { + pr_info("rfi-flush: Using fallback displacement flush\n"); diff --git a/queue-4.4/powerpc-rfi-flush-move-the-logic-to-avoid-a-redo-into-the-debugfs-code.patch b/queue-4.4/powerpc-rfi-flush-move-the-logic-to-avoid-a-redo-into-the-debugfs-code.patch new file mode 100644 index 00000000000..93de3e18967 --- /dev/null +++ b/queue-4.4/powerpc-rfi-flush-move-the-logic-to-avoid-a-redo-into-the-debugfs-code.patch @@ -0,0 +1,62 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:50 +1000 +Subject: powerpc/rfi-flush: Move the logic to avoid a redo into the debugfs code +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-6-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 1e2a9fc7496955faacbbed49461d611b704a7505 upstream. + +rfi_flush_enable() includes a check to see if we're already +enabled (or disabled), and in that case does nothing. + +But that means calling setup_rfi_flush() a 2nd time doesn't actually +work, which is a bit confusing. + +Move that check into the debugfs code, where it really belongs. + +Signed-off-by: Michael Ellerman +Signed-off-by: Mauricio Faria de Oliveira +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/setup_64.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -873,9 +873,6 @@ static void do_nothing(void *unused) + + void rfi_flush_enable(bool enable) + { +- if (rfi_flush == enable) +- return; +- + if (enable) { + do_rfi_flush_fixups(enabled_flush_types); + on_each_cpu(do_nothing, NULL, 1); +@@ -929,13 +926,19 @@ void __init setup_rfi_flush(enum l1d_flu + #ifdef CONFIG_DEBUG_FS + static int rfi_flush_set(void *data, u64 val) + { ++ bool enable; ++ + if (val == 1) +- rfi_flush_enable(true); ++ enable = true; + else if (val == 0) +- rfi_flush_enable(false); ++ enable = false; + else + return -EINVAL; + ++ /* Only do anything if we're changing state */ ++ if (enable != rfi_flush) ++ rfi_flush_enable(enable); ++ + return 0; + } + diff --git a/queue-4.4/powerpc-security-fix-spectre_v2-reporting.patch b/queue-4.4/powerpc-security-fix-spectre_v2-reporting.patch new file mode 100644 index 00000000000..ec3495fe260 --- /dev/null +++ b/queue-4.4/powerpc-security-fix-spectre_v2-reporting.patch @@ -0,0 +1,89 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:36 +1000 +Subject: powerpc/security: Fix spectre_v2 reporting +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-52-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 92edf8df0ff2ae86cc632eeca0e651fd8431d40d upstream. + +When I updated the spectre_v2 reporting to handle software count cache +flush I got the logic wrong when there's no software count cache +enabled at all. + +The result is that on systems with the software count cache flush +disabled we print: + + Mitigation: Indirect branch cache disabled, Software count cache flush + +Which correctly indicates that the count cache is disabled, but +incorrectly says the software count cache flush is enabled. + +The root of the problem is that we are trying to handle all +combinations of options. But we know now that we only expect to see +the software count cache flush enabled if the other options are false. + +So split the two cases, which simplifies the logic and fixes the bug. +We were also missing a space before "(hardware accelerated)". + +The result is we see one of: + + Mitigation: Indirect branch serialisation (kernel only) + Mitigation: Indirect branch cache disabled + Mitigation: Software count cache flush + Mitigation: Software count cache flush (hardware accelerated) + +Fixes: ee13cb249fab ("powerpc/64s: Add support for software count cache flush") +Cc: stable@vger.kernel.org # v4.19+ +Signed-off-by: Michael Ellerman +Reviewed-by: Michael Neuling +Reviewed-by: Diana Craciun +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/security.c | 23 ++++++++--------------- + 1 file changed, 8 insertions(+), 15 deletions(-) + +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -190,29 +190,22 @@ ssize_t cpu_show_spectre_v2(struct devic + bcs = security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED); + ccd = security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED); + +- if (bcs || ccd || count_cache_flush_type != COUNT_CACHE_FLUSH_NONE) { +- bool comma = false; ++ if (bcs || ccd) { + seq_buf_printf(&s, "Mitigation: "); + +- if (bcs) { ++ if (bcs) + seq_buf_printf(&s, "Indirect branch serialisation (kernel only)"); +- comma = true; +- } + +- if (ccd) { +- if (comma) +- seq_buf_printf(&s, ", "); +- seq_buf_printf(&s, "Indirect branch cache disabled"); +- comma = true; +- } +- +- if (comma) ++ if (bcs && ccd) + seq_buf_printf(&s, ", "); + +- seq_buf_printf(&s, "Software count cache flush"); ++ if (ccd) ++ seq_buf_printf(&s, "Indirect branch cache disabled"); ++ } else if (count_cache_flush_type != COUNT_CACHE_FLUSH_NONE) { ++ seq_buf_printf(&s, "Mitigation: Software count cache flush"); + + if (count_cache_flush_type == COUNT_CACHE_FLUSH_HW) +- seq_buf_printf(&s, "(hardware accelerated)"); ++ seq_buf_printf(&s, " (hardware accelerated)"); + } else if (btb_flush_enabled) { + seq_buf_printf(&s, "Mitigation: Branch predictor state flush"); + } else { diff --git a/queue-4.4/powerpc-use-barrier_nospec-in-copy_from_user.patch b/queue-4.4/powerpc-use-barrier_nospec-in-copy_from_user.patch new file mode 100644 index 00000000000..9dfd4465f00 --- /dev/null +++ b/queue-4.4/powerpc-use-barrier_nospec-in-copy_from_user.patch @@ -0,0 +1,117 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:15 +1000 +Subject: powerpc: Use barrier_nospec in copy_from_user() +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-31-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit ddf35cf3764b5a182b178105f57515b42e2634f8 upstream. + +Based on the x86 commit doing the same. + +See commit 304ec1b05031 ("x86/uaccess: Use __uaccess_begin_nospec() +and uaccess_try_nospec") and b3bbfb3fb5d2 ("x86: Introduce +__uaccess_begin_nospec() and uaccess_try_nospec") for more detail. + +In all cases we are ordering the load from the potentially +user-controlled pointer vs a previous branch based on an access_ok() +check or similar. + +Base on a patch from Michal Suchanek. + +Signed-off-by: Michal Suchanek +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/uaccess.h | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +--- a/arch/powerpc/include/asm/uaccess.h ++++ b/arch/powerpc/include/asm/uaccess.h +@@ -269,6 +269,7 @@ do { \ + __chk_user_ptr(ptr); \ + if (!is_kernel_addr((unsigned long)__gu_addr)) \ + might_fault(); \ ++ barrier_nospec(); \ + __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +@@ -283,6 +284,7 @@ do { \ + __chk_user_ptr(ptr); \ + if (!is_kernel_addr((unsigned long)__gu_addr)) \ + might_fault(); \ ++ barrier_nospec(); \ + __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +@@ -295,8 +297,10 @@ do { \ + unsigned long __gu_val = 0; \ + __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ + might_fault(); \ +- if (access_ok(VERIFY_READ, __gu_addr, (size))) \ ++ if (access_ok(VERIFY_READ, __gu_addr, (size))) { \ ++ barrier_nospec(); \ + __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ ++ } \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ + __gu_err; \ + }) +@@ -307,6 +311,7 @@ do { \ + unsigned long __gu_val; \ + __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ + __chk_user_ptr(ptr); \ ++ barrier_nospec(); \ + __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +@@ -323,8 +328,10 @@ extern unsigned long __copy_tofrom_user( + static inline unsigned long copy_from_user(void *to, + const void __user *from, unsigned long n) + { +- if (likely(access_ok(VERIFY_READ, from, n))) ++ if (likely(access_ok(VERIFY_READ, from, n))) { ++ barrier_nospec(); + return __copy_tofrom_user((__force void __user *)to, from, n); ++ } + memset(to, 0, n); + return n; + } +@@ -359,21 +366,27 @@ static inline unsigned long __copy_from_ + + switch (n) { + case 1: ++ barrier_nospec(); + __get_user_size(*(u8 *)to, from, 1, ret); + break; + case 2: ++ barrier_nospec(); + __get_user_size(*(u16 *)to, from, 2, ret); + break; + case 4: ++ barrier_nospec(); + __get_user_size(*(u32 *)to, from, 4, ret); + break; + case 8: ++ barrier_nospec(); + __get_user_size(*(u64 *)to, from, 8, ret); + break; + } + if (ret == 0) + return 0; + } ++ ++ barrier_nospec(); + return __copy_tofrom_user((__force void __user *)to, from, n); + } + +@@ -400,6 +413,7 @@ static inline unsigned long __copy_to_us + if (ret == 0) + return 0; + } ++ + return __copy_tofrom_user(to, (__force const void __user *)from, n); + } + diff --git a/queue-4.4/powerpc-xmon-add-rfi-flush-related-fields-to-paca-dump.patch b/queue-4.4/powerpc-xmon-add-rfi-flush-related-fields-to-paca-dump.patch new file mode 100644 index 00000000000..ebc5d942072 --- /dev/null +++ b/queue-4.4/powerpc-xmon-add-rfi-flush-related-fields-to-paca-dump.patch @@ -0,0 +1,31 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:19:46 +1000 +Subject: powerpc/xmon: Add RFI flush related fields to paca dump +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-2-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 274920a3ecd5f43af0cc380bc0a9ee73a52b9f8a upstream. + +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/xmon/xmon.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/powerpc/xmon/xmon.c ++++ b/arch/powerpc/xmon/xmon.c +@@ -2144,6 +2144,10 @@ static void dump_one_paca(int cpu) + DUMP(p, slb_cache_ptr, "x"); + for (i = 0; i < SLB_CACHE_ENTRIES; i++) + printf(" slb_cache[%d]: = 0x%016lx\n", i, p->slb_cache[i]); ++ ++ DUMP(p, rfi_flush_fallback_area, "px"); ++ DUMP(p, l1d_flush_congruence, "llx"); ++ DUMP(p, l1d_flush_sets, "llx"); + #endif + DUMP(p, dscr_default, "llx"); + #ifdef CONFIG_PPC_BOOK3E diff --git a/queue-4.4/powerpc64s-show-ori31-availability-in-spectre_v1-sysfs-file-not-v2.patch b/queue-4.4/powerpc64s-show-ori31-availability-in-spectre_v1-sysfs-file-not-v2.patch new file mode 100644 index 00000000000..b10bdd48edc --- /dev/null +++ b/queue-4.4/powerpc64s-show-ori31-availability-in-spectre_v1-sysfs-file-not-v2.patch @@ -0,0 +1,97 @@ +From foo@baz Mon 29 Apr 2019 11:38:37 AM CEST +From: Michael Ellerman +Date: Mon, 22 Apr 2019 00:20:17 +1000 +Subject: powerpc64s: Show ori31 availability in spectre_v1 sysfs file not v2 +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: linuxppc-dev@ozlabs.org, diana.craciun@nxp.com, msuchanek@suse.de, npiggin@gmail.com, christophe.leroy@c-s.fr +Message-ID: <20190421142037.21881-33-mpe@ellerman.id.au> + +From: Michael Ellerman + +commit 6d44acae1937b81cf8115ada8958e04f601f3f2e upstream. + +When I added the spectre_v2 information in sysfs, I included the +availability of the ori31 speculation barrier. + +Although the ori31 barrier can be used to mitigate v2, it's primarily +intended as a spectre v1 mitigation. Spectre v2 is mitigated by +hardware changes. + +So rework the sysfs files to show the ori31 information in the +spectre_v1 file, rather than v2. + +Currently we display eg: + + $ grep . spectre_v* + spectre_v1:Mitigation: __user pointer sanitization + spectre_v2:Mitigation: Indirect branch cache disabled, ori31 speculation barrier enabled + +After: + + $ grep . spectre_v* + spectre_v1:Mitigation: __user pointer sanitization, ori31 speculation barrier enabled + spectre_v2:Mitigation: Indirect branch cache disabled + +Fixes: d6fbe1c55c55 ("powerpc/64s: Wire up cpu_show_spectre_v2()") +Cc: stable@vger.kernel.org # v4.17+ +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/security.c | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -118,25 +118,35 @@ ssize_t cpu_show_meltdown(struct device + + ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf) + { +- if (!security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR)) +- return sprintf(buf, "Not affected\n"); ++ struct seq_buf s; ++ ++ seq_buf_init(&s, buf, PAGE_SIZE - 1); ++ ++ if (security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR)) { ++ if (barrier_nospec_enabled) ++ seq_buf_printf(&s, "Mitigation: __user pointer sanitization"); ++ else ++ seq_buf_printf(&s, "Vulnerable"); + +- if (barrier_nospec_enabled) +- return sprintf(buf, "Mitigation: __user pointer sanitization\n"); ++ if (security_ftr_enabled(SEC_FTR_SPEC_BAR_ORI31)) ++ seq_buf_printf(&s, ", ori31 speculation barrier enabled"); + +- return sprintf(buf, "Vulnerable\n"); ++ seq_buf_printf(&s, "\n"); ++ } else ++ seq_buf_printf(&s, "Not affected\n"); ++ ++ return s.len; + } + + ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, char *buf) + { +- bool bcs, ccd, ori; + struct seq_buf s; ++ bool bcs, ccd; + + seq_buf_init(&s, buf, PAGE_SIZE - 1); + + bcs = security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED); + ccd = security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED); +- ori = security_ftr_enabled(SEC_FTR_SPEC_BAR_ORI31); + + if (bcs || ccd) { + seq_buf_printf(&s, "Mitigation: "); +@@ -152,9 +162,6 @@ ssize_t cpu_show_spectre_v2(struct devic + } else + seq_buf_printf(&s, "Vulnerable"); + +- if (ori) +- seq_buf_printf(&s, ", ori31 speculation barrier enabled"); +- + seq_buf_printf(&s, "\n"); + + return s.len; diff --git a/queue-4.4/series b/queue-4.4/series index c459cded85e..0702e97fc0a 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -4,3 +4,61 @@ cifs-do-not-attempt-cifs-operation-on-smb2-rename-error.patch mips-scall64-o32-fix-indirect-syscall-number-load.patch trace-fix-preempt_enable_no_resched-abuse.patch sched-numa-fix-a-possible-divide-by-zero.patch +ceph-ensure-d_name-stability-in-ceph_dentry_hash.patch +ceph-fix-ci-i_head_snapc-leak.patch +nfsd-don-t-release-the-callback-slot-unless-it-was-actually-held.patch +sunrpc-don-t-mark-uninitialised-items-as-valid.patch +usb-add-new-usb-lpm-helpers.patch +usb-consolidate-lpm-checks-to-avoid-enabling-lpm-twice.patch +powerpc-xmon-add-rfi-flush-related-fields-to-paca-dump.patch +powerpc-64s-improve-rfi-l1-d-cache-flush-fallback.patch +powerpc-pseries-support-firmware-disable-of-rfi-flush.patch +powerpc-powernv-support-firmware-disable-of-rfi-flush.patch +powerpc-rfi-flush-move-the-logic-to-avoid-a-redo-into-the-debugfs-code.patch +powerpc-rfi-flush-make-it-possible-to-call-setup_rfi_flush-again.patch +powerpc-rfi-flush-always-enable-fallback-flush-on-pseries.patch +powerpc-rfi-flush-differentiate-enabled-and-patched-flush-types.patch +powerpc-pseries-add-new-h_get_cpu_characteristics-flags.patch +powerpc-rfi-flush-call-setup_rfi_flush-after-lpm-migration.patch +powerpc-add-security-feature-flags-for-spectre-meltdown.patch +powerpc-pseries-set-or-clear-security-feature-flags.patch +powerpc-powernv-set-or-clear-security-feature-flags.patch +powerpc-64s-move-cpu_show_meltdown.patch +powerpc-64s-enhance-the-information-in-cpu_show_meltdown.patch +powerpc-powernv-use-the-security-flags-in-pnv_setup_rfi_flush.patch +powerpc-pseries-use-the-security-flags-in-pseries_setup_rfi_flush.patch +powerpc-64s-wire-up-cpu_show_spectre_v1.patch +powerpc-64s-wire-up-cpu_show_spectre_v2.patch +powerpc-pseries-fix-clearing-of-security-feature-flags.patch +powerpc-move-default-security-feature-flags.patch +powerpc-pseries-restore-default-security-feature-flags-on-setup.patch +powerpc-64s-fix-section-mismatch-warnings-from-setup_rfi_flush.patch +powerpc-64s-add-support-for-a-store-forwarding-barrier-at-kernel-entry-exit.patch +powerpc-64s-add-barrier_nospec.patch +powerpc-64s-add-support-for-ori-barrier_nospec-patching.patch +powerpc-64s-patch-barrier_nospec-in-modules.patch +powerpc-64s-enable-barrier_nospec-based-on-firmware-settings.patch +powerpc-64-use-barrier_nospec-in-syscall-entry.patch +powerpc-use-barrier_nospec-in-copy_from_user.patch +powerpc-64s-enhance-the-information-in-cpu_show_spectre_v1.patch +powerpc64s-show-ori31-availability-in-spectre_v1-sysfs-file-not-v2.patch +powerpc-64-disable-the-speculation-barrier-from-the-command-line.patch +powerpc-64-make-stf-barrier-ppc_book3s_64-specific.patch +powerpc-64-add-config_ppc_barrier_nospec.patch +powerpc-64-call-setup_barrier_nospec-from-setup_arch.patch +powerpc-64-make-meltdown-reporting-book3s-64-specific.patch +powerpc-fsl-add-barrier_nospec-implementation-for-nxp-powerpc-book3e.patch +powerpc-asm-add-a-patch_site-macro-helpers-for-patching-instructions.patch +powerpc-64s-add-new-security-feature-flags-for-count-cache-flush.patch +powerpc-64s-add-support-for-software-count-cache-flush.patch +powerpc-pseries-query-hypervisor-for-count-cache-flush-settings.patch +powerpc-powernv-query-firmware-for-count-cache-flush-settings.patch +powerpc-avoid-code-patching-freed-init-sections.patch +powerpc-fsl-add-infrastructure-to-fixup-branch-predictor-flush.patch +powerpc-fsl-add-macro-to-flush-the-branch-predictor.patch +powerpc-fsl-fix-spectre_v2-mitigations-reporting.patch +powerpc-fsl-add-nospectre_v2-command-line-argument.patch +powerpc-fsl-flush-the-branch-predictor-at-each-kernel-entry-64bit.patch +powerpc-fsl-update-spectre-v2-reporting.patch +powerpc-security-fix-spectre_v2-reporting.patch +powerpc-fsl-fix-the-flush-of-branch-predictor.patch diff --git a/queue-4.4/sunrpc-don-t-mark-uninitialised-items-as-valid.patch b/queue-4.4/sunrpc-don-t-mark-uninitialised-items-as-valid.patch new file mode 100644 index 00000000000..226040a54a6 --- /dev/null +++ b/queue-4.4/sunrpc-don-t-mark-uninitialised-items-as-valid.patch @@ -0,0 +1,57 @@ +From d58431eacb226222430940134d97bfd72f292fcd Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Fri, 5 Apr 2019 11:34:40 +1100 +Subject: sunrpc: don't mark uninitialised items as VALID. + +From: NeilBrown + +commit d58431eacb226222430940134d97bfd72f292fcd upstream. + +A recent commit added a call to cache_fresh_locked() +when an expired item was found. +The call sets the CACHE_VALID flag, so it is important +that the item actually is valid. +There are two ways it could be valid: +1/ If ->update has been called to fill in relevant content +2/ if CACHE_NEGATIVE is set, to say that content doesn't exist. + +An expired item that is waiting for an update will be neither. +Setting CACHE_VALID will mean that a subsequent call to cache_put() +will be likely to dereference uninitialised pointers. + +So we must make sure the item is valid, and we already have code to do +that in try_to_negate_entry(). This takes the hash lock and so cannot +be used directly, so take out the two lines that we need and use them. + +Now cache_fresh_locked() is certain to be called only on +a valid item. + +Cc: stable@kernel.org # 2.6.35 +Fixes: 4ecd55ea0742 ("sunrpc: fix cache_head leak due to queued request") +Signed-off-by: NeilBrown +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/cache.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/sunrpc/cache.c ++++ b/net/sunrpc/cache.c +@@ -54,6 +54,7 @@ static void cache_init(struct cache_head + h->last_refresh = now; + } + ++static inline int cache_is_valid(struct cache_head *h); + static void cache_fresh_locked(struct cache_head *head, time_t expiry, + struct cache_detail *detail); + static void cache_fresh_unlocked(struct cache_head *head, +@@ -100,6 +101,8 @@ struct cache_head *sunrpc_cache_lookup(s + if (cache_is_expired(detail, tmp)) { + hlist_del_init(&tmp->cache_list); + detail->entries --; ++ if (cache_is_valid(tmp) == -EAGAIN) ++ set_bit(CACHE_NEGATIVE, &tmp->flags); + cache_fresh_locked(tmp, 0, detail); + freeme = tmp; + break; diff --git a/queue-4.4/usb-add-new-usb-lpm-helpers.patch b/queue-4.4/usb-add-new-usb-lpm-helpers.patch new file mode 100644 index 00000000000..3652365ccb5 --- /dev/null +++ b/queue-4.4/usb-add-new-usb-lpm-helpers.patch @@ -0,0 +1,160 @@ +From 7529b2574a7aaf902f1f8159fbc2a7caa74be559 Mon Sep 17 00:00:00 2001 +From: Kai-Heng Feng +Date: Sat, 12 Jan 2019 03:54:24 +0800 +Subject: USB: Add new USB LPM helpers + +From: Kai-Heng Feng + +commit 7529b2574a7aaf902f1f8159fbc2a7caa74be559 upstream. + +Use new helpers to make LPM enabling/disabling more clear. + +This is a preparation to subsequent patch. + +Signed-off-by: Kai-Heng Feng +Cc: stable # after much soaking +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/driver.c | 12 +++++++++++- + drivers/usb/core/hub.c | 12 ++++++------ + drivers/usb/core/message.c | 2 +- + drivers/usb/core/sysfs.c | 5 ++++- + drivers/usb/core/usb.h | 10 ++++++++-- + 5 files changed, 30 insertions(+), 11 deletions(-) + +--- a/drivers/usb/core/driver.c ++++ b/drivers/usb/core/driver.c +@@ -1888,7 +1888,7 @@ int usb_runtime_idle(struct device *dev) + return -EBUSY; + } + +-int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) ++static int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) + { + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + int ret = -EPERM; +@@ -1905,6 +1905,16 @@ int usb_set_usb2_hardware_lpm(struct usb + return ret; + } + ++int usb_enable_usb2_hardware_lpm(struct usb_device *udev) ++{ ++ return usb_set_usb2_hardware_lpm(udev, 1); ++} ++ ++int usb_disable_usb2_hardware_lpm(struct usb_device *udev) ++{ ++ return usb_set_usb2_hardware_lpm(udev, 0); ++} ++ + #endif /* CONFIG_PM */ + + struct bus_type usb_bus_type = { +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -3117,7 +3117,7 @@ int usb_port_suspend(struct usb_device * + + /* disable USB2 hardware LPM */ + if (udev->usb2_hw_lpm_enabled == 1) +- usb_set_usb2_hardware_lpm(udev, 0); ++ usb_disable_usb2_hardware_lpm(udev); + + if (usb_disable_ltm(udev)) { + dev_err(&udev->dev, "Failed to disable LTM before suspend\n."); +@@ -3164,7 +3164,7 @@ int usb_port_suspend(struct usb_device * + err_ltm: + /* Try to enable USB2 hardware LPM again */ + if (udev->usb2_hw_lpm_capable == 1) +- usb_set_usb2_hardware_lpm(udev, 1); ++ usb_enable_usb2_hardware_lpm(udev); + + if (udev->do_remote_wakeup) + (void) usb_disable_remote_wakeup(udev); +@@ -3444,7 +3444,7 @@ int usb_port_resume(struct usb_device *u + } else { + /* Try to enable USB2 hardware LPM */ + if (udev->usb2_hw_lpm_capable == 1) +- usb_set_usb2_hardware_lpm(udev, 1); ++ usb_enable_usb2_hardware_lpm(udev); + + /* Try to enable USB3 LTM and LPM */ + usb_enable_ltm(udev); +@@ -4270,7 +4270,7 @@ static void hub_set_initial_usb2_lpm_pol + if ((udev->bos->ext_cap->bmAttributes & cpu_to_le32(USB_BESL_SUPPORT)) || + connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { + udev->usb2_hw_lpm_allowed = 1; +- usb_set_usb2_hardware_lpm(udev, 1); ++ usb_enable_usb2_hardware_lpm(udev); + } + } + +@@ -5416,7 +5416,7 @@ static int usb_reset_and_verify_device(s + * It will be re-enabled by the enumeration process. + */ + if (udev->usb2_hw_lpm_enabled == 1) +- usb_set_usb2_hardware_lpm(udev, 0); ++ usb_disable_usb2_hardware_lpm(udev); + + /* Disable LPM and LTM while we reset the device and reinstall the alt + * settings. Device-initiated LPM settings, and system exit latency +@@ -5526,7 +5526,7 @@ static int usb_reset_and_verify_device(s + + done: + /* Now that the alt settings are re-installed, enable LTM and LPM. */ +- usb_set_usb2_hardware_lpm(udev, 1); ++ usb_enable_usb2_hardware_lpm(udev); + usb_unlocked_enable_lpm(udev); + usb_enable_ltm(udev); + usb_release_bos_descriptor(udev); +--- a/drivers/usb/core/message.c ++++ b/drivers/usb/core/message.c +@@ -1185,7 +1185,7 @@ void usb_disable_device(struct usb_devic + } + + if (dev->usb2_hw_lpm_enabled == 1) +- usb_set_usb2_hardware_lpm(dev, 0); ++ usb_disable_usb2_hardware_lpm(dev); + usb_unlocked_disable_lpm(dev); + usb_disable_ltm(dev); + +--- a/drivers/usb/core/sysfs.c ++++ b/drivers/usb/core/sysfs.c +@@ -472,7 +472,10 @@ static ssize_t usb2_hardware_lpm_store(s + + if (!ret) { + udev->usb2_hw_lpm_allowed = value; +- ret = usb_set_usb2_hardware_lpm(udev, value); ++ if (value) ++ ret = usb_enable_usb2_hardware_lpm(udev); ++ else ++ ret = usb_disable_usb2_hardware_lpm(udev); + } + + usb_unlock_device(udev); +--- a/drivers/usb/core/usb.h ++++ b/drivers/usb/core/usb.h +@@ -84,7 +84,8 @@ extern int usb_remote_wakeup(struct usb_ + extern int usb_runtime_suspend(struct device *dev); + extern int usb_runtime_resume(struct device *dev); + extern int usb_runtime_idle(struct device *dev); +-extern int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable); ++extern int usb_enable_usb2_hardware_lpm(struct usb_device *udev); ++extern int usb_disable_usb2_hardware_lpm(struct usb_device *udev); + + #else + +@@ -104,7 +105,12 @@ static inline int usb_autoresume_device( + return 0; + } + +-static inline int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) ++static inline int usb_enable_usb2_hardware_lpm(struct usb_device *udev) ++{ ++ return 0; ++} ++ ++static inline int usb_disable_usb2_hardware_lpm(struct usb_device *udev) + { + return 0; + } diff --git a/queue-4.4/usb-consolidate-lpm-checks-to-avoid-enabling-lpm-twice.patch b/queue-4.4/usb-consolidate-lpm-checks-to-avoid-enabling-lpm-twice.patch new file mode 100644 index 00000000000..6ca1ae9195e --- /dev/null +++ b/queue-4.4/usb-consolidate-lpm-checks-to-avoid-enabling-lpm-twice.patch @@ -0,0 +1,124 @@ +From d7a6c0ce8d26412903c7981503bad9e1cc7c45d2 Mon Sep 17 00:00:00 2001 +From: Kai-Heng Feng +Date: Sat, 12 Jan 2019 03:54:25 +0800 +Subject: USB: Consolidate LPM checks to avoid enabling LPM twice +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kai-Heng Feng + +commit d7a6c0ce8d26412903c7981503bad9e1cc7c45d2 upstream. + +USB Bluetooth controller QCA ROME (0cf3:e007) sometimes stops working +after S3: +[ 165.110742] Bluetooth: hci0: using NVM file: qca/nvm_usb_00000302.bin +[ 168.432065] Bluetooth: hci0: Failed to send body at 4 of 1953 (-110) + +After some experiments, I found that disabling LPM can workaround the +issue. + +On some platforms, the USB power is cut during S3, so the driver uses +reset-resume to resume the device. During port resume, LPM gets enabled +twice, by usb_reset_and_verify_device() and usb_port_resume(). + +Consolidate all checks into new LPM helpers to make sure LPM only gets +enabled once. + +Fixes: de68bab4fa96 ("usb: Don't enable USB 2.0 Link PM by default.”) +Signed-off-by: Kai-Heng Feng +Cc: stable # after much soaking +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/driver.c | 11 ++++++++--- + drivers/usb/core/hub.c | 12 ++++-------- + drivers/usb/core/message.c | 3 +-- + 3 files changed, 13 insertions(+), 13 deletions(-) + +--- a/drivers/usb/core/driver.c ++++ b/drivers/usb/core/driver.c +@@ -1893,9 +1893,6 @@ static int usb_set_usb2_hardware_lpm(str + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + int ret = -EPERM; + +- if (enable && !udev->usb2_hw_lpm_allowed) +- return 0; +- + if (hcd->driver->set_usb2_hw_lpm) { + ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, enable); + if (!ret) +@@ -1907,11 +1904,19 @@ static int usb_set_usb2_hardware_lpm(str + + int usb_enable_usb2_hardware_lpm(struct usb_device *udev) + { ++ if (!udev->usb2_hw_lpm_capable || ++ !udev->usb2_hw_lpm_allowed || ++ udev->usb2_hw_lpm_enabled) ++ return 0; ++ + return usb_set_usb2_hardware_lpm(udev, 1); + } + + int usb_disable_usb2_hardware_lpm(struct usb_device *udev) + { ++ if (!udev->usb2_hw_lpm_enabled) ++ return 0; ++ + return usb_set_usb2_hardware_lpm(udev, 0); + } + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -3116,8 +3116,7 @@ int usb_port_suspend(struct usb_device * + } + + /* disable USB2 hardware LPM */ +- if (udev->usb2_hw_lpm_enabled == 1) +- usb_disable_usb2_hardware_lpm(udev); ++ usb_disable_usb2_hardware_lpm(udev); + + if (usb_disable_ltm(udev)) { + dev_err(&udev->dev, "Failed to disable LTM before suspend\n."); +@@ -3163,8 +3162,7 @@ int usb_port_suspend(struct usb_device * + usb_enable_ltm(udev); + err_ltm: + /* Try to enable USB2 hardware LPM again */ +- if (udev->usb2_hw_lpm_capable == 1) +- usb_enable_usb2_hardware_lpm(udev); ++ usb_enable_usb2_hardware_lpm(udev); + + if (udev->do_remote_wakeup) + (void) usb_disable_remote_wakeup(udev); +@@ -3443,8 +3441,7 @@ int usb_port_resume(struct usb_device *u + hub_port_logical_disconnect(hub, port1); + } else { + /* Try to enable USB2 hardware LPM */ +- if (udev->usb2_hw_lpm_capable == 1) +- usb_enable_usb2_hardware_lpm(udev); ++ usb_enable_usb2_hardware_lpm(udev); + + /* Try to enable USB3 LTM and LPM */ + usb_enable_ltm(udev); +@@ -5415,8 +5412,7 @@ static int usb_reset_and_verify_device(s + /* Disable USB2 hardware LPM. + * It will be re-enabled by the enumeration process. + */ +- if (udev->usb2_hw_lpm_enabled == 1) +- usb_disable_usb2_hardware_lpm(udev); ++ usb_disable_usb2_hardware_lpm(udev); + + /* Disable LPM and LTM while we reset the device and reinstall the alt + * settings. Device-initiated LPM settings, and system exit latency +--- a/drivers/usb/core/message.c ++++ b/drivers/usb/core/message.c +@@ -1184,8 +1184,7 @@ void usb_disable_device(struct usb_devic + dev->actconfig->interface[i] = NULL; + } + +- if (dev->usb2_hw_lpm_enabled == 1) +- usb_disable_usb2_hardware_lpm(dev); ++ usb_disable_usb2_hardware_lpm(dev); + usb_unlocked_disable_lpm(dev); + usb_disable_ltm(dev); +