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] Move vmcs and I/O bitmap alloc

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [HVM][VMX] Move vmcs and I/O bitmap allocation into
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 05 Jul 2006 12:30:19 +0000
Delivery-date: Wed, 05 Jul 2006 05:32:26 -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 kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 82f481bda1c7c1c82545fb9d4aa0bab1509ab602
# Parent  4d2354be4aa691fc45ec8a33d3cc8e10b2b21a7c
[HVM][VMX] Move vmcs and I/O bitmap allocation into
vmx_initialise_guest_resources().

Signed-off-by: Xin B Li <xin.b.li@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/vmx/vmcs.c        |  195 ++++++++++++++++++-------------------
 xen/arch/x86/hvm/vmx/vmx.c         |  142 ++++++++++++++++----------
 xen/include/asm-x86/hvm/vmx/vmcs.h |   15 +-
 3 files changed, 196 insertions(+), 156 deletions(-)

diff -r 4d2354be4aa6 -r 82f481bda1c7 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Wed Jul 05 10:32:33 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Wed Jul 05 11:21:19 2006 +0100
@@ -41,34 +41,52 @@
 #include <asm/shadow_64.h>
 #endif
 
-int vmcs_size;
-
-struct vmcs_struct *vmx_alloc_vmcs(void)
+static int vmcs_size;
+static int vmcs_order;
+static u32 vmcs_revision_id;
+
+void vmx_init_vmcs_config(void)
+{
+    u32 vmx_msr_low, vmx_msr_high;
+
+    if ( vmcs_size )
+        return;
+
+    rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high);
+
+    vmcs_revision_id = vmx_msr_low;
+
+    vmcs_size  = vmx_msr_high & 0x1fff;
+    vmcs_order = get_order_from_bytes(vmcs_size);
+}
+
+static struct vmcs_struct *vmx_alloc_vmcs(void)
 {
     struct vmcs_struct *vmcs;
-    u32 vmx_msr_low, vmx_msr_high;
-
-    rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high);
-    vmcs_size = vmx_msr_high & 0x1fff;
-    vmcs = alloc_xenheap_pages(get_order_from_bytes(vmcs_size));
-    memset((char *)vmcs, 0, vmcs_size); /* don't remove this */
-
-    vmcs->vmcs_revision_id = vmx_msr_low;
+
+    if ( (vmcs = alloc_xenheap_pages(vmcs_order)) == NULL )
+    {
+        DPRINTK("Failed to allocate VMCS.\n");
+        return NULL;
+    }
+
+    memset(vmcs, 0, vmcs_size); /* don't remove this */
+    vmcs->vmcs_revision_id = vmcs_revision_id;
+
     return vmcs;
 }
 
-static void free_vmcs(struct vmcs_struct *vmcs)
-{
-    int order;
-
-    order = get_order_from_bytes(vmcs_size);
-    free_xenheap_pages(vmcs, order);
+static void vmx_free_vmcs(struct vmcs_struct *vmcs)
+{
+    free_xenheap_pages(vmcs, vmcs_order);
 }
 
 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;
 }
@@ -128,11 +146,19 @@ void vmx_vmcs_exit(struct vcpu *v)
     vcpu_unpause(v);
 }
 
+struct vmcs_struct *vmx_alloc_host_vmcs(void)
+{
+    return vmx_alloc_vmcs();
+}
+
+void vmx_free_host_vmcs(struct vmcs_struct *vmcs)
+{
+    vmx_free_vmcs(vmcs);
+}
+
 static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx)
 {
     int error = 0;
-    void *io_bitmap_a;
-    void *io_bitmap_b;
 
     error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL,
                        MONITOR_PIN_BASED_EXEC_CONTROLS);
@@ -141,19 +167,8 @@ static inline int construct_vmcs_control
 
     error |= __vmwrite(VM_ENTRY_CONTROLS, MONITOR_VM_ENTRY_CONTROLS);
 
-    /* need to use 0x1000 instead of PAGE_SIZE */
-    io_bitmap_a = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000));
-    io_bitmap_b = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000));
-    memset(io_bitmap_a, 0xff, 0x1000);
-    /* don't bother debug port access */
-    clear_bit(PC_DEBUG_PORT, io_bitmap_a);
-    memset(io_bitmap_b, 0xff, 0x1000);
-
-    error |= __vmwrite(IO_BITMAP_A, (u64) virt_to_maddr(io_bitmap_a));
-    error |= __vmwrite(IO_BITMAP_B, (u64) virt_to_maddr(io_bitmap_b));
-
-    arch_vmx->io_bitmap_a = io_bitmap_a;
-    arch_vmx->io_bitmap_b = io_bitmap_b;
+    error |= __vmwrite(IO_BITMAP_A, (u64)virt_to_maddr(arch_vmx->io_bitmap_a));
+    error |= __vmwrite(IO_BITMAP_B, (u64)virt_to_maddr(arch_vmx->io_bitmap_b));
 
     return error;
 }
