diff options
author | Sven Schnelle <svens@linux.ibm.com> | 2021-02-03 09:02:51 +0100 |
---|---|---|
committer | Vasily Gorbik <gor@linux.ibm.com> | 2021-02-13 17:17:53 +0100 |
commit | b61b1595124a1694501105e5dd488de0c0c6bc2a (patch) | |
tree | 6444ca0b97c066f15025886b70b21204fb841cfd /arch/s390/kernel/entry.S | |
parent | 64985c3a223d15f151204b3aa37e587b9466378d (diff) | |
download | linux-b61b1595124a1694501105e5dd488de0c0c6bc2a.tar.gz |
s390: add stack for machine check handler
The previous code used the normal kernel stack for machine checks.
This is problematic when a machine check interrupts a system call
or interrupt handler right at the beginning where registers are set up.
Assume system_call is interrupted at the first instruction and a machine
check is triggered. The machine check handler is called, checks the PSW
to see whether it is coming from user space, notices that it is already
in kernel mode but %r15 still contains the user space stack. This would
lead to a kernel crash.
There are basically two ways of fixing that: Either using the 'critical
cleanup' approach which compares the address in the PSW to see whether
it is already at a point where the stack has been set up, or use an extra
stack for the machine check handler.
For simplicity, we will go with the second approach and allocate an extra
stack. This adds some memory overhead for large systems, but usually large
system have plenty of memory so this isn't really a concern. But it keeps
the mchk stack setup simple and less error prone.
Fixes: 0b0ed657fe00 ("s390: remove critical section cleanup from entry.S")
Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Cc: <stable@kernel.org> # v5.8+
Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Diffstat (limited to 'arch/s390/kernel/entry.S')
-rw-r--r-- | arch/s390/kernel/entry.S | 17 |
1 files changed, 7 insertions, 10 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index ed5acf95235f..f7953bb17558 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -70,6 +70,8 @@ _LPP_OFFSET = __LC_LPP je \oklabel clg %r14,__LC_ASYNC_STACK je \oklabel + clg %r14,__LC_MCCK_STACK + je \oklabel clg %r14,__LC_NODAT_STACK je \oklabel clg %r14,__LC_RESTART_STACK @@ -548,20 +550,16 @@ ENTRY(mcck_int_handler) jhe .Lmcck_stack lghi %r11,__LC_GPREGS_SAVE_AREA+64 # inside critical section, do cleanup brasl %r14,.Lcleanup_sie -.Lmcck_stack: #endif - CHECK_STACK __LC_GPREGS_SAVE_AREA+64 - lgr %r11,%r15 - aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) - stg %r11,__SF_BACKCHAIN(%r15) - j 5f + j .Lmcck_stack .Lmcck_user: BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP +.Lmcck_stack: + lg %r15,__LC_MCCK_STACK +.Lmcck_skip: + la %r11,STACK_FRAME_OVERHEAD(%r15) lctlg %c1,%c1,__LC_KERNEL_ASCE - lg %r15,__LC_KERNEL_STACK xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) -5: la %r11,STACK_FRAME_OVERHEAD(%r15) -.Lmcck_skip: lghi %r14,__LC_GPREGS_SAVE_AREA+64 stmg %r0,%r7,__PT_R0(%r11) # clear user controlled registers to prevent speculative use @@ -602,7 +600,6 @@ ENTRY(mcck_int_handler) .Lmcck_panic: lg %r15,__LC_NODAT_STACK - la %r11,STACK_FRAME_OVERHEAD(%r15) j .Lmcck_skip ENDPROC(mcck_int_handler) |