Commit 9e96afab authored by Heiko Carstens's avatar Heiko Carstens

s390/nmi: remove register validation code

Remove the historic machine check handler code which validates registers.
Registers are automatically validated as part of the machine check handling
sequence (see Principles of Operation, Machine-Check Handling chapter,
Validation).
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 37edadee
...@@ -489,16 +489,11 @@ SYM_FUNC_END(psw_idle) ...@@ -489,16 +489,11 @@ SYM_FUNC_END(psw_idle)
*/ */
SYM_CODE_START(mcck_int_handler) SYM_CODE_START(mcck_int_handler)
BPOFF BPOFF
la %r1,4095 # validate r1
spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # validate cpu timer
LBEAR __LC_LAST_BREAK_SAVE_AREA-4095(%r1) # validate bear
lmg %r0,%r15,__LC_GPREGS_SAVE_AREA # validate gprs
lmg %r8,%r9,__LC_MCK_OLD_PSW lmg %r8,%r9,__LC_MCK_OLD_PSW
TSTMSK __LC_MCCK_CODE,MCCK_CODE_SYSTEM_DAMAGE TSTMSK __LC_MCCK_CODE,MCCK_CODE_SYSTEM_DAMAGE
jo .Lmcck_panic # yes -> rest of mcck code invalid jo .Lmcck_panic # yes -> rest of mcck code invalid
TSTMSK __LC_MCCK_CODE,MCCK_CODE_CR_VALID TSTMSK __LC_MCCK_CODE,MCCK_CODE_CR_VALID
jno .Lmcck_panic # control registers invalid -> panic jno .Lmcck_panic # control registers invalid -> panic
lctlg %c0,%c15,__LC_CREGS_SAVE_AREA # validate ctl regs
ptlb ptlb
lghi %r14,__LC_CPU_TIMER_SAVE_AREA lghi %r14,__LC_CPU_TIMER_SAVE_AREA
mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) mvc __LC_MCCK_ENTER_TIMER(8),0(%r14)
......
...@@ -203,64 +203,32 @@ void s390_handle_mcck(void) ...@@ -203,64 +203,32 @@ void s390_handle_mcck(void)
} }
} }
/* /**
* returns 0 if register contents could be validated * nmi_registers_valid - verify if registers are valid
* returns 1 otherwise * @mci: machine check interruption code
*
* Inspect a machine check interruption code and verify if all required
* registers are valid. For some registers the corresponding validity bit is
* ignored and the registers are set to the expected value.
* Returns true if all registers are valid, otherwise false.
*/ */
static int notrace s390_validate_registers(union mci mci) static bool notrace nmi_registers_valid(union mci mci)
{ {
struct mcesa *mcesa;
void *fpt_save_area;
union ctlreg2 cr2; union ctlreg2 cr2;
int kill_task;
u64 zero;
kill_task = 0;
zero = 0;
if (!mci.gr || !mci.fp)
kill_task = 1;
fpt_save_area = &S390_lowcore.floating_pt_save_area;
if (!mci.fc) {
kill_task = 1;
asm volatile(
" lfpc %0\n"
:
: "Q" (zero));
} else {
asm volatile(
" lfpc %0\n"
:
: "Q" (S390_lowcore.fpt_creg_save_area));
}
mcesa = __va(S390_lowcore.mcesad & MCESA_ORIGIN_MASK);
if (!cpu_has_vx()) {
/* Validate floating point registers */
asm volatile(
" ld 0,0(%0)\n"
" ld 1,8(%0)\n"
" ld 2,16(%0)\n"
" ld 3,24(%0)\n"
" ld 4,32(%0)\n"
" ld 5,40(%0)\n"
" ld 6,48(%0)\n"
" ld 7,56(%0)\n"
" ld 8,64(%0)\n"
" ld 9,72(%0)\n"
" ld 10,80(%0)\n"
" ld 11,88(%0)\n"
" ld 12,96(%0)\n"
" ld 13,104(%0)\n"
" ld 14,112(%0)\n"
" ld 15,120(%0)\n"
:
: "a" (fpt_save_area)
: "memory");
} else {
/* Validate vector registers */
union ctlreg0 cr0;
/*
* The getcpu vdso syscall reads the CPU number from the programmable
* field of the TOD clock. Disregard the TOD programmable register
* validity bit and load the CPU number into the TOD programmable field
* unconditionally.
*/
set_tod_programmable_field(raw_smp_processor_id());
/*
* Set the clock comparator register to the next expected value.
*/
set_clock_comparator(S390_lowcore.clock_comparator);
if (!mci.gr || !mci.fp || !mci.fc)
return false;
/* /*
* The vector validity must only be checked if not running a * The vector validity must only be checked if not running a
* KVM guest. For KVM guests the machine check is forwarded by * KVM guest. For KVM guests the machine check is forwarded by
...@@ -269,67 +237,29 @@ static int notrace s390_validate_registers(union mci mci) ...@@ -269,67 +237,29 @@ static int notrace s390_validate_registers(union mci mci)
* saved by KVM and will be restored by KVM. * saved by KVM and will be restored by KVM.
*/ */
if (!mci.vr && !test_cpu_flag(CIF_MCCK_GUEST)) if (!mci.vr && !test_cpu_flag(CIF_MCCK_GUEST))
kill_task = 1; return false;
cr0.reg = S390_lowcore.cregs_save_area[0];
cr0.afp = cr0.vx = 1;
local_ctl_load(0, &cr0.reg);
asm volatile(
" la 1,%0\n"
" VLM 0,15,0,1\n"
" VLM 16,31,256,1\n"
:
: "Q" (*(struct vx_array *)mcesa->vector_save_area)
: "1");
local_ctl_load(0, &S390_lowcore.cregs_save_area[0]);
}
/* Validate access registers */
asm volatile(
" lam 0,15,0(%0)\n"
:
: "a" (&S390_lowcore.access_regs_save_area)
: "memory");
if (!mci.ar) if (!mci.ar)
kill_task = 1; return false;
/* Validate guarded storage registers */
cr2.reg = S390_lowcore.cregs_save_area[2];
if (cr2.gse) {
if (!mci.gs) {
/* /*
* 2 cases: * Two cases for guarded storage registers:
* - machine check in kernel or userspace * - machine check in kernel or userspace
* - machine check while running SIE (KVM guest) * - machine check while running SIE (KVM guest)
* For kernel or userspace the userspace values of * For kernel or userspace the userspace values of guarded storage
* guarded storage control can not be recreated, the * control can not be recreated, the process must be terminated.
* process must be terminated. * For SIE the guest values of guarded storage can not be recreated.
* For SIE the guest values of guarded storage can not * This is either due to a bug or due to GS being disabled in the
* be recreated. This is either due to a bug or due to * guest. The guest will be notified by KVM code and the guests machine
* GS being disabled in the guest. The guest will be * check handling must take care of this. The host values are saved by
* notified by KVM code and the guests machine check * KVM and are not affected.
* handling must take care of this. The host values
* are saved by KVM and are not affected.
*/ */
if (!test_cpu_flag(CIF_MCCK_GUEST)) cr2.reg = S390_lowcore.cregs_save_area[2];
kill_task = 1; if (cr2.gse && !mci.gs && !test_cpu_flag(CIF_MCCK_GUEST))
} else { return false;
load_gs_cb((struct gs_cb *)mcesa->guarded_storage_save_area);
}
}
/*
* The getcpu vdso syscall reads CPU number from the programmable
* field of the TOD clock. Disregard the TOD programmable register
* validity bit and load the CPU number into the TOD programmable
* field unconditionally.
*/
set_tod_programmable_field(raw_smp_processor_id());
/* Validate clock comparator register */
set_clock_comparator(S390_lowcore.clock_comparator);
if (!mci.ms || !mci.pm || !mci.ia) if (!mci.ms || !mci.pm || !mci.ia)
kill_task = 1; return false;
return true;
return kill_task;
} }
NOKPROBE_SYMBOL(s390_validate_registers); NOKPROBE_SYMBOL(nmi_registers_valid);
/* /*
* Backup the guest's machine check info to its description block * Backup the guest's machine check info to its description block
...@@ -427,7 +357,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs) ...@@ -427,7 +357,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
s390_handle_damage(); s390_handle_damage();
} }
} }
if (s390_validate_registers(mci)) { if (!nmi_registers_valid(mci)) {
if (!user_mode(regs)) if (!user_mode(regs))
s390_handle_damage(); s390_handle_damage();
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment