s390/base: pass pt_regs to early program check handler
authorHeiko Carstens <hca@linux.ibm.com>
Mon, 28 Feb 2022 12:31:33 +0000 (13:31 +0100)
committerVasily Gorbik <gor@linux.ibm.com>
Mon, 7 Mar 2022 23:33:00 +0000 (00:33 +0100)
Pass pt_regs to early program check handler like it is done for every
other interrupt and exception handler.

Also the passed pt_regs can be changed by the called function and the
changes register contents and psw contents will be taken into account
when returning. In addition the return psw will not be copied to the
program check old psw in lowcore, but to the usual return psw
location, like it is also done by the regular program check handler.
This allows also to get rid of the code that disabled lowcore
protection when changing the return address.

Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/include/asm/processor.h
arch/s390/kernel/base.S
arch/s390/kernel/early.c

index 8fd9772c73709ed94767d67009582131ecd74fc9..022cf0925e56fcc826a0db7917debb584b70fd55 100644 (file)
@@ -313,7 +313,7 @@ static __always_inline void __noreturn disabled_wait(void)
  * Basic Program Check Handler.
  */
 extern void s390_base_pgm_handler(void);
-extern void (*s390_base_pgm_handler_fn)(void);
+extern void (*s390_base_pgm_handler_fn)(struct pt_regs *regs);
 
 #define ARCH_LOW_ADDRESS_LIMIT 0x7fffffffUL
 
index f7fe4033df369bb50035eb81198fe46377179614..172c23c8ca005ecb57d637b77997f9656f7e1688 100644 (file)
        GEN_BR_THUNK %r9
        GEN_BR_THUNK %r14
 
+__PT_R0 = __PT_GPRS
+__PT_R8 = __PT_GPRS + 64
+
 ENTRY(s390_base_pgm_handler)
-       stmg    %r0,%r15,__LC_SAVE_AREA_SYNC
-       basr    %r13,0
-0:     aghi    %r15,-STACK_FRAME_OVERHEAD
+       stmg    %r8,%r15,__LC_SAVE_AREA_SYNC
+       aghi    %r15,-(STACK_FRAME_OVERHEAD+__PT_SIZE)
+       la      %r11,STACK_FRAME_OVERHEAD(%r15)
+       xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
+       stmg    %r0,%r7,__PT_R0(%r11)
+       mvc     __PT_PSW(16,%r11),__LC_PGM_OLD_PSW
+       mvc     __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
+       lgr     %r2,%r11
        larl    %r1,s390_base_pgm_handler_fn
        lg      %r9,0(%r1)
        ltgr    %r9,%r9
        jz      1f
        BASR_EX %r14,%r9
-       lmg     %r0,%r15,__LC_SAVE_AREA_SYNC
-       lpswe   __LC_PGM_OLD_PSW
-1:     lpswe   disabled_wait_psw-0b(%r13)
+       mvc     __LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
+       lmg     %r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
+       lpswe   __LC_RETURN_PSW
+1:     larl    %r13,disabled_wait_psw
+       lpswe   0(%r13)
 ENDPROC(s390_base_pgm_handler)
 
        .align  8
index 9d151808d03e81902f1add4671d3553b1cf181d7..5715d1aab173ee9f7acbb1e41d86bd9ba6e85d32 100644 (file)
@@ -149,22 +149,14 @@ static __init void setup_topology(void)
        topology_max_mnest = max_mnest;
 }
 
-static void early_pgm_check_handler(void)
+static void early_pgm_check_handler(struct pt_regs *regs)
 {
        const struct exception_table_entry *fixup;
-       unsigned long cr0, cr0_new;
-       unsigned long addr;
 
-       addr = S390_lowcore.program_old_psw.addr;
-       fixup = s390_search_extables(addr);
+       fixup = s390_search_extables(regs->psw.addr);
        if (!fixup)
                disabled_wait();
-       /* Disable low address protection before storing into lowcore. */
-       __ctl_store(cr0, 0, 0);
-       cr0_new = cr0 & ~(1UL << 28);
-       __ctl_load(cr0_new, 0, 0);
-       S390_lowcore.program_old_psw.addr = extable_fixup(fixup);
-       __ctl_load(cr0, 0, 0);
+       regs->psw.addr = extable_fixup(fixup);
 }
 
 static noinline __init void setup_lowcore_early(void)