--- /dev/null
+From 5aa1437d2d9a068c0334bd7c9dafa8ec4f97f13b Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Thu, 17 May 2018 17:18:30 -0400
+Subject: ext2: fix a block leak
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 5aa1437d2d9a068c0334bd7c9dafa8ec4f97f13b upstream.
+
+open file, unlink it, then use ioctl(2) to make it immutable or
+append only. Now close it and watch the blocks *not* freed...
+
+Immutable/append-only checks belong in ->setattr().
+Note: the bug is old and backport to anything prior to 737f2e93b972
+("ext2: convert to use the new truncate convention") will need
+these checks lifted into ext2_setattr().
+
+Cc: stable@kernel.org
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext2/inode.c | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+--- a/fs/ext2/inode.c
++++ b/fs/ext2/inode.c
+@@ -1261,21 +1261,11 @@ do_indirects:
+
+ static void ext2_truncate_blocks(struct inode *inode, loff_t offset)
+ {
+- /*
+- * XXX: it seems like a bug here that we don't allow
+- * IS_APPEND inode to have blocks-past-i_size trimmed off.
+- * review and fix this.
+- *
+- * Also would be nice to be able to handle IO errors and such,
+- * but that's probably too much to ask.
+- */
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ S_ISLNK(inode->i_mode)))
+ return;
+ if (ext2_inode_is_fast_symlink(inode))
+ return;
+- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+- return;
+
+ dax_sem_down_write(EXT2_I(inode));
+ __ext2_truncate_blocks(inode, offset);
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:25 +1000
+Subject: powerpc/64s: Add support for a store forwarding barrier at kernel entry/exit
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-15-mpe@ellerman.id.au>
+
+From: Nicholas Piggin <npiggin@gmail.com>
+
+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 <npiggin@gmail.com>
+Signed-off-by: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
+Signed-off-by: Michael Neuling <mikey@neuling.org>
+Signed-off-by: Michal Suchánek <msuchanek@suse.de>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/include/asm/exception-64s.h | 29 +++++
+ arch/powerpc/include/asm/feature-fixups.h | 19 +++
+ arch/powerpc/include/asm/security_features.h | 11 +
+ arch/powerpc/kernel/exceptions-64s.S | 19 +++
+ arch/powerpc/kernel/security.c | 149 +++++++++++++++++++++++++++
+ arch/powerpc/kernel/vmlinux.lds.S | 14 ++
+ arch/powerpc/lib/feature-fixups.c | 115 ++++++++++++++++++++
+ arch/powerpc/platforms/powernv/setup.c | 1
+ arch/powerpc/platforms/pseries/setup.c | 1
+ 9 files changed, 356 insertions(+), 2 deletions(-)
+
+--- a/arch/powerpc/include/asm/exception-64s.h
++++ b/arch/powerpc/include/asm/exception-64s.h
+@@ -74,6 +74,27 @@
+ */
+ #define EX_R3 EX_DAR
+
++#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
+ *
+@@ -90,16 +111,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
+@@ -108,21 +132,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
+@@ -254,6 +282,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
+ #define __EXCEPTION_PROLOG_1_PRE(area) \
+ 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;
+
+--- a/arch/powerpc/include/asm/feature-fixups.h
++++ b/arch/powerpc/include/asm/feature-fixups.h
+@@ -187,6 +187,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"; \
+@@ -199,6 +215,9 @@ label##3: \
+ #ifndef __ASSEMBLY__
+ #include <linux/types.h>
+
++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;
+
+ void apply_feature_fixups(void);
+--- 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
+@@ -833,7 +833,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM)
+ #endif
+
+
+-EXC_REAL_MASKABLE(decrementer, 0x900, 0x80, IRQS_DISABLED)
++EXC_REAL_OOL_MASKABLE(decrementer, 0x900, 0x80, IRQS_DISABLED)
+ EXC_VIRT_MASKABLE(decrementer, 0x4900, 0x80, 0x900, IRQS_DISABLED)
+ TRAMP_KVM(PACA_EXGEN, 0x900)
+ EXC_COMMON_ASYNC(decrementer_common, 0x900, timer_interrupt)
+@@ -909,6 +909,7 @@ EXC_COMMON(trap_0b_common, 0xb00, unknow
+ mtctr r13; \
+ GET_PACA(r13); \
+ std r10,PACA_EXGEN+EX_R10(r13); \
++ INTERRUPT_TO_KERNEL; \
+ KVMTEST_PR(0xc00); /* uses r10, branch to do_kvm_0xc00_system_call */ \
+ HMT_MEDIUM; \
+ mfctr r9;
+@@ -917,7 +918,8 @@ EXC_COMMON(trap_0b_common, 0xb00, unknow
+ #define SYSCALL_KVMTEST \
+ HMT_MEDIUM; \
+ mr r9,r13; \
+- GET_PACA(r13);
++ GET_PACA(r13); \
++ INTERRUPT_TO_KERNEL;
+ #endif
+
+ #define LOAD_SYSCALL_HANDLER(reg) \
+@@ -1455,6 +1457,19 @@ masked_##_H##interrupt: \
+ b .; \
+ MASKED_DEC_HANDLER(_H)
+
++TRAMP_REAL_BEGIN(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
++
+ TRAMP_REAL_BEGIN(rfi_flush_fallback)
+ SET_SCRATCH0(r13);
+ GET_PACA(r13);
+--- a/arch/powerpc/kernel/security.c
++++ b/arch/powerpc/kernel/security.c
+@@ -8,6 +8,7 @@
+ #include <linux/device.h>
+ #include <linux/seq_buf.h>
+
++#include <asm/debugfs.h>
+ #include <asm/security_features.h>
+
+
+@@ -86,3 +87,151 @@ 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_300))
++ type = STF_BARRIER_EIEIO;
++ else 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
+@@ -134,6 +134,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
+@@ -23,6 +23,7 @@
+ #include <asm/page.h>
+ #include <asm/sections.h>
+ #include <asm/setup.h>
++#include <asm/security_features.h>
+ #include <asm/firmware.h>
+
+ struct fixup_entry {
+@@ -117,6 +118,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
+@@ -131,6 +131,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
+@@ -699,6 +699,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);
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:18 +1000
+Subject: powerpc/64s: Enhance the information in cpu_show_meltdown()
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-8-mpe@ellerman.id.au>
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+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 <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 <linux/kernel.h>
+ #include <linux/device.h>
++#include <linux/seq_buf.h>
+
+ #include <asm/security_features.h>
+
+@@ -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");
+ }
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:17 +1000
+Subject: powerpc/64s: Move cpu_show_meltdown()
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-7-mpe@ellerman.id.au>
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+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 <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 <linux/kernel.h>
++#include <linux/device.h>
++
+ #include <asm/security_features.h>
+
+
+@@ -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
+@@ -927,12 +927,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 */
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:21 +1000
+Subject: powerpc/64s: Wire up cpu_show_spectre_v1()
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-11-mpe@ellerman.id.au>
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+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 <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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");
++}
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:22 +1000
+Subject: powerpc/64s: Wire up cpu_show_spectre_v2()
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-12-mpe@ellerman.id.au>
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+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 <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
++}
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:13 +1000
+Subject: powerpc: Add security feature flags for Spectre/Meltdown
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-3-mpe@ellerman.id.au>
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+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 <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -42,7 +42,7 @@ obj-$(CONFIG_VDSO32) += vdso32/
+ obj-$(CONFIG_PPC_WATCHDOG) += watchdog.o
+ 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
+ obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o idle_book3e.o
+ obj-$(CONFIG_PPC64) += vdso64/
+--- /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 <linux/kernel.h>
++#include <asm/security_features.h>
++
++
++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;
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:24 +1000
+Subject: powerpc: Move default security feature flags
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-14-mpe@ellerman.id.au>
+
+From: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
+
+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 <mauricfo@linux.vnet.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 <asm/security_features.h>
+
+
+-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)
+ {
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:16 +1000
+Subject: powerpc/powernv: Set or clear security feature flags
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-6-mpe@ellerman.id.au>
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+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 <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -38,9 +38,63 @@
+ #include <asm/smp.h>
+ #include <asm/tm.h>
+ #include <asm/setup.h>
++#include <asm/security_features.h>
+
+ #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;
+@@ -56,6 +110,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;
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:19 +1000
+Subject: powerpc/powernv: Use the security flags in pnv_setup_rfi_flush()
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-9-mpe@ellerman.id.au>
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+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 <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -66,7 +66,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))
+@@ -99,11 +99,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");
+@@ -111,40 +110,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)
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:14 +1000
+Subject: powerpc/pseries: Add new H_GET_CPU_CHARACTERISTICS flags
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-4-mpe@ellerman.id.au>
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+commit c4bc36628d7f8b664657d8bd6ad1c44c177880b7 upstream.
+
+Add some additional values which have been defined for the
+H_GET_CPU_CHARACTERISTICS hypercall.
+
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -337,6 +337,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
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:23 +1000
+Subject: powerpc/pseries: Fix clearing of security feature flags
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-13-mpe@ellerman.id.au>
+
+From: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
+
+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 <mpe@ellerman.id.au>
+Fixes: f636c14790ea ("powerpc/pseries: Set or clear security feature flags")
+Signed-off-by: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -484,13 +484,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);
+ }
+
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:15 +1000
+Subject: powerpc/pseries: Set or clear security feature flags
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-5-mpe@ellerman.id.au>
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+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 <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -68,6 +68,7 @@
+ #include <asm/plpar_wrappers.h>
+ #include <asm/kexec.h>
+ #include <asm/isa-bridge.h>
++#include <asm/security_features.h>
+
+ #include "pseries.h"
+
+@@ -459,6 +460,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);
++}
++
+ static void pseries_setup_rfi_flush(void)
+ {
+ struct h_cpu_char_result result;
+@@ -472,6 +507,8 @@ static 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)
+@@ -482,6 +519,12 @@ static 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);
+ }
+
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:20 +1000
+Subject: powerpc/pseries: Use the security flags in pseries_setup_rfi_flush()
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-10-mpe@ellerman.id.au>
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+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 <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -501,30 +501,27 @@ static 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);
+ }
+
--- /dev/null
+From foo@baz Wed May 23 19:18:22 CEST 2018
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Wed, 23 May 2018 00:41:12 +1000
+Subject: powerpc/rfi-flush: Always enable fallback flush on pseries
+To: greg@kroah.com
+Cc: stable@vger.kernel.org, tglx@linutronix.de, linuxppc-dev@ozlabs.org
+Message-ID: <20180522144125.10345-2-mpe@ellerman.id.au>
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+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 <mpe@ellerman.id.au>
+Signed-off-by: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -468,26 +468,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);
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:21 +0200
+Subject: s390: add assembler macros for CPU alternatives
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-6-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit fba9eb7946251d6e420df3bdf7bc45195be7be9a ]
+
+Add a header with macros usable in assembler files to emit alternative
+code sequences. It works analog to the alternatives for inline assmeblies
+in C files, with the same restrictions and capabilities.
+The syntax is
+
+ ALTERNATIVE "<default instructions sequence>", \
+ "<alternative instructions sequence>", \
+ "<features-bit>"
+and
+
+ ALTERNATIVE_2 "<default instructions sequence>", \
+ "<alternative instructions sqeuence #1>", \
+ "<feature-bit #1>",
+ "<alternative instructions sqeuence #2>", \
+ "<feature-bit #2>"
+
+Reviewed-by: Vasily Gorbik <gor@linux.vnet.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/include/asm/alternative-asm.h | 108 ++++++++++++++++++++++++++++++++
+ 1 file changed, 108 insertions(+)
+ create mode 100644 arch/s390/include/asm/alternative-asm.h
+
+--- /dev/null
++++ b/arch/s390/include/asm/alternative-asm.h
+@@ -0,0 +1,108 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _ASM_S390_ALTERNATIVE_ASM_H
++#define _ASM_S390_ALTERNATIVE_ASM_H
++
++#ifdef __ASSEMBLY__
++
++/*
++ * Check the length of an instruction sequence. The length may not be larger
++ * than 254 bytes and it has to be divisible by 2.
++ */
++.macro alt_len_check start,end
++ .if ( \end - \start ) > 254
++ .error "cpu alternatives does not support instructions blocks > 254 bytes\n"
++ .endif
++ .if ( \end - \start ) % 2
++ .error "cpu alternatives instructions length is odd\n"
++ .endif
++.endm
++
++/*
++ * Issue one struct alt_instr descriptor entry (need to put it into
++ * the section .altinstructions, see below). This entry contains
++ * enough information for the alternatives patching code to patch an
++ * instruction. See apply_alternatives().
++ */
++.macro alt_entry orig_start, orig_end, alt_start, alt_end, feature
++ .long \orig_start - .
++ .long \alt_start - .
++ .word \feature
++ .byte \orig_end - \orig_start
++ .byte \alt_end - \alt_start
++.endm
++
++/*
++ * Fill up @bytes with nops. The macro emits 6-byte nop instructions
++ * for the bulk of the area, possibly followed by a 4-byte and/or
++ * a 2-byte nop if the size of the area is not divisible by 6.
++ */
++.macro alt_pad_fill bytes
++ .fill ( \bytes ) / 6, 6, 0xc0040000
++ .fill ( \bytes ) % 6 / 4, 4, 0x47000000
++ .fill ( \bytes ) % 6 % 4 / 2, 2, 0x0700
++.endm
++
++/*
++ * Fill up @bytes with nops. If the number of bytes is larger
++ * than 6, emit a jg instruction to branch over all nops, then
++ * fill an area of size (@bytes - 6) with nop instructions.
++ */
++.macro alt_pad bytes
++ .if ( \bytes > 0 )
++ .if ( \bytes > 6 )
++ jg . + \bytes
++ alt_pad_fill \bytes - 6
++ .else
++ alt_pad_fill \bytes
++ .endif
++ .endif
++.endm
++
++/*
++ * Define an alternative between two instructions. If @feature is
++ * present, early code in apply_alternatives() replaces @oldinstr with
++ * @newinstr. ".skip" directive takes care of proper instruction padding
++ * in case @newinstr is longer than @oldinstr.
++ */
++.macro ALTERNATIVE oldinstr, newinstr, feature
++ .pushsection .altinstr_replacement,"ax"
++770: \newinstr
++771: .popsection
++772: \oldinstr
++773: alt_len_check 770b, 771b
++ alt_len_check 772b, 773b
++ alt_pad ( ( 771b - 770b ) - ( 773b - 772b ) )
++774: .pushsection .altinstructions,"a"
++ alt_entry 772b, 774b, 770b, 771b, \feature
++ .popsection
++.endm
++
++/*
++ * Define an alternative between two instructions. If @feature is
++ * present, early code in apply_alternatives() replaces @oldinstr with
++ * @newinstr. ".skip" directive takes care of proper instruction padding
++ * in case @newinstr is longer than @oldinstr.
++ */
++.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
++ .pushsection .altinstr_replacement,"ax"
++770: \newinstr1
++771: \newinstr2
++772: .popsection
++773: \oldinstr
++774: alt_len_check 770b, 771b
++ alt_len_check 771b, 772b
++ alt_len_check 773b, 774b
++ .if ( 771b - 770b > 772b - 771b )
++ alt_pad ( ( 771b - 770b ) - ( 774b - 773b ) )
++ .else
++ alt_pad ( ( 772b - 771b ) - ( 774b - 773b ) )
++ .endif
++775: .pushsection .altinstructions,"a"
++ alt_entry 773b, 775b, 770b, 771b,\feature1
++ alt_entry 773b, 775b, 771b, 772b,\feature2
++ .popsection
++.endm
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* _ASM_S390_ALTERNATIVE_ASM_H */
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:18 +0200
+Subject: s390: add automatic detection of the spectre defense
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-3-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit 6e179d64126b909f0b288fa63cdbf07c531e9b1d ]
+
+Automatically decide between nobp vs. expolines if the spectre_v2=auto
+kernel parameter is specified or CONFIG_EXPOLINE_AUTO=y is set.
+
+The decision made at boot time due to CONFIG_EXPOLINE_AUTO=y being set
+can be overruled with the nobp, nospec and spectre_v2 kernel parameters.
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/Kconfig | 2 -
+ arch/s390/Makefile | 2 -
+ arch/s390/include/asm/nospec-branch.h | 6 +--
+ arch/s390/kernel/alternative.c | 1
+ arch/s390/kernel/module.c | 11 ++---
+ arch/s390/kernel/nospec-branch.c | 68 +++++++++++++++++++++-------------
+ 6 files changed, 52 insertions(+), 38 deletions(-)
+
+--- a/arch/s390/Kconfig
++++ b/arch/s390/Kconfig
+@@ -576,7 +576,7 @@ choice
+ config EXPOLINE_OFF
+ bool "spectre_v2=off"
+
+-config EXPOLINE_MEDIUM
++config EXPOLINE_AUTO
+ bool "spectre_v2=auto"
+
+ config EXPOLINE_FULL
+--- a/arch/s390/Makefile
++++ b/arch/s390/Makefile
+@@ -84,7 +84,7 @@ ifdef CONFIG_EXPOLINE
+ CC_FLAGS_EXPOLINE += -mfunction-return=thunk
+ CC_FLAGS_EXPOLINE += -mindirect-branch-table
+ export CC_FLAGS_EXPOLINE
+- cflags-y += $(CC_FLAGS_EXPOLINE)
++ cflags-y += $(CC_FLAGS_EXPOLINE) -DCC_USING_EXPOLINE
+ endif
+ endif
+
+--- a/arch/s390/include/asm/nospec-branch.h
++++ b/arch/s390/include/asm/nospec-branch.h
+@@ -6,12 +6,10 @@
+
+ #include <linux/types.h>
+
+-extern int nospec_call_disable;
+-extern int nospec_return_disable;
++extern int nospec_disable;
+
+ void nospec_init_branches(void);
+-void nospec_call_revert(s32 *start, s32 *end);
+-void nospec_return_revert(s32 *start, s32 *end);
++void nospec_revert(s32 *start, s32 *end);
+
+ #endif /* __ASSEMBLY__ */
+
+--- a/arch/s390/kernel/alternative.c
++++ b/arch/s390/kernel/alternative.c
+@@ -2,6 +2,7 @@
+ #include <linux/module.h>
+ #include <asm/alternative.h>
+ #include <asm/facility.h>
++#include <asm/nospec-branch.h>
+
+ #define MAX_PATCH_LEN (255 - 1)
+
+--- a/arch/s390/kernel/module.c
++++ b/arch/s390/kernel/module.c
+@@ -159,7 +159,7 @@ int module_frob_arch_sections(Elf_Ehdr *
+ me->core_layout.size += me->arch.got_size;
+ me->arch.plt_offset = me->core_layout.size;
+ if (me->arch.plt_size) {
+- if (IS_ENABLED(CONFIG_EXPOLINE) && !nospec_call_disable)
++ if (IS_ENABLED(CONFIG_EXPOLINE) && !nospec_disable)
+ me->arch.plt_size += PLT_ENTRY_SIZE;
+ me->core_layout.size += me->arch.plt_size;
+ }
+@@ -318,8 +318,7 @@ static int apply_rela(Elf_Rela *rela, El
+ info->plt_offset;
+ ip[0] = 0x0d10e310; /* basr 1,0 */
+ ip[1] = 0x100a0004; /* lg 1,10(1) */
+- if (IS_ENABLED(CONFIG_EXPOLINE) &&
+- !nospec_call_disable) {
++ if (IS_ENABLED(CONFIG_EXPOLINE) && !nospec_disable) {
+ unsigned int *ij;
+ ij = me->core_layout.base +
+ me->arch.plt_offset +
+@@ -440,7 +439,7 @@ int module_finalize(const Elf_Ehdr *hdr,
+ void *aseg;
+
+ if (IS_ENABLED(CONFIG_EXPOLINE) &&
+- !nospec_call_disable && me->arch.plt_size) {
++ !nospec_disable && me->arch.plt_size) {
+ unsigned int *ij;
+
+ ij = me->core_layout.base + me->arch.plt_offset +
+@@ -467,11 +466,11 @@ int module_finalize(const Elf_Ehdr *hdr,
+
+ if (IS_ENABLED(CONFIG_EXPOLINE) &&
+ (!strcmp(".nospec_call_table", secname)))
+- nospec_call_revert(aseg, aseg + s->sh_size);
++ nospec_revert(aseg, aseg + s->sh_size);
+
+ if (IS_ENABLED(CONFIG_EXPOLINE) &&
+ (!strcmp(".nospec_return_table", secname)))
+- nospec_return_revert(aseg, aseg + s->sh_size);
++ nospec_revert(aseg, aseg + s->sh_size);
+ }
+
+ jump_label_apply_nops(me);
+--- a/arch/s390/kernel/nospec-branch.c
++++ b/arch/s390/kernel/nospec-branch.c
+@@ -10,10 +10,17 @@ static int __init nobp_setup_early(char
+ rc = kstrtobool(str, &enabled);
+ if (rc)
+ return rc;
+- if (enabled && test_facility(82))
++ if (enabled && test_facility(82)) {
++ /*
++ * The user explicitely requested nobp=1, enable it and
++ * disable the expoline support.
++ */
+ __set_facility(82, S390_lowcore.alt_stfle_fac_list);
+- else
++ if (IS_ENABLED(CONFIG_EXPOLINE))
++ nospec_disable = 1;
++ } else {
+ __clear_facility(82, S390_lowcore.alt_stfle_fac_list);
++ }
+ return 0;
+ }
+ early_param("nobp", nobp_setup_early);
+@@ -27,31 +34,46 @@ early_param("nospec", nospec_setup_early
+
+ #ifdef CONFIG_EXPOLINE
+
+-int nospec_call_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF);
+-int nospec_return_disable = !IS_ENABLED(CONFIG_EXPOLINE_FULL);
++int nospec_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF);
+
+ static int __init nospectre_v2_setup_early(char *str)
+ {
+- nospec_call_disable = 1;
+- nospec_return_disable = 1;
++ nospec_disable = 1;
+ return 0;
+ }
+ early_param("nospectre_v2", nospectre_v2_setup_early);
+
++static int __init spectre_v2_auto_early(void)
++{
++ if (IS_ENABLED(CC_USING_EXPOLINE)) {
++ /*
++ * The kernel has been compiled with expolines.
++ * Keep expolines enabled and disable nobp.
++ */
++ nospec_disable = 0;
++ __clear_facility(82, S390_lowcore.alt_stfle_fac_list);
++ }
++ /*
++ * If the kernel has not been compiled with expolines the
++ * nobp setting decides what is done, this depends on the
++ * CONFIG_KERNEL_NP option and the nobp/nospec parameters.
++ */
++ return 0;
++}
++#ifdef CONFIG_EXPOLINE_AUTO
++early_initcall(spectre_v2_auto_early);
++#endif
++
+ static int __init spectre_v2_setup_early(char *str)
+ {
+ if (str && !strncmp(str, "on", 2)) {
+- nospec_call_disable = 0;
+- nospec_return_disable = 0;
+- }
+- if (str && !strncmp(str, "off", 3)) {
+- nospec_call_disable = 1;
+- nospec_return_disable = 1;
+- }
+- if (str && !strncmp(str, "auto", 4)) {
+- nospec_call_disable = 0;
+- nospec_return_disable = 1;
++ nospec_disable = 0;
++ __clear_facility(82, S390_lowcore.alt_stfle_fac_list);
+ }
++ if (str && !strncmp(str, "off", 3))
++ nospec_disable = 1;
++ if (str && !strncmp(str, "auto", 4))
++ spectre_v2_auto_early();
+ return 0;
+ }
+ early_param("spectre_v2", spectre_v2_setup_early);
+@@ -104,15 +126,9 @@ static void __init_or_module __nospec_re
+ }
+ }
+
+-void __init_or_module nospec_call_revert(s32 *start, s32 *end)
+-{
+- if (nospec_call_disable)
+- __nospec_revert(start, end);
+-}
+-
+-void __init_or_module nospec_return_revert(s32 *start, s32 *end)
++void __init_or_module nospec_revert(s32 *start, s32 *end)
+ {
+- if (nospec_return_disable)
++ if (nospec_disable)
+ __nospec_revert(start, end);
+ }
+
+@@ -120,8 +136,8 @@ extern s32 __nospec_call_start[], __nosp
+ extern s32 __nospec_return_start[], __nospec_return_end[];
+ void __init nospec_init_branches(void)
+ {
+- nospec_call_revert(__nospec_call_start, __nospec_call_end);
+- nospec_return_revert(__nospec_return_start, __nospec_return_end);
++ nospec_revert(__nospec_call_start, __nospec_call_end);
++ nospec_revert(__nospec_return_start, __nospec_return_end);
+ }
+
+ #endif /* CONFIG_EXPOLINE */
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:20 +0200
+Subject: s390: add sysfs attributes for spectre
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-5-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit d424986f1d6b16079b3231db0314923f4f8deed1 ]
+
+Set CONFIG_GENERIC_CPU_VULNERABILITIES and provide the two functions
+cpu_show_spectre_v1 and cpu_show_spectre_v2 to report the spectre
+mitigations.
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/Kconfig | 1 +
+ arch/s390/kernel/nospec-branch.c | 19 +++++++++++++++++++
+ 2 files changed, 20 insertions(+)
+
+--- a/arch/s390/Kconfig
++++ b/arch/s390/Kconfig
+@@ -120,6 +120,7 @@ config S390
+ select GENERIC_CLOCKEVENTS
+ select GENERIC_CPU_AUTOPROBE
+ select GENERIC_CPU_DEVICES if !SMP
++ select GENERIC_CPU_VULNERABILITIES
+ select GENERIC_FIND_FIRST_BIT
+ select GENERIC_SMP_IDLE_THREAD
+ select GENERIC_TIME_VSYSCALL
+--- a/arch/s390/kernel/nospec-branch.c
++++ b/arch/s390/kernel/nospec-branch.c
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ #include <linux/module.h>
++#include <linux/device.h>
+ #include <asm/nospec-branch.h>
+
+ static int __init nobp_setup_early(char *str)
+@@ -42,6 +43,24 @@ static int __init nospec_report(void)
+ }
+ arch_initcall(nospec_report);
+
++#ifdef CONFIG_SYSFS
++ssize_t cpu_show_spectre_v1(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "Mitigation: __user pointer sanitization\n");
++}
++
++ssize_t cpu_show_spectre_v2(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
++ return sprintf(buf, "Mitigation: execute trampolines\n");
++ if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
++ return sprintf(buf, "Mitigation: limited branch prediction.\n");
++ return sprintf(buf, "Vulnerable\n");
++}
++#endif
++
+ #ifdef CONFIG_EXPOLINE
+
+ int nospec_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF);
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:23 +0200
+Subject: s390: correct module section names for expoline code revert
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-8-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit 6cf09958f32b9667bb3ebadf74367c791112771b ]
+
+The main linker script vmlinux.lds.S for the kernel image merges
+the expoline code patch tables into two section ".nospec_call_table"
+and ".nospec_return_table". This is *not* done for the modules,
+there the sections retain their original names as generated by gcc:
+".s390_indirect_call", ".s390_return_mem" and ".s390_return_reg".
+
+The module_finalize code has to check for the compiler generated
+section names, otherwise no code patching is done. This slows down
+the module code in case of "spectre_v2=off".
+
+Cc: stable@vger.kernel.org # 4.16
+Fixes: f19fbd5ed6 ("s390: introduce execute-trampolines for branches")
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kernel/module.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/s390/kernel/module.c
++++ b/arch/s390/kernel/module.c
+@@ -465,11 +465,11 @@ int module_finalize(const Elf_Ehdr *hdr,
+ apply_alternatives(aseg, aseg + s->sh_size);
+
+ if (IS_ENABLED(CONFIG_EXPOLINE) &&
+- (!strcmp(".nospec_call_table", secname)))
++ (!strncmp(".s390_indirect", secname, 14)))
+ nospec_revert(aseg, aseg + s->sh_size);
+
+ if (IS_ENABLED(CONFIG_EXPOLINE) &&
+- (!strcmp(".nospec_return_table", secname)))
++ (!strncmp(".s390_return", secname, 12)))
+ nospec_revert(aseg, aseg + s->sh_size);
+ }
+
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:22 +0200
+Subject: s390: correct nospec auto detection init order
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-7-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit 6a3d1e81a434fc311f224b8be77258bafc18ccc6 ]
+
+With CONFIG_EXPOLINE_AUTO=y the call of spectre_v2_auto_early() via
+early_initcall is done *after* the early_param functions. This
+overwrites any settings done with the nobp/no_spectre_v2/spectre_v2
+parameters. The code patching for the kernel is done after the
+evaluation of the early parameters but before the early_initcall
+is done. The end result is a kernel image that is patched correctly
+but the kernel modules are not.
+
+Make sure that the nospec auto detection function is called before the
+early parameters are evaluated and before the code patching is done.
+
+Fixes: 6e179d64126b ("s390: add automatic detection of the spectre defense")
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/include/asm/nospec-branch.h | 1 +
+ arch/s390/kernel/nospec-branch.c | 8 ++------
+ arch/s390/kernel/setup.c | 3 +++
+ 3 files changed, 6 insertions(+), 6 deletions(-)
+
+--- a/arch/s390/include/asm/nospec-branch.h
++++ b/arch/s390/include/asm/nospec-branch.h
+@@ -9,6 +9,7 @@
+ extern int nospec_disable;
+
+ void nospec_init_branches(void);
++void nospec_auto_detect(void);
+ void nospec_revert(s32 *start, s32 *end);
+
+ #endif /* __ASSEMBLY__ */
+--- a/arch/s390/kernel/nospec-branch.c
++++ b/arch/s390/kernel/nospec-branch.c
+@@ -72,7 +72,7 @@ static int __init nospectre_v2_setup_ear
+ }
+ early_param("nospectre_v2", nospectre_v2_setup_early);
+
+-static int __init spectre_v2_auto_early(void)
++void __init nospec_auto_detect(void)
+ {
+ if (IS_ENABLED(CC_USING_EXPOLINE)) {
+ /*
+@@ -87,11 +87,7 @@ static int __init spectre_v2_auto_early(
+ * nobp setting decides what is done, this depends on the
+ * CONFIG_KERNEL_NP option and the nobp/nospec parameters.
+ */
+- return 0;
+ }
+-#ifdef CONFIG_EXPOLINE_AUTO
+-early_initcall(spectre_v2_auto_early);
+-#endif
+
+ static int __init spectre_v2_setup_early(char *str)
+ {
+@@ -102,7 +98,7 @@ static int __init spectre_v2_setup_early
+ if (str && !strncmp(str, "off", 3))
+ nospec_disable = 1;
+ if (str && !strncmp(str, "auto", 4))
+- spectre_v2_auto_early();
++ nospec_auto_detect();
+ return 0;
+ }
+ early_param("spectre_v2", spectre_v2_setup_early);
+--- a/arch/s390/kernel/setup.c
++++ b/arch/s390/kernel/setup.c
+@@ -893,6 +893,9 @@ void __init setup_arch(char **cmdline_p)
+ init_mm.end_data = (unsigned long) &_edata;
+ init_mm.brk = (unsigned long) &_end;
+
++ if (IS_ENABLED(CONFIG_EXPOLINE_AUTO))
++ nospec_auto_detect();
++
+ parse_early_param();
+ #ifdef CONFIG_CRASH_DUMP
+ /* Deactivate elfcorehdr= kernel parameter */
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:25 +0200
+Subject: s390/crc32-vx: use expoline for indirect branches
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-10-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit 467a3bf219cee12259182c5cb4821f88fd518a51 ]
+
+The return from the crc32_le_vgfm_16/crc32c_le_vgfm_16 and the
+crc32_be_vgfm_16 functions are done with "br %r14". These are indirect
+branches as well and need to use execute trampolines for CONFIG_EXPOLINE=y.
+
+Cc: stable@vger.kernel.org # 4.16
+Fixes: f19fbd5ed6 ("s390: introduce execute-trampolines for branches")
+Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/crypto/crc32be-vx.S | 5 ++++-
+ arch/s390/crypto/crc32le-vx.S | 4 +++-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+--- a/arch/s390/crypto/crc32be-vx.S
++++ b/arch/s390/crypto/crc32be-vx.S
+@@ -13,6 +13,7 @@
+ */
+
+ #include <linux/linkage.h>
++#include <asm/nospec-insn.h>
+ #include <asm/vx-insn.h>
+
+ /* Vector register range containing CRC-32 constants */
+@@ -67,6 +68,8 @@
+
+ .previous
+
++ GEN_BR_THUNK %r14
++
+ .text
+ /*
+ * The CRC-32 function(s) use these calling conventions:
+@@ -203,6 +206,6 @@ ENTRY(crc32_be_vgfm_16)
+
+ .Ldone:
+ VLGVF %r2,%v2,3
+- br %r14
++ BR_EX %r14
+
+ .previous
+--- a/arch/s390/crypto/crc32le-vx.S
++++ b/arch/s390/crypto/crc32le-vx.S
+@@ -14,6 +14,7 @@
+ */
+
+ #include <linux/linkage.h>
++#include <asm/nospec-insn.h>
+ #include <asm/vx-insn.h>
+
+ /* Vector register range containing CRC-32 constants */
+@@ -76,6 +77,7 @@
+
+ .previous
+
++ GEN_BR_THUNK %r14
+
+ .text
+
+@@ -264,6 +266,6 @@ crc32_le_vgfm_generic:
+
+ .Ldone:
+ VLGVF %r2,%v2,2
+- br %r14
++ BR_EX %r14
+
+ .previous
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:30 +0200
+Subject: s390: extend expoline to BC instructions
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-15-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit 6deaa3bbca804b2a3627fd685f75de64da7be535 ]
+
+The BPF JIT uses a 'b <disp>(%r<x>)' instruction in the definition
+of the sk_load_word and sk_load_half functions.
+
+Add support for branch-on-condition instructions contained in the
+thunk code of an expoline.
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/include/asm/nospec-insn.h | 57 ++++++++++++++++++++++++++++++++++++
+ arch/s390/kernel/nospec-branch.c | 25 ++++++++++++---
+ 2 files changed, 77 insertions(+), 5 deletions(-)
+
+--- a/arch/s390/include/asm/nospec-insn.h
++++ b/arch/s390/include/asm/nospec-insn.h
+@@ -35,10 +35,18 @@ _LC_BR_R1 = __LC_BR_R1
+ __THUNK_PROLOG_NAME __s390x_indirect_jump_r\r2\()use_r\r1
+ .endm
+
++ .macro __THUNK_PROLOG_BC d0,r1,r2
++ __THUNK_PROLOG_NAME __s390x_indirect_branch_\d0\()_\r2\()use_\r1
++ .endm
++
+ .macro __THUNK_BR r1,r2
+ jg __s390x_indirect_jump_r\r2\()use_r\r1
+ .endm
+
++ .macro __THUNK_BC d0,r1,r2
++ jg __s390x_indirect_branch_\d0\()_\r2\()use_\r1
++ .endm
++
+ .macro __THUNK_BRASL r1,r2,r3
+ brasl \r1,__s390x_indirect_jump_r\r3\()use_r\r2
+ .endm
+@@ -81,6 +89,23 @@ _LC_BR_R1 = __LC_BR_R1
+ .endif
+ .endm
+
++ .macro __DECODE_DRR expand,disp,reg,ruse
++ .set __decode_fail,1
++ .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
++ .ifc \reg,%r\r1
++ .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
++ .ifc \ruse,%r\r2
++ \expand \disp,\r1,\r2
++ .set __decode_fail,0
++ .endif
++ .endr
++ .endif
++ .endr
++ .if __decode_fail == 1
++ .error "__DECODE_DRR failed"
++ .endif
++ .endm
++
+ .macro __THUNK_EX_BR reg,ruse
+ # Be very careful when adding instructions to this macro!
+ # The ALTERNATIVE replacement code has a .+10 which targets
+@@ -101,12 +126,30 @@ _LC_BR_R1 = __LC_BR_R1
+ 555: br \reg
+ .endm
+
++ .macro __THUNK_EX_BC disp,reg,ruse
++#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
++ exrl 0,556f
++ j .
++#else
++ larl \ruse,556f
++ ex 0,0(\ruse)
++ j .
++#endif
++556: b \disp(\reg)
++ .endm
++
+ .macro GEN_BR_THUNK reg,ruse=%r1
+ __DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse
+ __THUNK_EX_BR \reg,\ruse
+ __THUNK_EPILOG
+ .endm
+
++ .macro GEN_B_THUNK disp,reg,ruse=%r1
++ __DECODE_DRR __THUNK_PROLOG_BC,\disp,\reg,\ruse
++ __THUNK_EX_BC \disp,\reg,\ruse
++ __THUNK_EPILOG
++ .endm
++
+ .macro BR_EX reg,ruse=%r1
+ 557: __DECODE_RR __THUNK_BR,\reg,\ruse
+ .pushsection .s390_indirect_branches,"a",@progbits
+@@ -114,6 +157,13 @@ _LC_BR_R1 = __LC_BR_R1
+ .popsection
+ .endm
+
++ .macro B_EX disp,reg,ruse=%r1
++558: __DECODE_DRR __THUNK_BC,\disp,\reg,\ruse
++ .pushsection .s390_indirect_branches,"a",@progbits
++ .long 558b-.
++ .popsection
++ .endm
++
+ .macro BASR_EX rsave,rtarget,ruse=%r1
+ 559: __DECODE_RRR __THUNK_BRASL,\rsave,\rtarget,\ruse
+ .pushsection .s390_indirect_branches,"a",@progbits
+@@ -125,10 +175,17 @@ _LC_BR_R1 = __LC_BR_R1
+ .macro GEN_BR_THUNK reg,ruse=%r1
+ .endm
+
++ .macro GEN_B_THUNK disp,reg,ruse=%r1
++ .endm
++
+ .macro BR_EX reg,ruse=%r1
+ br \reg
+ .endm
+
++ .macro B_EX disp,reg,ruse=%r1
++ b \disp(\reg)
++ .endm
++
+ .macro BASR_EX rsave,rtarget,ruse=%r1
+ basr \rsave,\rtarget
+ .endm
+--- a/arch/s390/kernel/nospec-branch.c
++++ b/arch/s390/kernel/nospec-branch.c
+@@ -93,7 +93,6 @@ static void __init_or_module __nospec_re
+ s32 *epo;
+
+ /* Second part of the instruction replace is always a nop */
+- memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x00, 0x00 }, 4);
+ for (epo = start; epo < end; epo++) {
+ instr = (u8 *) epo + *epo;
+ if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x04)
+@@ -114,18 +113,34 @@ static void __init_or_module __nospec_re
+ br = thunk + (*(int *)(thunk + 2)) * 2;
+ else
+ continue;
+- if (br[0] != 0x07 || (br[1] & 0xf0) != 0xf0)
++ /* Check for unconditional branch 0x07f? or 0x47f???? */
++ if ((br[0] & 0xbf) != 0x07 || (br[1] & 0xf0) != 0xf0)
+ continue;
++
++ memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x07, 0x00 }, 4);
+ switch (type) {
+ case BRCL_EXPOLINE:
+- /* brcl to thunk, replace with br + nop */
+ insnbuf[0] = br[0];
+ insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
++ if (br[0] == 0x47) {
++ /* brcl to b, replace with bc + nopr */
++ insnbuf[2] = br[2];
++ insnbuf[3] = br[3];
++ } else {
++ /* brcl to br, replace with bcr + nop */
++ }
+ break;
+ case BRASL_EXPOLINE:
+- /* brasl to thunk, replace with basr + nop */
+- insnbuf[0] = 0x0d;
+ insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
++ if (br[0] == 0x47) {
++ /* brasl to b, replace with bas + nopr */
++ insnbuf[0] = 0x4d;
++ insnbuf[2] = br[2];
++ insnbuf[3] = br[3];
++ } else {
++ /* brasl to br, replace with basr + nop */
++ insnbuf[0] = 0x0d;
++ }
+ break;
+ }
+
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:27 +0200
+Subject: s390/ftrace: use expoline for indirect branches
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-12-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit 23a4d7fd34856da8218c4cfc23dba7a6ec0a423a ]
+
+The return from the ftrace_stub, _mcount, ftrace_caller and
+return_to_handler functions is done with "br %r14" and "br %r1".
+These are indirect branches as well and need to use execute
+trampolines for CONFIG_EXPOLINE=y.
+
+The ftrace_caller function is a special case as it returns to the
+start of a function and may only use %r0 and %r1. For a pre z10
+machine the standard execute trampoline uses a LARL + EX to do
+this, but this requires *two* registers in the range %r1..%r15.
+To get around this the 'br %r1' located in the lowcore is used,
+then the EX instruction does not need an address register.
+But the lowcore trick may only be used for pre z14 machines,
+with noexec=on the mapping for the first page may not contain
+instructions. The solution for that is an ALTERNATIVE in the
+expoline THUNK generated by 'GEN_BR_THUNK %r1' to switch to
+EXRL, this relies on the fact that a machine that supports
+noexec=on has EXRL as well.
+
+Cc: stable@vger.kernel.org # 4.16
+Fixes: f19fbd5ed6 ("s390: introduce execute-trampolines for branches")
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/include/asm/nospec-insn.h | 12 ++++++++++++
+ arch/s390/kernel/asm-offsets.c | 1 +
+ arch/s390/kernel/mcount.S | 14 +++++++++-----
+ 3 files changed, 22 insertions(+), 5 deletions(-)
+
+--- a/arch/s390/include/asm/nospec-insn.h
++++ b/arch/s390/include/asm/nospec-insn.h
+@@ -2,12 +2,16 @@
+ #ifndef _ASM_S390_NOSPEC_ASM_H
+ #define _ASM_S390_NOSPEC_ASM_H
+
++#include <asm/alternative-asm.h>
++#include <asm/asm-offsets.h>
+ #include <asm/dwarf.h>
+
+ #ifdef __ASSEMBLY__
+
+ #ifdef CONFIG_EXPOLINE
+
++_LC_BR_R1 = __LC_BR_R1
++
+ /*
+ * The expoline macros are used to create thunks in the same format
+ * as gcc generates them. The 'comdat' section flag makes sure that
+@@ -78,13 +82,21 @@
+ .endm
+
+ .macro __THUNK_EX_BR reg,ruse
++ # Be very careful when adding instructions to this macro!
++ # The ALTERNATIVE replacement code has a .+10 which targets
++ # the "br \reg" after the code has been patched.
+ #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
+ exrl 0,555f
+ j .
+ #else
++ .ifc \reg,%r1
++ ALTERNATIVE "ex %r0,_LC_BR_R1", ".insn ril,0xc60000000000,0,.+10", 35
++ j .
++ .else
+ larl \ruse,555f
+ ex 0,0(\ruse)
+ j .
++ .endif
+ #endif
+ 555: br \reg
+ .endm
+--- a/arch/s390/kernel/asm-offsets.c
++++ b/arch/s390/kernel/asm-offsets.c
+@@ -179,6 +179,7 @@ int main(void)
+ OFFSET(__LC_MACHINE_FLAGS, lowcore, machine_flags);
+ OFFSET(__LC_PREEMPT_COUNT, lowcore, preempt_count);
+ OFFSET(__LC_GMAP, lowcore, gmap);
++ OFFSET(__LC_BR_R1, lowcore, br_r1_trampoline);
+ /* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */
+ OFFSET(__LC_DUMP_REIPL, lowcore, ipib);
+ /* hardware defined lowcore locations 0x1000 - 0x18ff */
+--- a/arch/s390/kernel/mcount.S
++++ b/arch/s390/kernel/mcount.S
+@@ -9,13 +9,17 @@
+ #include <linux/linkage.h>
+ #include <asm/asm-offsets.h>
+ #include <asm/ftrace.h>
++#include <asm/nospec-insn.h>
+ #include <asm/ptrace.h>
+ #include <asm/export.h>
+
++ GEN_BR_THUNK %r1
++ GEN_BR_THUNK %r14
++
+ .section .kprobes.text, "ax"
+
+ ENTRY(ftrace_stub)
+- br %r14
++ BR_EX %r14
+
+ #define STACK_FRAME_SIZE (STACK_FRAME_OVERHEAD + __PT_SIZE)
+ #define STACK_PTREGS (STACK_FRAME_OVERHEAD)
+@@ -23,7 +27,7 @@ ENTRY(ftrace_stub)
+ #define STACK_PTREGS_PSW (STACK_PTREGS + __PT_PSW)
+
+ ENTRY(_mcount)
+- br %r14
++ BR_EX %r14
+
+ EXPORT_SYMBOL(_mcount)
+
+@@ -53,7 +57,7 @@ ENTRY(ftrace_caller)
+ #endif
+ lgr %r3,%r14
+ la %r5,STACK_PTREGS(%r15)
+- basr %r14,%r1
++ BASR_EX %r14,%r1
+ #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ # The j instruction gets runtime patched to a nop instruction.
+ # See ftrace_enable_ftrace_graph_caller.
+@@ -68,7 +72,7 @@ ftrace_graph_caller_end:
+ #endif
+ lg %r1,(STACK_PTREGS_PSW+8)(%r15)
+ lmg %r2,%r15,(STACK_PTREGS_GPRS+2*8)(%r15)
+- br %r1
++ BR_EX %r1
+
+ #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+@@ -81,6 +85,6 @@ ENTRY(return_to_handler)
+ aghi %r15,STACK_FRAME_OVERHEAD
+ lgr %r14,%r2
+ lmg %r2,%r5,32(%r15)
+- br %r14
++ BR_EX %r14
+
+ #endif
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:28 +0200
+Subject: s390/kernel: use expoline for indirect branches
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-13-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit c50c84c3ac4d5db683904bdb3257798b6ef980ae ]
+
+The assember code in arch/s390/kernel uses a few more indirect branches
+which need to be done with execute trampolines for CONFIG_EXPOLINE=y.
+
+Cc: stable@vger.kernel.org # 4.16
+Fixes: f19fbd5ed6 ("s390: introduce execute-trampolines for branches")
+Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kernel/base.S | 24 ++++++++++++++----------
+ arch/s390/kernel/reipl.S | 7 +++++--
+ arch/s390/kernel/swsusp.S | 10 ++++++----
+ 3 files changed, 25 insertions(+), 16 deletions(-)
+
+--- a/arch/s390/kernel/base.S
++++ b/arch/s390/kernel/base.S
+@@ -9,18 +9,22 @@
+
+ #include <linux/linkage.h>
+ #include <asm/asm-offsets.h>
++#include <asm/nospec-insn.h>
+ #include <asm/ptrace.h>
+ #include <asm/sigp.h>
+
++ GEN_BR_THUNK %r9
++ GEN_BR_THUNK %r14
++
+ ENTRY(s390_base_mcck_handler)
+ basr %r13,0
+ 0: lg %r15,__LC_PANIC_STACK # load panic stack
+ aghi %r15,-STACK_FRAME_OVERHEAD
+ larl %r1,s390_base_mcck_handler_fn
+- lg %r1,0(%r1)
+- ltgr %r1,%r1
++ lg %r9,0(%r1)
++ ltgr %r9,%r9
+ jz 1f
+- basr %r14,%r1
++ BASR_EX %r14,%r9
+ 1: la %r1,4095
+ lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
+ lpswe __LC_MCK_OLD_PSW
+@@ -37,10 +41,10 @@ ENTRY(s390_base_ext_handler)
+ basr %r13,0
+ 0: aghi %r15,-STACK_FRAME_OVERHEAD
+ larl %r1,s390_base_ext_handler_fn
+- lg %r1,0(%r1)
+- ltgr %r1,%r1
++ lg %r9,0(%r1)
++ ltgr %r9,%r9
+ jz 1f
+- basr %r14,%r1
++ BASR_EX %r14,%r9
+ 1: lmg %r0,%r15,__LC_SAVE_AREA_ASYNC
+ ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit
+ lpswe __LC_EXT_OLD_PSW
+@@ -57,10 +61,10 @@ ENTRY(s390_base_pgm_handler)
+ basr %r13,0
+ 0: aghi %r15,-STACK_FRAME_OVERHEAD
+ larl %r1,s390_base_pgm_handler_fn
+- lg %r1,0(%r1)
+- ltgr %r1,%r1
++ lg %r9,0(%r1)
++ ltgr %r9,%r9
+ jz 1f
+- basr %r14,%r1
++ BASR_EX %r14,%r9
+ lmg %r0,%r15,__LC_SAVE_AREA_SYNC
+ lpswe __LC_PGM_OLD_PSW
+ 1: lpswe disabled_wait_psw-0b(%r13)
+@@ -117,7 +121,7 @@ ENTRY(diag308_reset)
+ larl %r4,.Lcontinue_psw # Restore PSW flags
+ lpswe 0(%r4)
+ .Lcontinue:
+- br %r14
++ BR_EX %r14
+ .align 16
+ .Lrestart_psw:
+ .long 0x00080000,0x80000000 + .Lrestart_part2
+--- a/arch/s390/kernel/reipl.S
++++ b/arch/s390/kernel/reipl.S
+@@ -7,8 +7,11 @@
+
+ #include <linux/linkage.h>
+ #include <asm/asm-offsets.h>
++#include <asm/nospec-insn.h>
+ #include <asm/sigp.h>
+
++ GEN_BR_THUNK %r9
++
+ #
+ # Issue "store status" for the current CPU to its prefix page
+ # and call passed function afterwards
+@@ -67,9 +70,9 @@ ENTRY(store_status)
+ st %r4,0(%r1)
+ st %r5,4(%r1)
+ stg %r2,8(%r1)
+- lgr %r1,%r2
++ lgr %r9,%r2
+ lgr %r2,%r3
+- br %r1
++ BR_EX %r9
+
+ .section .bss
+ .align 8
+--- a/arch/s390/kernel/swsusp.S
++++ b/arch/s390/kernel/swsusp.S
+@@ -13,6 +13,7 @@
+ #include <asm/ptrace.h>
+ #include <asm/thread_info.h>
+ #include <asm/asm-offsets.h>
++#include <asm/nospec-insn.h>
+ #include <asm/sigp.h>
+
+ /*
+@@ -24,6 +25,8 @@
+ * (see below) in the resume process.
+ * This function runs with disabled interrupts.
+ */
++ GEN_BR_THUNK %r14
++
+ .section .text
+ ENTRY(swsusp_arch_suspend)
+ stmg %r6,%r15,__SF_GPRS(%r15)
+@@ -103,7 +106,7 @@ ENTRY(swsusp_arch_suspend)
+ spx 0x318(%r1)
+ lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
+ lghi %r2,0
+- br %r14
++ BR_EX %r14
+
+ /*
+ * Restore saved memory image to correct place and restore register context.
+@@ -197,11 +200,10 @@ pgm_check_entry:
+ larl %r15,init_thread_union
+ ahi %r15,1<<(PAGE_SHIFT+THREAD_SIZE_ORDER)
+ larl %r2,.Lpanic_string
+- larl %r3,sclp_early_printk
+ lghi %r1,0
+ sam31
+ sigp %r1,%r0,SIGP_SET_ARCHITECTURE
+- basr %r14,%r3
++ brasl %r14,sclp_early_printk
+ larl %r3,.Ldisabled_wait_31
+ lpsw 0(%r3)
+ 4:
+@@ -267,7 +269,7 @@ restore_registers:
+ /* Return 0 */
+ lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
+ lghi %r2,0
+- br %r14
++ BR_EX %r14
+
+ .section .data..nosave,"aw",@progbits
+ .align 8
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:26 +0200
+Subject: s390/lib: use expoline for indirect branches
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-11-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit 97489e0663fa700d6e7febddc43b58df98d7bcda ]
+
+The return from the memmove, memset, memcpy, __memset16, __memset32 and
+__memset64 functions are done with "br %r14". These are indirect branches
+as well and need to use execute trampolines for CONFIG_EXPOLINE=y.
+
+Cc: stable@vger.kernel.org # 4.16
+Fixes: f19fbd5ed6 ("s390: introduce execute-trampolines for branches")
+Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/lib/mem.S | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+--- a/arch/s390/lib/mem.S
++++ b/arch/s390/lib/mem.S
+@@ -7,6 +7,9 @@
+
+ #include <linux/linkage.h>
+ #include <asm/export.h>
++#include <asm/nospec-insn.h>
++
++ GEN_BR_THUNK %r14
+
+ /*
+ * void *memmove(void *dest, const void *src, size_t n)
+@@ -33,14 +36,14 @@ ENTRY(memmove)
+ .Lmemmove_forward_remainder:
+ larl %r5,.Lmemmove_mvc
+ ex %r4,0(%r5)
+- br %r14
++ BR_EX %r14
+ .Lmemmove_reverse:
+ ic %r0,0(%r4,%r3)
+ stc %r0,0(%r4,%r1)
+ brctg %r4,.Lmemmove_reverse
+ ic %r0,0(%r4,%r3)
+ stc %r0,0(%r4,%r1)
+- br %r14
++ BR_EX %r14
+ .Lmemmove_mvc:
+ mvc 0(1,%r1),0(%r3)
+ EXPORT_SYMBOL(memmove)
+@@ -77,7 +80,7 @@ ENTRY(memset)
+ .Lmemset_clear_remainder:
+ larl %r3,.Lmemset_xc
+ ex %r4,0(%r3)
+- br %r14
++ BR_EX %r14
+ .Lmemset_fill:
+ cghi %r4,1
+ lgr %r1,%r2
+@@ -95,10 +98,10 @@ ENTRY(memset)
+ stc %r3,0(%r1)
+ larl %r5,.Lmemset_mvc
+ ex %r4,0(%r5)
+- br %r14
++ BR_EX %r14
+ .Lmemset_fill_exit:
+ stc %r3,0(%r1)
+- br %r14
++ BR_EX %r14
+ .Lmemset_xc:
+ xc 0(1,%r1),0(%r1)
+ .Lmemset_mvc:
+@@ -121,7 +124,7 @@ ENTRY(memcpy)
+ .Lmemcpy_remainder:
+ larl %r5,.Lmemcpy_mvc
+ ex %r4,0(%r5)
+- br %r14
++ BR_EX %r14
+ .Lmemcpy_loop:
+ mvc 0(256,%r1),0(%r3)
+ la %r1,256(%r1)
+@@ -159,10 +162,10 @@ ENTRY(__memset\bits)
+ \insn %r3,0(%r1)
+ larl %r5,.L__memset_mvc\bits
+ ex %r4,0(%r5)
+- br %r14
++ BR_EX %r14
+ .L__memset_exit\bits:
+ \insn %r3,0(%r2)
+- br %r14
++ BR_EX %r14
+ .L__memset_mvc\bits:
+ mvc \bytes(1,%r1),0(%r1)
+ .endm
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:24 +0200
+Subject: s390: move expoline assembler macros to a header
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-9-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit 6dd85fbb87d1d6b87a3b1f02ca28d7b2abd2e7ba ]
+
+To be able to use the expoline branches in different assembler
+files move the associated macros from entry.S to a new header
+nospec-insn.h.
+
+While we are at it make the macros a bit nicer to use.
+
+Cc: stable@vger.kernel.org # 4.16
+Fixes: f19fbd5ed6 ("s390: introduce execute-trampolines for branches")
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/include/asm/nospec-insn.h | 127 ++++++++++++++++++++++++++++++++++++
+ arch/s390/kernel/entry.S | 105 ++++++-----------------------
+ 2 files changed, 151 insertions(+), 81 deletions(-)
+ create mode 100644 arch/s390/include/asm/nospec-insn.h
+
+--- /dev/null
++++ b/arch/s390/include/asm/nospec-insn.h
+@@ -0,0 +1,127 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _ASM_S390_NOSPEC_ASM_H
++#define _ASM_S390_NOSPEC_ASM_H
++
++#include <asm/dwarf.h>
++
++#ifdef __ASSEMBLY__
++
++#ifdef CONFIG_EXPOLINE
++
++/*
++ * The expoline macros are used to create thunks in the same format
++ * as gcc generates them. The 'comdat' section flag makes sure that
++ * the various thunks are merged into a single copy.
++ */
++ .macro __THUNK_PROLOG_NAME name
++ .pushsection .text.\name,"axG",@progbits,\name,comdat
++ .globl \name
++ .hidden \name
++ .type \name,@function
++\name:
++ CFI_STARTPROC
++ .endm
++
++ .macro __THUNK_EPILOG
++ CFI_ENDPROC
++ .popsection
++ .endm
++
++ .macro __THUNK_PROLOG_BR r1,r2
++ __THUNK_PROLOG_NAME __s390x_indirect_jump_r\r2\()use_r\r1
++ .endm
++
++ .macro __THUNK_BR r1,r2
++ jg __s390x_indirect_jump_r\r2\()use_r\r1
++ .endm
++
++ .macro __THUNK_BRASL r1,r2,r3
++ brasl \r1,__s390x_indirect_jump_r\r3\()use_r\r2
++ .endm
++
++ .macro __DECODE_RR expand,reg,ruse
++ .set __decode_fail,1
++ .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
++ .ifc \reg,%r\r1
++ .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
++ .ifc \ruse,%r\r2
++ \expand \r1,\r2
++ .set __decode_fail,0
++ .endif
++ .endr
++ .endif
++ .endr
++ .if __decode_fail == 1
++ .error "__DECODE_RR failed"
++ .endif
++ .endm
++
++ .macro __DECODE_RRR expand,rsave,rtarget,ruse
++ .set __decode_fail,1
++ .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
++ .ifc \rsave,%r\r1
++ .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
++ .ifc \rtarget,%r\r2
++ .irp r3,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
++ .ifc \ruse,%r\r3
++ \expand \r1,\r2,\r3
++ .set __decode_fail,0
++ .endif
++ .endr
++ .endif
++ .endr
++ .endif
++ .endr
++ .if __decode_fail == 1
++ .error "__DECODE_RRR failed"
++ .endif
++ .endm
++
++ .macro __THUNK_EX_BR reg,ruse
++#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
++ exrl 0,555f
++ j .
++#else
++ larl \ruse,555f
++ ex 0,0(\ruse)
++ j .
++#endif
++555: br \reg
++ .endm
++
++ .macro GEN_BR_THUNK reg,ruse=%r1
++ __DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse
++ __THUNK_EX_BR \reg,\ruse
++ __THUNK_EPILOG
++ .endm
++
++ .macro BR_EX reg,ruse=%r1
++557: __DECODE_RR __THUNK_BR,\reg,\ruse
++ .pushsection .s390_indirect_branches,"a",@progbits
++ .long 557b-.
++ .popsection
++ .endm
++
++ .macro BASR_EX rsave,rtarget,ruse=%r1
++559: __DECODE_RRR __THUNK_BRASL,\rsave,\rtarget,\ruse
++ .pushsection .s390_indirect_branches,"a",@progbits
++ .long 559b-.
++ .popsection
++ .endm
++
++#else
++ .macro GEN_BR_THUNK reg,ruse=%r1
++ .endm
++
++ .macro BR_EX reg,ruse=%r1
++ br \reg
++ .endm
++
++ .macro BASR_EX rsave,rtarget,ruse=%r1
++ basr \rsave,\rtarget
++ .endm
++#endif
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* _ASM_S390_NOSPEC_ASM_H */
+--- a/arch/s390/kernel/entry.S
++++ b/arch/s390/kernel/entry.S
+@@ -27,6 +27,7 @@
+ #include <asm/setup.h>
+ #include <asm/nmi.h>
+ #include <asm/export.h>
++#include <asm/nospec-insn.h>
+
+ __PT_R0 = __PT_GPRS
+ __PT_R1 = __PT_GPRS + 8
+@@ -223,67 +224,9 @@ _PIF_WORK = (_PIF_PER_TRAP | _PIF_SYSCAL
+ .popsection
+ .endm
+
+-#ifdef CONFIG_EXPOLINE
+-
+- .macro GEN_BR_THUNK name,reg,tmp
+- .section .text.\name,"axG",@progbits,\name,comdat
+- .globl \name
+- .hidden \name
+- .type \name,@function
+-\name:
+- CFI_STARTPROC
+-#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
+- exrl 0,0f
+-#else
+- larl \tmp,0f
+- ex 0,0(\tmp)
+-#endif
+- j .
+-0: br \reg
+- CFI_ENDPROC
+- .endm
+-
+- GEN_BR_THUNK __s390x_indirect_jump_r1use_r9,%r9,%r1
+- GEN_BR_THUNK __s390x_indirect_jump_r1use_r14,%r14,%r1
+- GEN_BR_THUNK __s390x_indirect_jump_r11use_r14,%r14,%r11
+-
+- .macro BASR_R14_R9
+-0: brasl %r14,__s390x_indirect_jump_r1use_r9
+- .pushsection .s390_indirect_branches,"a",@progbits
+- .long 0b-.
+- .popsection
+- .endm
+-
+- .macro BR_R1USE_R14
+-0: jg __s390x_indirect_jump_r1use_r14
+- .pushsection .s390_indirect_branches,"a",@progbits
+- .long 0b-.
+- .popsection
+- .endm
+-
+- .macro BR_R11USE_R14
+-0: jg __s390x_indirect_jump_r11use_r14
+- .pushsection .s390_indirect_branches,"a",@progbits
+- .long 0b-.
+- .popsection
+- .endm
+-
+-#else /* CONFIG_EXPOLINE */
+-
+- .macro BASR_R14_R9
+- basr %r14,%r9
+- .endm
+-
+- .macro BR_R1USE_R14
+- br %r14
+- .endm
+-
+- .macro BR_R11USE_R14
+- br %r14
+- .endm
+-
+-#endif /* CONFIG_EXPOLINE */
+-
++ GEN_BR_THUNK %r9
++ GEN_BR_THUNK %r14
++ GEN_BR_THUNK %r14,%r11
+
+ .section .kprobes.text, "ax"
+ .Ldummy:
+@@ -300,7 +243,7 @@ _PIF_WORK = (_PIF_PER_TRAP | _PIF_SYSCAL
+ ENTRY(__bpon)
+ .globl __bpon
+ BPON
+- BR_R1USE_R14
++ BR_EX %r14
+
+ /*
+ * Scheduler resume function, called by switch_to
+@@ -326,7 +269,7 @@ ENTRY(__switch_to)
+ TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP
+ jz 0f
+ .insn s,0xb2800000,__LC_LPP # set program parameter
+-0: BR_R1USE_R14
++0: BR_EX %r14
+
+ .L__critical_start:
+
+@@ -393,7 +336,7 @@ sie_exit:
+ xgr %r5,%r5
+ lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
+ lg %r2,__SF_EMPTY+16(%r15) # return exit reason code
+- BR_R1USE_R14
++ BR_EX %r14
+ .Lsie_fault:
+ lghi %r14,-EFAULT
+ stg %r14,__SF_EMPTY+16(%r15) # set exit reason code
+@@ -452,7 +395,7 @@ ENTRY(system_call)
+ lgf %r9,0(%r8,%r10) # get system call add.
+ TSTMSK __TI_flags(%r12),_TIF_TRACE
+ jnz .Lsysc_tracesys
+- BASR_R14_R9 # call sys_xxxx
++ BASR_EX %r14,%r9 # call sys_xxxx
+ stg %r2,__PT_R2(%r11) # store return value
+
+ .Lsysc_return:
+@@ -637,7 +580,7 @@ ENTRY(system_call)
+ lmg %r3,%r7,__PT_R3(%r11)
+ stg %r7,STACK_FRAME_OVERHEAD(%r15)
+ lg %r2,__PT_ORIG_GPR2(%r11)
+- BASR_R14_R9 # call sys_xxx
++ BASR_EX %r14,%r9 # call sys_xxx
+ stg %r2,__PT_R2(%r11) # store return value
+ .Lsysc_tracenogo:
+ TSTMSK __TI_flags(%r12),_TIF_TRACE
+@@ -661,7 +604,7 @@ ENTRY(ret_from_fork)
+ lmg %r9,%r10,__PT_R9(%r11) # load gprs
+ ENTRY(kernel_thread_starter)
+ la %r2,0(%r10)
+- BASR_R14_R9
++ BASR_EX %r14,%r9
+ j .Lsysc_tracenogo
+
+ /*
+@@ -743,7 +686,7 @@ ENTRY(pgm_check_handler)
+ je .Lpgm_return
+ lgf %r9,0(%r10,%r1) # load address of handler routine
+ lgr %r2,%r11 # pass pointer to pt_regs
+- BASR_R14_R9 # branch to interrupt-handler
++ BASR_EX %r14,%r9 # branch to interrupt-handler
+ .Lpgm_return:
+ LOCKDEP_SYS_EXIT
+ tm __PT_PSW+1(%r11),0x01 # returning to user ?
+@@ -1061,7 +1004,7 @@ ENTRY(psw_idle)
+ stpt __TIMER_IDLE_ENTER(%r2)
+ .Lpsw_idle_lpsw:
+ lpswe __SF_EMPTY(%r15)
+- BR_R1USE_R14
++ BR_EX %r14
+ .Lpsw_idle_end:
+
+ /*
+@@ -1103,7 +1046,7 @@ ENTRY(save_fpu_regs)
+ .Lsave_fpu_regs_done:
+ oi __LC_CPU_FLAGS+7,_CIF_FPU
+ .Lsave_fpu_regs_exit:
+- BR_R1USE_R14
++ BR_EX %r14
+ .Lsave_fpu_regs_end:
+ EXPORT_SYMBOL(save_fpu_regs)
+
+@@ -1149,7 +1092,7 @@ load_fpu_regs:
+ .Lload_fpu_regs_done:
+ ni __LC_CPU_FLAGS+7,255-_CIF_FPU
+ .Lload_fpu_regs_exit:
+- BR_R1USE_R14
++ BR_EX %r14
+ .Lload_fpu_regs_end:
+
+ .L__critical_end:
+@@ -1366,7 +1309,7 @@ cleanup_critical:
+ jl 0f
+ clg %r9,BASED(.Lcleanup_table+104) # .Lload_fpu_regs_end
+ jl .Lcleanup_load_fpu_regs
+-0: BR_R11USE_R14
++0: BR_EX %r14
+
+ .align 8
+ .Lcleanup_table:
+@@ -1402,7 +1345,7 @@ cleanup_critical:
+ ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE
+ lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
+ larl %r9,sie_exit # skip forward to sie_exit
+- BR_R11USE_R14
++ BR_EX %r14
+ #endif
+
+ .Lcleanup_system_call:
+@@ -1456,7 +1399,7 @@ cleanup_critical:
+ stg %r15,56(%r11) # r15 stack pointer
+ # set new psw address and exit
+ larl %r9,.Lsysc_do_svc
+- BR_R11USE_R14
++ BR_EX %r14,%r11
+ .Lcleanup_system_call_insn:
+ .quad system_call
+ .quad .Lsysc_stmg
+@@ -1468,7 +1411,7 @@ cleanup_critical:
+
+ .Lcleanup_sysc_tif:
+ larl %r9,.Lsysc_tif
+- BR_R11USE_R14
++ BR_EX %r14,%r11
+
+ .Lcleanup_sysc_restore:
+ # check if stpt has been executed
+@@ -1485,14 +1428,14 @@ cleanup_critical:
+ mvc 0(64,%r11),__PT_R8(%r9)
+ lmg %r0,%r7,__PT_R0(%r9)
+ 1: lmg %r8,%r9,__LC_RETURN_PSW
+- BR_R11USE_R14
++ BR_EX %r14,%r11
+ .Lcleanup_sysc_restore_insn:
+ .quad .Lsysc_exit_timer
+ .quad .Lsysc_done - 4
+
+ .Lcleanup_io_tif:
+ larl %r9,.Lio_tif
+- BR_R11USE_R14
++ BR_EX %r14,%r11
+
+ .Lcleanup_io_restore:
+ # check if stpt has been executed
+@@ -1506,7 +1449,7 @@ cleanup_critical:
+ mvc 0(64,%r11),__PT_R8(%r9)
+ lmg %r0,%r7,__PT_R0(%r9)
+ 1: lmg %r8,%r9,__LC_RETURN_PSW
+- BR_R11USE_R14
++ BR_EX %r14,%r11
+ .Lcleanup_io_restore_insn:
+ .quad .Lio_exit_timer
+ .quad .Lio_done - 4
+@@ -1559,17 +1502,17 @@ cleanup_critical:
+ # prepare return psw
+ nihh %r8,0xfcfd # clear irq & wait state bits
+ lg %r9,48(%r11) # return from psw_idle
+- BR_R11USE_R14
++ BR_EX %r14,%r11
+ .Lcleanup_idle_insn:
+ .quad .Lpsw_idle_lpsw
+
+ .Lcleanup_save_fpu_regs:
+ larl %r9,save_fpu_regs
+- BR_R11USE_R14
++ BR_EX %r14,%r11
+
+ .Lcleanup_load_fpu_regs:
+ larl %r9,load_fpu_regs
+- BR_R11USE_R14
++ BR_EX %r14,%r11
+
+ /*
+ * Integer constants
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:17 +0200
+Subject: s390: move nobp parameter functions to nospec-branch.c
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-2-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit b2e2f43a01bace1a25bdbae04c9f9846882b727a ]
+
+Keep the code for the nobp parameter handling with the code for
+expolines. Both are related to the spectre v2 mitigation.
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kernel/Makefile | 4 ++--
+ arch/s390/kernel/alternative.c | 23 -----------------------
+ arch/s390/kernel/nospec-branch.c | 27 +++++++++++++++++++++++++++
+ 3 files changed, 29 insertions(+), 25 deletions(-)
+
+--- a/arch/s390/kernel/Makefile
++++ b/arch/s390/kernel/Makefile
+@@ -61,11 +61,11 @@ obj-y += debug.o irq.o ipl.o dis.o diag.
+ obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
+ obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o
+ obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o alternative.o
++obj-y += nospec-branch.o
+
+ extra-y += head.o head64.o vmlinux.lds
+
+-obj-$(CONFIG_EXPOLINE) += nospec-branch.o
+-CFLAGS_REMOVE_expoline.o += $(CC_FLAGS_EXPOLINE)
++CFLAGS_REMOVE_nospec-branch.o += $(CC_FLAGS_EXPOLINE)
+
+ obj-$(CONFIG_MODULES) += module.o
+ obj-$(CONFIG_SMP) += smp.o
+--- a/arch/s390/kernel/alternative.c
++++ b/arch/s390/kernel/alternative.c
+@@ -15,29 +15,6 @@ static int __init disable_alternative_in
+
+ early_param("noaltinstr", disable_alternative_instructions);
+
+-static int __init nobp_setup_early(char *str)
+-{
+- bool enabled;
+- int rc;
+-
+- rc = kstrtobool(str, &enabled);
+- if (rc)
+- return rc;
+- if (enabled && test_facility(82))
+- __set_facility(82, S390_lowcore.alt_stfle_fac_list);
+- else
+- __clear_facility(82, S390_lowcore.alt_stfle_fac_list);
+- return 0;
+-}
+-early_param("nobp", nobp_setup_early);
+-
+-static int __init nospec_setup_early(char *str)
+-{
+- __clear_facility(82, S390_lowcore.alt_stfle_fac_list);
+- return 0;
+-}
+-early_param("nospec", nospec_setup_early);
+-
+ struct brcl_insn {
+ u16 opc;
+ s32 disp;
+--- a/arch/s390/kernel/nospec-branch.c
++++ b/arch/s390/kernel/nospec-branch.c
+@@ -2,6 +2,31 @@
+ #include <linux/module.h>
+ #include <asm/nospec-branch.h>
+
++static int __init nobp_setup_early(char *str)
++{
++ bool enabled;
++ int rc;
++
++ rc = kstrtobool(str, &enabled);
++ if (rc)
++ return rc;
++ if (enabled && test_facility(82))
++ __set_facility(82, S390_lowcore.alt_stfle_fac_list);
++ else
++ __clear_facility(82, S390_lowcore.alt_stfle_fac_list);
++ return 0;
++}
++early_param("nobp", nobp_setup_early);
++
++static int __init nospec_setup_early(char *str)
++{
++ __clear_facility(82, S390_lowcore.alt_stfle_fac_list);
++ return 0;
++}
++early_param("nospec", nospec_setup_early);
++
++#ifdef CONFIG_EXPOLINE
++
+ int nospec_call_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF);
+ int nospec_return_disable = !IS_ENABLED(CONFIG_EXPOLINE_FULL);
+
+@@ -98,3 +123,5 @@ void __init nospec_init_branches(void)
+ nospec_call_revert(__nospec_call_start, __nospec_call_end);
+ nospec_return_revert(__nospec_return_start, __nospec_return_end);
+ }
++
++#endif /* CONFIG_EXPOLINE */
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:29 +0200
+Subject: s390: move spectre sysfs attribute code
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-14-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit 4253b0e0627ee3461e64c2495c616f1c8f6b127b ]
+
+The nospec-branch.c file is compiled without the gcc options to
+generate expoline thunks. The return branch of the sysfs show
+functions cpu_show_spectre_v1 and cpu_show_spectre_v2 is an indirect
+branch as well. These need to be compiled with expolines.
+
+Move the sysfs functions for spectre reporting to a separate file
+and loose an '.' for one of the messages.
+
+Cc: stable@vger.kernel.org # 4.16
+Fixes: d424986f1d ("s390: add sysfs attributes for spectre")
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kernel/Makefile | 1 +
+ arch/s390/kernel/nospec-branch.c | 18 ------------------
+ arch/s390/kernel/nospec-sysfs.c | 21 +++++++++++++++++++++
+ 3 files changed, 22 insertions(+), 18 deletions(-)
+ create mode 100644 arch/s390/kernel/nospec-sysfs.c
+
+--- a/arch/s390/kernel/Makefile
++++ b/arch/s390/kernel/Makefile
+@@ -65,6 +65,7 @@ obj-y += nospec-branch.o
+
+ extra-y += head.o head64.o vmlinux.lds
+
++obj-$(CONFIG_SYSFS) += nospec-sysfs.o
+ CFLAGS_REMOVE_nospec-branch.o += $(CC_FLAGS_EXPOLINE)
+
+ obj-$(CONFIG_MODULES) += module.o
+--- a/arch/s390/kernel/nospec-branch.c
++++ b/arch/s390/kernel/nospec-branch.c
+@@ -43,24 +43,6 @@ static int __init nospec_report(void)
+ }
+ arch_initcall(nospec_report);
+
+-#ifdef CONFIG_SYSFS
+-ssize_t cpu_show_spectre_v1(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- return sprintf(buf, "Mitigation: __user pointer sanitization\n");
+-}
+-
+-ssize_t cpu_show_spectre_v2(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
+- return sprintf(buf, "Mitigation: execute trampolines\n");
+- if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
+- return sprintf(buf, "Mitigation: limited branch prediction.\n");
+- return sprintf(buf, "Vulnerable\n");
+-}
+-#endif
+-
+ #ifdef CONFIG_EXPOLINE
+
+ int nospec_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF);
+--- /dev/null
++++ b/arch/s390/kernel/nospec-sysfs.c
+@@ -0,0 +1,21 @@
++// SPDX-License-Identifier: GPL-2.0
++#include <linux/device.h>
++#include <linux/cpu.h>
++#include <asm/facility.h>
++#include <asm/nospec-branch.h>
++
++ssize_t cpu_show_spectre_v1(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "Mitigation: __user pointer sanitization\n");
++}
++
++ssize_t cpu_show_spectre_v2(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
++ return sprintf(buf, "Mitigation: execute trampolines\n");
++ if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
++ return sprintf(buf, "Mitigation: limited branch prediction\n");
++ return sprintf(buf, "Vulnerable\n");
++}
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:19 +0200
+Subject: s390: report spectre mitigation via syslog
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-4-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit bc035599718412cfba9249aa713f90ef13f13ee9 ]
+
+Add a boot message if either of the spectre defenses is active.
+The message is
+ "Spectre V2 mitigation: execute trampolines."
+or "Spectre V2 mitigation: limited branch prediction."
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kernel/nospec-branch.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/arch/s390/kernel/nospec-branch.c
++++ b/arch/s390/kernel/nospec-branch.c
+@@ -32,6 +32,16 @@ static int __init nospec_setup_early(cha
+ }
+ early_param("nospec", nospec_setup_early);
+
++static int __init nospec_report(void)
++{
++ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
++ pr_info("Spectre V2 mitigation: execute trampolines.\n");
++ if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
++ pr_info("Spectre V2 mitigation: limited branch prediction.\n");
++ return 0;
++}
++arch_initcall(nospec_report);
++
+ #ifdef CONFIG_EXPOLINE
+
+ int nospec_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF);
--- /dev/null
+From foo@baz Wed May 23 19:22:17 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 23 May 2018 18:22:31 +0200
+Subject: s390: use expoline thunks in the BPF JIT
+To: stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <1527092551-24476-16-git-send-email-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+[ Upstream commit de5cb6eb514ebe241e3edeb290cb41deb380b81d ]
+
+The BPF JIT need safe guarding against spectre v2 in the sk_load_xxx
+assembler stubs and the indirect branches generated by the JIT itself
+need to be converted to expolines.
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/net/bpf_jit.S | 16 ++++++----
+ arch/s390/net/bpf_jit_comp.c | 63 +++++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 71 insertions(+), 8 deletions(-)
+
+--- a/arch/s390/net/bpf_jit.S
++++ b/arch/s390/net/bpf_jit.S
+@@ -9,6 +9,7 @@
+ */
+
+ #include <linux/linkage.h>
++#include <asm/nospec-insn.h>
+ #include "bpf_jit.h"
+
+ /*
+@@ -54,7 +55,7 @@ ENTRY(sk_load_##NAME##_pos); \
+ clg %r3,STK_OFF_HLEN(%r15); /* Offset + SIZE > hlen? */ \
+ jh sk_load_##NAME##_slow; \
+ LOAD %r14,-SIZE(%r3,%r12); /* Get data from skb */ \
+- b OFF_OK(%r6); /* Return */ \
++ B_EX OFF_OK,%r6; /* Return */ \
+ \
+ sk_load_##NAME##_slow:; \
+ lgr %r2,%r7; /* Arg1 = skb pointer */ \
+@@ -64,11 +65,14 @@ sk_load_##NAME##_slow:; \
+ brasl %r14,skb_copy_bits; /* Get data from skb */ \
+ LOAD %r14,STK_OFF_TMP(%r15); /* Load from temp bufffer */ \
+ ltgr %r2,%r2; /* Set cc to (%r2 != 0) */ \
+- br %r6; /* Return */
++ BR_EX %r6; /* Return */
+
+ sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */
+ sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */
+
++ GEN_BR_THUNK %r6
++ GEN_B_THUNK OFF_OK,%r6
++
+ /*
+ * Load 1 byte from SKB (optimized version)
+ */
+@@ -80,7 +84,7 @@ ENTRY(sk_load_byte_pos)
+ clg %r3,STK_OFF_HLEN(%r15) # Offset >= hlen?
+ jnl sk_load_byte_slow
+ llgc %r14,0(%r3,%r12) # Get byte from skb
+- b OFF_OK(%r6) # Return OK
++ B_EX OFF_OK,%r6 # Return OK
+
+ sk_load_byte_slow:
+ lgr %r2,%r7 # Arg1 = skb pointer
+@@ -90,7 +94,7 @@ sk_load_byte_slow:
+ brasl %r14,skb_copy_bits # Get data from skb
+ llgc %r14,STK_OFF_TMP(%r15) # Load result from temp buffer
+ ltgr %r2,%r2 # Set cc to (%r2 != 0)
+- br %r6 # Return cc
++ BR_EX %r6 # Return cc
+
+ #define sk_negative_common(NAME, SIZE, LOAD) \
+ sk_load_##NAME##_slow_neg:; \
+@@ -104,7 +108,7 @@ sk_load_##NAME##_slow_neg:; \
+ jz bpf_error; \
+ LOAD %r14,0(%r2); /* Get data from pointer */ \
+ xr %r3,%r3; /* Set cc to zero */ \
+- br %r6; /* Return cc */
++ BR_EX %r6; /* Return cc */
+
+ sk_negative_common(word, 4, llgf)
+ sk_negative_common(half, 2, llgh)
+@@ -113,4 +117,4 @@ sk_negative_common(byte, 1, llgc)
+ bpf_error:
+ # force a return 0 from jit handler
+ ltgr %r15,%r15 # Set condition code
+- br %r6
++ BR_EX %r6
+--- a/arch/s390/net/bpf_jit_comp.c
++++ b/arch/s390/net/bpf_jit_comp.c
+@@ -25,6 +25,8 @@
+ #include <linux/bpf.h>
+ #include <asm/cacheflush.h>
+ #include <asm/dis.h>
++#include <asm/facility.h>
++#include <asm/nospec-branch.h>
+ #include <asm/set_memory.h>
+ #include "bpf_jit.h"
+
+@@ -41,6 +43,8 @@ struct bpf_jit {
+ int base_ip; /* Base address for literal pool */
+ int ret0_ip; /* Address of return 0 */
+ int exit_ip; /* Address of exit */
++ int r1_thunk_ip; /* Address of expoline thunk for 'br %r1' */
++ int r14_thunk_ip; /* Address of expoline thunk for 'br %r14' */
+ int tail_call_start; /* Tail call start offset */
+ int labels[1]; /* Labels for local jumps */
+ };
+@@ -250,6 +254,19 @@ static inline void reg_set_seen(struct b
+ REG_SET_SEEN(b2); \
+ })
+
++#define EMIT6_PCREL_RILB(op, b, target) \
++({ \
++ int rel = (target - jit->prg) / 2; \
++ _EMIT6(op | reg_high(b) << 16 | rel >> 16, rel & 0xffff); \
++ REG_SET_SEEN(b); \
++})
++
++#define EMIT6_PCREL_RIL(op, target) \
++({ \
++ int rel = (target - jit->prg) / 2; \
++ _EMIT6(op | rel >> 16, rel & 0xffff); \
++})
++
+ #define _EMIT6_IMM(op, imm) \
+ ({ \
+ unsigned int __imm = (imm); \
+@@ -469,8 +486,45 @@ static void bpf_jit_epilogue(struct bpf_
+ EMIT4(0xb9040000, REG_2, BPF_REG_0);
+ /* Restore registers */
+ save_restore_regs(jit, REGS_RESTORE, stack_depth);
++ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) {
++ jit->r14_thunk_ip = jit->prg;
++ /* Generate __s390_indirect_jump_r14 thunk */
++ if (test_facility(35)) {
++ /* exrl %r0,.+10 */
++ EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10);
++ } else {
++ /* larl %r1,.+14 */
++ EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14);
++ /* ex 0,0(%r1) */
++ EMIT4_DISP(0x44000000, REG_0, REG_1, 0);
++ }
++ /* j . */
++ EMIT4_PCREL(0xa7f40000, 0);
++ }
+ /* br %r14 */
+ _EMIT2(0x07fe);
++
++ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable &&
++ (jit->seen & SEEN_FUNC)) {
++ jit->r1_thunk_ip = jit->prg;
++ /* Generate __s390_indirect_jump_r1 thunk */
++ if (test_facility(35)) {
++ /* exrl %r0,.+10 */
++ EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10);
++ /* j . */
++ EMIT4_PCREL(0xa7f40000, 0);
++ /* br %r1 */
++ _EMIT2(0x07f1);
++ } else {
++ /* larl %r1,.+14 */
++ EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14);
++ /* ex 0,S390_lowcore.br_r1_tampoline */
++ EMIT4_DISP(0x44000000, REG_0, REG_0,
++ offsetof(struct lowcore, br_r1_trampoline));
++ /* j . */
++ EMIT4_PCREL(0xa7f40000, 0);
++ }
++ }
+ }
+
+ /*
+@@ -966,8 +1020,13 @@ static noinline int bpf_jit_insn(struct
+ /* lg %w1,<d(imm)>(%l) */
+ EMIT6_DISP_LH(0xe3000000, 0x0004, REG_W1, REG_0, REG_L,
+ EMIT_CONST_U64(func));
+- /* basr %r14,%w1 */
+- EMIT2(0x0d00, REG_14, REG_W1);
++ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) {
++ /* brasl %r14,__s390_indirect_jump_r1 */
++ EMIT6_PCREL_RILB(0xc0050000, REG_14, jit->r1_thunk_ip);
++ } else {
++ /* basr %r14,%w1 */
++ EMIT2(0x0d00, REG_14, REG_W1);
++ }
+ /* lgr %b0,%r2: load return value into %b0 */
+ EMIT4(0xb9040000, BPF_REG_0, REG_2);
+ if ((jit->seen & SEEN_SKB) &&
qed-fix-possibility-of-list-corruption-during-rmmod-flows.patch
qed-fix-ll2-race-during-connection-terminate.patch
sparc-vio-use-put_device-instead-of-kfree.patch
+ext2-fix-a-block-leak.patch
+powerpc-rfi-flush-always-enable-fallback-flush-on-pseries.patch
+powerpc-add-security-feature-flags-for-spectre-meltdown.patch
+powerpc-pseries-add-new-h_get_cpu_characteristics-flags.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-64s-add-support-for-a-store-forwarding-barrier-at-kernel-entry-exit.patch
+s390-move-nobp-parameter-functions-to-nospec-branch.c.patch
+s390-add-automatic-detection-of-the-spectre-defense.patch
+s390-report-spectre-mitigation-via-syslog.patch
+s390-add-sysfs-attributes-for-spectre.patch
+s390-add-assembler-macros-for-cpu-alternatives.patch
+s390-correct-nospec-auto-detection-init-order.patch
+s390-correct-module-section-names-for-expoline-code-revert.patch
+s390-move-expoline-assembler-macros-to-a-header.patch
+s390-crc32-vx-use-expoline-for-indirect-branches.patch
+s390-lib-use-expoline-for-indirect-branches.patch
+s390-ftrace-use-expoline-for-indirect-branches.patch
+s390-kernel-use-expoline-for-indirect-branches.patch
+s390-move-spectre-sysfs-attribute-code.patch
+s390-extend-expoline-to-bc-instructions.patch
+s390-use-expoline-thunks-in-the-bpf-jit.patch