Commit 41f77991 authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman
Browse files

KVM: PPC: Book3S HV P9: Switch to guest MMU context as late as possible



Move MMU context switch as late as reasonably possible to minimise code
running with guest context switched in. This becomes more important when
this code may run in real-mode, with later changes.

Move WARN_ON as early as possible so program check interrupts are less
likely to tangle everything up.

Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210528090752.3542186-21-npiggin@gmail.com
parent edba6aff
Loading
Loading
Loading
Loading
+20 −20
Original line number Diff line number Diff line
@@ -138,8 +138,13 @@ int kvmhv_vcpu_entry_p9(struct kvm_vcpu *vcpu, u64 time_limit, unsigned long lpc
	if (hdec < 0)
		return BOOK3S_INTERRUPT_HV_DECREMENTER;

	WARN_ON_ONCE(vcpu->arch.shregs.msr & MSR_HV);
	WARN_ON_ONCE(!(vcpu->arch.shregs.msr & MSR_ME));

	start_timing(vcpu, &vcpu->arch.rm_entry);

	vcpu->arch.ceded = 0;

	if (vc->tb_offset) {
		u64 new_tb = mftb() + vc->tb_offset;
		mtspr(SPRN_TBU40, new_tb);
@@ -188,26 +193,6 @@ int kvmhv_vcpu_entry_p9(struct kvm_vcpu *vcpu, u64 time_limit, unsigned long lpc

	mtspr(SPRN_HFSCR, vcpu->arch.hfscr);

	mtspr(SPRN_SPRG0, vcpu->arch.shregs.sprg0);
	mtspr(SPRN_SPRG1, vcpu->arch.shregs.sprg1);
	mtspr(SPRN_SPRG2, vcpu->arch.shregs.sprg2);
	mtspr(SPRN_SPRG3, vcpu->arch.shregs.sprg3);

	mtspr(SPRN_AMOR, ~0UL);

	switch_mmu_to_guest_radix(kvm, vcpu, lpcr);

	/*
	 * P9 suppresses the HDEC exception when LPCR[HDICE] = 0,
	 * so set guest LPCR (with HDICE) before writing HDEC.
	 */
	mtspr(SPRN_HDEC, hdec);

	vcpu->arch.ceded = 0;

	WARN_ON_ONCE(vcpu->arch.shregs.msr & MSR_HV);
	WARN_ON_ONCE(!(vcpu->arch.shregs.msr & MSR_ME));

	mtspr(SPRN_HSRR0, vcpu->arch.regs.nip);
	mtspr(SPRN_HSRR1, (vcpu->arch.shregs.msr & ~MSR_HV) | MSR_ME);

@@ -226,6 +211,21 @@ int kvmhv_vcpu_entry_p9(struct kvm_vcpu *vcpu, u64 time_limit, unsigned long lpc
	 */
	mtspr(SPRN_HDSISR, HDSISR_CANARY);

	mtspr(SPRN_SPRG0, vcpu->arch.shregs.sprg0);
	mtspr(SPRN_SPRG1, vcpu->arch.shregs.sprg1);
	mtspr(SPRN_SPRG2, vcpu->arch.shregs.sprg2);
	mtspr(SPRN_SPRG3, vcpu->arch.shregs.sprg3);

	mtspr(SPRN_AMOR, ~0UL);

	switch_mmu_to_guest_radix(kvm, vcpu, lpcr);

	/*
	 * P9 suppresses the HDEC exception when LPCR[HDICE] = 0,
	 * so set guest LPCR (with HDICE) before writing HDEC.
	 */
	mtspr(SPRN_HDEC, hdec);

	__mtmsrd(0, 1); /* clear RI */

	mtspr(SPRN_DAR, vcpu->arch.shregs.dar);