diff options
author | Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com> | 2012-11-28 07:54:14 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2012-11-29 18:14:46 -0500 |
commit | 5a560f8b5ed361c7be783d5a671ea26ca4d6fa01 (patch) | |
tree | ec3e4aa913bcdc0f97222f7a9ee4b52104d1ed1f /arch/x86/kvm/vmx.c | |
parent | e6c7d32172f10b68fa9a3be05aa1231352a52171 (diff) |
KVM: VMX: fix memory order between loading vmcs and clearing vmcs
vmcs->cpu indicates whether it exists on the target cpu, -1 means the vmcs
does not exist on any vcpu
If vcpu load vmcs with vmcs.cpu = -1, it can be directly added to cpu's percpu
list. The list can be corrupted if the cpu prefetch the vmcs's list before
reading vmcs->cpu. Meanwhile, we should remove vmcs from the list before
making vmcs->vcpu == -1 be visible
Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 4406374e3b6d..3606154bbc8b 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -1002,6 +1002,15 @@ static void __loaded_vmcs_clear(void *arg) | |||
1002 | if (per_cpu(current_vmcs, cpu) == loaded_vmcs->vmcs) | 1002 | if (per_cpu(current_vmcs, cpu) == loaded_vmcs->vmcs) |
1003 | per_cpu(current_vmcs, cpu) = NULL; | 1003 | per_cpu(current_vmcs, cpu) = NULL; |
1004 | list_del(&loaded_vmcs->loaded_vmcss_on_cpu_link); | 1004 | list_del(&loaded_vmcs->loaded_vmcss_on_cpu_link); |
1005 | |||
1006 | /* | ||
1007 | * we should ensure updating loaded_vmcs->loaded_vmcss_on_cpu_link | ||
1008 | * is before setting loaded_vmcs->vcpu to -1 which is done in | ||
1009 | * loaded_vmcs_init. Otherwise, other cpu can see vcpu = -1 fist | ||
1010 | * then adds the vmcs into percpu list before it is deleted. | ||
1011 | */ | ||
1012 | smp_wmb(); | ||
1013 | |||
1005 | loaded_vmcs_init(loaded_vmcs); | 1014 | loaded_vmcs_init(loaded_vmcs); |
1006 | } | 1015 | } |
1007 | 1016 | ||
@@ -1537,6 +1546,14 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | |||
1537 | 1546 | ||
1538 | kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu); | 1547 | kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu); |
1539 | local_irq_disable(); | 1548 | local_irq_disable(); |
1549 | |||
1550 | /* | ||
1551 | * Read loaded_vmcs->cpu should be before fetching | ||
1552 | * loaded_vmcs->loaded_vmcss_on_cpu_link. | ||
1553 | * See the comments in __loaded_vmcs_clear(). | ||
1554 | */ | ||
1555 | smp_rmb(); | ||
1556 | |||
1540 | list_add(&vmx->loaded_vmcs->loaded_vmcss_on_cpu_link, | 1557 | list_add(&vmx->loaded_vmcs->loaded_vmcss_on_cpu_link, |
1541 | &per_cpu(loaded_vmcss_on_cpu, cpu)); | 1558 | &per_cpu(loaded_vmcss_on_cpu, cpu)); |
1542 | local_irq_enable(); | 1559 | local_irq_enable(); |