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>
This commit is contained in:
parent
e2c13d6420
commit
7f6dc8d4c8
|
@ -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
|
||||
|
|
|
@ -205,14 +205,6 @@ static int notrace s390_check_registers(union mci mci, int umode)
|
|||
s390_handle_damage();
|
||||
kill_task = 1;
|
||||
}
|
||||
/* Check control registers */
|
||||
if (!mci.cr) {
|
||||
/*
|
||||
* Control registers have unknown contents.
|
||||
* Can't recover and therefore stopping machine.
|
||||
*/
|
||||
s390_handle_damage();
|
||||
}
|
||||
if (!mci.fp) {
|
||||
/*
|
||||
* Floating point registers can't be restored. If the
|
||||
|
@ -273,22 +265,6 @@ static int notrace s390_check_registers(union mci mci, int umode)
|
|||
kill_task = 1;
|
||||
}
|
||||
}
|
||||
/* Check if old PSW is valid */
|
||||
if (!mci.wp) {
|
||||
/*
|
||||
* Can't tell if we come from user or kernel mode
|
||||
* -> stopping machine.
|
||||
*/
|
||||
s390_handle_damage();
|
||||
}
|
||||
/* Check for invalid kernel instruction address */
|
||||
if (!mci.ia && !umode) {
|
||||
/*
|
||||
* The instruction address got lost while running
|
||||
* in the kernel -> stopping machine.
|
||||
*/
|
||||
s390_handle_damage();
|
||||
}
|
||||
|
||||
if (!mci.ms || !mci.pm || !mci.ia)
|
||||
kill_task = 1;
|
||||
|
@ -353,11 +329,6 @@ int notrace s390_do_machine_check(struct pt_regs *regs)
|
|||
mci.val = S390_lowcore.mcck_interruption_code;
|
||||
mcck = this_cpu_ptr(&cpu_mcck);
|
||||
|
||||
if (mci.sd) {
|
||||
/* System damage -> stopping machine */
|
||||
s390_handle_damage();
|
||||
}
|
||||
|
||||
/*
|
||||
* Reinject the instruction processing damages' machine checks
|
||||
* including Delayed Access Exception into the guest
|
||||
|
|
Loading…
Reference in New Issue