summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/processor.h2
-rw-r--r--arch/s390/kernel/base.S22
-rw-r--r--arch/s390/kernel/early.c14
3 files changed, 20 insertions, 18 deletions
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 8fd9772c7370..022cf0925e56 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -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
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S
index f7fe4033df36..172c23c8ca00 100644
--- a/arch/s390/kernel/base.S
+++ b/arch/s390/kernel/base.S
@@ -14,18 +14,28 @@
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
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 9d151808d03e..5715d1aab173 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -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)