Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: PPC: Book3S HV: Add more barriers in XIVE load/unload code

On POWER9 systems, we push the VCPU context onto the XIVE (eXternal
Interrupt Virtualization Engine) hardware when entering a guest,
and pull the context off the XIVE when exiting the guest. The push
is done with cache-inhibited stores, and the pull with cache-inhibited
loads.

Testing has revealed that it is possible (though very rare) for
the stores to get reordered with the loads so that we end up with the
guest VCPU context still loaded on the XIVE after we have exited the
guest. When that happens, it is possible for the same VCPU context
to then get loaded on another CPU, which causes the machine to
checkstop.

To fix this, we add I/O barrier instructions (eieio) before and
after the push and pull operations. As partial compensation for the
potential slowdown caused by the extra barriers, we remove the eieio
instructions between the two stores in the push operation, and between
the two loads in the pull operation. (The architecture requires
loads to cache-inhibited, guarded storage to be kept in order, and
requires stores to cache-inhibited, guarded storage likewise to be
kept in order, but allows such loads and stores to be reordered with
respect to each other.)

Reported-by: Carol L Soto <clsoto@us.ibm.com>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>

authored by

Benjamin Herrenschmidt and committed by
Paul Mackerras
ad98dd1a 8f6a9f0d

+5 -3
+5 -3
arch/powerpc/kvm/book3s_hv_rmhandlers.S
··· 989 989 beq no_xive 990 990 ld r11, VCPU_XIVE_SAVED_STATE(r4) 991 991 li r9, TM_QW1_OS 992 - stdcix r11,r9,r10 993 992 eieio 993 + stdcix r11,r9,r10 994 994 lwz r11, VCPU_XIVE_CAM_WORD(r4) 995 995 li r9, TM_QW1_OS + TM_WORD2 996 996 stwcix r11,r9,r10 997 997 li r9, 1 998 998 stw r9, VCPU_XIVE_PUSHED(r4) 999 + eieio 999 1000 no_xive: 1000 1001 #endif /* CONFIG_KVM_XICS */ 1001 1002 ··· 1402 1401 cmpldi cr0, r10, 0 1403 1402 beq 1f 1404 1403 /* First load to pull the context, we ignore the value */ 1405 - lwzx r11, r7, r10 1406 1404 eieio 1405 + lwzx r11, r7, r10 1407 1406 /* Second load to recover the context state (Words 0 and 1) */ 1408 1407 ldx r11, r6, r10 1409 1408 b 3f ··· 1411 1410 cmpldi cr0, r10, 0 1412 1411 beq 1f 1413 1412 /* First load to pull the context, we ignore the value */ 1414 - lwzcix r11, r7, r10 1415 1413 eieio 1414 + lwzcix r11, r7, r10 1416 1415 /* Second load to recover the context state (Words 0 and 1) */ 1417 1416 ldcix r11, r6, r10 1418 1417 3: std r11, VCPU_XIVE_SAVED_STATE(r9) ··· 1422 1421 stw r10, VCPU_XIVE_PUSHED(r9) 1423 1422 stb r10, (VCPU_XIVE_SAVED_STATE+3)(r9) 1424 1423 stb r0, (VCPU_XIVE_SAVED_STATE+4)(r9) 1424 + eieio 1425 1425 1: 1426 1426 #endif /* CONFIG_KVM_XICS */ 1427 1427 /* Save more register state */