WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [HVM][VMX] Cleanups and fixes to VMCS lif

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [HVM][VMX] Cleanups and fixes to VMCS lifecycle.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Sun, 11 Jun 2006 20:20:24 +0000
Delivery-date: Sun, 11 Jun 2006 13:22:24 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID d7543cff88ae4b9eb8a561dc72e6e126223ef720
# Parent  be05097d5d69925a72405201140df8da4c1cfa5c
[HVM][VMX] Cleanups and fixes to VMCS lifecycle.
 1. Maintain a 'launched' software flag to select between
    VMLAUNCH and VMRESUME.
 2. Take more care with VMPTRLD/VMCLEAR.
Also various other fixes (e.g., safe testing of
condition codes after executing a VMX instruction).

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/ia64/vmx/vmx_init.c        |    3 
 xen/arch/x86/hvm/vmx/vmcs.c         |  177 ++++++++++++++++++------------------
 xen/arch/x86/hvm/vmx/vmx.c          |   89 ++----------------
 xen/arch/x86/hvm/vmx/x86_32/exits.S |   74 +++++----------
 xen/arch/x86/hvm/vmx/x86_64/exits.S |   75 +++++----------
 xen/arch/x86/x86_32/asm-offsets.c   |    3 
 xen/arch/x86/x86_64/asm-offsets.c   |    3 
 xen/include/asm-ia64/vmx_vpd.h      |    3 
 xen/include/asm-x86/hvm/vmx/vmcs.h  |   56 ++++++-----
 xen/include/asm-x86/hvm/vmx/vmx.h   |   74 ++++++---------
 10 files changed, 231 insertions(+), 326 deletions(-)

diff -r be05097d5d69 -r d7543cff88ae xen/arch/ia64/vmx/vmx_init.c
--- a/xen/arch/ia64/vmx/vmx_init.c      Sun Jun 11 09:54:35 2006 +0100
+++ b/xen/arch/ia64/vmx/vmx_init.c      Sun Jun 11 14:33:16 2006 +0100
@@ -288,9 +288,6 @@ vmx_final_setup_guest(struct vcpu *v)
        /* v->arch.schedule_tail = arch_vmx_do_launch; */
        vmx_create_vp(v);
 
-       /* Set this ed to be vmx */
-       set_bit(ARCH_VMX_VMCS_LOADED, &v->arch.arch_vmx.flags);
-
        /* Physical mode emulation initialization, including
        * emulation ID allcation and related memory request
        */
diff -r be05097d5d69 -r d7543cff88ae xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Sun Jun 11 09:54:35 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Sun Jun 11 14:33:16 2006 +0100
@@ -42,7 +42,7 @@
 
 int vmcs_size;
 
