Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: PPC: Book3S HV: Make idle_kvm_start_guest() return 0 if it went to guest

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

+7 -2
+7 -2
arch/powerpc/kvm/book3s_hv_rmhandlers.S
··· 264 264 stdu r1, -SWITCH_FRAME_SIZE(r4) 265 265 // Switch to new frame on emergency stack 266 266 mr r1, r4 267 + std r3, 32(r1) // Save SRR1 wakeup value 267 268 SAVE_NVGPRS(r1) 268 269 269 270 /* ··· 315 314 beq kvm_no_guest 316 315 317 316 kvm_secondary_got_guest: 317 + 318 + // About to go to guest, clear saved SRR1 319 + li r0, 0 320 + std r0, 32(r1) 318 321 319 322 /* Set HSTATE_DSCR(r13) to something sensible */ 320 323 ld r6, PACA_DSCR_DEFAULT(r13) ··· 399 394 mfspr r4, SPRN_LPCR 400 395 rlwimi r4, r3, 0, LPCR_PECE0 | LPCR_PECE1 401 396 mtspr SPRN_LPCR, r4 402 - /* set up r3 for return */ 403 - mfspr r3,SPRN_SRR1 397 + // Return SRR1 wakeup value, or 0 if we went into the guest 398 + ld r3, 32(r1) 404 399 REST_NVGPRS(r1) 405 400 ld r1, 0(r1) // Switch back to caller stack 406 401 ld r0, 16(r1) // Reload LR