aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2013-11-16 01:46:03 -0500
committerAlexander Graf <agraf@suse.de>2013-11-18 16:38:30 -0500
commitf019b7ad76e6bdbc8462cbe17ad5b86a25fcdf24 (patch)
tree03a6ed2ce877bb17576ac8337305828d16b8a3bc /arch/powerpc
parentcaaa4c804fae7bb654f7d00b35b8583280a9c52c (diff)
KVM: PPC: Book3S HV: Refine barriers in guest entry/exit
Some users have reported instances of the host hanging with secondary threads of a core waiting for the primary thread to exit the guest, and the primary thread stuck in nap mode. This prompted a review of the memory barriers in the guest entry/exit code, and this is the result. Most of these changes are the suggestions of Dean Burdick <deanburdick@us.ibm.com>. The barriers between updating napping_threads and reading the entry_exit_count on the one hand, and updating entry_exit_count and reading napping_threads on the other, need to be isync not lwsync, since we need to ensure that either the napping_threads update or the entry_exit_count update get seen. It is not sufficient to order the load vs. lwarx, as lwsync does; we need to order the load vs. the stwcx., so we need isync. In addition, we need a full sync before sending IPIs to wake other threads from nap, to ensure that the write to the entry_exit_count is visible before the IPI occurs. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S16
1 files changed, 10 insertions, 6 deletions
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index bc8de75b1925..bde28da69610 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -153,7 +153,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
153 153
15413: b machine_check_fwnmi 15413: b machine_check_fwnmi
155 155
156
157/* 156/*
158 * We come in here when wakened from nap mode on a secondary hw thread. 157 * We come in here when wakened from nap mode on a secondary hw thread.
159 * Relocation is off and most register values are lost. 158 * Relocation is off and most register values are lost.
@@ -224,6 +223,11 @@ kvm_start_guest:
224 /* Clear our vcpu pointer so we don't come back in early */ 223 /* Clear our vcpu pointer so we don't come back in early */
225 li r0, 0 224 li r0, 0
226 std r0, HSTATE_KVM_VCPU(r13) 225 std r0, HSTATE_KVM_VCPU(r13)
226 /*
227 * Make sure we clear HSTATE_KVM_VCPU(r13) before incrementing
228 * the nap_count, because once the increment to nap_count is
229 * visible we could be given another vcpu.
230 */
227 lwsync 231 lwsync
228 /* Clear any pending IPI - we're an offline thread */ 232 /* Clear any pending IPI - we're an offline thread */
229 ld r5, HSTATE_XICS_PHYS(r13) 233 ld r5, HSTATE_XICS_PHYS(r13)
@@ -241,7 +245,6 @@ kvm_start_guest:
241 /* increment the nap count and then go to nap mode */ 245 /* increment the nap count and then go to nap mode */
242 ld r4, HSTATE_KVM_VCORE(r13) 246 ld r4, HSTATE_KVM_VCORE(r13)
243 addi r4, r4, VCORE_NAP_COUNT 247 addi r4, r4, VCORE_NAP_COUNT
244 lwsync /* make previous updates visible */
24551: lwarx r3, 0, r4 24851: lwarx r3, 0, r4
246 addi r3, r3, 1 249 addi r3, r3, 1
247 stwcx. r3, 0, r4 250 stwcx. r3, 0, r4
@@ -990,14 +993,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
990 */ 993 */
991 /* Increment the threads-exiting-guest count in the 0xff00 994 /* Increment the threads-exiting-guest count in the 0xff00
992 bits of vcore->entry_exit_count */ 995 bits of vcore->entry_exit_count */
993 lwsync
994 ld r5,HSTATE_KVM_VCORE(r13) 996 ld r5,HSTATE_KVM_VCORE(r13)
995 addi r6,r5,VCORE_ENTRY_EXIT 997 addi r6,r5,VCORE_ENTRY_EXIT
99641: lwarx r3,0,r6 99841: lwarx r3,0,r6
997 addi r0,r3,0x100 999 addi r0,r3,0x100
998 stwcx. r0,0,r6 1000 stwcx. r0,0,r6
999 bne 41b 1001 bne 41b
1000 lwsync 1002 isync /* order stwcx. vs. reading napping_threads */
1001 1003
1002 /* 1004 /*
1003 * At this point we have an interrupt that we have to pass 1005 * At this point we have an interrupt that we have to pass
@@ -1030,6 +1032,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
1030 sld r0,r0,r4 1032 sld r0,r0,r4
1031 andc. r3,r3,r0 /* no sense IPI'ing ourselves */ 1033 andc. r3,r3,r0 /* no sense IPI'ing ourselves */
1032 beq 43f 1034 beq 43f
1035 /* Order entry/exit update vs. IPIs */
1036 sync
1033 mulli r4,r4,PACA_SIZE /* get paca for thread 0 */ 1037 mulli r4,r4,PACA_SIZE /* get paca for thread 0 */
1034 subf r6,r4,r13 1038 subf r6,r4,r13
103542: andi. r0,r3,1 103942: andi. r0,r3,1
@@ -1638,10 +1642,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
1638 bge kvm_cede_exit 1642 bge kvm_cede_exit
1639 stwcx. r4,0,r6 1643 stwcx. r4,0,r6
1640 bne 31b 1644 bne 31b
1645 /* order napping_threads update vs testing entry_exit_count */
1646 isync
1641 li r0,1 1647 li r0,1
1642 stb r0,HSTATE_NAPPING(r13) 1648 stb r0,HSTATE_NAPPING(r13)
1643 /* order napping_threads update vs testing entry_exit_count */
1644 lwsync
1645 mr r4,r3 1649 mr r4,r3
1646 lwz r7,VCORE_ENTRY_EXIT(r5) 1650 lwz r7,VCORE_ENTRY_EXIT(r5)
1647 cmpwi r7,0x100 1651 cmpwi r7,0x100