KVM: nVMX: introduce nested_get_vmcs12_pages
authorWanpeng Li <wanpeng.li@linux.intel.com>
Thu, 21 Aug 2014 11:46:49 +0000 (19:46 +0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 29 Aug 2014 12:02:48 +0000 (14:02 +0200)
Introduce function nested_get_vmcs12_pages() to check the valid
of nested apic access page and virtual apic page earlier.

Signed-off-by: Wanpeng Li <wanpeng.li@linux.intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx.c

index 661abc2f7049b136c85d023202a80542e566c258..70516e11f051a2a6e4a03fc52ad4b13e4b8bbd9e 100644 (file)
@@ -7927,6 +7927,30 @@ static void vmx_inject_page_fault_nested(struct kvm_vcpu *vcpu,
                kvm_inject_page_fault(vcpu, fault);
 }
 
+static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu,
+                                       struct vmcs12 *vmcs12)
+{
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+       if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
+               if (!PAGE_ALIGNED(vmcs12->apic_access_addr))
+                       /*TODO: Also verify bits beyond physical address width are 0*/
+                       return false;
+
+               /*
+                * Translate L1 physical address to host physical
+                * address for vmcs02. Keep the page pinned, so this
+                * physical address remains valid. We keep a reference
+                * to it so we can release it later.
+                */
+               if (vmx->nested.apic_access_page) /* shouldn't happen */
+                       nested_release_page(vmx->nested.apic_access_page);
+               vmx->nested.apic_access_page =
+                       nested_get_page(vcpu, vmcs12->apic_access_addr);
+       }
+       return true;
+}
+
 static void vmx_start_preemption_timer(struct kvm_vcpu *vcpu)
 {
        u64 preemption_timeout = get_vmcs12(vcpu)->vmx_preemption_timer_value;
@@ -8072,16 +8096,6 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
                        exec_control |= vmcs12->secondary_vm_exec_control;
 
                if (exec_control & SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES) {
-                       /*
-                        * Translate L1 physical address to host physical
-                        * address for vmcs02. Keep the page pinned, so this
-                        * physical address remains valid. We keep a reference
-                        * to it so we can release it later.
-                        */
-                       if (vmx->nested.apic_access_page) /* shouldn't happen */
-                               nested_release_page(vmx->nested.apic_access_page);
-                       vmx->nested.apic_access_page =
-                               nested_get_page(vcpu, vmcs12->apic_access_addr);
                        /*
                         * If translation failed, no matter: This feature asks
                         * to exit when accessing the given address, and if it
@@ -8288,8 +8302,7 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
                return 1;
        }
 
-       if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES) &&
-                       !PAGE_ALIGNED(vmcs12->apic_access_addr)) {
+       if (!nested_get_vmcs12_pages(vcpu, vmcs12)) {
                /*TODO: Also verify bits beyond physical address width are 0*/
                nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
                return 1;