-struct vmcs_struct *alloc_vmcs(void)
+struct vmcs_struct *vmx_alloc_vmcs(void)
 {
     struct vmcs_struct *vmcs;
     u32 vmx_msr_low, vmx_msr_high;
@@ -64,47 +64,63 @@ static void free_vmcs(struct vmcs_struct
     free_xenheap_pages(vmcs, order);
 }
 
-static int load_vmcs(struct arch_vmx_struct *arch_vmx, u64 phys_ptr)
-{
-    int error;
-
-    if ((error = __vmptrld(phys_ptr))) {
-        clear_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
-        return error;
-    }
-    set_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
-    return 0;
-}
-
-static void vmx_smp_clear_vmcs(void *info)
-{
-    struct vcpu *v = (struct vcpu *)info;
-
-    ASSERT(hvm_guest(v));
-
-    if (v->arch.hvm_vmx.launch_cpu == smp_processor_id())
-        __vmpclear(virt_to_maddr(v->arch.hvm_vmx.vmcs));
-}
-
-void vmx_request_clear_vmcs(struct vcpu *v)
-{
-    ASSERT(hvm_guest(v));
-
-    if (v->arch.hvm_vmx.launch_cpu == smp_processor_id())
-        __vmpclear(virt_to_maddr(v->arch.hvm_vmx.vmcs));
+static void __vmx_clear_vmcs(void *info)
+{
+    struct vcpu *v = info;
+    __vmpclear(virt_to_maddr(v->arch.hvm_vmx.vmcs));
+    v->arch.hvm_vmx.active_cpu = -1;
+    v->arch.hvm_vmx.launched   = 0;
+}
+
+static void vmx_clear_vmcs(struct vcpu *v)
+{
+    unsigned int cpu = v->arch.hvm_vmx.active_cpu;
+
+    if ( (cpu == -1) || (cpu == smp_processor_id()) )
+        __vmx_clear_vmcs(v);
     else
-        smp_call_function(vmx_smp_clear_vmcs, v, 1, 1);
-}
-
-#if 0
-static int store_vmcs(struct arch_vmx_struct *arch_vmx, u64 phys_ptr)
-{
-    /* take the current VMCS */
-    __vmptrst(phys_ptr);
-    clear_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
-    return 0;
-}
-#endif
+        on_selected_cpus(cpumask_of_cpu(cpu), __vmx_clear_vmcs, v, 1, 1);
+}
+
+static void vmx_load_vmcs(struct vcpu *v)
+{
+    __vmptrld(virt_to_maddr(v->arch.hvm_vmx.vmcs));
+    v->arch.hvm_vmx.active_cpu = smp_processor_id();
+}
+
+void vmx_vmcs_enter(struct vcpu *v)
+{
+    /*
+     * NB. We must *always* run an HVM VCPU on its own VMCS, except for
+     * vmx_vmcs_enter/exit critical regions. This leads to some XXX TODOs XXX:
+     *  1. Move construct_vmcs() much earlier, to domain creation or
+     *     context initialisation.
+     *  2. VMPTRLD as soon as we context-switch to a HVM VCPU.
+     *  3. VMCS destruction needs to happen later (from domain_destroy()).
+     */
+    if ( v == current )
+        return;
+
+    vcpu_pause(v);
+    spin_lock(&v->arch.hvm_vmx.vmcs_lock);
+
+    vmx_clear_vmcs(v);
+    vmx_load_vmcs(v);
+}
+
+void vmx_vmcs_exit(struct vcpu *v)
+{
+    if ( v == current )
+        return;
+
+    /* Don't confuse arch_vmx_do_resume (for @v or @current!) */
+    vmx_clear_vmcs(v);
+    if ( hvm_guest(current) )
+        vmx_load_vmcs(current);
+
+    spin_unlock(&v->arch.hvm_vmx.vmcs_lock);
+    vcpu_unpause(v);
+}
 
 static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx)
 {
@@ -247,7 +263,6 @@ static void vmx_do_launch(struct vcpu *v
     __vmwrite(HOST_CR3, pagetable_get_paddr(v->arch.monitor_table));
 
     v->arch.schedule_tail = arch_vmx_do_resume;
-    v->arch.hvm_vmx.launch_cpu = smp_processor_id();
 
     /* init guest tsc to start from 0 */
     set_guest_time(v, 0);
@@ -410,53 +425,49 @@ static inline int construct_vmcs_host(vo
 /*
  * Need to extend to support full virtualization.
  */
-static int construct_vmcs(struct arch_vmx_struct *arch_vmx,
+static int construct_vmcs(struct vcpu *v,
                           cpu_user_regs_t *regs)
 {
+    struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx;
     int error;
     long rc;
-    u64 vmcs_phys_ptr;
 
     memset(arch_vmx, 0, sizeof(struct arch_vmx_struct));
+
+    spin_lock_init(&arch_vmx->vmcs_lock);
+    arch_vmx->active_cpu = -1;
 
     /*
      * Create a new VMCS
      */
-    if (!(arch_vmx->vmcs = alloc_vmcs())) {
+    if (!(arch_vmx->vmcs = vmx_alloc_vmcs())) {
         printk("Failed to create a new VMCS\n");
-        rc = -ENOMEM;
-        goto err_out;
-    }
-    vmcs_phys_ptr = (u64) virt_to_maddr(arch_vmx->vmcs);
-
-    if ((error = __vmpclear(vmcs_phys_ptr))) {
-        printk("construct_vmcs: VMCLEAR failed\n");
-        rc = -EINVAL;
-        goto err_out;
-    }
-    if ((error = load_vmcs(arch_vmx, vmcs_phys_ptr))) {
-        printk("construct_vmcs: load_vmcs failed: VMCS = %lx\n",
-               (unsigned long) vmcs_phys_ptr);
-        rc = -EINVAL;
-        goto err_out;
-    }
+        return -ENOMEM;
+    }
+
+    vmx_clear_vmcs(v);
+    vmx_load_vmcs(v);
+
     if ((error = construct_vmcs_controls(arch_vmx))) {
         printk("construct_vmcs: construct_vmcs_controls failed\n");
         rc = -EINVAL;
         goto err_out;
     }
+
     /* host selectors */
     if ((error = construct_vmcs_host())) {
         printk("construct_vmcs: construct_vmcs_host failed\n");
         rc = -EINVAL;
         goto err_out;
     }
+
     /* guest selectors */
     if ((error = construct_init_vmcs_guest(regs))) {
         printk("construct_vmcs: construct_vmcs_guest failed\n");
         rc = -EINVAL;
         goto err_out;
     }
+
     if ((error |= __vmwrite(EXCEPTION_BITMAP,
                             MONITOR_DEFAULT_EXCEPTION_BITMAP))) {
         printk("construct_vmcs: setting Exception bitmap failed\n");
@@ -472,12 +483,16 @@ static int construct_vmcs(struct arch_vm
     return 0;
 
 err_out:
-    destroy_vmcs(arch_vmx);
+    vmx_destroy_vmcs(v);
     return rc;
 }
 
-void destroy_vmcs(struct arch_vmx_struct *arch_vmx)
-{
+void vmx_destroy_vmcs(struct vcpu *v)
+{
+    struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx;
+
+    vmx_clear_vmcs(v);
+
     free_vmcs(arch_vmx->vmcs);
     arch_vmx->vmcs = NULL;
 
@@ -506,22 +521,20 @@ void vm_resume_fail(unsigned long eflags
 
 void arch_vmx_do_resume(struct vcpu *v)
 {
-    if ( v->arch.hvm_vmx.launch_cpu == smp_processor_id() )
+    if ( v->arch.hvm_vmx.active_cpu == smp_processor_id() )
     {
-        load_vmcs(&v->arch.hvm_vmx, virt_to_maddr(v->arch.hvm_vmx.vmcs));
-        vmx_do_resume(v);
-        reset_stack_and_jump(vmx_asm_do_resume);
+        vmx_load_vmcs(v);
     }
     else
     {
-        vmx_request_clear_vmcs(v);
-        load_vmcs(&v->arch.hvm_vmx, virt_to_maddr(v->arch.hvm_vmx.vmcs));
+        vmx_clear_vmcs(v);
+        vmx_load_vmcs(v);
         vmx_migrate_timers(v);
         vmx_set_host_env(v);
-        vmx_do_resume(v);
-        v->arch.hvm_vmx.launch_cpu = smp_processor_id();
-        reset_stack_and_jump(vmx_asm_do_relaunch);
-    }
+    }
+
+    vmx_do_resume(v);
+    reset_stack_and_jump(vmx_asm_do_vmentry);
 }
 
 void arch_vmx_do_launch(struct vcpu *v)
@@ -529,7 +542,7 @@ void arch_vmx_do_launch(struct vcpu *v)
     int error;
     cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
 
-    error = construct_vmcs(&v->arch.hvm_vmx, regs);
+    error = construct_vmcs(v, regs);
     if ( error < 0 )
     {
         if (v->vcpu_id == 0) {
@@ -540,7 +553,7 @@ void arch_vmx_do_launch(struct vcpu *v)
         domain_crash_synchronous();
     }
     vmx_do_launch(v);
-    reset_stack_and_jump(vmx_asm_do_launch);
+    reset_stack_and_jump(vmx_asm_do_vmentry);
 }
 
 
@@ -613,17 +626,9 @@ static void vmcs_dump(unsigned char ch)
             }
             printk("\tVCPU %d\n", v->vcpu_id);
 
-            if (v != current) {
-                vcpu_pause(v);
-                __vmptrld(virt_to_maddr(v->arch.hvm_vmx.vmcs));
-            }
-
+            vmx_vmcs_enter(v);
             vmcs_dump_vcpu();
-
-            if (v != current) {
-                __vmptrld(virt_to_maddr(current->arch.hvm_vmx.vmcs));
-                vcpu_unpause(v);
-            }
+            vmx_vmcs_exit(v);
         }
     }
 
diff -r be05097d5d69 -r d7543cff88ae xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Sun Jun 11 09:54:35 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Sun Jun 11 14:33:16 2006 +0100
@@ -91,8 +91,7 @@ static void vmx_relinquish_guest_resourc
     {
         if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
             continue;
-        vmx_request_clear_vmcs(v);
-        destroy_vmcs(&v->arch.hvm_vmx);
+        vmx_destroy_vmcs(v);
         free_monitor_pagetable(v);
         kill_timer(&v->arch.hvm_vmx.hlt_timer);
         if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) )
@@ -402,54 +401,10 @@ void vmx_migrate_timers(struct vcpu *v)
         migrate_timer(&(VLAPIC(v)->vlapic_timer), v->processor);
 }
 
-struct vmx_cpu_guest_regs_callback_info {
-    struct vcpu *v;
-    struct cpu_user_regs *regs;
-    unsigned long *crs;
-};
-
-static void vmx_store_cpu_guest_regs(
-    struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs);
-
-static void vmx_load_cpu_guest_regs(
-    struct vcpu *v, struct cpu_user_regs *regs);
-
-static void vmx_store_cpu_guest_regs_callback(void *data)
-{
-    struct vmx_cpu_guest_regs_callback_info *info = data;
-    vmx_store_cpu_guest_regs(info->v, info->regs, info->crs);
-}
-
-static void vmx_load_cpu_guest_regs_callback(void *data)
-{
-    struct vmx_cpu_guest_regs_callback_info *info = data;
-    vmx_load_cpu_guest_regs(info->v, info->regs);
-}
-
 static void vmx_store_cpu_guest_regs(
     struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs)
 {
-    if ( v != current )
-    {
-        /* Non-current VCPUs must be paused to get a register snapshot. */
-        ASSERT(atomic_read(&v->pausecnt) != 0);
-
-        if ( v->arch.hvm_vmx.launch_cpu != smp_processor_id() )
-        {
-            /* Get register details from remote CPU. */
-            struct vmx_cpu_guest_regs_callback_info info = {
-                .v = v, .regs = regs, .crs = crs };
-            cpumask_t cpumask = cpumask_of_cpu(v->arch.hvm_vmx.launch_cpu);
-            on_selected_cpus(cpumask, vmx_store_cpu_guest_regs_callback,
-                             &info, 1, 1);
-            return;
-        }
-
-        /* Register details are on this CPU. Load the correct VMCS. */
-        __vmptrld(virt_to_maddr(v->arch.hvm_vmx.vmcs));
-    }
-
-    ASSERT(v->arch.hvm_vmx.launch_cpu == smp_processor_id());
+    vmx_vmcs_enter(v);
 
     if ( regs != NULL )
     {
@@ -471,9 +426,7 @@ static void vmx_store_cpu_guest_regs(
         __vmread(CR4_READ_SHADOW, &crs[4]);
     }
 
-    /* Reload current VCPU's VMCS if it was temporarily unloaded. */
-    if ( (v != current) && hvm_guest(current) )
-        __vmptrld(virt_to_maddr(current->arch.hvm_vmx.vmcs));
+    vmx_vmcs_exit(v);
 }
 
 /*
@@ -517,26 +470,7 @@ static void fixup_vm86_seg_bases(struct 
 
 void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
 {
-    if ( v != current )
-    {
-        /* Non-current VCPUs must be paused to set the register snapshot. */
-        ASSERT(atomic_read(&v->pausecnt) != 0);
-
-        if ( v->arch.hvm_vmx.launch_cpu != smp_processor_id() )
-        {
-            struct vmx_cpu_guest_regs_callback_info info = {
-                .v = v, .regs = regs };
-            cpumask_t cpumask = cpumask_of_cpu(v->arch.hvm_vmx.launch_cpu);
-            on_selected_cpus(cpumask, vmx_load_cpu_guest_regs_callback,
-                             &info, 1, 1);
-            return;
-        }
-
-        /* Register details are on this CPU. Load the correct VMCS. */
-        __vmptrld(virt_to_maddr(v->arch.hvm_vmx.vmcs));
-    }
-
-    ASSERT(v->arch.hvm_vmx.launch_cpu == smp_processor_id());
+    vmx_vmcs_enter(v);
 
     __vmwrite(GUEST_SS_SELECTOR, regs->ss);
     __vmwrite(GUEST_DS_SELECTOR, regs->ds);
@@ -557,9 +491,7 @@ void vmx_load_cpu_guest_regs(struct vcpu
     __vmwrite(GUEST_CS_SELECTOR, regs->cs);
     __vmwrite(GUEST_RIP, regs->eip);
 
-    /* Reload current VCPU's VMCS if it was temporarily unloaded. */
-    if ( (v != current) && hvm_guest(current) )
-        __vmptrld(virt_to_maddr(current->arch.hvm_vmx.vmcs));
+    vmx_vmcs_exit(v);
 }
 
 int vmx_realmode(struct vcpu *v)
@@ -688,16 +620,19 @@ int start_vmx(void)
 
     set_in_cr4(X86_CR4_VMXE);   /* Enable VMXE */
 
-    if (!(vmcs = alloc_vmcs())) {
+    if (!(vmcs = vmx_alloc_vmcs())) {
         printk("Failed to allocate VMCS\n");
         return 0;
     }
 
     phys_vmcs = (u64) virt_to_maddr(vmcs);
 
-    if (!(__vmxon(phys_vmcs))) {
-        printk("VMXON is done\n");
-    }
+    if (__vmxon(phys_vmcs)) {
+        printk("VMXON failed\n");
+        return 0;
+    }
+
+    printk("VMXON is done\n");
 
     vmx_save_init_msrs();
 
diff -r be05097d5d69 -r d7543cff88ae xen/arch/x86/hvm/vmx/x86_32/exits.S
--- a/xen/arch/x86/hvm/vmx/x86_32/exits.S       Sun Jun 11 09:54:35 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S       Sun Jun 11 14:33:16 2006 +0100
@@ -78,69 +78,49 @@
         addl $(NR_SKIPPED_REGS*4), %esp
 
         ALIGN
-
 ENTRY(vmx_asm_vmexit_handler)
         /* selectors are restored/saved by VMX */
         HVM_SAVE_ALL_NOSEGREGS
         call vmx_trace_vmexit
         call vmx_vmexit_handler
-        jmp vmx_asm_do_resume
+        jmp vmx_asm_do_vmentry
 
-.macro vmx_asm_common launch, initialized
-1:
-/* vmx_test_all_events */
-        .if \initialized
+        ALIGN
+vmx_process_softirqs:
+        sti       
+        call do_softirq
+        jmp vmx_asm_do_vmentry
+
+        ALIGN
+ENTRY(vmx_asm_do_vmentry)
         GET_CURRENT(%ebx)
-/*test_all_events:*/
-        xorl %ecx,%ecx
-        notl %ecx
         cli                             # tests must not race interrupts
-/*test_softirqs:*/  
+
         movl VCPU_processor(%ebx),%eax
         shl  $IRQSTAT_shift,%eax
-        test %ecx,irq_stat(%eax,1)
-        jnz 2f
+        cmpl $0,irq_stat(%eax,1)
+        jnz  vmx_process_softirqs
 
-/* vmx_restore_all_guest */
         call vmx_intr_assist
         call vmx_load_cr2
         call vmx_trace_vmentry
-        .endif
+
+        cmpl $0,VCPU_vmx_launched(%ebx)
+        je   vmx_launch
+
+/*vmx_resume:*/
         HVM_RESTORE_ALL_NOSEGREGS
-        /* 
-         * Check if we are going back to VMX-based VM
-         * By this time, all the setups in the VMCS must be complete.
-         */
-        .if \launch
+        /* VMRESUME */
+        .byte 0x0f,0x01,0xc3
+        pushf
+        call vm_resume_fail
+        ud2
+
+vmx_launch:
+        movl $1,VCPU_vmx_launched(%ebx)
+        HVM_RESTORE_ALL_NOSEGREGS
         /* VMLAUNCH */
         .byte 0x0f,0x01,0xc2
         pushf
         call vm_launch_fail
-        .else
-        /* VMRESUME */
-        .byte 0x0f,0x01,0xc3
-        pushf
-        call vm_resume_fail
-        .endif
-        /* Should never reach here */
-        hlt
-
-        ALIGN
-        .if \initialized
-2:
-/* vmx_process_softirqs */
-        sti       
-        call do_softirq
-        jmp 1b
-        ALIGN
-        .endif
-.endm
-
-ENTRY(vmx_asm_do_launch)
-    vmx_asm_common 1, 0
-
-ENTRY(vmx_asm_do_resume)
-    vmx_asm_common 0, 1
-
-ENTRY(vmx_asm_do_relaunch)
-    vmx_asm_common 1, 1
+        ud2
diff -r be05097d5d69 -r d7543cff88ae xen/arch/x86/hvm/vmx/x86_64/exits.S
--- a/xen/arch/x86/hvm/vmx/x86_64/exits.S       Sun Jun 11 09:54:35 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S       Sun Jun 11 14:33:16 2006 +0100
@@ -88,68 +88,51 @@
         popq %rdi;                              \
         addq $(NR_SKIPPED_REGS*8), %rsp;
 
+        ALIGN
 ENTRY(vmx_asm_vmexit_handler)
         /* selectors are restored/saved by VMX */
         HVM_SAVE_ALL_NOSEGREGS
         call vmx_trace_vmexit
         call vmx_vmexit_handler
-        jmp vmx_asm_do_resume
+        jmp vmx_asm_do_vmentry
 
-.macro vmx_asm_common launch, initialized 
-1:
-        .if \initialized
-/* vmx_test_all_events */
+        ALIGN
+vmx_process_softirqs:
+        sti       
+        call do_softirq
+        jmp vmx_asm_do_vmentry
+
+        ALIGN
+ENTRY(vmx_asm_do_vmentry)
         GET_CURRENT(%rbx)
-/* test_all_events: */
         cli                             # tests must not race interrupts
-/*test_softirqs:*/  
+
         movl  VCPU_processor(%rbx),%eax
         shl   $IRQSTAT_shift,%rax
-        leaq  irq_stat(%rip), %rdx
-        testl $~0,(%rdx,%rax,1)
-        jnz  2f 
+        leaq  irq_stat(%rip),%rdx
+        cmpl  $0,(%rdx,%rax,1)
+        jnz   vmx_process_softirqs
 
-/* vmx_restore_all_guest */
         call vmx_intr_assist
         call vmx_load_cr2
         call vmx_trace_vmentry
-        .endif
-        /* 
-         * Check if we are going back to VMX-based VM
-         * By this time, all the setups in the VMCS must be complete.
-         */
+
+        cmpl $0,VCPU_vmx_launched(%rbx)
+        je   vmx_launch
+
+/*vmx_resume:*/
         HVM_RESTORE_ALL_NOSEGREGS
-        .if \launch
+        /* VMRESUME */
+        .byte 0x0f,0x01,0xc3
+        pushfq
+        call vm_resume_fail
+        ud2
+
+vmx_launch:
+        movl $1,VCPU_vmx_launched(%rbx)
+        HVM_RESTORE_ALL_NOSEGREGS
         /* VMLAUNCH */
         .byte 0x0f,0x01,0xc2
         pushfq
         call vm_launch_fail
-        .else
-        /* VMRESUME */
-        .byte 0x0f,0x01,0xc3
-        pushfq
-        call vm_resume_fail
-        .endif
-        /* Should never reach here */
-        hlt
-
-        ALIGN
-
-        .if \initialized
-2:
-/* vmx_process_softirqs */
-        sti       
-        call do_softirq
-        jmp 1b
-        ALIGN
-        .endif
-.endm
-
-ENTRY(vmx_asm_do_launch)
-      vmx_asm_common 1, 0
-
-ENTRY(vmx_asm_do_resume)
-      vmx_asm_common 0, 1
-
-ENTRY(vmx_asm_do_relaunch)
-      vmx_asm_common 1, 1
+        ud2
diff -r be05097d5d69 -r d7543cff88ae xen/arch/x86/x86_32/asm-offsets.c
--- a/xen/arch/x86/x86_32/asm-offsets.c Sun Jun 11 09:54:35 2006 +0100
+++ b/xen/arch/x86/x86_32/asm-offsets.c Sun Jun 11 14:33:16 2006 +0100
@@ -86,6 +86,9 @@ void __dummy__(void)
     OFFSET(VCPU_svm_vmexit_tsc, struct vcpu, arch.hvm_svm.vmexit_tsc);
     BLANK();
 
+    OFFSET(VCPU_vmx_launched, struct vcpu, arch.hvm_vmx.launched);
+    BLANK();
+
     OFFSET(VMCB_rax, struct vmcb_struct, rax);
     OFFSET(VMCB_tsc_offset, struct vmcb_struct, tsc_offset);
     BLANK();
diff -r be05097d5d69 -r d7543cff88ae xen/arch/x86/x86_64/asm-offsets.c
--- a/xen/arch/x86/x86_64/asm-offsets.c Sun Jun 11 09:54:35 2006 +0100
+++ b/xen/arch/x86/x86_64/asm-offsets.c Sun Jun 11 14:33:16 2006 +0100
@@ -80,6 +80,9 @@ void __dummy__(void)
     OFFSET(VCPU_svm_vmexit_tsc, struct vcpu, arch.hvm_svm.vmexit_tsc);
     BLANK();
 
+    OFFSET(VCPU_vmx_launched, struct vcpu, arch.hvm_vmx.launched);
+    BLANK();
+
     OFFSET(VMCB_rax, struct vmcb_struct, rax);
     OFFSET(VMCB_tsc_offset, struct vmcb_struct, tsc_offset);
     BLANK();
diff -r be05097d5d69 -r d7543cff88ae xen/include/asm-ia64/vmx_vpd.h
--- a/xen/include/asm-ia64/vmx_vpd.h    Sun Jun 11 09:54:35 2006 +0100
+++ b/xen/include/asm-ia64/vmx_vpd.h    Sun Jun 11 14:33:16 2006 +0100
@@ -104,9 +104,6 @@ struct arch_vmx_struct {
 
 #define VMX_DOMAIN(d)   d->arch.arch_vmx.flags
 
-#define ARCH_VMX_VMCS_LOADED    0       /* VMCS has been loaded and active */
-#define ARCH_VMX_VMCS_LAUNCH    1       /* Needs VMCS launch */
-#define ARCH_VMX_VMCS_RESUME    2       /* Needs VMCS resume */
 #define ARCH_VMX_IO_WAIT        3       /* Waiting for I/O completion */
 #define ARCH_VMX_INTR_ASSIST    4       /* Need DM's assist to issue intr */
 #define ARCH_VMX_CONTIG_MEM    5       /* Need contiguous machine pages */
diff -r be05097d5d69 -r d7543cff88ae xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h        Sun Jun 11 09:54:35 2006 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h        Sun Jun 11 14:33:16 2006 +0100
@@ -65,34 +65,46 @@ struct vmx_msr_state {
 };
 
 struct arch_vmx_struct {
-    struct vmcs_struct      *vmcs;  /* VMCS pointer in virtual. */
-    unsigned int            launch_cpu; /* VMCS is valid on this CPU. */
-    u32                     exec_control; /* cache of cpu execution control */
-    u32                     vector_injected; /* if there is vector installed 
in the INTR_INFO_FIELD */
-    unsigned long           flags;  /* VMCS flags */
-    unsigned long           cpu_cr0; /* copy of guest CR0 */
-    unsigned long           cpu_shadow_cr0; /* copy of guest read shadow CR0 */
-    unsigned long           cpu_cr2; /* save CR2 */
-    unsigned long           cpu_cr3;
-    unsigned long           cpu_state;
-    unsigned long           cpu_based_exec_control;
-    struct vmx_msr_state    msr_content;
-    void                    *io_bitmap_a, *io_bitmap_b;
-    struct timer            hlt_timer;  /* hlt ins emulation wakeup timer */
+    /* Virtual address of VMCS. */
+    struct vmcs_struct  *vmcs;
+
+    /* Protects remote usage of VMCS (VMPTRLD/VMCLEAR). */
+    spinlock_t           vmcs_lock;
+
+    /*
+     * Activation and launch status of this VMCS.
+     *  - Activated on a CPU by VMPTRLD. Deactivated by VMCLEAR.
+     *  - Launched on active CPU by VMLAUNCH when current VMCS.
+     */
+    int                  active_cpu;
+    int                  launched;
+
+    /* Cache of cpu execution control. */
+    u32                  exec_control;
+
+    /* If there is vector installed in the INTR_INFO_FIELD. */
+    u32                  vector_injected;
+
+    unsigned long        cpu_cr0; /* copy of guest CR0 */
+    unsigned long        cpu_shadow_cr0; /* copy of guest read shadow CR0 */
+    unsigned long        cpu_cr2; /* save CR2 */
+    unsigned long        cpu_cr3;
+    unsigned long        cpu_state;
+    unsigned long        cpu_based_exec_control;
+    struct vmx_msr_state msr_content;
+    void                *io_bitmap_a, *io_bitmap_b;
+    struct timer         hlt_timer;  /* hlt ins emulation wakeup timer */
 };
 
 #define vmx_schedule_tail(next)         \
     (next)->thread.arch_vmx.arch_vmx_schedule_tail((next))
 
-#define ARCH_VMX_VMCS_LOADED    0       /* VMCS has been loaded and active */
-#define ARCH_VMX_VMCS_LAUNCH    1       /* Needs VMCS launch */
-#define ARCH_VMX_VMCS_RESUME    2       /* Needs VMCS resume */
-
 void vmx_do_resume(struct vcpu *);
-struct vmcs_struct *alloc_vmcs(void);
-void destroy_vmcs(struct arch_vmx_struct *arch_vmx);
-
-extern void vmx_request_clear_vmcs(struct vcpu *v);
+
+struct vmcs_struct *vmx_alloc_vmcs(void);
+void vmx_destroy_vmcs(struct vcpu *v);
+void vmx_vmcs_enter(struct vcpu *v);
+void vmx_vmcs_exit(struct vcpu *v);
 
 #define VMCS_USE_HOST_ENV       1
 #define VMCS_USE_SEPARATE_ENV   0
diff -r be05097d5d69 -r d7543cff88ae xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Sun Jun 11 09:54:35 2006 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Sun Jun 11 14:33:16 2006 +0100
@@ -27,8 +27,7 @@
 #include <asm/i387.h>
 
 extern void vmx_asm_vmexit_handler(struct cpu_user_regs);
-extern void vmx_asm_do_resume(void);
-extern void vmx_asm_do_launch(void);
+extern void vmx_asm_do_vmentry(void);
 extern void vmx_intr_assist(void);
 extern void vmx_migrate_timers(struct vcpu *v);
 extern void arch_vmx_do_launch(struct vcpu *);
@@ -200,22 +199,18 @@ extern unsigned int cpu_rev;
 #define MODRM_EAX_07    ".byte 0x38\n" /* [EAX], with reg/opcode: /7 */
 #define MODRM_EAX_ECX   ".byte 0xc1\n" /* [EAX], [ECX] */
 
-static inline int __vmptrld (u64 addr)
-{
-    unsigned long eflags;
+static inline void __vmptrld(u64 addr)
+{
     __asm__ __volatile__ ( VMPTRLD_OPCODE
                            MODRM_EAX_06
+                           /* CF==1 or ZF==1 --> crash (ud2) */
+                           "ja 1f ; ud2 ; 1:\n"
                            :
                            : "a" (&addr) 
                            : "memory");
-
-    __save_flags(eflags);
-    if (eflags & X86_EFLAGS_ZF || eflags & X86_EFLAGS_CF)
-        return -1;
-    return 0;
-}
-
-static inline void __vmptrst (u64 addr)
+}
+
+static inline void __vmptrst(u64 addr)
 {
     __asm__ __volatile__ ( VMPTRST_OPCODE
                            MODRM_EAX_07
@@ -224,31 +219,30 @@ static inline void __vmptrst (u64 addr)
                            : "memory");
 }
 
-static inline int __vmpclear (u64 addr)
-{
-    unsigned long eflags;
-
+static inline void __vmpclear(u64 addr)
+{
     __asm__ __volatile__ ( VMCLEAR_OPCODE
                            MODRM_EAX_06
+                           /* CF==1 or ZF==1 --> crash (ud2) */
+                           "ja 1f ; ud2 ; 1:\n"
                            :
                            : "a" (&addr) 
                            : "memory");
-    __save_flags(eflags);
-    if (eflags & X86_EFLAGS_ZF || eflags & X86_EFLAGS_CF)
-        return -1;
-    return 0;
 }
 
 #define __vmread(x, ptr) ___vmread((x), (ptr), sizeof(*(ptr)))
 
-static always_inline int ___vmread (const unsigned long field,  void *ptr, 
const int size)
-{
-    unsigned long eflags;
+static always_inline int ___vmread(
+    const unsigned long field, void *ptr, const int size)
+{
     unsigned long ecx = 0;
+    int rc;
 
     __asm__ __volatile__ ( VMREAD_OPCODE
-                           MODRM_EAX_ECX       
-                           : "=c" (ecx)
+                           MODRM_EAX_ECX
+                           /* CF==1 or ZF==1 --> rc = -1 */
+                           "setna %b0 ; neg %0"
+                           : "=r" (rc), "=c" (ecx)
                            : "a" (field)
                            : "memory");
 
@@ -270,10 +264,7 @@ static always_inline int ___vmread (cons
         break;
     }
 
-    __save_flags(eflags);
-    if (eflags & X86_EFLAGS_ZF || eflags & X86_EFLAGS_CF)
-        return -1;
-    return 0;
+    return rc;
 }
 
 
@@ -315,17 +306,16 @@ static always_inline void __vmread_vcpu(
 
 static inline int __vmwrite (unsigned long field, unsigned long value)
 {
-    unsigned long eflags;
     struct vcpu *v = current;
+    int rc;
 
     __asm__ __volatile__ ( VMWRITE_OPCODE
                            MODRM_EAX_ECX
-                           :
+                           /* CF==1 or ZF==1 --> rc = -1 */
+                           "setna %b0 ; neg %0"
+                           : "=r" (rc)
                            : "a" (field) , "c" (value)
                            : "memory");
-    __save_flags(eflags);
-    if (eflags & X86_EFLAGS_ZF || eflags & X86_EFLAGS_CF)
-        return -1;
 
     switch(field) {
     case CR0_READ_SHADOW:
@@ -335,7 +325,7 @@ static inline int __vmwrite (unsigned lo
        break;
     }
 
-    return 0;
+    return rc;
 }
 
 static inline int __vm_set_bit(unsigned long field, unsigned long mask)
@@ -370,17 +360,17 @@ static inline void __vmxoff (void)
 
 static inline int __vmxon (u64 addr)
 {
-    unsigned long eflags;
+    int rc;
 
     __asm__ __volatile__ ( VMXON_OPCODE
                            MODRM_EAX_06
-                           :
+                           /* CF==1 or ZF==1 --> rc = -1 */
+                           "setna %b0 ; neg %0"
+                           : "=r" (rc)
                            : "a" (&addr) 
                            : "memory");
-    __save_flags(eflags);
-    if (eflags & X86_EFLAGS_ZF || eflags & X86_EFLAGS_CF)
-        return -1;
-    return 0;
+
+    return rc;
 }
 
 /* Make sure that xen intercepts any FP accesses from current */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [HVM][VMX] Cleanups and fixes to VMCS lifecycle., Xen patchbot-unstable <=