--- /dev/null
+From foo@baz Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:34 +0200
+Subject: KVM: s390: force bp isolation for VSIE
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-11-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+
+From: Christian Borntraeger <borntraeger@de.ibm.com>
+
+[ Upstream commit f315104ad8b0c32be13eac628569ae707c332cb5 ]
+
+If the guest runs with bp isolation when doing a SIE instruction,
+we must also run the nested guest with bp isolation when emulating
+that SIE instruction.
+This is done by activating BPBC in the lpar, which acts as an override
+for lower level guests.
+
+Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
+Reviewed-by: Janosch Frank <frankja@linux.vnet.ibm.com>
+Reviewed-by: David Hildenbrand <david@redhat.com>
+Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kvm/vsie.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+--- a/arch/s390/kvm/vsie.c
++++ b/arch/s390/kvm/vsie.c
+@@ -831,6 +831,7 @@ static int do_vsie_run(struct kvm_vcpu *
+ {
+ struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s;
+ struct kvm_s390_sie_block *scb_o = vsie_page->scb_o;
++ int guest_bp_isolation;
+ int rc;
+
+ handle_last_fault(vcpu, vsie_page);
+@@ -841,6 +842,20 @@ static int do_vsie_run(struct kvm_vcpu *
+ s390_handle_mcck();
+
+ srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
++
++ /* save current guest state of bp isolation override */
++ guest_bp_isolation = test_thread_flag(TIF_ISOLATE_BP_GUEST);
++
++ /*
++ * The guest is running with BPBC, so we have to force it on for our
++ * nested guest. This is done by enabling BPBC globally, so the BPBC
++ * control in the SCB (which the nested guest can modify) is simply
++ * ignored.
++ */
++ if (test_kvm_facility(vcpu->kvm, 82) &&
++ vcpu->arch.sie_block->fpf & FPF_BPBC)
++ set_thread_flag(TIF_ISOLATE_BP_GUEST);
++
+ local_irq_disable();
+ guest_enter_irqoff();
+ local_irq_enable();
+@@ -850,6 +865,11 @@ static int do_vsie_run(struct kvm_vcpu *
+ local_irq_disable();
+ guest_exit_irqoff();
+ local_irq_enable();
++
++ /* restore guest state for bp isolation override */
++ if (!guest_bp_isolation)
++ clear_thread_flag(TIF_ISOLATE_BP_GUEST);
++
+ vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+ if (rc == -EINTR) {
--- /dev/null
+From foo@baz Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:27 +0200
+Subject: KVM: s390: wire up bpb feature
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-4-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+
+From: Christian Borntraeger <borntraeger@de.ibm.com>
+
+[ Upstream commit 35b3fde6203b932b2b1a5b53b3d8808abc9c4f60 ]
+
+The new firmware interfaces for branch prediction behaviour changes
+are transparently available for the guest. Nevertheless, there is
+new state attached that should be migrated and properly resetted.
+Provide a mechanism for handling reset, migration and VSIE.
+
+Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
+Reviewed-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Cornelia Huck <cohuck@redhat.com>
+[Changed capability number to 152. - Radim]
+Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/include/asm/kvm_host.h | 3 ++-
+ arch/s390/include/uapi/asm/kvm.h | 5 ++++-
+ arch/s390/kvm/kvm-s390.c | 12 ++++++++++++
+ arch/s390/kvm/vsie.c | 10 ++++++++++
+ include/uapi/linux/kvm.h | 1 +
+ 5 files changed, 29 insertions(+), 2 deletions(-)
+
+--- a/arch/s390/include/asm/kvm_host.h
++++ b/arch/s390/include/asm/kvm_host.h
+@@ -210,7 +210,8 @@ struct kvm_s390_sie_block {
+ __u16 ipa; /* 0x0056 */
+ __u32 ipb; /* 0x0058 */
+ __u32 scaoh; /* 0x005c */
+- __u8 reserved60; /* 0x0060 */
++#define FPF_BPBC 0x20
++ __u8 fpf; /* 0x0060 */
+ #define ECB_GS 0x40
+ #define ECB_TE 0x10
+ #define ECB_SRSI 0x04
+--- a/arch/s390/include/uapi/asm/kvm.h
++++ b/arch/s390/include/uapi/asm/kvm.h
+@@ -228,6 +228,7 @@ struct kvm_guest_debug_arch {
+ #define KVM_SYNC_RICCB (1UL << 7)
+ #define KVM_SYNC_FPRS (1UL << 8)
+ #define KVM_SYNC_GSCB (1UL << 9)
++#define KVM_SYNC_BPBC (1UL << 10)
+ /* length and alignment of the sdnx as a power of two */
+ #define SDNXC 8
+ #define SDNXL (1UL << SDNXC)
+@@ -251,7 +252,9 @@ struct kvm_sync_regs {
+ };
+ __u8 reserved[512]; /* for future vector expansion */
+ __u32 fpc; /* valid on KVM_SYNC_VRS or KVM_SYNC_FPRS */
+- __u8 padding1[52]; /* riccb needs to be 64byte aligned */
++ __u8 bpbc : 1; /* bp mode */
++ __u8 reserved2 : 7;
++ __u8 padding1[51]; /* riccb needs to be 64byte aligned */
+ __u8 riccb[64]; /* runtime instrumentation controls block */
+ __u8 padding2[192]; /* sdnx needs to be 256byte aligned */
+ union {
+--- a/arch/s390/kvm/kvm-s390.c
++++ b/arch/s390/kvm/kvm-s390.c
+@@ -449,6 +449,9 @@ int kvm_vm_ioctl_check_extension(struct
+ case KVM_CAP_S390_GS:
+ r = test_facility(133);
+ break;
++ case KVM_CAP_S390_BPB:
++ r = test_facility(82);
++ break;
+ default:
+ r = 0;
+ }
+@@ -2231,6 +2234,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *
+ kvm_s390_set_prefix(vcpu, 0);
+ if (test_kvm_facility(vcpu->kvm, 64))
+ vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB;
++ if (test_kvm_facility(vcpu->kvm, 82))
++ vcpu->run->kvm_valid_regs |= KVM_SYNC_BPBC;
+ if (test_kvm_facility(vcpu->kvm, 133))
+ vcpu->run->kvm_valid_regs |= KVM_SYNC_GSCB;
+ /* fprs can be synchronized via vrs, even if the guest has no vx. With
+@@ -2372,6 +2377,7 @@ static void kvm_s390_vcpu_initial_reset(
+ current->thread.fpu.fpc = 0;
+ vcpu->arch.sie_block->gbea = 1;
+ vcpu->arch.sie_block->pp = 0;
++ vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
+ vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
+ kvm_clear_async_pf_completion_queue(vcpu);
+ if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
+@@ -3318,6 +3324,11 @@ static void sync_regs(struct kvm_vcpu *v
+ vcpu->arch.sie_block->ecd |= ECD_HOSTREGMGMT;
+ vcpu->arch.gs_enabled = 1;
+ }
++ if ((kvm_run->kvm_dirty_regs & KVM_SYNC_BPBC) &&
++ test_kvm_facility(vcpu->kvm, 82)) {
++ vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
++ vcpu->arch.sie_block->fpf |= kvm_run->s.regs.bpbc ? FPF_BPBC : 0;
++ }
+ save_access_regs(vcpu->arch.host_acrs);
+ restore_access_regs(vcpu->run->s.regs.acrs);
+ /* save host (userspace) fprs/vrs */
+@@ -3364,6 +3375,7 @@ static void store_regs(struct kvm_vcpu *
+ kvm_run->s.regs.pft = vcpu->arch.pfault_token;
+ kvm_run->s.regs.pfs = vcpu->arch.pfault_select;
+ kvm_run->s.regs.pfc = vcpu->arch.pfault_compare;
++ kvm_run->s.regs.bpbc = (vcpu->arch.sie_block->fpf & FPF_BPBC) == FPF_BPBC;
+ save_access_regs(vcpu->run->s.regs.acrs);
+ restore_access_regs(vcpu->arch.host_acrs);
+ /* Save guest register state */
+--- a/arch/s390/kvm/vsie.c
++++ b/arch/s390/kvm/vsie.c
+@@ -234,6 +234,12 @@ static void unshadow_scb(struct kvm_vcpu
+ memcpy(scb_o->gcr, scb_s->gcr, 128);
+ scb_o->pp = scb_s->pp;
+
++ /* branch prediction */
++ if (test_kvm_facility(vcpu->kvm, 82)) {
++ scb_o->fpf &= ~FPF_BPBC;
++ scb_o->fpf |= scb_s->fpf & FPF_BPBC;
++ }
++
+ /* interrupt intercept */
+ switch (scb_s->icptcode) {
+ case ICPT_PROGI:
+@@ -280,6 +286,7 @@ static int shadow_scb(struct kvm_vcpu *v
+ scb_s->ecb3 = 0;
+ scb_s->ecd = 0;
+ scb_s->fac = 0;
++ scb_s->fpf = 0;
+
+ rc = prepare_cpuflags(vcpu, vsie_page);
+ if (rc)
+@@ -339,6 +346,9 @@ static int shadow_scb(struct kvm_vcpu *v
+ prefix_unmapped(vsie_page);
+ scb_s->ecb |= ECB_TE;
+ }
++ /* branch prediction */
++ if (test_kvm_facility(vcpu->kvm, 82))
++ scb_s->fpf |= scb_o->fpf & FPF_BPBC;
+ /* SIMD */
+ if (test_kvm_facility(vcpu->kvm, 129)) {
+ scb_s->eca |= scb_o->eca & ECA_VX;
+--- a/include/uapi/linux/kvm.h
++++ b/include/uapi/linux/kvm.h
+@@ -931,6 +931,7 @@ struct kvm_ppc_resize_hpt {
+ #define KVM_CAP_PPC_SMT_POSSIBLE 147
+ #define KVM_CAP_HYPERV_SYNIC2 148
+ #define KVM_CAP_HYPERV_VP_INDEX 149
++#define KVM_CAP_S390_BPB 152
+
+ #ifdef KVM_CAP_IRQ_ROUTING
+
--- /dev/null
+From foo@baz Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:39 +0200
+Subject: s390: add automatic detection of the spectre defense
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-16-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
+@@ -575,7 +575,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
+@@ -87,7 +87,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
+@@ -1,6 +1,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
+@@ -172,7 +172,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;
+ }
+@@ -331,8 +331,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 +
+@@ -453,7 +452,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 +
+@@ -480,11 +479,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
+@@ -11,10 +11,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);
+@@ -28,31 +35,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);
+@@ -105,15 +127,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);
+ }
+
+@@ -121,8 +137,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 Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:29 +0200
+Subject: s390: add optimized array_index_mask_nospec
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-6-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+
+[ Upstream commit e2dd833389cc4069a96b57bdd24227b5f52288f5 ]
+
+Add an optimized version of the array_index_mask_nospec function for
+s390 based on a compare and a subtract with borrow.
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/include/asm/barrier.h | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+--- a/arch/s390/include/asm/barrier.h
++++ b/arch/s390/include/asm/barrier.h
+@@ -49,6 +49,30 @@ do { \
+ #define __smp_mb__before_atomic() barrier()
+ #define __smp_mb__after_atomic() barrier()
+
++/**
++ * array_index_mask_nospec - generate a mask for array_idx() that is
++ * ~0UL when the bounds check succeeds and 0 otherwise
++ * @index: array element index
++ * @size: number of elements in array
++ */
++#define array_index_mask_nospec array_index_mask_nospec
++static inline unsigned long array_index_mask_nospec(unsigned long index,
++ unsigned long size)
++{
++ unsigned long mask;
++
++ if (__builtin_constant_p(size) && size > 0) {
++ asm(" clgr %2,%1\n"
++ " slbgr %0,%0\n"
++ :"=d" (mask) : "d" (size-1), "d" (index) :"cc");
++ return mask;
++ }
++ asm(" clgr %1,%2\n"
++ " slbgr %0,%0\n"
++ :"=d" (mask) : "d" (size), "d" (index) :"cc");
++ return ~mask;
++}
++
+ #include <asm-generic/barrier.h>
+
+ #endif /* __ASM_BARRIER_H */
--- /dev/null
+From foo@baz Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:31 +0200
+Subject: s390: add options to change branch prediction behaviour for the kernel
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-8-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+
+[ Upstream commit d768bd892fc8f066cd3aa000eb1867bcf32db0ee ]
+
+Add the PPA instruction to the system entry and exit path to switch
+the kernel to a different branch prediction behaviour. The instructions
+are added via CPU alternatives and can be disabled with the "nospec"
+or the "nobp=0" kernel parameter. If the default behaviour selected
+with CONFIG_KERNEL_NOBP is set to "n" then the "nobp=1" parameter can be
+used to enable the changed kernel branch prediction.
+
+Acked-by: Cornelia Huck <cohuck@redhat.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/Kconfig | 17 +++++++++++++
+ arch/s390/include/asm/processor.h | 1
+ arch/s390/kernel/alternative.c | 23 ++++++++++++++++++
+ arch/s390/kernel/early.c | 2 +
+ arch/s390/kernel/entry.S | 48 ++++++++++++++++++++++++++++++++++++++
+ arch/s390/kernel/ipl.c | 1
+ arch/s390/kernel/smp.c | 2 +
+ 7 files changed, 94 insertions(+)
+
+--- a/arch/s390/Kconfig
++++ b/arch/s390/Kconfig
+@@ -538,6 +538,23 @@ config ARCH_RANDOM
+
+ If unsure, say Y.
+
++config KERNEL_NOBP
++ def_bool n
++ prompt "Enable modified branch prediction for the kernel by default"
++ help
++ If this option is selected the kernel will switch to a modified
++ branch prediction mode if the firmware interface is available.
++ The modified branch prediction mode improves the behaviour in
++ regard to speculative execution.
++
++ With the option enabled the kernel parameter "nobp=0" or "nospec"
++ can be used to run the kernel in the normal branch prediction mode.
++
++ With the option disabled the modified branch prediction mode is
++ enabled with the "nobp=1" kernel parameter.
++
++ If unsure, say N.
++
+ endmenu
+
+ menu "Memory setup"
+--- a/arch/s390/include/asm/processor.h
++++ b/arch/s390/include/asm/processor.h
+@@ -89,6 +89,7 @@ void cpu_detect_mhz_feature(void);
+ extern const struct seq_operations cpuinfo_op;
+ extern int sysctl_ieee_emulation_warnings;
+ extern void execve_tail(void);
++extern void __bpon(void);
+
+ /*
+ * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
+--- a/arch/s390/kernel/alternative.c
++++ b/arch/s390/kernel/alternative.c
+@@ -14,6 +14,29 @@ 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/early.c
++++ b/arch/s390/kernel/early.c
+@@ -332,6 +332,8 @@ static noinline __init void setup_facili
+ memcpy(S390_lowcore.alt_stfle_fac_list,
+ S390_lowcore.stfle_fac_list,
+ sizeof(S390_lowcore.alt_stfle_fac_list));
++ if (!IS_ENABLED(CONFIG_KERNEL_NOBP))
++ __clear_facility(82, S390_lowcore.alt_stfle_fac_list);
+ }
+
+ static __init void detect_diag9c(void)
+--- a/arch/s390/kernel/entry.S
++++ b/arch/s390/kernel/entry.S
+@@ -158,6 +158,34 @@ _PIF_WORK = (_PIF_PER_TRAP | _PIF_SYSCAL
+ tm off+\addr, \mask
+ .endm
+
++ .macro BPOFF
++ .pushsection .altinstr_replacement, "ax"
++660: .long 0xb2e8c000
++ .popsection
++661: .long 0x47000000
++ .pushsection .altinstructions, "a"
++ .long 661b - .
++ .long 660b - .
++ .word 82
++ .byte 4
++ .byte 4
++ .popsection
++ .endm
++
++ .macro BPON
++ .pushsection .altinstr_replacement, "ax"
++662: .long 0xb2e8d000
++ .popsection
++663: .long 0x47000000
++ .pushsection .altinstructions, "a"
++ .long 663b - .
++ .long 662b - .
++ .word 82
++ .byte 4
++ .byte 4
++ .popsection
++ .endm
++
+ .section .kprobes.text, "ax"
+ .Ldummy:
+ /*
+@@ -170,6 +198,11 @@ _PIF_WORK = (_PIF_PER_TRAP | _PIF_SYSCAL
+ */
+ nop 0
+
++ENTRY(__bpon)
++ .globl __bpon
++ BPON
++ br %r14
++
+ /*
+ * Scheduler resume function, called by switch_to
+ * gpr2 = (task_struct *) prev
+@@ -226,8 +259,11 @@ ENTRY(sie64a)
+ jnz .Lsie_skip
+ TSTMSK __LC_CPU_FLAGS,_CIF_FPU
+ jo .Lsie_skip # exit if fp/vx regs changed
++ BPON
+ .Lsie_entry:
+ sie 0(%r14)
++.Lsie_exit:
++ BPOFF
+ .Lsie_skip:
+ ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE
+ lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
+@@ -279,6 +315,7 @@ ENTRY(system_call)
+ stpt __LC_SYNC_ENTER_TIMER
+ .Lsysc_stmg:
+ stmg %r8,%r15,__LC_SAVE_AREA_SYNC
++ BPOFF
+ lg %r12,__LC_CURRENT
+ lghi %r13,__TASK_thread
+ lghi %r14,_PIF_SYSCALL
+@@ -325,6 +362,7 @@ ENTRY(system_call)
+ jnz .Lsysc_work # check for work
+ TSTMSK __LC_CPU_FLAGS,_CIF_WORK
+ jnz .Lsysc_work
++ BPON
+ .Lsysc_restore:
+ lg %r14,__LC_VDSO_PER_CPU
+ lmg %r0,%r10,__PT_R0(%r11)
+@@ -522,6 +560,7 @@ ENTRY(kernel_thread_starter)
+
+ ENTRY(pgm_check_handler)
+ stpt __LC_SYNC_ENTER_TIMER
++ BPOFF
+ stmg %r8,%r15,__LC_SAVE_AREA_SYNC
+ lg %r10,__LC_LAST_BREAK
+ lg %r12,__LC_CURRENT
+@@ -626,6 +665,7 @@ ENTRY(pgm_check_handler)
+ ENTRY(io_int_handler)
+ STCK __LC_INT_CLOCK
+ stpt __LC_ASYNC_ENTER_TIMER
++ BPOFF
+ stmg %r8,%r15,__LC_SAVE_AREA_ASYNC
+ lg %r12,__LC_CURRENT
+ larl %r13,cleanup_critical
+@@ -676,9 +716,13 @@ ENTRY(io_int_handler)
+ lg %r14,__LC_VDSO_PER_CPU
+ lmg %r0,%r10,__PT_R0(%r11)
+ mvc __LC_RETURN_PSW(16),__PT_PSW(%r11)
++ tm __PT_PSW+1(%r11),0x01 # returning to user ?
++ jno .Lio_exit_kernel
++ BPON
+ .Lio_exit_timer:
+ stpt __LC_EXIT_TIMER
+ mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
++.Lio_exit_kernel:
+ lmg %r11,%r15,__PT_R11(%r11)
+ lpswe __LC_RETURN_PSW
+ .Lio_done:
+@@ -841,6 +885,7 @@ ENTRY(io_int_handler)
+ ENTRY(ext_int_handler)
+ STCK __LC_INT_CLOCK
+ stpt __LC_ASYNC_ENTER_TIMER
++ BPOFF
+ stmg %r8,%r15,__LC_SAVE_AREA_ASYNC
+ lg %r12,__LC_CURRENT
+ larl %r13,cleanup_critical
+@@ -889,6 +934,7 @@ ENTRY(psw_idle)
+ .Lpsw_idle_stcctm:
+ #endif
+ oi __LC_CPU_FLAGS+7,_CIF_ENABLED_WAIT
++ BPON
+ STCK __CLOCK_IDLE_ENTER(%r2)
+ stpt __TIMER_IDLE_ENTER(%r2)
+ .Lpsw_idle_lpsw:
+@@ -989,6 +1035,7 @@ load_fpu_regs:
+ */
+ ENTRY(mcck_int_handler)
+ STCK __LC_MCCK_CLOCK
++ BPOFF
+ la %r1,4095 # revalidate r1
+ spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer
+ lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
+@@ -1054,6 +1101,7 @@ ENTRY(mcck_int_handler)
+ mvc __LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW
+ tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
+ jno 0f
++ BPON
+ stpt __LC_EXIT_TIMER
+ mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
+ 0: lmg %r11,%r15,__PT_R11(%r11)
+--- a/arch/s390/kernel/ipl.c
++++ b/arch/s390/kernel/ipl.c
+@@ -564,6 +564,7 @@ static struct kset *ipl_kset;
+
+ static void __ipl_run(void *unused)
+ {
++ __bpon();
+ diag308(DIAG308_LOAD_CLEAR, NULL);
+ if (MACHINE_IS_VM)
+ __cpcmd("IPL", NULL, 0, NULL);
+--- a/arch/s390/kernel/smp.c
++++ b/arch/s390/kernel/smp.c
+@@ -334,6 +334,7 @@ static void pcpu_delegate(struct pcpu *p
+ mem_assign_absolute(lc->restart_fn, (unsigned long) func);
+ mem_assign_absolute(lc->restart_data, (unsigned long) data);
+ mem_assign_absolute(lc->restart_source, source_cpu);
++ __bpon();
+ asm volatile(
+ "0: sigp 0,%0,%2 # sigp restart to target cpu\n"
+ " brc 2,0b # busy, try again\n"
+@@ -909,6 +910,7 @@ void __cpu_die(unsigned int cpu)
+ void __noreturn cpu_die(void)
+ {
+ idle_task_exit();
++ __bpon();
+ pcpu_sigp_retry(pcpu_devices + smp_processor_id(), SIGP_STOP, 0);
+ for (;;) ;
+ }
--- /dev/null
+From foo@baz Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:41 +0200
+Subject: s390: add sysfs attributes for spectre
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-18-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
+@@ -121,6 +121,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/facility.h>
+ #include <asm/nospec-branch.h>
+
+@@ -43,6 +44,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 Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:30 +0200
+Subject: s390/alternative: use a copy of the facility bit mask
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-7-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+
+[ Upstream commit cf1489984641369611556bf00c48f945c77bcf02 ]
+
+To be able to switch off specific CPU alternatives with kernel parameters
+make a copy of the facility bit mask provided by STFLE and use the copy
+for the decision to apply an alternative.
+
+Reviewed-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Cornelia Huck <cohuck@redhat.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/include/asm/facility.h | 18 ++++++++++++++++++
+ arch/s390/include/asm/lowcore.h | 3 ++-
+ arch/s390/kernel/alternative.c | 3 ++-
+ arch/s390/kernel/early.c | 3 +++
+ arch/s390/kernel/setup.c | 4 +++-
+ arch/s390/kernel/smp.c | 4 +++-
+ 6 files changed, 31 insertions(+), 4 deletions(-)
+
+--- a/arch/s390/include/asm/facility.h
++++ b/arch/s390/include/asm/facility.h
+@@ -15,6 +15,24 @@
+
+ #define MAX_FACILITY_BIT (sizeof(((struct lowcore *)0)->stfle_fac_list) * 8)
+
++static inline void __set_facility(unsigned long nr, void *facilities)
++{
++ unsigned char *ptr = (unsigned char *) facilities;
++
++ if (nr >= MAX_FACILITY_BIT)
++ return;
++ ptr[nr >> 3] |= 0x80 >> (nr & 7);
++}
++
++static inline void __clear_facility(unsigned long nr, void *facilities)
++{
++ unsigned char *ptr = (unsigned char *) facilities;
++
++ if (nr >= MAX_FACILITY_BIT)
++ return;
++ ptr[nr >> 3] &= ~(0x80 >> (nr & 7));
++}
++
+ static inline int __test_facility(unsigned long nr, void *facilities)
+ {
+ unsigned char *ptr;
+--- a/arch/s390/include/asm/lowcore.h
++++ b/arch/s390/include/asm/lowcore.h
+@@ -155,7 +155,8 @@ struct lowcore {
+ __u8 pad_0x0e20[0x0f00-0x0e20]; /* 0x0e20 */
+
+ /* Extended facility list */
+- __u64 stfle_fac_list[32]; /* 0x0f00 */
++ __u64 stfle_fac_list[16]; /* 0x0f00 */
++ __u64 alt_stfle_fac_list[16]; /* 0x0f80 */
+ __u8 pad_0x1000[0x11b0-0x1000]; /* 0x1000 */
+
+ /* Pointer to the machine check extended save area */
+--- a/arch/s390/kernel/alternative.c
++++ b/arch/s390/kernel/alternative.c
+@@ -74,7 +74,8 @@ static void __init_or_module __apply_alt
+ instr = (u8 *)&a->instr_offset + a->instr_offset;
+ replacement = (u8 *)&a->repl_offset + a->repl_offset;
+
+- if (!test_facility(a->facility))
++ if (!__test_facility(a->facility,
++ S390_lowcore.alt_stfle_fac_list))
+ continue;
+
+ if (unlikely(a->instrlen % 2 || a->replacementlen % 2)) {
+--- a/arch/s390/kernel/early.c
++++ b/arch/s390/kernel/early.c
+@@ -329,6 +329,9 @@ static noinline __init void setup_facili
+ {
+ stfle(S390_lowcore.stfle_fac_list,
+ ARRAY_SIZE(S390_lowcore.stfle_fac_list));
++ memcpy(S390_lowcore.alt_stfle_fac_list,
++ S390_lowcore.stfle_fac_list,
++ sizeof(S390_lowcore.alt_stfle_fac_list));
+ }
+
+ static __init void detect_diag9c(void)
+--- a/arch/s390/kernel/setup.c
++++ b/arch/s390/kernel/setup.c
+@@ -339,7 +339,9 @@ static void __init setup_lowcore(void)
+ lc->preempt_count = S390_lowcore.preempt_count;
+ lc->stfl_fac_list = S390_lowcore.stfl_fac_list;
+ memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
+- MAX_FACILITY_BIT/8);
++ sizeof(lc->stfle_fac_list));
++ memcpy(lc->alt_stfle_fac_list, S390_lowcore.alt_stfle_fac_list,
++ sizeof(lc->alt_stfle_fac_list));
+ if (MACHINE_HAS_VX || MACHINE_HAS_GS) {
+ unsigned long bits, size;
+
+--- a/arch/s390/kernel/smp.c
++++ b/arch/s390/kernel/smp.c
+@@ -282,7 +282,9 @@ static void pcpu_prepare_secondary(struc
+ __ctl_store(lc->cregs_save_area, 0, 15);
+ save_access_regs((unsigned int *) lc->access_regs_save_area);
+ memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
+- MAX_FACILITY_BIT/8);
++ sizeof(lc->stfle_fac_list));
++ memcpy(lc->alt_stfle_fac_list, S390_lowcore.alt_stfle_fac_list,
++ sizeof(lc->alt_stfle_fac_list));
+ }
+
+ static void pcpu_attach_task(struct pcpu *pcpu, struct task_struct *tsk)
--- /dev/null
+From foo@baz Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:43 +0200
+Subject: s390: correct module section names for expoline code revert
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-20-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
+@@ -478,11 +478,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 Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:42 +0200
+Subject: s390: correct nospec auto detection init order
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-19-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
+@@ -73,7 +73,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)) {
+ /*
+@@ -88,11 +88,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)
+ {
+@@ -103,7 +99,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
+@@ -897,6 +897,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 Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:36 +0200
+Subject: s390: do not bypass BPENTER for interrupt system calls
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-13-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+
+[ Upstream commit d5feec04fe578c8dbd9e2e1439afc2f0af761ed4 ]
+
+The system call path can be interrupted before the switch back to the
+standard branch prediction with BPENTER has been done. The critical
+section cleanup code skips forward to .Lsysc_do_svc and bypasses the
+BPENTER. In this case the kernel and all subsequent code will run with
+the limited branch prediction.
+
+Fixes: eacf67eb9b32 ("s390: run user space and KVM guests with modified branch prediction")
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kernel/entry.S | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/s390/kernel/entry.S
++++ b/arch/s390/kernel/entry.S
+@@ -1375,6 +1375,7 @@ cleanup_critical:
+ stg %r15,__LC_SYSTEM_TIMER
+ 0: # update accounting time stamp
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
++ BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
+ # set up saved register r11
+ lg %r15,__LC_KERNEL_STACK
+ la %r9,STACK_FRAME_OVERHEAD(%r15)
--- /dev/null
+From foo@baz Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:26 +0200
+Subject: s390: enable CPU alternatives unconditionally
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-3-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+
+From: Heiko Carstens <heiko.carstens@de.ibm.com>
+
+[ Upstream commit 049a2c2d486e8cc82c5cd79fa479c5b105b109e9 ]
+
+Remove the CPU_ALTERNATIVES config option and enable the code
+unconditionally. The config option was only added to avoid a conflict
+with the named saved segment support. Since that code is gone there is
+no reason to keep the CPU_ALTERNATIVES config option.
+
+Just enable it unconditionally to also reduce the number of config
+options and make it less likely that something breaks.
+
+Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/Kconfig | 16 ----------------
+ arch/s390/include/asm/alternative.h | 20 +++-----------------
+ arch/s390/kernel/Makefile | 3 +--
+ arch/s390/kernel/module.c | 15 ++++++---------
+ 4 files changed, 10 insertions(+), 44 deletions(-)
+
+--- a/arch/s390/Kconfig
++++ b/arch/s390/Kconfig
+@@ -538,22 +538,6 @@ config ARCH_RANDOM
+
+ If unsure, say Y.
+
+-config ALTERNATIVES
+- def_bool y
+- prompt "Patch optimized instructions for running CPU type"
+- help
+- When enabled the kernel code is compiled with additional
+- alternative instructions blocks optimized for newer CPU types.
+- These alternative instructions blocks are patched at kernel boot
+- time when running CPU supports them. This mechanism is used to
+- optimize some critical code paths (i.e. spinlocks) for newer CPUs
+- even if kernel is build to support older machine generations.
+-
+- This mechanism could be disabled by appending "noaltinstr"
+- option to the kernel command line.
+-
+- If unsure, say Y.
+-
+ endmenu
+
+ menu "Memory setup"
+--- a/arch/s390/include/asm/alternative.h
++++ b/arch/s390/include/asm/alternative.h
+@@ -15,14 +15,9 @@ struct alt_instr {
+ u8 replacementlen; /* length of new instruction */
+ } __packed;
+
+-#ifdef CONFIG_ALTERNATIVES
+-extern void apply_alternative_instructions(void);
+-extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
+-#else
+-static inline void apply_alternative_instructions(void) {};
+-static inline void apply_alternatives(struct alt_instr *start,
+- struct alt_instr *end) {};
+-#endif
++void apply_alternative_instructions(void);
++void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
++
+ /*
+ * |661: |662: |6620 |663:
+ * +-----------+---------------------+
+@@ -109,7 +104,6 @@ static inline void apply_alternatives(st
+ b_altinstr(num)":\n\t" altinstr "\n" e_altinstr(num) ":\n" \
+ INSTR_LEN_SANITY_CHECK(altinstr_len(num))
+
+-#ifdef CONFIG_ALTERNATIVES
+ /* alternative assembly primitive: */
+ #define ALTERNATIVE(oldinstr, altinstr, facility) \
+ ".pushsection .altinstr_replacement, \"ax\"\n" \
+@@ -130,14 +124,6 @@ static inline void apply_alternatives(st
+ ALTINSTR_ENTRY(facility1, 1) \
+ ALTINSTR_ENTRY(facility2, 2) \
+ ".popsection\n"
+-#else
+-/* Alternative instructions are disabled, let's put just oldinstr in */
+-#define ALTERNATIVE(oldinstr, altinstr, facility) \
+- oldinstr "\n"
+-
+-#define ALTERNATIVE_2(oldinstr, altinstr1, facility1, altinstr2, facility2) \
+- oldinstr "\n"
+-#endif
+
+ /*
+ * Alternative instructions for different CPU types or capabilities.
+--- a/arch/s390/kernel/Makefile
++++ b/arch/s390/kernel/Makefile
+@@ -57,7 +57,7 @@ obj-y += processor.o sys_s390.o ptrace.o
+ obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o als.o
+ 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
+-obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o
++obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o alternative.o
+
+ extra-y += head.o head64.o vmlinux.lds
+
+@@ -75,7 +75,6 @@ obj-$(CONFIG_KPROBES) += kprobes.o
+ obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
+ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
+ obj-$(CONFIG_UPROBES) += uprobes.o
+-obj-$(CONFIG_ALTERNATIVES) += alternative.o
+
+ obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o perf_cpum_sf.o
+ obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o
+--- a/arch/s390/kernel/module.c
++++ b/arch/s390/kernel/module.c
+@@ -433,16 +433,13 @@ int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *s;
+ char *secstrings;
+
+- if (IS_ENABLED(CONFIG_ALTERNATIVES)) {
+- secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+- for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+- if (!strcmp(".altinstructions",
+- secstrings + s->sh_name)) {
+- /* patch .altinstructions */
+- void *aseg = (void *)s->sh_addr;
++ secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
++ for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
++ if (!strcmp(".altinstructions", secstrings + s->sh_name)) {
++ /* patch .altinstructions */
++ void *aseg = (void *)s->sh_addr;
+
+- apply_alternatives(aseg, aseg + s->sh_size);
+- }
++ apply_alternatives(aseg, aseg + s->sh_size);
+ }
+ }
+
--- /dev/null
+From foo@baz Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:37 +0200
+Subject: s390/entry.S: fix spurious zeroing of r0
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-14-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+
+From: Christian Borntraeger <borntraeger@de.ibm.com>
+
+[ Upstream commit d3f468963cd6fd6d2aa5e26aed8b24232096d0e1 ]
+
+when a system call is interrupted we might call the critical section
+cleanup handler that re-does some of the operations. When we are between
+.Lsysc_vtime and .Lsysc_do_svc we might also redo the saving of the
+problem state registers r0-r7:
+
+.Lcleanup_system_call:
+[...]
+0: # update accounting time stamp
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+ # set up saved register r11
+ lg %r15,__LC_KERNEL_STACK
+ la %r9,STACK_FRAME_OVERHEAD(%r15)
+ stg %r9,24(%r11) # r11 pt_regs pointer
+ # fill pt_regs
+ mvc __PT_R8(64,%r9),__LC_SAVE_AREA_SYNC
+---> stmg %r0,%r7,__PT_R0(%r9)
+
+The problem is now, that we might have already zeroed out r0.
+The fix is to move the zeroing of r0 after sysc_do_svc.
+
+Reported-by: Farhan Ali <alifm@linux.vnet.ibm.com>
+Fixes: 7041d28115e91 ("s390: scrub registers on kernel entry and KVM exit")
+Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kernel/entry.S | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/s390/kernel/entry.S
++++ b/arch/s390/kernel/entry.S
+@@ -426,13 +426,13 @@ ENTRY(system_call)
+ UPDATE_VTIME %r8,%r9,__LC_SYNC_ENTER_TIMER
+ BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
+ stmg %r0,%r7,__PT_R0(%r11)
+- # clear user controlled register to prevent speculative use
+- xgr %r0,%r0
+ mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
+ mvc __PT_PSW(16,%r11),__LC_SVC_OLD_PSW
+ mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC
+ stg %r14,__PT_FLAGS(%r11)
+ .Lsysc_do_svc:
++ # clear user controlled register to prevent speculative use
++ xgr %r0,%r0
+ # load address of system call table
+ lg %r10,__THREAD_sysc_table(%r13,%r12)
+ llgh %r8,__PT_INT_CODE+2(%r11)
--- /dev/null
+From foo@baz Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:25 +0200
+Subject: s390: introduce CPU alternatives
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-2-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+
+From: Vasily Gorbik <gor@linux.vnet.ibm.com>
+
+[ Upstream commit 686140a1a9c41d85a4212a1c26d671139b76404b ]
+
+Implement CPU alternatives, which allows to optionally patch newer
+instructions at runtime, based on CPU facilities availability.
+
+A new kernel boot parameter "noaltinstr" disables patching.
+
+Current implementation is derived from x86 alternatives. Although
+ideal instructions padding (when altinstr is longer then oldinstr)
+is added at compile time, and no oldinstr nops optimization has to be
+done at runtime. Also couple of compile time sanity checks are done:
+1. oldinstr and altinstr must be <= 254 bytes long,
+2. oldinstr and altinstr must not have an odd length.
+
+alternative(oldinstr, altinstr, facility);
+alternative_2(oldinstr, altinstr1, facility1, altinstr2, facility2);
+
+Both compile time and runtime padding consists of either 6/4/2 bytes nop
+or a jump (brcl) + 2 bytes nop filler if padding is longer then 6 bytes.
+
+.altinstructions and .altinstr_replacement sections are part of
+__init_begin : __init_end region and are freed after initialization.
+
+Signed-off-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>
+---
+ Documentation/admin-guide/kernel-parameters.txt | 3
+ arch/s390/Kconfig | 17 ++
+ arch/s390/include/asm/alternative.h | 163 ++++++++++++++++++++++++
+ arch/s390/kernel/Makefile | 1
+ arch/s390/kernel/alternative.c | 110 ++++++++++++++++
+ arch/s390/kernel/module.c | 17 ++
+ arch/s390/kernel/setup.c | 3
+ arch/s390/kernel/vmlinux.lds.S | 23 +++
+ 8 files changed, 337 insertions(+)
+ create mode 100644 arch/s390/include/asm/alternative.h
+ create mode 100644 arch/s390/kernel/alternative.c
+
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -2541,6 +2541,9 @@
+
+ noalign [KNL,ARM]
+
++ noaltinstr [S390] Disables alternative instructions patching
++ (CPU alternatives feature).
++
+ noapic [SMP,APIC] Tells the kernel to not make use of any
+ IOAPICs that may be present in the system.
+
+--- a/arch/s390/Kconfig
++++ b/arch/s390/Kconfig
+@@ -538,6 +538,22 @@ config ARCH_RANDOM
+
+ If unsure, say Y.
+
++config ALTERNATIVES
++ def_bool y
++ prompt "Patch optimized instructions for running CPU type"
++ help
++ When enabled the kernel code is compiled with additional
++ alternative instructions blocks optimized for newer CPU types.
++ These alternative instructions blocks are patched at kernel boot
++ time when running CPU supports them. This mechanism is used to
++ optimize some critical code paths (i.e. spinlocks) for newer CPUs
++ even if kernel is build to support older machine generations.
++
++ This mechanism could be disabled by appending "noaltinstr"
++ option to the kernel command line.
++
++ If unsure, say Y.
++
+ endmenu
+
+ menu "Memory setup"
+@@ -812,6 +828,7 @@ config PFAULT
+ config SHARED_KERNEL
+ bool "VM shared kernel support"
+ depends on !JUMP_LABEL
++ depends on !ALTERNATIVES
+ help
+ Select this option, if you want to share the text segment of the
+ Linux kernel between different VM guests. This reduces memory
+--- /dev/null
++++ b/arch/s390/include/asm/alternative.h
+@@ -0,0 +1,163 @@
++#ifndef _ASM_S390_ALTERNATIVE_H
++#define _ASM_S390_ALTERNATIVE_H
++
++#ifndef __ASSEMBLY__
++
++#include <linux/types.h>
++#include <linux/stddef.h>
++#include <linux/stringify.h>
++
++struct alt_instr {
++ s32 instr_offset; /* original instruction */
++ s32 repl_offset; /* offset to replacement instruction */
++ u16 facility; /* facility bit set for replacement */
++ u8 instrlen; /* length of original instruction */
++ u8 replacementlen; /* length of new instruction */
++} __packed;
++
++#ifdef CONFIG_ALTERNATIVES
++extern void apply_alternative_instructions(void);
++extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
++#else
++static inline void apply_alternative_instructions(void) {};
++static inline void apply_alternatives(struct alt_instr *start,
++ struct alt_instr *end) {};
++#endif
++/*
++ * |661: |662: |6620 |663:
++ * +-----------+---------------------+
++ * | oldinstr | oldinstr_padding |
++ * | +----------+----------+
++ * | | | |
++ * | | >6 bytes |6/4/2 nops|
++ * | |6 bytes jg----------->
++ * +-----------+---------------------+
++ * ^^ static padding ^^
++ *
++ * .altinstr_replacement section
++ * +---------------------+-----------+
++ * |6641: |6651:
++ * | alternative instr 1 |
++ * +-----------+---------+- - - - - -+
++ * |6642: |6652: |
++ * | alternative instr 2 | padding
++ * +---------------------+- - - - - -+
++ * ^ runtime ^
++ *
++ * .altinstructions section
++ * +---------------------------------+
++ * | alt_instr entries for each |
++ * | alternative instr |
++ * +---------------------------------+
++ */
++
++#define b_altinstr(num) "664"#num
++#define e_altinstr(num) "665"#num
++
++#define e_oldinstr_pad_end "663"
++#define oldinstr_len "662b-661b"
++#define oldinstr_total_len e_oldinstr_pad_end"b-661b"
++#define altinstr_len(num) e_altinstr(num)"b-"b_altinstr(num)"b"
++#define oldinstr_pad_len(num) \
++ "-(((" altinstr_len(num) ")-(" oldinstr_len ")) > 0) * " \
++ "((" altinstr_len(num) ")-(" oldinstr_len "))"
++
++#define INSTR_LEN_SANITY_CHECK(len) \
++ ".if " len " > 254\n" \
++ "\t.error \"cpu alternatives does not support instructions " \
++ "blocks > 254 bytes\"\n" \
++ ".endif\n" \
++ ".if (" len ") %% 2\n" \
++ "\t.error \"cpu alternatives instructions length is odd\"\n" \
++ ".endif\n"
++
++#define OLDINSTR_PADDING(oldinstr, num) \
++ ".if " oldinstr_pad_len(num) " > 6\n" \
++ "\tjg " e_oldinstr_pad_end "f\n" \
++ "6620:\n" \
++ "\t.fill (" oldinstr_pad_len(num) " - (6620b-662b)) / 2, 2, 0x0700\n" \
++ ".else\n" \
++ "\t.fill " oldinstr_pad_len(num) " / 6, 6, 0xc0040000\n" \
++ "\t.fill " oldinstr_pad_len(num) " %% 6 / 4, 4, 0x47000000\n" \
++ "\t.fill " oldinstr_pad_len(num) " %% 6 %% 4 / 2, 2, 0x0700\n" \
++ ".endif\n"
++
++#define OLDINSTR(oldinstr, num) \
++ "661:\n\t" oldinstr "\n662:\n" \
++ OLDINSTR_PADDING(oldinstr, num) \
++ e_oldinstr_pad_end ":\n" \
++ INSTR_LEN_SANITY_CHECK(oldinstr_len)
++
++#define OLDINSTR_2(oldinstr, num1, num2) \
++ "661:\n\t" oldinstr "\n662:\n" \
++ ".if " altinstr_len(num1) " < " altinstr_len(num2) "\n" \
++ OLDINSTR_PADDING(oldinstr, num2) \
++ ".else\n" \
++ OLDINSTR_PADDING(oldinstr, num1) \
++ ".endif\n" \
++ e_oldinstr_pad_end ":\n" \
++ INSTR_LEN_SANITY_CHECK(oldinstr_len)
++
++#define ALTINSTR_ENTRY(facility, num) \
++ "\t.long 661b - .\n" /* old instruction */ \
++ "\t.long " b_altinstr(num)"b - .\n" /* alt instruction */ \
++ "\t.word " __stringify(facility) "\n" /* facility bit */ \
++ "\t.byte " oldinstr_total_len "\n" /* source len */ \
++ "\t.byte " altinstr_len(num) "\n" /* alt instruction len */
++
++#define ALTINSTR_REPLACEMENT(altinstr, num) /* replacement */ \
++ b_altinstr(num)":\n\t" altinstr "\n" e_altinstr(num) ":\n" \
++ INSTR_LEN_SANITY_CHECK(altinstr_len(num))
++
++#ifdef CONFIG_ALTERNATIVES
++/* alternative assembly primitive: */
++#define ALTERNATIVE(oldinstr, altinstr, facility) \
++ ".pushsection .altinstr_replacement, \"ax\"\n" \
++ ALTINSTR_REPLACEMENT(altinstr, 1) \
++ ".popsection\n" \
++ OLDINSTR(oldinstr, 1) \
++ ".pushsection .altinstructions,\"a\"\n" \
++ ALTINSTR_ENTRY(facility, 1) \
++ ".popsection\n"
++
++#define ALTERNATIVE_2(oldinstr, altinstr1, facility1, altinstr2, facility2)\
++ ".pushsection .altinstr_replacement, \"ax\"\n" \
++ ALTINSTR_REPLACEMENT(altinstr1, 1) \
++ ALTINSTR_REPLACEMENT(altinstr2, 2) \
++ ".popsection\n" \
++ OLDINSTR_2(oldinstr, 1, 2) \
++ ".pushsection .altinstructions,\"a\"\n" \
++ ALTINSTR_ENTRY(facility1, 1) \
++ ALTINSTR_ENTRY(facility2, 2) \
++ ".popsection\n"
++#else
++/* Alternative instructions are disabled, let's put just oldinstr in */
++#define ALTERNATIVE(oldinstr, altinstr, facility) \
++ oldinstr "\n"
++
++#define ALTERNATIVE_2(oldinstr, altinstr1, facility1, altinstr2, facility2) \
++ oldinstr "\n"
++#endif
++
++/*
++ * Alternative instructions for different CPU types or capabilities.
++ *
++ * This allows to use optimized instructions even on generic binary
++ * kernels.
++ *
++ * oldinstr is padded with jump and nops at compile time if altinstr is
++ * longer. altinstr is padded with jump and nops at run-time during patching.
++ *
++ * For non barrier like inlines please define new variants
++ * without volatile and memory clobber.
++ */
++#define alternative(oldinstr, altinstr, facility) \
++ asm volatile(ALTERNATIVE(oldinstr, altinstr, facility) : : : "memory")
++
++#define alternative_2(oldinstr, altinstr1, facility1, altinstr2, facility2) \
++ asm volatile(ALTERNATIVE_2(oldinstr, altinstr1, facility1, \
++ altinstr2, facility2) ::: "memory")
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* _ASM_S390_ALTERNATIVE_H */
+--- a/arch/s390/kernel/Makefile
++++ b/arch/s390/kernel/Makefile
+@@ -75,6 +75,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o
+ obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
+ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
+ obj-$(CONFIG_UPROBES) += uprobes.o
++obj-$(CONFIG_ALTERNATIVES) += alternative.o
+
+ obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o perf_cpum_sf.o
+ obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o
+--- /dev/null
++++ b/arch/s390/kernel/alternative.c
+@@ -0,0 +1,110 @@
++#include <linux/module.h>
++#include <asm/alternative.h>
++#include <asm/facility.h>
++
++#define MAX_PATCH_LEN (255 - 1)
++
++static int __initdata_or_module alt_instr_disabled;
++
++static int __init disable_alternative_instructions(char *str)
++{
++ alt_instr_disabled = 1;
++ return 0;
++}
++
++early_param("noaltinstr", disable_alternative_instructions);
++
++struct brcl_insn {
++ u16 opc;
++ s32 disp;
++} __packed;
++
++static u16 __initdata_or_module nop16 = 0x0700;
++static u32 __initdata_or_module nop32 = 0x47000000;
++static struct brcl_insn __initdata_or_module nop48 = {
++ 0xc004, 0
++};
++
++static const void *nops[] __initdata_or_module = {
++ &nop16,
++ &nop32,
++ &nop48
++};
++
++static void __init_or_module add_jump_padding(void *insns, unsigned int len)
++{
++ struct brcl_insn brcl = {
++ 0xc0f4,
++ len / 2
++ };
++
++ memcpy(insns, &brcl, sizeof(brcl));
++ insns += sizeof(brcl);
++ len -= sizeof(brcl);
++
++ while (len > 0) {
++ memcpy(insns, &nop16, 2);
++ insns += 2;
++ len -= 2;
++ }
++}
++
++static void __init_or_module add_padding(void *insns, unsigned int len)
++{
++ if (len > 6)
++ add_jump_padding(insns, len);
++ else if (len >= 2)
++ memcpy(insns, nops[len / 2 - 1], len);
++}
++
++static void __init_or_module __apply_alternatives(struct alt_instr *start,
++ struct alt_instr *end)
++{
++ struct alt_instr *a;
++ u8 *instr, *replacement;
++ u8 insnbuf[MAX_PATCH_LEN];
++
++ /*
++ * The scan order should be from start to end. A later scanned
++ * alternative code can overwrite previously scanned alternative code.
++ */
++ for (a = start; a < end; a++) {
++ int insnbuf_sz = 0;
++
++ instr = (u8 *)&a->instr_offset + a->instr_offset;
++ replacement = (u8 *)&a->repl_offset + a->repl_offset;
++
++ if (!test_facility(a->facility))
++ continue;
++
++ if (unlikely(a->instrlen % 2 || a->replacementlen % 2)) {
++ WARN_ONCE(1, "cpu alternatives instructions length is "
++ "odd, skipping patching\n");
++ continue;
++ }
++
++ memcpy(insnbuf, replacement, a->replacementlen);
++ insnbuf_sz = a->replacementlen;
++
++ if (a->instrlen > a->replacementlen) {
++ add_padding(insnbuf + a->replacementlen,
++ a->instrlen - a->replacementlen);
++ insnbuf_sz += a->instrlen - a->replacementlen;
++ }
++
++ s390_kernel_write(instr, insnbuf, insnbuf_sz);
++ }
++}
++
++void __init_or_module apply_alternatives(struct alt_instr *start,
++ struct alt_instr *end)
++{
++ if (!alt_instr_disabled)
++ __apply_alternatives(start, end);
++}
++
++extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
++void __init apply_alternative_instructions(void)
++{
++ apply_alternatives(__alt_instructions, __alt_instructions_end);
++}
+--- a/arch/s390/kernel/module.c
++++ b/arch/s390/kernel/module.c
+@@ -31,6 +31,7 @@
+ #include <linux/kernel.h>
+ #include <linux/moduleloader.h>
+ #include <linux/bug.h>
++#include <asm/alternative.h>
+
+ #if 0
+ #define DEBUGP printk
+@@ -429,6 +430,22 @@ int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+ {
++ const Elf_Shdr *s;
++ char *secstrings;
++
++ if (IS_ENABLED(CONFIG_ALTERNATIVES)) {
++ secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
++ for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
++ if (!strcmp(".altinstructions",
++ secstrings + s->sh_name)) {
++ /* patch .altinstructions */
++ void *aseg = (void *)s->sh_addr;
++
++ apply_alternatives(aseg, aseg + s->sh_size);
++ }
++ }
++ }
++
+ jump_label_apply_nops(me);
+ return 0;
+ }
+--- a/arch/s390/kernel/setup.c
++++ b/arch/s390/kernel/setup.c
+@@ -66,6 +66,7 @@
+ #include <asm/sclp.h>
+ #include <asm/sysinfo.h>
+ #include <asm/numa.h>
++#include <asm/alternative.h>
+ #include "entry.h"
+
+ /*
+@@ -955,6 +956,8 @@ void __init setup_arch(char **cmdline_p)
+ conmode_default();
+ set_preferred_console();
+
++ apply_alternative_instructions();
++
+ /* Setup zfcpdump support */
+ setup_zfcpdump();
+
+--- a/arch/s390/kernel/vmlinux.lds.S
++++ b/arch/s390/kernel/vmlinux.lds.S
+@@ -105,6 +105,29 @@ SECTIONS
+ EXIT_DATA
+ }
+
++ /*
++ * struct alt_inst entries. From the header (alternative.h):
++ * "Alternative instructions for different CPU types or capabilities"
++ * Think locking instructions on spinlocks.
++ * Note, that it is a part of __init region.
++ */
++ . = ALIGN(8);
++ .altinstructions : {
++ __alt_instructions = .;
++ *(.altinstructions)
++ __alt_instructions_end = .;
++ }
++
++ /*
++ * And here are the replacement instructions. The linker sticks
++ * them as binary blobs. The .altinstructions has enough data to
++ * get the address and the length of them to patch the kernel safely.
++ * Note, that it is a part of __init region.
++ */
++ .altinstr_replacement : {
++ *(.altinstr_replacement)
++ }
++
+ /* early.c uses stsi, which requires page aligned data. */
+ . = ALIGN(PAGE_SIZE);
+ INIT_DATA_SECTION(0x100)
--- /dev/null
+From foo@baz Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:33 +0200
+Subject: s390: introduce execute-trampolines for branches
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-10-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+
+[ Upstream commit f19fbd5ed642dc31c809596412dab1ed56f2f156 ]
+
+Add CONFIG_EXPOLINE to enable the use of the new -mindirect-branch= and
+-mfunction_return= compiler options to create a kernel fortified against
+the specte v2 attack.
+
+With CONFIG_EXPOLINE=y all indirect branches will be issued with an
+execute type instruction. For z10 or newer the EXRL instruction will
+be used, for older machines the EX instruction. The typical indirect
+call
+
+ basr %r14,%r1
+
+is replaced with a PC relative call to a new thunk
+
+ brasl %r14,__s390x_indirect_jump_r1
+
+The thunk contains the EXRL/EX instruction to the indirect branch
+
+__s390x_indirect_jump_r1:
+ exrl 0,0f
+ j .
+0: br %r1
+
+The detour via the execute type instruction has a performance impact.
+To get rid of the detour the new kernel parameter "nospectre_v2" and
+"spectre_v2=[on,off,auto]" can be used. If the parameter is specified
+the kernel and module code will be patched at runtime.
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/Kconfig | 28 ++++++++
+ arch/s390/Makefile | 10 +++
+ arch/s390/include/asm/lowcore.h | 4 -
+ arch/s390/include/asm/nospec-branch.h | 18 +++++
+ arch/s390/kernel/Makefile | 4 +
+ arch/s390/kernel/entry.S | 113 ++++++++++++++++++++++++++--------
+ arch/s390/kernel/module.c | 62 +++++++++++++++---
+ arch/s390/kernel/nospec-branch.c | 101 ++++++++++++++++++++++++++++++
+ arch/s390/kernel/setup.c | 4 +
+ arch/s390/kernel/smp.c | 1
+ arch/s390/kernel/vmlinux.lds.S | 14 ++++
+ drivers/s390/char/Makefile | 2
+ 12 files changed, 326 insertions(+), 35 deletions(-)
+ create mode 100644 arch/s390/include/asm/nospec-branch.h
+ create mode 100644 arch/s390/kernel/nospec-branch.c
+
+--- a/arch/s390/Kconfig
++++ b/arch/s390/Kconfig
+@@ -555,6 +555,34 @@ config KERNEL_NOBP
+
+ If unsure, say N.
+
++config EXPOLINE
++ def_bool n
++ prompt "Avoid speculative indirect branches in the kernel"
++ help
++ Compile the kernel with the expoline compiler options to guard
++ against kernel-to-user data leaks by avoiding speculative indirect
++ branches.
++ Requires a compiler with -mindirect-branch=thunk support for full
++ protection. The kernel may run slower.
++
++ If unsure, say N.
++
++choice
++ prompt "Expoline default"
++ depends on EXPOLINE
++ default EXPOLINE_FULL
++
++config EXPOLINE_OFF
++ bool "spectre_v2=off"
++
++config EXPOLINE_MEDIUM
++ bool "spectre_v2=auto"
++
++config EXPOLINE_FULL
++ bool "spectre_v2=on"
++
++endchoice
++
+ endmenu
+
+ menu "Memory setup"
+--- a/arch/s390/Makefile
++++ b/arch/s390/Makefile
+@@ -81,6 +81,16 @@ ifeq ($(call cc-option-yn,-mwarn-dynamic
+ cflags-$(CONFIG_WARN_DYNAMIC_STACK) += -mwarn-dynamicstack
+ endif
+
++ifdef CONFIG_EXPOLINE
++ ifeq ($(call cc-option-yn,$(CC_FLAGS_MARCH) -mindirect-branch=thunk),y)
++ CC_FLAGS_EXPOLINE := -mindirect-branch=thunk
++ CC_FLAGS_EXPOLINE += -mfunction-return=thunk
++ CC_FLAGS_EXPOLINE += -mindirect-branch-table
++ export CC_FLAGS_EXPOLINE
++ cflags-y += $(CC_FLAGS_EXPOLINE)
++ endif
++endif
++
+ ifdef CONFIG_FUNCTION_TRACER
+ # make use of hotpatch feature if the compiler supports it
+ cc_hotpatch := -mhotpatch=0,3
+--- a/arch/s390/include/asm/lowcore.h
++++ b/arch/s390/include/asm/lowcore.h
+@@ -140,7 +140,9 @@ struct lowcore {
+ /* Per cpu primary space access list */
+ __u32 paste[16]; /* 0x0400 */
+
+- __u8 pad_0x04c0[0x0e00-0x0440]; /* 0x0440 */
++ /* br %r1 trampoline */
++ __u16 br_r1_trampoline; /* 0x0440 */
++ __u8 pad_0x0442[0x0e00-0x0442]; /* 0x0442 */
+
+ /*
+ * 0xe00 contains the address of the IPL Parameter Information
+--- /dev/null
++++ b/arch/s390/include/asm/nospec-branch.h
+@@ -0,0 +1,18 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _ASM_S390_EXPOLINE_H
++#define _ASM_S390_EXPOLINE_H
++
++#ifndef __ASSEMBLY__
++
++#include <linux/types.h>
++
++extern int nospec_call_disable;
++extern int nospec_return_disable;
++
++void nospec_init_branches(void);
++void nospec_call_revert(s32 *start, s32 *end);
++void nospec_return_revert(s32 *start, s32 *end);
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* _ASM_S390_EXPOLINE_H */
+--- a/arch/s390/kernel/Makefile
++++ b/arch/s390/kernel/Makefile
+@@ -29,6 +29,7 @@ UBSAN_SANITIZE_early.o := n
+ #
+ ifneq ($(CC_FLAGS_MARCH),-march=z900)
+ CFLAGS_REMOVE_als.o += $(CC_FLAGS_MARCH)
++CFLAGS_REMOVE_als.o += $(CC_FLAGS_EXPOLINE)
+ CFLAGS_als.o += -march=z900
+ AFLAGS_REMOVE_head.o += $(CC_FLAGS_MARCH)
+ AFLAGS_head.o += -march=z900
+@@ -61,6 +62,9 @@ obj-y += entry.o reipl.o relocate_kernel
+
+ extra-y += head.o head64.o vmlinux.lds
+
++obj-$(CONFIG_EXPOLINE) += nospec-branch.o
++CFLAGS_REMOVE_expoline.o += $(CC_FLAGS_EXPOLINE)
++
+ obj-$(CONFIG_MODULES) += module.o
+ obj-$(CONFIG_SMP) += smp.o
+ obj-$(CONFIG_SCHED_TOPOLOGY) += topology.o
+--- a/arch/s390/kernel/entry.S
++++ b/arch/s390/kernel/entry.S
+@@ -221,6 +221,68 @@ _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 */
++
++
+ .section .kprobes.text, "ax"
+ .Ldummy:
+ /*
+@@ -236,7 +298,7 @@ _PIF_WORK = (_PIF_PER_TRAP | _PIF_SYSCAL
+ ENTRY(__bpon)
+ .globl __bpon
+ BPON
+- br %r14
++ BR_R1USE_R14
+
+ /*
+ * Scheduler resume function, called by switch_to
+@@ -261,9 +323,9 @@ ENTRY(__switch_to)
+ mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next
+ lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task
+ TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP
+- bzr %r14
++ jz 0f
+ .insn s,0xb2800000,__LC_LPP # set program parameter
+- br %r14
++0: BR_R1USE_R14
+
+ .L__critical_start:
+
+@@ -330,7 +392,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 %r14
++ BR_R1USE_R14
+ .Lsie_fault:
+ lghi %r14,-EFAULT
+ stg %r14,__SF_EMPTY+16(%r15) # set exit reason code
+@@ -389,7 +451,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_R14_R9 # call sys_xxxx
+ stg %r2,__PT_R2(%r11) # store return value
+
+ .Lsysc_return:
+@@ -566,7 +628,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_R14_R9 # call sys_xxx
+ stg %r2,__PT_R2(%r11) # store return value
+ .Lsysc_tracenogo:
+ TSTMSK __TI_flags(%r12),_TIF_TRACE
+@@ -590,7 +652,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_R14_R9
+ j .Lsysc_tracenogo
+
+ /*
+@@ -667,9 +729,9 @@ ENTRY(pgm_check_handler)
+ nill %r10,0x007f
+ sll %r10,2
+ je .Lpgm_return
+- lgf %r1,0(%r10,%r1) # load address of handler routine
++ lgf %r9,0(%r10,%r1) # load address of handler routine
+ lgr %r2,%r11 # pass pointer to pt_regs
+- basr %r14,%r1 # branch to interrupt-handler
++ BASR_R14_R9 # branch to interrupt-handler
+ .Lpgm_return:
+ LOCKDEP_SYS_EXIT
+ tm __PT_PSW+1(%r11),0x01 # returning to user ?
+@@ -979,7 +1041,7 @@ ENTRY(psw_idle)
+ stpt __TIMER_IDLE_ENTER(%r2)
+ .Lpsw_idle_lpsw:
+ lpswe __SF_EMPTY(%r15)
+- br %r14
++ BR_R1USE_R14
+ .Lpsw_idle_end:
+
+ /*
+@@ -993,7 +1055,7 @@ ENTRY(save_fpu_regs)
+ lg %r2,__LC_CURRENT
+ aghi %r2,__TASK_thread
+ TSTMSK __LC_CPU_FLAGS,_CIF_FPU
+- bor %r14
++ jo .Lsave_fpu_regs_exit
+ stfpc __THREAD_FPU_fpc(%r2)
+ lg %r3,__THREAD_FPU_regs(%r2)
+ TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX
+@@ -1020,7 +1082,8 @@ ENTRY(save_fpu_regs)
+ std 15,120(%r3)
+ .Lsave_fpu_regs_done:
+ oi __LC_CPU_FLAGS+7,_CIF_FPU
+- br %r14
++.Lsave_fpu_regs_exit:
++ BR_R1USE_R14
+ .Lsave_fpu_regs_end:
+ EXPORT_SYMBOL(save_fpu_regs)
+
+@@ -1038,7 +1101,7 @@ load_fpu_regs:
+ lg %r4,__LC_CURRENT
+ aghi %r4,__TASK_thread
+ TSTMSK __LC_CPU_FLAGS,_CIF_FPU
+- bnor %r14
++ jno .Lload_fpu_regs_exit
+ lfpc __THREAD_FPU_fpc(%r4)
+ TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX
+ lg %r4,__THREAD_FPU_regs(%r4) # %r4 <- reg save area
+@@ -1065,7 +1128,8 @@ load_fpu_regs:
+ ld 15,120(%r4)
+ .Lload_fpu_regs_done:
+ ni __LC_CPU_FLAGS+7,255-_CIF_FPU
+- br %r14
++.Lload_fpu_regs_exit:
++ BR_R1USE_R14
+ .Lload_fpu_regs_end:
+
+ .L__critical_end:
+@@ -1237,7 +1301,7 @@ cleanup_critical:
+ jl 0f
+ clg %r9,BASED(.Lcleanup_table+104) # .Lload_fpu_regs_end
+ jl .Lcleanup_load_fpu_regs
+-0: br %r14
++0: BR_R11USE_R14
+
+ .align 8
+ .Lcleanup_table:
+@@ -1273,7 +1337,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 %r14
++ BR_R11USE_R14
+ #endif
+
+ .Lcleanup_system_call:
+@@ -1326,7 +1390,7 @@ cleanup_critical:
+ stg %r15,56(%r11) # r15 stack pointer
+ # set new psw address and exit
+ larl %r9,.Lsysc_do_svc
+- br %r14
++ BR_R11USE_R14
+ .Lcleanup_system_call_insn:
+ .quad system_call
+ .quad .Lsysc_stmg
+@@ -1338,7 +1402,7 @@ cleanup_critical:
+
+ .Lcleanup_sysc_tif:
+ larl %r9,.Lsysc_tif
+- br %r14
++ BR_R11USE_R14
+
+ .Lcleanup_sysc_restore:
+ # check if stpt has been executed
+@@ -1355,14 +1419,14 @@ cleanup_critical:
+ mvc 0(64,%r11),__PT_R8(%r9)
+ lmg %r0,%r7,__PT_R0(%r9)
+ 1: lmg %r8,%r9,__LC_RETURN_PSW
+- br %r14
++ BR_R11USE_R14
+ .Lcleanup_sysc_restore_insn:
+ .quad .Lsysc_exit_timer
+ .quad .Lsysc_done - 4
+
+ .Lcleanup_io_tif:
+ larl %r9,.Lio_tif
+- br %r14
++ BR_R11USE_R14
+
+ .Lcleanup_io_restore:
+ # check if stpt has been executed
+@@ -1376,7 +1440,7 @@ cleanup_critical:
+ mvc 0(64,%r11),__PT_R8(%r9)
+ lmg %r0,%r7,__PT_R0(%r9)
+ 1: lmg %r8,%r9,__LC_RETURN_PSW
+- br %r14
++ BR_R11USE_R14
+ .Lcleanup_io_restore_insn:
+ .quad .Lio_exit_timer
+ .quad .Lio_done - 4
+@@ -1429,17 +1493,17 @@ cleanup_critical:
+ # prepare return psw
+ nihh %r8,0xfcfd # clear irq & wait state bits
+ lg %r9,48(%r11) # return from psw_idle
+- br %r14
++ BR_R11USE_R14
+ .Lcleanup_idle_insn:
+ .quad .Lpsw_idle_lpsw
+
+ .Lcleanup_save_fpu_regs:
+ larl %r9,save_fpu_regs
+- br %r14
++ BR_R11USE_R14
+
+ .Lcleanup_load_fpu_regs:
+ larl %r9,load_fpu_regs
+- br %r14
++ BR_R11USE_R14
+
+ /*
+ * Integer constants
+@@ -1459,7 +1523,6 @@ cleanup_critical:
+ .Lsie_crit_mcck_length:
+ .quad .Lsie_skip - .Lsie_entry
+ #endif
+-
+ .section .rodata, "a"
+ #define SYSCALL(esame,emu) .long esame
+ .globl sys_call_table
+--- a/arch/s390/kernel/module.c
++++ b/arch/s390/kernel/module.c
+@@ -32,6 +32,8 @@
+ #include <linux/moduleloader.h>
+ #include <linux/bug.h>
+ #include <asm/alternative.h>
++#include <asm/nospec-branch.h>
++#include <asm/facility.h>
+
+ #if 0
+ #define DEBUGP printk
+@@ -169,7 +171,11 @@ int module_frob_arch_sections(Elf_Ehdr *
+ me->arch.got_offset = me->core_layout.size;
+ me->core_layout.size += me->arch.got_size;
+ me->arch.plt_offset = me->core_layout.size;
+- me->core_layout.size += me->arch.plt_size;
++ if (me->arch.plt_size) {
++ if (IS_ENABLED(CONFIG_EXPOLINE) && !nospec_call_disable)
++ me->arch.plt_size += PLT_ENTRY_SIZE;
++ me->core_layout.size += me->arch.plt_size;
++ }
+ return 0;
+ }
+
+@@ -323,9 +329,21 @@ static int apply_rela(Elf_Rela *rela, El
+ unsigned int *ip;
+ ip = me->core_layout.base + me->arch.plt_offset +
+ info->plt_offset;
+- ip[0] = 0x0d10e310; /* basr 1,0; lg 1,10(1); br 1 */
+- ip[1] = 0x100a0004;
+- ip[2] = 0x07f10000;
++ ip[0] = 0x0d10e310; /* basr 1,0 */
++ ip[1] = 0x100a0004; /* lg 1,10(1) */
++ if (IS_ENABLED(CONFIG_EXPOLINE) &&
++ !nospec_call_disable) {
++ unsigned int *ij;
++ ij = me->core_layout.base +
++ me->arch.plt_offset +
++ me->arch.plt_size - PLT_ENTRY_SIZE;
++ ip[2] = 0xa7f40000 + /* j __jump_r1 */
++ (unsigned int)(u16)
++ (((unsigned long) ij - 8 -
++ (unsigned long) ip) / 2);
++ } else {
++ ip[2] = 0x07f10000; /* br %r1 */
++ }
+ ip[3] = (unsigned int) (val >> 32);
+ ip[4] = (unsigned int) val;
+ info->plt_initialized = 1;
+@@ -431,16 +449,42 @@ int module_finalize(const Elf_Ehdr *hdr,
+ struct module *me)
+ {
+ const Elf_Shdr *s;
+- char *secstrings;
++ char *secstrings, *secname;
++ void *aseg;
++
++ if (IS_ENABLED(CONFIG_EXPOLINE) &&
++ !nospec_call_disable && me->arch.plt_size) {
++ unsigned int *ij;
++
++ ij = me->core_layout.base + me->arch.plt_offset +
++ me->arch.plt_size - PLT_ENTRY_SIZE;
++ if (test_facility(35)) {
++ ij[0] = 0xc6000000; /* exrl %r0,.+10 */
++ ij[1] = 0x0005a7f4; /* j . */
++ ij[2] = 0x000007f1; /* br %r1 */
++ } else {
++ ij[0] = 0x44000000 | (unsigned int)
++ offsetof(struct lowcore, br_r1_trampoline);
++ ij[1] = 0xa7f40000; /* j . */
++ }
++ }
+
+ secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+ for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+- if (!strcmp(".altinstructions", secstrings + s->sh_name)) {
+- /* patch .altinstructions */
+- void *aseg = (void *)s->sh_addr;
++ aseg = (void *) s->sh_addr;
++ secname = secstrings + s->sh_name;
+
++ if (!strcmp(".altinstructions", secname))
++ /* patch .altinstructions */
+ apply_alternatives(aseg, aseg + s->sh_size);
+- }
++
++ if (IS_ENABLED(CONFIG_EXPOLINE) &&
++ (!strcmp(".nospec_call_table", secname)))
++ nospec_call_revert(aseg, aseg + s->sh_size);
++
++ if (IS_ENABLED(CONFIG_EXPOLINE) &&
++ (!strcmp(".nospec_return_table", secname)))
++ nospec_return_revert(aseg, aseg + s->sh_size);
+ }
+
+ jump_label_apply_nops(me);
+--- /dev/null
++++ b/arch/s390/kernel/nospec-branch.c
+@@ -0,0 +1,101 @@
++// SPDX-License-Identifier: GPL-2.0
++#include <linux/module.h>
++#include <asm/facility.h>
++#include <asm/nospec-branch.h>
++
++int nospec_call_disable = IS_ENABLED(EXPOLINE_OFF);
++int nospec_return_disable = !IS_ENABLED(EXPOLINE_FULL);
++
++static int __init nospectre_v2_setup_early(char *str)
++{
++ nospec_call_disable = 1;
++ nospec_return_disable = 1;
++ return 0;
++}
++early_param("nospectre_v2", nospectre_v2_setup_early);
++
++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;
++ }
++ return 0;
++}
++early_param("spectre_v2", spectre_v2_setup_early);
++
++static void __init_or_module __nospec_revert(s32 *start, s32 *end)
++{
++ enum { BRCL_EXPOLINE, BRASL_EXPOLINE } type;
++ u8 *instr, *thunk, *br;
++ u8 insnbuf[6];
++ 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)
++ type = BRCL_EXPOLINE; /* brcl instruction */
++ else if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x05)
++ type = BRASL_EXPOLINE; /* brasl instruction */
++ else
++ continue;
++ thunk = instr + (*(int *)(instr + 2)) * 2;
++ if (thunk[0] == 0xc6 && thunk[1] == 0x00)
++ /* exrl %r0,<target-br> */
++ br = thunk + (*(int *)(thunk + 2)) * 2;
++ else if (thunk[0] == 0xc0 && (thunk[1] & 0x0f) == 0x00 &&
++ thunk[6] == 0x44 && thunk[7] == 0x00 &&
++ (thunk[8] & 0x0f) == 0x00 && thunk[9] == 0x00 &&
++ (thunk[1] & 0xf0) == (thunk[8] & 0xf0))
++ /* larl %rx,<target br> + ex %r0,0(%rx) */
++ br = thunk + (*(int *)(thunk + 2)) * 2;
++ else
++ continue;
++ if (br[0] != 0x07 || (br[1] & 0xf0) != 0xf0)
++ continue;
++ switch (type) {
++ case BRCL_EXPOLINE:
++ /* brcl to thunk, replace with br + nop */
++ insnbuf[0] = br[0];
++ insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
++ break;
++ case BRASL_EXPOLINE:
++ /* brasl to thunk, replace with basr + nop */
++ insnbuf[0] = 0x0d;
++ insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
++ break;
++ }
++
++ s390_kernel_write(instr, insnbuf, 6);
++ }
++}
++
++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)
++{
++ if (nospec_return_disable)
++ __nospec_revert(start, end);
++}
++
++extern s32 __nospec_call_start[], __nospec_call_end[];
++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);
++}
+--- a/arch/s390/kernel/setup.c
++++ b/arch/s390/kernel/setup.c
+@@ -67,6 +67,7 @@
+ #include <asm/sysinfo.h>
+ #include <asm/numa.h>
+ #include <asm/alternative.h>
++#include <asm/nospec-branch.h>
+ #include "entry.h"
+
+ /*
+@@ -384,6 +385,7 @@ static void __init setup_lowcore(void)
+ #ifdef CONFIG_SMP
+ lc->spinlock_lockval = arch_spin_lockval(0);
+ #endif
++ lc->br_r1_trampoline = 0x07f1; /* br %r1 */
+
+ set_prefix((u32)(unsigned long) lc);
+ lowcore_ptr[0] = lc;
+@@ -959,6 +961,8 @@ void __init setup_arch(char **cmdline_p)
+ set_preferred_console();
+
+ apply_alternative_instructions();
++ if (IS_ENABLED(CONFIG_EXPOLINE))
++ nospec_init_branches();
+
+ /* Setup zfcpdump support */
+ setup_zfcpdump();
+--- a/arch/s390/kernel/smp.c
++++ b/arch/s390/kernel/smp.c
+@@ -228,6 +228,7 @@ static int pcpu_alloc_lowcore(struct pcp
+ lc->mcesad = mcesa_origin | mcesa_bits;
+ lc->cpu_nr = cpu;
+ lc->spinlock_lockval = arch_spin_lockval(cpu);
++ lc->br_r1_trampoline = 0x07f1; /* br %r1 */
+ if (vdso_alloc_per_cpu(lc))
+ goto out;
+ lowcore_ptr[cpu] = lc;
+--- a/arch/s390/kernel/vmlinux.lds.S
++++ b/arch/s390/kernel/vmlinux.lds.S
+@@ -128,6 +128,20 @@ SECTIONS
+ *(.altinstr_replacement)
+ }
+
++ /*
++ * Table with the patch locations to undo expolines
++ */
++ .nospec_call_table : {
++ __nospec_call_start = . ;
++ *(.s390_indirect*)
++ __nospec_call_end = . ;
++ }
++ .nospec_return_table : {
++ __nospec_return_start = . ;
++ *(.s390_return*)
++ __nospec_return_end = . ;
++ }
++
+ /* early.c uses stsi, which requires page aligned data. */
+ . = ALIGN(PAGE_SIZE);
+ INIT_DATA_SECTION(0x100)
+--- a/drivers/s390/char/Makefile
++++ b/drivers/s390/char/Makefile
+@@ -17,6 +17,8 @@ CFLAGS_REMOVE_sclp_early_core.o += $(CC_
+ CFLAGS_sclp_early_core.o += -march=z900
+ endif
+
++CFLAGS_REMOVE_sclp_early_core.o += $(CC_FLAGS_EXPOLINE)
++
+ obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \
+ sclp_cmd.o sclp_config.o sclp_cpi_sys.o sclp_ocf.o sclp_ctl.o \
+ sclp_early.o sclp_early_core.o
--- /dev/null
+From foo@baz Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:38 +0200
+Subject: s390: move nobp parameter functions to nospec-branch.c
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-15-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
+@@ -59,11 +59,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
+ 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
+@@ -14,29 +14,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
+@@ -3,6 +3,31 @@
+ #include <asm/facility.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);
+
+@@ -99,3 +124,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 Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:35 +0200
+Subject: s390: Replace IS_ENABLED(EXPOLINE_*) with IS_ENABLED(CONFIG_EXPOLINE_*)
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-12-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+
+From: Eugeniu Rosca <erosca@de.adit-jv.com>
+
+[ Upstream commit 2cb370d615e9fbed9e95ed222c2c8f337181aa90 ]
+
+I've accidentally stumbled upon the IS_ENABLED(EXPOLINE_*) lines, which
+obviously always evaluate to false. Fix this.
+
+Fixes: f19fbd5ed642 ("s390: introduce execute-trampolines for branches")
+Signed-off-by: Eugeniu Rosca <erosca@de.adit-jv.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kernel/nospec-branch.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/s390/kernel/nospec-branch.c
++++ b/arch/s390/kernel/nospec-branch.c
+@@ -3,8 +3,8 @@
+ #include <asm/facility.h>
+ #include <asm/nospec-branch.h>
+
+-int nospec_call_disable = IS_ENABLED(EXPOLINE_OFF);
+-int nospec_return_disable = !IS_ENABLED(EXPOLINE_FULL);
++int nospec_call_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF);
++int nospec_return_disable = !IS_ENABLED(CONFIG_EXPOLINE_FULL);
+
+ static int __init nospectre_v2_setup_early(char *str)
+ {
--- /dev/null
+From foo@baz Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:40 +0200
+Subject: s390: report spectre mitigation via syslog
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-17-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
+@@ -33,6 +33,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 Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:32 +0200
+Subject: s390: run user space and KVM guests with modified branch prediction
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-9-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+
+[ Upstream commit 6b73044b2b0081ee3dd1cd6eaab7dee552601efb ]
+
+Define TIF_ISOLATE_BP and TIF_ISOLATE_BP_GUEST and add the necessary
+plumbing in entry.S to be able to run user space and KVM guests with
+limited branch prediction.
+
+To switch a user space process to limited branch prediction the
+s390_isolate_bp() function has to be call, and to run a vCPU of a KVM
+guest associated with the current task with limited branch prediction
+call s390_isolate_bp_guest().
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/include/asm/processor.h | 3 ++
+ arch/s390/include/asm/thread_info.h | 4 ++
+ arch/s390/kernel/entry.S | 51 ++++++++++++++++++++++++++++++++----
+ arch/s390/kernel/processor.c | 18 ++++++++++++
+ 4 files changed, 71 insertions(+), 5 deletions(-)
+
+--- a/arch/s390/include/asm/processor.h
++++ b/arch/s390/include/asm/processor.h
+@@ -378,6 +378,9 @@ extern void memcpy_absolute(void *, void
+ memcpy_absolute(&(dest), &__tmp, sizeof(__tmp)); \
+ } while (0)
+
++extern int s390_isolate_bp(void);
++extern int s390_isolate_bp_guest(void);
++
+ #endif /* __ASSEMBLY__ */
+
+ #endif /* __ASM_S390_PROCESSOR_H */
+--- a/arch/s390/include/asm/thread_info.h
++++ b/arch/s390/include/asm/thread_info.h
+@@ -60,6 +60,8 @@ int arch_dup_task_struct(struct task_str
+ #define TIF_GUARDED_STORAGE 4 /* load guarded storage control block */
+ #define TIF_PATCH_PENDING 5 /* pending live patching update */
+ #define TIF_PGSTE 6 /* New mm's will use 4K page tables */
++#define TIF_ISOLATE_BP 8 /* Run process with isolated BP */
++#define TIF_ISOLATE_BP_GUEST 9 /* Run KVM guests with isolated BP */
+
+ #define TIF_31BIT 16 /* 32bit process */
+ #define TIF_MEMDIE 17 /* is terminating due to OOM killer */
+@@ -80,6 +82,8 @@ int arch_dup_task_struct(struct task_str
+ #define _TIF_UPROBE _BITUL(TIF_UPROBE)
+ #define _TIF_GUARDED_STORAGE _BITUL(TIF_GUARDED_STORAGE)
+ #define _TIF_PATCH_PENDING _BITUL(TIF_PATCH_PENDING)
++#define _TIF_ISOLATE_BP _BITUL(TIF_ISOLATE_BP)
++#define _TIF_ISOLATE_BP_GUEST _BITUL(TIF_ISOLATE_BP_GUEST)
+
+ #define _TIF_31BIT _BITUL(TIF_31BIT)
+ #define _TIF_SINGLE_STEP _BITUL(TIF_SINGLE_STEP)
+--- a/arch/s390/kernel/entry.S
++++ b/arch/s390/kernel/entry.S
+@@ -106,6 +106,7 @@ _PIF_WORK = (_PIF_PER_TRAP | _PIF_SYSCAL
+ aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
+ j 3f
+ 1: UPDATE_VTIME %r14,%r15,\timer
++ BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
+ 2: lg %r15,__LC_ASYNC_STACK # load async stack
+ 3: la %r11,STACK_FRAME_OVERHEAD(%r15)
+ .endm
+@@ -186,6 +187,40 @@ _PIF_WORK = (_PIF_PER_TRAP | _PIF_SYSCAL
+ .popsection
+ .endm
+
++ .macro BPENTER tif_ptr,tif_mask
++ .pushsection .altinstr_replacement, "ax"
++662: .word 0xc004, 0x0000, 0x0000 # 6 byte nop
++ .word 0xc004, 0x0000, 0x0000 # 6 byte nop
++ .popsection
++664: TSTMSK \tif_ptr,\tif_mask
++ jz . + 8
++ .long 0xb2e8d000
++ .pushsection .altinstructions, "a"
++ .long 664b - .
++ .long 662b - .
++ .word 82
++ .byte 12
++ .byte 12
++ .popsection
++ .endm
++
++ .macro BPEXIT tif_ptr,tif_mask
++ TSTMSK \tif_ptr,\tif_mask
++ .pushsection .altinstr_replacement, "ax"
++662: jnz . + 8
++ .long 0xb2e8d000
++ .popsection
++664: jz . + 8
++ .long 0xb2e8c000
++ .pushsection .altinstructions, "a"
++ .long 664b - .
++ .long 662b - .
++ .word 82
++ .byte 8
++ .byte 8
++ .popsection
++ .endm
++
+ .section .kprobes.text, "ax"
+ .Ldummy:
+ /*
+@@ -240,9 +275,11 @@ ENTRY(__switch_to)
+ */
+ ENTRY(sie64a)
+ stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers
++ lg %r12,__LC_CURRENT
+ stg %r2,__SF_EMPTY(%r15) # save control block pointer
+ stg %r3,__SF_EMPTY+8(%r15) # save guest register save area
+ xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # reason code = 0
++ mvc __SF_EMPTY+24(8,%r15),__TI_flags(%r12) # copy thread flags
+ TSTMSK __LC_CPU_FLAGS,_CIF_FPU # load guest fp/vx registers ?
+ jno .Lsie_load_guest_gprs
+ brasl %r14,load_fpu_regs # load guest fp/vx regs
+@@ -259,11 +296,12 @@ ENTRY(sie64a)
+ jnz .Lsie_skip
+ TSTMSK __LC_CPU_FLAGS,_CIF_FPU
+ jo .Lsie_skip # exit if fp/vx regs changed
+- BPON
++ BPEXIT __SF_EMPTY+24(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
+ .Lsie_entry:
+ sie 0(%r14)
+ .Lsie_exit:
+ BPOFF
++ BPENTER __SF_EMPTY+24(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
+ .Lsie_skip:
+ ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE
+ lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
+@@ -324,6 +362,7 @@ ENTRY(system_call)
+ la %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs
+ .Lsysc_vtime:
+ UPDATE_VTIME %r8,%r9,__LC_SYNC_ENTER_TIMER
++ BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
+ stmg %r0,%r7,__PT_R0(%r11)
+ # clear user controlled register to prevent speculative use
+ xgr %r0,%r0
+@@ -362,7 +401,7 @@ ENTRY(system_call)
+ jnz .Lsysc_work # check for work
+ TSTMSK __LC_CPU_FLAGS,_CIF_WORK
+ jnz .Lsysc_work
+- BPON
++ BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
+ .Lsysc_restore:
+ lg %r14,__LC_VDSO_PER_CPU
+ lmg %r0,%r10,__PT_R0(%r11)
+@@ -587,6 +626,7 @@ ENTRY(pgm_check_handler)
+ aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
+ j 4f
+ 2: UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER
++ BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
+ lg %r15,__LC_KERNEL_STACK
+ lgr %r14,%r12
+ aghi %r14,__TASK_thread # pointer to thread_struct
+@@ -718,7 +758,7 @@ ENTRY(io_int_handler)
+ mvc __LC_RETURN_PSW(16),__PT_PSW(%r11)
+ tm __PT_PSW+1(%r11),0x01 # returning to user ?
+ jno .Lio_exit_kernel
+- BPON
++ BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
+ .Lio_exit_timer:
+ stpt __LC_EXIT_TIMER
+ mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
+@@ -1101,7 +1141,7 @@ ENTRY(mcck_int_handler)
+ mvc __LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW
+ tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
+ jno 0f
+- BPON
++ BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
+ stpt __LC_EXIT_TIMER
+ mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
+ 0: lmg %r11,%r15,__PT_R11(%r11)
+@@ -1228,7 +1268,8 @@ cleanup_critical:
+ clg %r9,BASED(.Lsie_crit_mcck_length)
+ jh 1f
+ oi __LC_CPU_FLAGS+7, _CIF_MCCK_GUEST
+-1: lg %r9,__SF_EMPTY(%r15) # get control block pointer
++1: BPENTER __SF_EMPTY+24(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
++ lg %r9,__SF_EMPTY(%r15) # get control block pointer
+ 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
+--- a/arch/s390/kernel/processor.c
++++ b/arch/s390/kernel/processor.c
+@@ -197,3 +197,21 @@ const struct seq_operations cpuinfo_op =
+ .stop = c_stop,
+ .show = show_cpuinfo,
+ };
++
++int s390_isolate_bp(void)
++{
++ if (!test_facility(82))
++ return -EOPNOTSUPP;
++ set_thread_flag(TIF_ISOLATE_BP);
++ return 0;
++}
++EXPORT_SYMBOL(s390_isolate_bp);
++
++int s390_isolate_bp_guest(void)
++{
++ if (!test_facility(82))
++ return -EOPNOTSUPP;
++ set_thread_flag(TIF_ISOLATE_BP_GUEST);
++ return 0;
++}
++EXPORT_SYMBOL(s390_isolate_bp_guest);
--- /dev/null
+From foo@baz Fri Apr 27 10:56:30 CEST 2018
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 27 Apr 2018 07:36:28 +0200
+Subject: s390: scrub registers on kernel entry and KVM exit
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Message-ID: <20180427053643.56777-5-schwidefsky@de.ibm.com>
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+
+[ Upstream commit 7041d28115e91f2144f811ffe8a195c696b1e1d0 ]
+
+Clear all user space registers on entry to the kernel and all KVM guest
+registers on KVM guest exit if the register does not contain either a
+parameter or a result value.
+
+Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kernel/entry.S | 47 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 47 insertions(+)
+
+--- a/arch/s390/kernel/entry.S
++++ b/arch/s390/kernel/entry.S
+@@ -248,6 +248,12 @@ ENTRY(sie64a)
+ sie_exit:
+ lg %r14,__SF_EMPTY+8(%r15) # load guest register save area
+ stmg %r0,%r13,0(%r14) # save guest gprs 0-13
++ xgr %r0,%r0 # clear guest registers to
++ xgr %r1,%r1 # prevent speculative use
++ xgr %r2,%r2
++ xgr %r3,%r3
++ xgr %r4,%r4
++ xgr %r5,%r5
+ lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
+ lg %r2,__SF_EMPTY+16(%r15) # return exit reason code
+ br %r14
+@@ -282,6 +288,8 @@ ENTRY(system_call)
+ .Lsysc_vtime:
+ UPDATE_VTIME %r8,%r9,__LC_SYNC_ENTER_TIMER
+ stmg %r0,%r7,__PT_R0(%r11)
++ # clear user controlled register to prevent speculative use
++ xgr %r0,%r0
+ mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
+ mvc __PT_PSW(16,%r11),__LC_SVC_OLD_PSW
+ mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC
+@@ -550,6 +558,15 @@ ENTRY(pgm_check_handler)
+ 3: stg %r10,__THREAD_last_break(%r14)
+ 4: la %r11,STACK_FRAME_OVERHEAD(%r15)
+ stmg %r0,%r7,__PT_R0(%r11)
++ # clear user controlled registers to prevent speculative use
++ xgr %r0,%r0
++ xgr %r1,%r1
++ xgr %r2,%r2
++ xgr %r3,%r3
++ xgr %r4,%r4
++ xgr %r5,%r5
++ xgr %r6,%r6
++ xgr %r7,%r7
+ mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
+ stmg %r8,%r9,__PT_PSW(%r11)
+ mvc __PT_INT_CODE(4,%r11),__LC_PGM_ILC
+@@ -615,6 +632,16 @@ ENTRY(io_int_handler)
+ lmg %r8,%r9,__LC_IO_OLD_PSW
+ SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_ENTER_TIMER
+ stmg %r0,%r7,__PT_R0(%r11)
++ # clear user controlled registers to prevent speculative use
++ xgr %r0,%r0
++ xgr %r1,%r1
++ xgr %r2,%r2
++ xgr %r3,%r3
++ xgr %r4,%r4
++ xgr %r5,%r5
++ xgr %r6,%r6
++ xgr %r7,%r7
++ xgr %r10,%r10
+ mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
+ stmg %r8,%r9,__PT_PSW(%r11)
+ mvc __PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID
+@@ -820,6 +847,16 @@ ENTRY(ext_int_handler)
+ lmg %r8,%r9,__LC_EXT_OLD_PSW
+ SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_ENTER_TIMER
+ stmg %r0,%r7,__PT_R0(%r11)
++ # clear user controlled registers to prevent speculative use
++ xgr %r0,%r0
++ xgr %r1,%r1
++ xgr %r2,%r2
++ xgr %r3,%r3
++ xgr %r4,%r4
++ xgr %r5,%r5
++ xgr %r6,%r6
++ xgr %r7,%r7
++ xgr %r10,%r10
+ mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
+ stmg %r8,%r9,__PT_PSW(%r11)
+ lghi %r1,__LC_EXT_PARAMS2
+@@ -982,6 +1019,16 @@ ENTRY(mcck_int_handler)
+ .Lmcck_skip:
+ lghi %r14,__LC_GPREGS_SAVE_AREA+64
+ stmg %r0,%r7,__PT_R0(%r11)
++ # clear user controlled registers to prevent speculative use
++ xgr %r0,%r0
++ xgr %r1,%r1
++ xgr %r2,%r2
++ xgr %r3,%r3
++ xgr %r4,%r4
++ xgr %r5,%r5
++ xgr %r6,%r6
++ xgr %r7,%r7
++ xgr %r10,%r10
+ mvc __PT_R8(64,%r11),0(%r14)
+ stmg %r8,%r9,__PT_PSW(%r11)
+ xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
virtio_net-split-out-ctrl-buffer.patch
virtio_net-fix-adding-vids-on-big-endian.patch
revert-microblaze-fix-endian-handling.patch
+s390-introduce-cpu-alternatives.patch
+s390-enable-cpu-alternatives-unconditionally.patch
+kvm-s390-wire-up-bpb-feature.patch
+s390-scrub-registers-on-kernel-entry-and-kvm-exit.patch
+s390-add-optimized-array_index_mask_nospec.patch
+s390-alternative-use-a-copy-of-the-facility-bit-mask.patch
+s390-add-options-to-change-branch-prediction-behaviour-for-the-kernel.patch
+s390-run-user-space-and-kvm-guests-with-modified-branch-prediction.patch
+s390-introduce-execute-trampolines-for-branches.patch
+kvm-s390-force-bp-isolation-for-vsie.patch
+s390-replace-is_enabled-expoline_-with-is_enabled-config_expoline_.patch
+s390-do-not-bypass-bpenter-for-interrupt-system-calls.patch
+s390-entry.s-fix-spurious-zeroing-of-r0.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-correct-nospec-auto-detection-init-order.patch
+s390-correct-module-section-names-for-expoline-code-revert.patch