diff options
author | Paul Mackerras <paulus@samba.org> | 2013-11-16 01:46:03 -0500 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2013-11-18 16:38:30 -0500 |
commit | f019b7ad76e6bdbc8462cbe17ad5b86a25fcdf24 (patch) | |
tree | 03a6ed2ce877bb17576ac8337305828d16b8a3bc /arch/powerpc | |
parent | caaa4c804fae7bb654f7d00b35b8583280a9c52c (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.S | 16 |
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 | ||
154 | 13: b machine_check_fwnmi | 154 | 13: 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 */ | ||
245 | 51: lwarx r3, 0, r4 | 248 | 51: 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 |
996 | 41: lwarx r3,0,r6 | 998 | 41: 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 |
1035 | 42: andi. r0,r3,1 | 1039 | 42: 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 |