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

Commit 17065671 authored by Shreyas B. Prabhu's avatar Shreyas B. Prabhu Committed by Michael Ellerman
Browse files

powerpc/kvm: make hypervisor state restore a function



In the current code, when the thread wakes up in reset vector, some
of the state restore code and check for whether a thread needs to
branch to kvm is duplicated. Reorder the code such that this
duplication is avoided.

At a higher level this is what the change looks like-

Before this patch -
power7_wakeup_tb_loss:
	restore hypervisor state
	if (thread needed by kvm)
		goto kvm_start_guest
	restore nvgprs, cr, pc
	rfid to process context

power7_wakeup_loss:
	restore nvgprs, cr, pc
	rfid to process context

reset vector:
	if (waking from deep idle states)
		goto power7_wakeup_tb_loss
	else
		if (thread needed by kvm)
			goto kvm_start_guest
		goto power7_wakeup_loss

After this patch -
power7_wakeup_tb_loss:
	restore hypervisor state
	return

power7_restore_hyp_resource():
	if (waking from deep idle states)
		goto power7_wakeup_tb_loss
	return

power7_wakeup_loss:
	restore nvgprs, cr, pc
	rfid to process context

reset vector:
	power7_restore_hyp_resource()
	if (thread needed by kvm)
                goto kvm_start_guest
	goto power7_wakeup_loss

Reviewed-by: default avatarPaul Mackerras <paulus@samba.org>
Reviewed-by: default avatarGautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: default avatarShreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent bfd1b7ae
Loading
Loading
Loading
Loading
+4 −24
Original line number Diff line number Diff line
@@ -107,25 +107,9 @@ BEGIN_FTR_SECTION
	beq	9f

	cmpwi	cr3,r13,2

	/*
	 * Check if last bit of HSPGR0 is set. This indicates whether we are
	 * waking up from winkle.
	 */
	GET_PACA(r13)
	clrldi	r5,r13,63
	clrrdi	r13,r13,1
	cmpwi	cr4,r5,1
	mtspr	SPRN_HSPRG0,r13
	bl	power7_restore_hyp_resource

	lbz	r0,PACA_THREAD_IDLE_STATE(r13)
	cmpwi   cr2,r0,PNV_THREAD_NAP
	bgt     cr2,8f				/* Either sleep or Winkle */

	/* Waking up from nap should not cause hypervisor state loss */
	bgt	cr3,.

	/* Waking up from nap */
	li	r0,PNV_THREAD_RUNNING
	stb	r0,PACA_THREAD_IDLE_STATE(r13)	/* Clear thread state */

@@ -143,13 +127,9 @@ BEGIN_FTR_SECTION

	/* Return SRR1 from power7_nap() */
	mfspr	r3,SPRN_SRR1
	beq	cr3,2f
	b	power7_wakeup_noloss
2:	b	power7_wakeup_loss

	/* Fast Sleep wakeup on PowerNV */
8:	GET_PACA(r13)
	b 	power7_wakeup_tb_loss
	blt	cr3,2f
	b	power7_wakeup_loss
2:	b	power7_wakeup_noloss

9:
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+42 −30
Original line number Diff line number Diff line
@@ -276,6 +276,39 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \
20:	nop;


/*
 * Called from reset vector. Check whether we have woken up with
 * hypervisor state loss. If yes, restore hypervisor state and return
 * back to reset vector.
 *
 * r13 - Contents of HSPRG0
 * cr3 - set to gt if waking up with partial/complete hypervisor state loss
 */
_GLOBAL(power7_restore_hyp_resource)
	/*
	 * Check if last bit of HSPGR0 is set. This indicates whether we are
	 * waking up from winkle.
	 */
	clrldi	r5,r13,63
	clrrdi	r13,r13,1
	cmpwi	cr4,r5,1
	mtspr	SPRN_HSPRG0,r13

	lbz	r0,PACA_THREAD_IDLE_STATE(r13)
	cmpwi   cr2,r0,PNV_THREAD_NAP
	bgt     cr2,power7_wakeup_tb_loss	/* Either sleep or Winkle */

	/*
	 * We fall through here if PACA_THREAD_IDLE_STATE shows we are waking
	 * up from nap. At this stage CR3 shouldn't contains 'gt' since that
	 * indicates we are waking with hypervisor state loss from nap.
	 */
	bgt	cr3,.

	blr	/* Return back to System Reset vector from where
		   power7_restore_hyp_resource was invoked */


_GLOBAL(power7_wakeup_tb_loss)
	ld	r2,PACATOC(r13);
	ld	r1,PACAR1(r13)
@@ -284,11 +317,13 @@ _GLOBAL(power7_wakeup_tb_loss)
	 * and they are restored before switching to the process context. Hence
	 * until they are restored, they are free to be used.
	 *
	 * Save SRR1 in a NVGPR as it might be clobbered in opal_call_realmode
	 * (called in CHECK_HMI_INTERRUPT). SRR1 is required to determine the
	 * wakeup reason if we branch to kvm_start_guest.
	 * Save SRR1 and LR in NVGPRs as they might be clobbered in
	 * opal_call_realmode (called in CHECK_HMI_INTERRUPT). SRR1 is required
	 * to determine the wakeup reason if we branch to kvm_start_guest. LR
	 * is required to return back to reset vector after hypervisor state
	 * restore is complete.
	 */

	mflr	r17
	mfspr	r16,SPRN_SRR1
BEGIN_FTR_SECTION
	CHECK_HMI_INTERRUPT
@@ -438,33 +473,10 @@ common_exit:

hypervisor_state_restored:

	li	r5,PNV_THREAD_RUNNING
	stb     r5,PACA_THREAD_IDLE_STATE(r13)

	mtspr	SPRN_SRR1,r16
#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     6f
	b       kvm_start_guest
6:
#endif

	REST_NVGPRS(r1)
	REST_GPR(2, r1)
	ld	r3,_CCR(r1)
	ld	r4,_MSR(r1)
	ld	r5,_NIP(r1)
	addi	r1,r1,INT_FRAME_SIZE
	mtcr	r3
	mfspr	r3,SPRN_SRR1		/* Return SRR1 */
	mtspr	SPRN_SRR1,r4
	mtspr	SPRN_SRR0,r5
	rfid
	mtlr	r17
	blr	/* Return back to System Reset vector from where
		   power7_restore_hyp_resource was invoked */

fastsleep_workaround_at_exit:
	li	r3,1