KVM: PPC: Book3S HV: Make idle_kvm_start_guest() return 0 if it went to guest
authorMichael Ellerman <mpe@ellerman.id.au>
Fri, 15 Oct 2021 12:02:08 +0000 (23:02 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 15 Oct 2021 13:40:03 +0000 (00:40 +1100)
We call idle_kvm_start_guest() from power7_offline() if the thread has
been requested to enter KVM. We pass it the SRR1 value that was returned
from power7_idle_insn() which tells us what sort of wakeup we're
processing.

Depending on the SRR1 value we pass in, the KVM code might enter the
guest, or it might return to us to do some host action if the wakeup
requires it.

If idle_kvm_start_guest() is able to handle the wakeup, and enter the
guest it is supposed to indicate that by returning a zero SRR1 value to
us.

That was the behaviour prior to commit 10d91611f426 ("powerpc/64s:
Reimplement book3s idle code in C"), however in that commit the
handling of SRR1 was reworked, and the zeroing behaviour was lost.

Returning from idle_kvm_start_guest() without zeroing the SRR1 value can
confuse the host offline code, causing the guest to crash and other
weirdness.

Fixes: 10d91611f426 ("powerpc/64s: Reimplement book3s idle code in C")
Cc: stable@vger.kernel.org # v5.2+
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20211015133929.832061-2-mpe@ellerman.id.au
arch/powerpc/kvm/book3s_hv_rmhandlers.S

index ec57952b60b012059683f6fac45d7c4dbb0b9722..eb776d0c5d8e97115714e79ffdfcd9b8de177576 100644 (file)
@@ -264,6 +264,7 @@ _GLOBAL(idle_kvm_start_guest)
        stdu    r1, -SWITCH_FRAME_SIZE(r4)
        // Switch to new frame on emergency stack
        mr      r1, r4
+       std     r3, 32(r1)      // Save SRR1 wakeup value
        SAVE_NVGPRS(r1)
 
        /*
@@ -315,6 +316,10 @@ kvm_unsplit_wakeup:
 
 kvm_secondary_got_guest:
 
+       // About to go to guest, clear saved SRR1
+       li      r0, 0
+       std     r0, 32(r1)
+
        /* Set HSTATE_DSCR(r13) to something sensible */
        ld      r6, PACA_DSCR_DEFAULT(r13)
        std     r6, HSTATE_DSCR(r13)
@@ -394,8 +399,8 @@ kvm_no_guest:
        mfspr   r4, SPRN_LPCR
        rlwimi  r4, r3, 0, LPCR_PECE0 | LPCR_PECE1
        mtspr   SPRN_LPCR, r4
-       /* set up r3 for return */
-       mfspr   r3,SPRN_SRR1
+       // Return SRR1 wakeup value, or 0 if we went into the guest
+       ld      r3, 32(r1)
        REST_NVGPRS(r1)
        ld      r1, 0(r1)       // Switch back to caller stack
        ld      r0, 16(r1)      // Reload LR