aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm
diff options
context:
space:
mode:
authorDavid Matlack <dmatlack@google.com>2016-07-13 20:16:37 -0400
committerRadim Krčmář <rkrcmar@redhat.com>2016-08-01 08:49:05 -0400
commit4f2777bc97974b0df9276ee9a85155a9e27a5282 (patch)
tree44b8579722765e29f3a69ff09d2950165f94cfb4 /arch/x86/kvm
parent601045bff74569374b3d5b34dbb9bad71adf3aa5 (diff)
kvm: x86: nVMX: maintain internal copy of current VMCS
KVM maintains L1's current VMCS in guest memory, at the guest physical page identified by the argument to VMPTRLD. This makes hairy time-of-check to time-of-use bugs possible,as VCPUs can be writing the the VMCS page in memory while KVM is emulating VMLAUNCH and VMRESUME. The spec documents that writing to the VMCS page while it is loaded is "undefined". Therefore it is reasonable to load the entire VMCS into an internal cache during VMPTRLD and ignore writes to the VMCS page -- the guest should be using VMREAD and VMWRITE to access the current VMCS. To adhere to the spec, KVM should flush the current VMCS during VMPTRLD, and the target VMCS during VMCLEAR (as given by the operand to VMCLEAR). Since this implementation of VMCS caching only maintains the the current VMCS, VMCLEAR will only do a flush if the operand to VMCLEAR is the current VMCS pointer. KVM will also flush during VMXOFF, which is not mandated by the spec, but also not in conflict with the spec. Signed-off-by: David Matlack <dmatlack@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r--arch/x86/kvm/vmx.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index b61cdadf8623..151d2619238c 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -405,6 +405,12 @@ struct nested_vmx {
405 /* The host-usable pointer to the above */ 405 /* The host-usable pointer to the above */
406 struct page *current_vmcs12_page; 406 struct page *current_vmcs12_page;
407 struct vmcs12 *current_vmcs12; 407 struct vmcs12 *current_vmcs12;
408 /*
409 * Cache of the guest's VMCS, existing outside of guest memory.
410 * Loaded from guest memory during VMPTRLD. Flushed to guest
411 * memory during VMXOFF, VMCLEAR, VMPTRLD.
412 */
413 struct vmcs12 *cached_vmcs12;
408 struct vmcs *current_shadow_vmcs; 414 struct vmcs *current_shadow_vmcs;
409 /* 415 /*
410 * Indicates if the shadow vmcs must be updated with the 416 * Indicates if the shadow vmcs must be updated with the
@@ -858,7 +864,7 @@ static inline short vmcs_field_to_offset(unsigned long field)
858 864
859static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu) 865static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
860{ 866{
861 return to_vmx(vcpu)->nested.current_vmcs12; 867 return to_vmx(vcpu)->nested.cached_vmcs12;
862} 868}
863 869
864static struct page *nested_get_page(struct kvm_vcpu *vcpu, gpa_t addr) 870static struct page *nested_get_page(struct kvm_vcpu *vcpu, gpa_t addr)
@@ -6987,10 +6993,16 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
6987 return 1; 6993 return 1;
6988 } 6994 }
6989 6995
6996 vmx->nested.cached_vmcs12 = kmalloc(VMCS12_SIZE, GFP_KERNEL);
6997 if (!vmx->nested.cached_vmcs12)
6998 return -ENOMEM;
6999
6990 if (enable_shadow_vmcs) { 7000 if (enable_shadow_vmcs) {
6991 shadow_vmcs = alloc_vmcs(); 7001 shadow_vmcs = alloc_vmcs();
6992 if (!shadow_vmcs) 7002 if (!shadow_vmcs) {
7003 kfree(vmx->nested.cached_vmcs12);
6993 return -ENOMEM; 7004 return -ENOMEM;
7005 }
6994 /* mark vmcs as shadow */ 7006 /* mark vmcs as shadow */
6995 shadow_vmcs->revision_id |= (1u << 31); 7007 shadow_vmcs->revision_id |= (1u << 31);
6996 /* init shadow vmcs */ 7008 /* init shadow vmcs */
@@ -7061,6 +7073,11 @@ static inline void nested_release_vmcs12(struct vcpu_vmx *vmx)
7061 vmcs_write64(VMCS_LINK_POINTER, -1ull); 7073 vmcs_write64(VMCS_LINK_POINTER, -1ull);
7062 } 7074 }
7063 vmx->nested.posted_intr_nv = -1; 7075 vmx->nested.posted_intr_nv = -1;
7076
7077 /* Flush VMCS12 to guest memory */
7078 memcpy(vmx->nested.current_vmcs12, vmx->nested.cached_vmcs12,
7079 VMCS12_SIZE);
7080
7064 kunmap(vmx->nested.current_vmcs12_page); 7081 kunmap(vmx->nested.current_vmcs12_page);
7065 nested_release_page(vmx->nested.current_vmcs12_page); 7082 nested_release_page(vmx->nested.current_vmcs12_page);
7066 vmx->nested.current_vmptr = -1ull; 7083 vmx->nested.current_vmptr = -1ull;
@@ -7081,6 +7098,7 @@ static void free_nested(struct vcpu_vmx *vmx)
7081 nested_release_vmcs12(vmx); 7098 nested_release_vmcs12(vmx);
7082 if (enable_shadow_vmcs) 7099 if (enable_shadow_vmcs)
7083 free_vmcs(vmx->nested.current_shadow_vmcs); 7100 free_vmcs(vmx->nested.current_shadow_vmcs);
7101 kfree(vmx->nested.cached_vmcs12);
7084 /* Unpin physical memory we referred to in current vmcs02 */ 7102 /* Unpin physical memory we referred to in current vmcs02 */
7085 if (vmx->nested.apic_access_page) { 7103 if (vmx->nested.apic_access_page) {
7086 nested_release_page(vmx->nested.apic_access_page); 7104 nested_release_page(vmx->nested.apic_access_page);
@@ -7484,6 +7502,13 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)
7484 vmx->nested.current_vmptr = vmptr; 7502 vmx->nested.current_vmptr = vmptr;
7485 vmx->nested.current_vmcs12 = new_vmcs12; 7503 vmx->nested.current_vmcs12 = new_vmcs12;
7486 vmx->nested.current_vmcs12_page = page; 7504 vmx->nested.current_vmcs12_page = page;
7505 /*
7506 * Load VMCS12 from guest memory since it is not already
7507 * cached.
7508 */
7509 memcpy(vmx->nested.cached_vmcs12,
7510 vmx->nested.current_vmcs12, VMCS12_SIZE);
7511
7487 if (enable_shadow_vmcs) { 7512 if (enable_shadow_vmcs) {
7488 vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL, 7513 vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
7489 SECONDARY_EXEC_SHADOW_VMCS); 7514 SECONDARY_EXEC_SHADOW_VMCS);
@@ -8456,7 +8481,7 @@ static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu, hpa_t hpa)
8456 * the next L2->L1 exit. 8481 * the next L2->L1 exit.
8457 */ 8482 */
8458 if (!is_guest_mode(vcpu) || 8483 if (!is_guest_mode(vcpu) ||
8459 !nested_cpu_has2(vmx->nested.current_vmcs12, 8484 !nested_cpu_has2(get_vmcs12(&vmx->vcpu),
8460 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) 8485 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))
8461 vmcs_write64(APIC_ACCESS_ADDR, hpa); 8486 vmcs_write64(APIC_ACCESS_ADDR, hpa);
8462} 8487}