Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 94a04bc2 authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman
Browse files

KVM: PPC: Book3S HV: POWER9 does not require secondary thread management



POWER9 CPUs have independent MMU contexts per thread, so KVM does not
need to quiesce secondary threads, so the hwthread_req/hwthread_state
protocol does not have to be used. So patch it away on POWER9, and patch
away the branch from the Linux idle wakeup to kvm_start_guest that is
never used.

Add a warning and error out of kvmppc_grab_hwthread in case it is ever
called on POWER9.

This avoids a hwsync in the idle wakeup path on POWER9.

Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Acked-by: default avatarPaul Mackerras <paulus@ozlabs.org>
[mpe: Use WARN(...) instead of WARN_ON()/pr_err(...)]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 94171b19
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -104,6 +104,10 @@ struct kvmppc_host_state {
	u8 napping;

#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
	/*
	 * hwthread_req/hwthread_state pair is used to pull sibling threads
	 * out of guest on pre-ISAv3.0B CPUs where threads share MMU.
	 */
	u8 hwthread_req;
	u8 hwthread_state;
	u8 host_ipi;
+24 −11
Original line number Diff line number Diff line
@@ -242,13 +242,20 @@ enter_winkle:
/*
 * r3 - PSSCR value corresponding to the requested stop state.
 */
power_enter_stop:
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
	/* Tell KVM we're entering idle */
power_enter_stop_kvm_rm:
	/*
	 * This is currently unused because POWER9 KVM does not have to
	 * gather secondary threads into sibling mode, but the code is
	 * here in case that function is required.
	 *
	 * Tell KVM we're entering idle.
	 */
	li	r4,KVM_HWTHREAD_IN_IDLE
	/* DO THIS IN REAL MODE!  See comment above. */
	stb	r4,HSTATE_HWTHREAD_STATE(r13)
#endif
power_enter_stop:
/*
 * Check if we are executing the lite variant with ESL=EC=0
 */
@@ -411,6 +418,18 @@ pnv_powersave_wakeup_mce:

	b	pnv_powersave_wakeup

#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
kvm_start_guest_check:
	li	r0,KVM_HWTHREAD_IN_KERNEL
	stb	r0,HSTATE_HWTHREAD_STATE(r13)
	/* Order setting hwthread_state vs. testing hwthread_req */
	sync
	lbz	r0,HSTATE_HWTHREAD_REQ(r13)
	cmpwi	r0,0
	beqlr
	b	kvm_start_guest
#endif

/*
 * Called from reset vector for powersave wakeups.
 * cr3 - set to gt if waking up with partial/complete hypervisor state loss
@@ -435,15 +454,9 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300)
	mr	r3,r12

#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
	li	r0,KVM_HWTHREAD_IN_KERNEL
	stb	r0,HSTATE_HWTHREAD_STATE(r13)
	/* Order setting hwthread_state vs. testing hwthread_req */
	sync
	lbz	r0,HSTATE_HWTHREAD_REQ(r13)
	cmpwi	r0,0
	beq	1f
	b	kvm_start_guest
1:
BEGIN_FTR_SECTION
	bl	kvm_start_guest_check
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
#endif

	/* Return SRR1 from power7_nap() */
+12 −1
Original line number Diff line number Diff line
@@ -2111,6 +2111,15 @@ static int kvmppc_grab_hwthread(int cpu)
	struct paca_struct *tpaca;
	long timeout = 10000;

	/*
	 * ISA v3.0 idle routines do not set hwthread_state or test
	 * hwthread_req, so they can not grab idle threads.
	 */
	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
		WARN(1, "KVM: can not control sibling threads\n");
		return -EBUSY;
	}

	tpaca = &paca[cpu];

	/* Ensure the thread won't go into the kernel if it wakes */
@@ -2145,10 +2154,12 @@ static void kvmppc_release_hwthread(int cpu)
	struct paca_struct *tpaca;

	tpaca = &paca[cpu];
	tpaca->kvm_hstate.hwthread_req = 0;
	tpaca->kvm_hstate.kvm_vcpu = NULL;
	tpaca->kvm_hstate.kvm_vcore = NULL;
	tpaca->kvm_hstate.kvm_split_mode = NULL;
	if (!cpu_has_feature(CPU_FTR_ARCH_300))
		tpaca->kvm_hstate.hwthread_req = 0;

}

static void radix_flush_cpu(struct kvm *kvm, int cpu, struct kvm_vcpu *vcpu)
+8 −0
Original line number Diff line number Diff line
@@ -149,9 +149,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
	subf	r4, r4, r3
	mtspr	SPRN_DEC, r4

BEGIN_FTR_SECTION
	/* hwthread_req may have got set by cede or no vcpu, so clear it */
	li	r0, 0
	stb	r0, HSTATE_HWTHREAD_REQ(r13)
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)

	/*
	 * For external interrupts we need to call the Linux
@@ -314,6 +316,7 @@ kvm_novcpu_exit:
 * Relocation is off and most register values are lost.
 * r13 points to the PACA.
 * r3 contains the SRR1 wakeup value, SRR1 is trashed.
 * This is not used by ISAv3.0B processors.
 */
	.globl	kvm_start_guest
kvm_start_guest:
@@ -432,6 +435,9 @@ kvm_secondary_got_guest:
 * While waiting we also need to check if we get given a vcpu to run.
 */
kvm_no_guest:
BEGIN_FTR_SECTION
	twi	31,0,0
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
	lbz	r3, HSTATE_HWTHREAD_REQ(r13)
	cmpwi	r3, 0
	bne	53f
@@ -2466,8 +2472,10 @@ kvm_do_nap:
	clrrdi	r0, r0, 1
	mtspr	SPRN_CTRLT, r0

BEGIN_FTR_SECTION
	li	r0,1
	stb	r0,HSTATE_HWTHREAD_REQ(r13)
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
	mfspr	r5,SPRN_LPCR
	ori	r5,r5,LPCR_PECE0 | LPCR_PECE1
BEGIN_FTR_SECTION