#include <linux/pgtable.h>
 #include <asm/idle.h>
 #include <asm/gmap.h>
-#include <asm/nmi.h>
-#include <asm/setup.h>
 #include <asm/stacktrace.h>
 
 int main(void)
        OFFSET(__LC_LAST_UPDATE_CLOCK, lowcore, last_update_clock);
        OFFSET(__LC_INT_CLOCK, lowcore, int_clock);
        OFFSET(__LC_MCCK_CLOCK, lowcore, mcck_clock);
-       OFFSET(__LC_CLOCK_COMPARATOR, lowcore, clock_comparator);
        OFFSET(__LC_BOOT_CLOCK, lowcore, boot_clock);
        OFFSET(__LC_CURRENT, lowcore, current_task);
        OFFSET(__LC_KERNEL_STACK, lowcore, kernel_stack);
        OFFSET(__LC_CREGS_SAVE_AREA, lowcore, cregs_save_area);
        OFFSET(__LC_PGM_TDB, lowcore, pgm_tdb);
        BLANK();
-       /* extended machine check save area */
-       OFFSET(__MCESA_GS_SAVE_AREA, mcesa, guarded_storage_save_area);
-       BLANK();
        /* gmap/sie offsets */
        OFFSET(__GMAP_ASCE, gmap, asce);
        OFFSET(__SIE_PROG0C, kvm_s390_sie_block, prog0c);
 
 #include <asm/alternative-asm.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
-#include <asm/ctl_reg.h>
 #include <asm/dwarf.h>
 #include <asm/errno.h>
 #include <asm/ptrace.h>
        BPOFF
        la      %r1,4095                # validate r1
        spt     __LC_CPU_TIMER_SAVE_AREA-4095(%r1)      # validate cpu timer
-       sckc    __LC_CLOCK_COMPARATOR                   # validate comparator
-       lam     %a0,%a15,__LC_AREGS_SAVE_AREA-4095(%r1) # validate acrs
        lmg     %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# validate gprs
        lg      %r12,__LC_CURRENT
        lmg     %r8,%r9,__LC_MCK_OLD_PSW
        la      %r14,4095
        lctlg   %c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r14) # validate ctl regs
        ptlb
-       lg      %r11,__LC_MCESAD-4095(%r14) # extended machine check save area
-       nill    %r11,0xfc00             # MCESA_ORIGIN_MASK
-       TSTMSK  __LC_CREGS_SAVE_AREA+16-4095(%r14),CR2_GUARDED_STORAGE
-       jno     0f
-       TSTMSK  __LC_MCCK_CODE,MCCK_CODE_GS_VALID
-       jno     0f
-       .insn    rxy,0xe3000000004d,0,__MCESA_GS_SAVE_AREA(%r11) # LGSC
-0:     l       %r14,__LC_FP_CREG_SAVE_AREA-4095(%r14)
-       TSTMSK  __LC_MCCK_CODE,MCCK_CODE_FC_VALID
-       jo      0f
-       sr      %r14,%r14
-0:     sfpc    %r14
-       TSTMSK  __LC_MACHINE_FLAGS,MACHINE_FLAG_VX
-       jo      0f
-       lghi    %r14,__LC_FPREGS_SAVE_AREA
-       ld      %f0,0(%r14)
-       ld      %f1,8(%r14)
-       ld      %f2,16(%r14)
-       ld      %f3,24(%r14)
-       ld      %f4,32(%r14)
-       ld      %f5,40(%r14)
-       ld      %f6,48(%r14)
-       ld      %f7,56(%r14)
-       ld      %f8,64(%r14)
-       ld      %f9,72(%r14)
-       ld      %f10,80(%r14)
-       ld      %f11,88(%r14)
-       ld      %f12,96(%r14)
-       ld      %f13,104(%r14)
-       ld      %f14,112(%r14)
-       ld      %f15,120(%r14)
-       j       1f
-0:     VLM     %v0,%v15,0,%r11
-       VLM     %v16,%v31,256,%r11
-1:     lghi    %r14,__LC_CPU_TIMER_SAVE_AREA
+       lghi    %r14,__LC_CPU_TIMER_SAVE_AREA
        mvc     __LC_MCCK_ENTER_TIMER(8),0(%r14)
        TSTMSK  __LC_MCCK_CODE,MCCK_CODE_CPU_TIMER_VALID
        jo      3f
 
  * returns 0 if all required registers are available
  * returns 1 otherwise
  */