@@ -429,67 +444,52 @@ static inline int construct_vmcs_host(vo
 }
 
 /*
- * Need to extend to support full virtualization.
+ * the working VMCS pointer has been set properly
+ * just before entering this function.
  */
 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;
-
-    memset(arch_vmx, 0, sizeof(struct arch_vmx_struct));
-
-    spin_lock_init(&arch_vmx->vmcs_lock);
-
-    /*
-     * Create a new VMCS
-     */
-    if (!(arch_vmx->vmcs = vmx_alloc_vmcs())) {
-        printk("Failed to create a new VMCS\n");
+
+    if ( (error = construct_vmcs_controls(arch_vmx)) ) {
+        printk("construct_vmcs: construct_vmcs_controls failed.\n");
+        return error;
+    }
+
+    /* host selectors */
+    if ( (error = construct_vmcs_host()) ) {
+        printk("construct_vmcs: construct_vmcs_host failed.\n");
+        return error;
+    }
+
+    /* guest selectors */
+    if ( (error = construct_init_vmcs_guest(regs)) ) {
+        printk("construct_vmcs: construct_vmcs_guest failed.\n");
+        return error;
+    }
+
+    if ( (error = __vmwrite(EXCEPTION_BITMAP,
+                            MONITOR_DEFAULT_EXCEPTION_BITMAP)) ) {
+        printk("construct_vmcs: setting exception bitmap failed.\n");
+        return error;
+    }
+
+    if ( regs->eflags & EF_TF )
+        error = __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
+    else
+        error = __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
+
+    return error;
+}
+
+int vmx_create_vmcs(struct vcpu *v)
+{
+    if ( (v->arch.hvm_vmx.vmcs = vmx_alloc_vmcs()) == NULL )
         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");
-        rc = -EINVAL;
-        goto err_out;
-    }
-
-    if (regs->eflags & EF_TF)
-        __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
-    else
-        __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
-
     return 0;
-
-err_out:
-    vmx_destroy_vmcs(v);
-    return rc;
 }
 
 void vmx_destroy_vmcs(struct vcpu *v)
@@ -501,14 +501,14 @@ void vmx_destroy_vmcs(struct vcpu *v)
 
     vmx_clear_vmcs(v);
 
-    free_vmcs(arch_vmx->vmcs);
+    free_xenheap_pages(arch_vmx->io_bitmap_a, IO_BITMAP_ORDER);
+    free_xenheap_pages(arch_vmx->io_bitmap_b, IO_BITMAP_ORDER);
+
+    arch_vmx->io_bitmap_a = NULL;
+    arch_vmx->io_bitmap_b = NULL;
+
+    vmx_free_vmcs(arch_vmx->vmcs);
     arch_vmx->vmcs = NULL;
-
-    free_xenheap_pages(arch_vmx->io_bitmap_a, get_order_from_bytes(0x1000));
-    arch_vmx->io_bitmap_a = NULL;
-
-    free_xenheap_pages(arch_vmx->io_bitmap_b, get_order_from_bytes(0x1000));
-    arch_vmx->io_bitmap_b = NULL;
 }
 
 void vm_launch_fail(unsigned long eflags)
@@ -547,19 +547,20 @@ void arch_vmx_do_resume(struct vcpu *v)
 
 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, regs);
-    if ( error < 0 )
+    vmx_load_vmcs(v);
+
+    if ( construct_vmcs(v, regs) < 0 )
     {
-        if (v->vcpu_id == 0) {
-            printk("Failed to construct a new VMCS for BSP.\n");
+        if ( v->vcpu_id == 0 ) {
+            printk("Failed to construct VMCS for BSP.\n");
         } else {
-            printk("Failed to construct a new VMCS for AP %d\n", v->vcpu_id);
+            printk("Failed to construct VMCS for AP %d.\n", v->vcpu_id);
         }
         domain_crash_synchronous();
     }
+
     vmx_do_launch(v);
     reset_stack_and_jump(vmx_asm_do_vmentry);
 }
