From: QingFeng Hao <haoqf@linux.vnet.ibm.com>
Subject: s390/kvm: fix detection of guest machine checks
Patch-mainline: v4.14-rc7
Git-commit: 0a5e2ec2647737907d267c09dc9a25fab1468865
References: FATE#324256,LTC#160417,bsc#1066327
Summary: kvm: Robust Machine Check Handling
Description: A machine check is caused by a machine malfunction and not by data
or instructions. The machine check could happen on CPU, I/O,
storage etc.
There are several kinds of machine checks, e.g. System Damage(SD),
Instruction Processing Damage(IPD), Delayed Access Exception(DAE),
Channel Report Pending(CRW), External Damage(ED).
In general, they are of two types: exigent condition and
repressible condition. The 64 bits Machine-Check-Interruption
Code(MCIC) in lowcore is set to indicate the current machine
check's type with the validity bits when a machine check happens.
Meanwhile, the machine check handler set in lowcore is called to
handle it. Through the validity bits in MCIC, the program can
determine if the machine check could be recovered.
The present machine check handler can handle almost all of the
machine checks and validate the registers to recover the machine
by the validity bits in MCIC. It can also inject the CRW machine
check request from QEMU to the guest.
VS1522 improves it to inject most of the host supported machine
checks to the guest if they happen during the guest's running
and the necessary validity bits to recover are set. Exceptions are
the SD and Timer Facility Damage. The original handling is kept
and they will not be injected into the guest.
Additionally, this line item reinjects the DAE machine check
if it happens during the guest's running instead of damage host
because DAE could be caused by the program's using an improper
procedure to update the DAT tables.
The program will not inject the machine check for device hotplug
such as CRW into the guest. For machine checks happening during
the nested guest's(guest-3) running, guest-2 will reinject them
into guest-3.
Upstream-Description:
s390/kvm: fix detection of guest machine checks
The new detection code for guest machine checks added a check based
on %r11 to .Lcleanup_sie to distinguish between normal asynchronous
interrupts and machine checks. But the funtion is called from the
program check handler as well with an undefined value in %r11.
The effect is that all program exceptions pointing to the SIE instruction
will set the CIF_MCCK_GUEST bit. The bit stays set for the CPU until the
next machine check comes in which will incorrectly be interpreted as a
guest machine check.
The simplest fix is to stop using .Lcleanup_sie in the program check
handler and duplicate a few instructions.
Fixes: c929500d7a5a ("s390/nmi: s390: New low level handling for machine check happening in guest")
Cc: <stable@vger.kernel.org> # v4.13+
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
Acked-by: Hannes Reinecke <hare@suse.com>
---
arch/s390/kernel/entry.S | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -508,12 +508,15 @@ ENTRY(pgm_check_handler)
tmhh %r8,0x0001 # test problem state bit
jnz 2f # -> fault in user space
#if IS_ENABLED(CONFIG_KVM)
- # cleanup critical section for sie64a
+ # cleanup critical section for program checks in sie64a
lgr %r14,%r9
slg %r14,BASED(.Lsie_critical_start)
clg %r14,BASED(.Lsie_critical_length)
jhe 0f
- brasl %r14,.Lcleanup_sie
+ lg %r14,__SF_EMPTY(%r15) # get control block pointer
+ ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE
+ lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
+ larl %r9,sie_exit # skip forward to sie_exit
#endif
0: tmhh %r8,0x4000 # PER bit set in old PSW ?
jnz 1f # -> enabled, can't be a double fault