KVM: PPC: Book3S HV P9: Fix guest TM support

The conversion to C introduced several bugs in TM handling that can
cause host crashes with TM bad thing interrupts. Mostly just simple
typos or missed logic in the conversion that got through due to my
not testing TM in the guest sufficiently.

- Early TM emulation for the softpatch interrupt should be done if fake
suspend mode is _not_ active.

- Early TM emulation wants to return immediately to the guest so as to
not doom transactions unnecessarily.

- And if exiting from the guest, the host MSR should include the TM[S]
bit if the guest was T/S, before it is treclaimed.

After this fix, all the TM selftests pass when running on a P9 processor
that implements TM with softpatch interrupt.

Fixes: 89d35b2391015 ("KVM: PPC: Book3S HV P9: Implement the rest of the P9 path in C")
Reported-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210712013650.376325-1-npiggin@gmail.com

authored by Nicholas Piggin and committed by Michael Ellerman e44fbdb6 e73f0f0e

+22 -3
+22 -3
arch/powerpc/kvm/book3s_hv_p9_entry.c
··· 317 */ 318 mtspr(SPRN_HDEC, hdec); 319 320 mtspr(SPRN_DAR, vcpu->arch.shregs.dar); 321 mtspr(SPRN_DSISR, vcpu->arch.shregs.dsisr); 322 mtspr(SPRN_SRR0, vcpu->arch.shregs.srr0); ··· 418 * is in real suspend mode and is trying to transition to 419 * transactional mode. 420 */ 421 - if (local_paca->kvm_hstate.fake_suspend && 422 (vcpu->arch.shregs.msr & MSR_TS_S)) { 423 if (kvmhv_p9_tm_emulation_early(vcpu)) { 424 - /* Prevent it being handled again. */ 425 - trap = 0; 426 } 427 } 428 #endif ··· 514 * If we are in real mode, only switch MMU on after the MMU is 515 * switched to host, to avoid the P9_RADIX_PREFETCH_BUG. 516 */ 517 __mtmsrd(msr, 0); 518 519 end_timing(vcpu);
··· 317 */ 318 mtspr(SPRN_HDEC, hdec); 319 320 + #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 321 + tm_return_to_guest: 322 + #endif 323 mtspr(SPRN_DAR, vcpu->arch.shregs.dar); 324 mtspr(SPRN_DSISR, vcpu->arch.shregs.dsisr); 325 mtspr(SPRN_SRR0, vcpu->arch.shregs.srr0); ··· 415 * is in real suspend mode and is trying to transition to 416 * transactional mode. 417 */ 418 + if (!local_paca->kvm_hstate.fake_suspend && 419 (vcpu->arch.shregs.msr & MSR_TS_S)) { 420 if (kvmhv_p9_tm_emulation_early(vcpu)) { 421 + /* 422 + * Go straight back into the guest with the 423 + * new NIP/MSR as set by TM emulation. 424 + */ 425 + mtspr(SPRN_HSRR0, vcpu->arch.regs.nip); 426 + mtspr(SPRN_HSRR1, vcpu->arch.shregs.msr); 427 + 428 + /* 429 + * tm_return_to_guest re-loads SRR0/1, DAR, 430 + * DSISR after RI is cleared, in case they had 431 + * been clobbered by a MCE. 432 + */ 433 + __mtmsrd(0, 1); /* clear RI */ 434 + goto tm_return_to_guest; 435 } 436 } 437 #endif ··· 499 * If we are in real mode, only switch MMU on after the MMU is 500 * switched to host, to avoid the P9_RADIX_PREFETCH_BUG. 501 */ 502 + if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) && 503 + vcpu->arch.shregs.msr & MSR_TS_MASK) 504 + msr |= MSR_TS_S; 505 + 506 __mtmsrd(msr, 0); 507 508 end_timing(vcpu);