diff options
author | Alexander Gordeev <agordeev@linux.ibm.com> | 2021-06-18 08:17:15 +0200 |
---|---|---|
committer | Vasily Gorbik <gor@linux.ibm.com> | 2021-07-05 12:44:23 +0200 |
commit | 7f6dc8d4c880f64b9d450d780d88985b264d8793 (patch) | |
tree | c96580754a851422b877d68f1d8bf7e73869b3e5 /arch/s390/kernel/entry.S | |
parent | e2c13d64200bff0aa3964017cfabb0bc47691022 (diff) | |
download | lwn-7f6dc8d4c880f64b9d450d780d88985b264d8793.tar.gz lwn-7f6dc8d4c880f64b9d450d780d88985b264d8793.zip |
s390/mcck: always enter C handler with DAT enabled
The machine check handler must be entered with DAT disabled
in case control registers are corrupted or a storage error
happened and we can not tell if such error corresponds to a
page table.
Both of described conditions end up in stopping all CPUs and
entering the disabled wait in C half of the handler. However,
the storage errors are still checked after the DAT is enabled
and C code is entered. In case a page table is damaged such
flow is not expected to work.
This update paves the way for moving the storage error checks
from C to assembler half. All fatal errors that can only be
handled with DAT disabled are handled in assembler half also.
As result, the C half is only entered if the DAT is secured.
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-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 | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index ff715cc2b77b..6bc8ed800458 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -570,7 +570,6 @@ ENTRY(mcck_int_handler) BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP .Lmcck_stack: lg %r15,__LC_MCCK_STACK -.Lmcck_skip: la %r11,STACK_FRAME_OVERHEAD(%r15) stctg %c1,%c1,__PT_CR1(%r11) lctlg %c1,%c1,__LC_KERNEL_ASCE @@ -612,8 +611,33 @@ ENTRY(mcck_int_handler) b __LC_RETURN_MCCK_LPSWE .Lmcck_panic: - lg %r15,__LC_NODAT_STACK - j .Lmcck_skip + /* + * Iterate over all possible CPU addresses in the range 0..0xffff + * and stop each CPU using signal processor. Use compare and swap + * to allow just one CPU-stopper and prevent concurrent CPUs from + * stopping each other while leaving the others running. + */ + lhi %r5,0 + lhi %r6,1 + larl %r7,.Lstop_lock + cs %r5,%r6,0(%r7) # single CPU-stopper only + jnz 4f + larl %r7,.Lthis_cpu + stap 0(%r7) # this CPU address + lh %r4,0(%r7) + nilh %r4,0 + lhi %r0,1 + sll %r0,16 # CPU counter + lhi %r3,0 # next CPU address +0: cr %r3,%r4 + je 2f +1: sigp %r1,%r3,SIGP_STOP # stop next CPU + brc SIGP_CC_BUSY,1b +2: ahi %r3,1 + brct %r0,0b +3: sigp %r1,%r4,SIGP_STOP # stop this CPU + brc SIGP_CC_BUSY,3b +4: j 4b ENDPROC(mcck_int_handler) # @@ -664,6 +688,11 @@ ENTRY(stack_overflow) ENDPROC(stack_overflow) #endif + .section .data, "aw" + .align 4 +.Lstop_lock: .long 0 +.Lthis_cpu: .short 0 + .section .rodata, "a" #define SYSCALL(esame,emu) .quad __s390x_ ## esame .globl sys_call_table |