diff -r 4d2354be4aa6 -r 82f481bda1c7 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Wed Jul 05 10:32:33 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Wed Jul 05 11:21:19 2006 +0100
@@ -54,34 +54,73 @@ static void vmx_ctxt_switch_from(struct 
 static void vmx_ctxt_switch_from(struct vcpu *v);
 static void vmx_ctxt_switch_to(struct vcpu *v);
 
-void vmx_final_setup_guest(struct vcpu *v)
-{
+static int vmx_initialize_guest_resources(struct vcpu *v)
+{
+    struct domain *d = v->domain;
+    struct vcpu *vc;
+    void *io_bitmap_a, *io_bitmap_b;
+    int rc;
+
     v->arch.schedule_tail    = arch_vmx_do_launch;
     v->arch.ctxt_switch_from = vmx_ctxt_switch_from;
     v->arch.ctxt_switch_to   = vmx_ctxt_switch_to;
 
-    if ( v->vcpu_id == 0 )
-    {
-        struct domain *d = v->domain;
-        struct vcpu *vc;
-
+    if ( v->vcpu_id != 0 )
+        return 1;
+
+    for_each_vcpu ( d, vc )
+    {
         /* Initialize monitor page table */
-        for_each_vcpu(d, vc)
-            vc->arch.monitor_table = pagetable_null();
-
-        /*
-         * Required to do this once per domain
-         * XXX todo: add a seperate function to do these.
-         */
-        memset(&d->shared_info->evtchn_mask[0], 0xff,
-               sizeof(d->shared_info->evtchn_mask));
-
-        /* Put the domain in shadow mode even though we're going to be using
-         * the shared 1:1 page table initially. It shouldn't hurt */
-        shadow_mode_enable(d,
-                           SHM_enable|SHM_refcounts|
-                           SHM_translate|SHM_external|SHM_wr_pt_pte);
-    }
+        vc->arch.monitor_table = pagetable_null();
+
+        memset(&vc->arch.hvm_vmx, 0, sizeof(struct arch_vmx_struct));
+
+        if ( (rc = vmx_create_vmcs(vc)) != 0 )
+        {
+            DPRINTK("Failed to create VMCS for vcpu %d: err=%d.\n",
+                    vc->vcpu_id, rc);
+            return 0;
+        }
+
+        spin_lock_init(&vc->arch.hvm_vmx.vmcs_lock);
+
+        if ( (io_bitmap_a = alloc_xenheap_pages(IO_BITMAP_ORDER)) == NULL )
+        {
+            DPRINTK("Failed to allocate io bitmap b for vcpu %d.\n",
+                    vc->vcpu_id);
+            return 0;
+        }
+
+        if ( (io_bitmap_b = alloc_xenheap_pages(IO_BITMAP_ORDER)) == NULL )
+        {
+            DPRINTK("Failed to allocate io bitmap b for vcpu %d.\n",
+                    vc->vcpu_id);
+            return 0;
+        }
+
+        memset(io_bitmap_a, 0xff, 0x1000);
+        memset(io_bitmap_b, 0xff, 0x1000);
+
+        /* don't bother debug port access */
+        clear_bit(PC_DEBUG_PORT, io_bitmap_a);
+
+        vc->arch.hvm_vmx.io_bitmap_a = io_bitmap_a;
+        vc->arch.hvm_vmx.io_bitmap_b = io_bitmap_b;
+    }
+
+    /*
+     * Required to do this once per domain XXX todo: add a seperate function 
+     * to do these.
+     */
+    memset(&d->shared_info->evtchn_mask[0], 0xff,
+           sizeof(d->shared_info->evtchn_mask));
+
+    /* Put the domain in shadow mode even though we're going to be using
+     * the shared 1:1 page table initially. It shouldn't hurt */
+    shadow_mode_enable(
+        d, SHM_enable|SHM_refcounts|SHM_translate|SHM_external|SHM_wr_pt_pte);
+
+    return 1;
 }
 
 static void vmx_relinquish_guest_resources(struct domain *d)
@@ -90,9 +129,9 @@ static void vmx_relinquish_guest_resourc
 
     for_each_vcpu ( d, v )
     {
+        vmx_destroy_vmcs(v);
         if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
             continue;
-        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) )
@@ -442,12 +481,6 @@ void stop_vmx(void)
 {
     if (read_cr4() & X86_CR4_VMXE)
         __vmxoff();
-}
-
-int vmx_initialize_guest_resources(struct vcpu *v)
-{
-    vmx_final_setup_guest(v);
-    return 1;
 }
 
 void vmx_migrate_timers(struct vcpu *v)
@@ -638,58 +671,61 @@ static int check_vmx_controls(u32 ctrls,
 
 int start_vmx(void)
 {
+    u32 eax, edx;
     struct vmcs_struct *vmcs;
-    u32 ecx;
-    u32 eax, edx;
-    u64 phys_vmcs;      /* debugging */
 
     /*
      * Xen does not fill x86_capability words except 0.
      */
-    ecx = cpuid_ecx(1);
-    boot_cpu_data.x86_capability[4] = ecx;
+    boot_cpu_data.x86_capability[4] = cpuid_ecx(1);
 
     if (!(test_bit(X86_FEATURE_VMXE, &boot_cpu_data.x86_capability)))
         return 0;
 
     rdmsr(IA32_FEATURE_CONTROL_MSR, eax, edx);
 
-    if (eax & IA32_FEATURE_CONTROL_MSR_LOCK) {
-        if ((eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON) == 0x0) {
+    if ( eax & IA32_FEATURE_CONTROL_MSR_LOCK )
+    {
+        if ( (eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON) == 0x0 )
+        {
             printk("VMX disabled by Feature Control MSR.\n");
             return 0;
         }
     }
-    else {
+    else
+    {
         wrmsr(IA32_FEATURE_CONTROL_MSR,
               IA32_FEATURE_CONTROL_MSR_LOCK |
               IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON, 0);
     }
 
-    if (!check_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS,
-                            MSR_IA32_VMX_PINBASED_CTLS_MSR))
+    if ( !check_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS,
+                             MSR_IA32_VMX_PINBASED_CTLS_MSR) )
         return 0;
-    if (!check_vmx_controls(MONITOR_CPU_BASED_EXEC_CONTROLS,
-                            MSR_IA32_VMX_PROCBASED_CTLS_MSR))
+    if ( !check_vmx_controls(MONITOR_CPU_BASED_EXEC_CONTROLS,
+                             MSR_IA32_VMX_PROCBASED_CTLS_MSR) )
         return 0;
-    if (!check_vmx_controls(MONITOR_VM_EXIT_CONTROLS,
-                            MSR_IA32_VMX_EXIT_CTLS_MSR))
+    if ( !check_vmx_controls(MONITOR_VM_EXIT_CONTROLS,
+                             MSR_IA32_VMX_EXIT_CTLS_MSR) )
         return 0;
-    if (!check_vmx_controls(MONITOR_VM_ENTRY_CONTROLS,
-                            MSR_IA32_VMX_ENTRY_CTLS_MSR))
+    if ( !check_vmx_controls(MONITOR_VM_ENTRY_CONTROLS,
+                             MSR_IA32_VMX_ENTRY_CTLS_MSR) )
         return 0;
 
-    set_in_cr4(X86_CR4_VMXE);   /* Enable VMXE */
-
-    if (!(vmcs = vmx_alloc_vmcs())) {
-        printk("Failed to allocate VMCS\n");
+    set_in_cr4(X86_CR4_VMXE);
+
+    vmx_init_vmcs_config();
+
+    if ( (vmcs = vmx_alloc_host_vmcs()) == NULL )
+    {
+        printk("Failed to allocate host VMCS\n");
         return 0;
     }
 
-    phys_vmcs = (u64) virt_to_maddr(vmcs);
-
-    if (__vmxon(phys_vmcs)) {
+    if ( __vmxon(virt_to_maddr(vmcs)) )
+    {
         printk("VMXON failed\n");
+        vmx_free_host_vmcs(vmcs);
         return 0;
     }
 
diff -r 4d2354be4aa6 -r 82f481bda1c7 xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h        Wed Jul 05 10:32:33 2006 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h        Wed Jul 05 11:21:19 2006 +0100
@@ -27,9 +27,7 @@ extern int start_vmx(void);
 extern int start_vmx(void);
 extern void stop_vmx(void);
 extern void vmcs_dump_vcpu(void);
-void vmx_final_setup_guest(struct vcpu *v);
-
-void vmx_enter_scheduler(void);
+extern void vmx_init_vmcs_config(void);
 
 enum {
     VMX_CPU_STATE_PAE_ENABLED=0,
@@ -45,8 +43,6 @@ struct vmcs_struct {
     u32 vmcs_revision_id;
     unsigned char data [0]; /* vmcs size is read from MSR */
 };
-
-extern int vmcs_size;
 
 enum {
     VMX_INDEX_MSR_LSTAR = 0,
@@ -63,6 +59,10 @@ struct vmx_msr_state {
     unsigned long msr_items[VMX_MSR_COUNT];
     unsigned long shadow_gs;
 };
+
+/* io bitmap is 4KBytes in size */
+#define IO_BITMAP_SIZE      0x1000
+#define IO_BITMAP_ORDER     (get_order_from_bytes(IO_BITMAP_SIZE))
 
 struct arch_vmx_struct {
     /* Virtual address of VMCS. */
@@ -101,7 +101,10 @@ struct arch_vmx_struct {
 
 void vmx_do_resume(struct vcpu *);
 
-struct vmcs_struct *vmx_alloc_vmcs(void);
+struct vmcs_struct *vmx_alloc_host_vmcs(void);
+void vmx_free_host_vmcs(struct vmcs_struct *vmcs);
+
+int vmx_create_vmcs(struct vcpu *v);
 void vmx_destroy_vmcs(struct vcpu *v);
 void vmx_vmcs_enter(struct vcpu *v);
 void vmx_vmcs_exit(struct vcpu *v);

_______________________________________________
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] Move vmcs and I/O bitmap allocation into, Xen patchbot-unstable <=