-static int notrace s390_check_registers(union mci mci, int umode)
+static int notrace s390_validate_registers(union mci mci, int umode)
 {
+       struct mcesa *mcesa;
+       void *fpt_save_area;
        union ctlreg2 cr2;
        int kill_task;
+       u64 zero;
 
        kill_task = 0;
+       zero = 0;
 
        if (!mci.gr) {
                /*
                if (!test_cpu_flag(CIF_FPU))
                        kill_task = 1;
        }
+       fpt_save_area = &S390_lowcore.floating_pt_save_area;
        if (!mci.fc) {
                /*
                 * Floating point control register can't be restored.
                 * If the kernel currently uses the floating pointer
                 * registers and needs the FPC register the system is
                 * stopped. If the process has its floating pointer
-                * registers loaded it is terminated.
+                * registers loaded it is terminated. Otherwise the
+                * FPC is just validated.
                 */
                if (S390_lowcore.fpu_flags & KERNEL_FPC)
                        s390_handle_damage();
+               asm volatile(
+                       "       lfpc    %0\n"
+                       :
+                       : "Q" (zero));
                if (!test_cpu_flag(CIF_FPU))
                        kill_task = 1;
+       } else {
+               asm volatile(
+                       "       lfpc    %0\n"
+                       :
+                       : "Q" (S390_lowcore.fpt_creg_save_area));
        }
 
-       if (MACHINE_HAS_VX) {
+       mcesa = (struct mcesa *)(S390_lowcore.mcesad & MCESA_ORIGIN_MASK);
+       if (!MACHINE_HAS_VX) {
+               /* Validate floating point registers */
+               asm volatile(
+                       "       ld      0,0(%0)\n"
+                       "       ld      1,8(%0)\n"
+                       "       ld      2,16(%0)\n"
+                       "       ld      3,24(%0)\n"
+                       "       ld      4,32(%0)\n"
+                       "       ld      5,40(%0)\n"
+                       "       ld      6,48(%0)\n"
+                       "       ld      7,56(%0)\n"
+                       "       ld      8,64(%0)\n"
+                       "       ld      9,72(%0)\n"
+                       "       ld      10,80(%0)\n"
+                       "       ld      11,88(%0)\n"
+                       "       ld      12,96(%0)\n"
+                       "       ld      13,104(%0)\n"
+                       "       ld      14,112(%0)\n"
+                       "       ld      15,120(%0)\n"
+                       :
+                       : "a" (fpt_save_area)
+                       : "memory");
+       } else {
+               /* Validate vector registers */
+               union ctlreg0 cr0;
+
                if (!mci.vr) {
                        /*
                         * Vector registers can't be restored. If the kernel
                         * currently uses vector registers the system is
                         * stopped. If the process has its vector registers
-                        * loaded it is terminated.
+                        * loaded it is terminated. Otherwise just validate
+                        * the registers.
                         */
                        if (S390_lowcore.fpu_flags & KERNEL_VXR)
                                s390_handle_damage();
                        if (!test_cpu_flag(CIF_FPU))
                                kill_task = 1;
                }
+               cr0.val = S390_lowcore.cregs_save_area[0];
+               cr0.afp = cr0.vx = 1;
+               __ctl_load(cr0.val, 0, 0);
+               asm volatile(
+                       "       la      1,%0\n"
+                       "       .word   0xe70f,0x1000,0x0036\n" /* vlm 0,15,0(1) */
+                       "       .word   0xe70f,0x1100,0x0c36\n" /* vlm 16,31,256(1) */
+                       :
+                       : "Q" (*(struct vx_array *)mcesa->vector_save_area)
+                       : "1");
+               __ctl_load(S390_lowcore.cregs_save_area[0], 0, 0);
        }
-       /* Check if access registers are valid */
+       /* Validate access registers */
+       asm volatile(
+               "       lam     0,15,0(%0)\n"
+               :
+               : "a" (&S390_lowcore.access_regs_save_area)
+               : "memory");
        if (!mci.ar) {
                /*
                 * Access registers have unknown contents.
                 */
                kill_task = 1;
        }
-       /* Check guarded storage registers */
+       /* Validate guarded storage registers */
        cr2.val = S390_lowcore.cregs_save_area[2];
        if (cr2.gse) {
                if (!mci.gs) {
                         * It has to be terminated.
                         */
                        kill_task = 1;
+               } else {
+                       load_gs_cb((struct gs_cb *)mcesa->guarded_storage_save_area);
                }
        }
+       /*
+        * The getcpu vdso syscall reads CPU number from the programmable
+        * field of the TOD clock. Disregard the TOD programmable register
+        * validity bit and load the CPU number into the TOD programmable
+        * field unconditionally.
+        */
+       set_tod_programmable_field(raw_smp_processor_id());
+       /* Validate clock comparator register */
+       set_clock_comparator(S390_lowcore.clock_comparator);
 
        if (!mci.ms || !mci.pm || !mci.ia)
                kill_task = 1;
 
        return kill_task;
 }
-NOKPROBE_SYMBOL(s390_check_registers);
+NOKPROBE_SYMBOL(s390_validate_registers);
 
 /*
  * Backup the guest's machine check info to its description block
                        s390_handle_damage();
                }
        }
-       if (s390_check_registers(mci, user_mode(regs))) {
+       if (s390_validate_registers(mci, user_mode(regs))) {
                /*
                 * Couldn't restore all register contents for the
                 * user space process -> mark task for termination.