diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2017-10-05 02:29:47 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2017-10-25 01:59:30 -0400 |
commit | 0a5e2ec2647737907d267c09dc9a25fab1468865 (patch) | |
tree | b6788e55a1560e921419acaea0ed48772b9ed1e6 | |
parent | f34157878d3b17641ad2366988600c23c89d98b2 (diff) |
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>
-rw-r--r-- | arch/s390/kernel/entry.S | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 21900e1cee9c..d185aa3965bf 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -521,12 +521,15 @@ ENTRY(pgm_check_handler) | |||
521 | tmhh %r8,0x0001 # test problem state bit | 521 | tmhh %r8,0x0001 # test problem state bit |
522 | jnz 2f # -> fault in user space | 522 | jnz 2f # -> fault in user space |
523 | #if IS_ENABLED(CONFIG_KVM) | 523 | #if IS_ENABLED(CONFIG_KVM) |
524 | # cleanup critical section for sie64a | 524 | # cleanup critical section for program checks in sie64a |
525 | lgr %r14,%r9 | 525 | lgr %r14,%r9 |
526 | slg %r14,BASED(.Lsie_critical_start) | 526 | slg %r14,BASED(.Lsie_critical_start) |
527 | clg %r14,BASED(.Lsie_critical_length) | 527 | clg %r14,BASED(.Lsie_critical_length) |
528 | jhe 0f | 528 | jhe 0f |
529 | brasl %r14,.Lcleanup_sie | 529 | lg %r14,__SF_EMPTY(%r15) # get control block pointer |
530 | ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE | ||
531 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | ||
532 | larl %r9,sie_exit # skip forward to sie_exit | ||
530 | #endif | 533 | #endif |
531 | 0: tmhh %r8,0x4000 # PER bit set in old PSW ? | 534 | 0: tmhh %r8,0x4000 # PER bit set in old PSW ? |
532 | jnz 1f # -> enabled, can't be a double fault | 535 | jnz 1f # -> enabled, can't be a double fault |