]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
s390/kvm: fix detection of guest machine checks
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 5 Oct 2017 06:29:47 +0000 (08:29 +0200)
committerThadeu Lima de Souza Cascardo <cascardo@canonical.com>
Thu, 16 Nov 2017 13:23:25 +0000 (11:23 -0200)
BugLink: http://bugs.launchpad.net/bugs/1731961
commit 0a5e2ec2647737907d267c09dc9a25fab1468865 upstream.

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")
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
arch/s390/kernel/entry.S

index 21900e1cee9c2e4f35c5bfc5bcb125b303a0d067..d185aa3965bfd0652dfb83f8e07f33939526eb30 100644 (file)
@@ -521,12 +521,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