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

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
...@@ -107,25 +107,9 @@ BEGIN_FTR_SECTION ...@@ -107,25 +107,9 @@ BEGIN_FTR_SECTION
beq 9f beq 9f
cmpwi cr3,r13,2 cmpwi cr3,r13,2
/*
* Check if last bit of HSPGR0 is set. This indicates whether we are
* waking up from winkle.
*/
GET_PACA(r13) GET_PACA(r13)
clrldi r5,r13,63 bl power7_restore_hyp_resource
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,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 li r0,PNV_THREAD_RUNNING
stb r0,PACA_THREAD_IDLE_STATE(r13) /* Clear thread state */ stb r0,PACA_THREAD_IDLE_STATE(r13) /* Clear thread state */
...@@ -143,13 +127,9 @@ BEGIN_FTR_SECTION ...@@ -143,13 +127,9 @@ BEGIN_FTR_SECTION
/* Return SRR1 from power7_nap() */ /* Return SRR1 from power7_nap() */
mfspr r3,SPRN_SRR1 mfspr r3,SPRN_SRR1
beq cr3,2f blt cr3,2f
b power7_wakeup_noloss b power7_wakeup_loss
2: b power7_wakeup_loss 2: b power7_wakeup_noloss
/* Fast Sleep wakeup on PowerNV */
8: GET_PACA(r13)
b power7_wakeup_tb_loss
9: 9:
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206) END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
......
...@@ -276,6 +276,39 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \ ...@@ -276,6 +276,39 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \
20: nop; 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) _GLOBAL(power7_wakeup_tb_loss)
ld r2,PACATOC(r13); ld r2,PACATOC(r13);
ld r1,PACAR1(r13) ld r1,PACAR1(r13)
...@@ -284,11 +317,13 @@ _GLOBAL(power7_wakeup_tb_loss) ...@@ -284,11 +317,13 @@ _GLOBAL(power7_wakeup_tb_loss)
* and they are restored before switching to the process context. Hence * and they are restored before switching to the process context. Hence
* until they are restored, they are free to be used. * until they are restored, they are free to be used.
* *
* Save SRR1 in a NVGPR as it might be clobbered in opal_call_realmode * Save SRR1 and LR in NVGPRs as they might be clobbered in
* (called in CHECK_HMI_INTERRUPT). SRR1 is required to determine the * opal_call_realmode (called in CHECK_HMI_INTERRUPT). SRR1 is required
* wakeup reason if we branch to kvm_start_guest. * 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 mfspr r16,SPRN_SRR1
BEGIN_FTR_SECTION BEGIN_FTR_SECTION
CHECK_HMI_INTERRUPT CHECK_HMI_INTERRUPT
...@@ -438,33 +473,10 @@ common_exit: ...@@ -438,33 +473,10 @@ common_exit:
hypervisor_state_restored: hypervisor_state_restored:
li r5,PNV_THREAD_RUNNING
stb r5,PACA_THREAD_IDLE_STATE(r13)
mtspr SPRN_SRR1,r16 mtspr SPRN_SRR1,r16
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE mtlr r17
li r0,KVM_HWTHREAD_IN_KERNEL blr /* Return back to System Reset vector from where
stb r0,HSTATE_HWTHREAD_STATE(r13) power7_restore_hyp_resource was invoked */
/* 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
fastsleep_workaround_at_exit: fastsleep_workaround_at_exit:
li r3,1 li r3,1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment