[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [SVM] Move VMCB construction to VCPU creation time.



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxxx
# Node ID 81c451bd398e950f9df8819ab7fab4b847815c82
# Parent  f8ffeb540ec168ac3461e3572ba2244cf53d23db
[SVM] Move VMCB construction to VCPU creation time.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/svm/svm.c         |   53 ++-------
 xen/arch/x86/hvm/svm/vmcb.c        |  217 +++++++++++++++----------------------
 xen/include/asm-x86/hvm/svm/vmcb.h |   20 +--
 3 files changed, 113 insertions(+), 177 deletions(-)

diff -r f8ffeb540ec1 -r 81c451bd398e xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Mon Nov 06 18:57:33 2006 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c        Mon Nov 06 20:23:08 2006 +0000
@@ -213,10 +213,7 @@ static void stop_svm(void)
     free_vmcb(root_vmcb[cpu]);
     root_vmcb[cpu] = NULL;
     root_vmcb_pa[cpu] = 0;
-
-    printk("AMD SVM Extension is disabled.\n");
-}
-
+}
 
 static void svm_store_cpu_guest_regs(
     struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs)
@@ -690,35 +687,13 @@ int svm_long_mode_enabled(struct vcpu *v
     return SVM_LONG_GUEST(v);
 }
 
-
-
 static void arch_svm_do_launch(struct vcpu *v) 
 {
-    cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
-    int error;
-
-#if 0
-    if (svm_dbg_on)
-        printk("Do launch\n");
-#endif
-    error = construct_vmcb(&v->arch.hvm_svm, regs);
-    if ( error < 0 )
-    {
-        if (v->vcpu_id == 0) {
-            printk("Failed to construct a new VMCB for BSP.\n");
-        } else {
-            printk("Failed to construct a new VMCB for AP %d\n", v->vcpu_id);
-        }
-        domain_crash_synchronous();
-    }
-
     svm_do_launch(v);
-#if 0
-    if (svm_dbg_on)
-        svm_dump_host_regs(__func__);
-#endif
-    if (v->vcpu_id != 0) 
-    {
+
+    if ( v->vcpu_id != 0 )
+    {
+        cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
         u16 cs_sel = regs->cs;
         /*
          * This is the launch of an AP; set state so that we begin executing
@@ -770,24 +745,26 @@ static void svm_ctxt_switch_to(struct vc
 
 static int svm_vcpu_initialise(struct vcpu *v)
 {
+    int rc;
+
     v->arch.schedule_tail    = arch_svm_do_launch;
     v->arch.ctxt_switch_from = svm_ctxt_switch_from;
     v->arch.ctxt_switch_to   = svm_ctxt_switch_to;
 
-    if ( (v->arch.hvm_svm.vmcb = alloc_vmcb()) == NULL )
-    {
-        printk("Failed to create a new VMCB\n");
-        return -ENOMEM;
-    }
-
-    v->arch.hvm_svm.vmcb_pa = virt_to_maddr(v->arch.hvm_svm.vmcb);
+    if ( (rc = svm_create_vmcb(v)) != 0 )
+    {
+        dprintk(XENLOG_WARNING,
+                "Failed to create VMCB for vcpu %d: err=%d.\n",
+                v->vcpu_id, rc);
+        return rc;
+    }
 
     return 0;
 }
 
 static void svm_vcpu_destroy(struct vcpu *v)
 {
-    destroy_vmcb(&v->arch.hvm_svm);
+    svm_destroy_vmcb(v);
 }
 
 int start_svm(void)
diff -r f8ffeb540ec1 -r 81c451bd398e xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Mon Nov 06 18:57:33 2006 +0000
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Mon Nov 06 20:23:08 2006 +0000
@@ -86,13 +86,14 @@ void free_host_save_area(struct host_sav
     free_xenheap_page(hsa);
 }
 
-/* Set up intercepts to exit the guest into the hypervisor when we want it. */
-static int construct_vmcb_controls(struct arch_svm_struct *arch_svm)
-{
+static int construct_vmcb(struct vcpu *v)
+{
+    struct arch_svm_struct *arch_svm = &v->arch.hvm_svm;
     struct vmcb_struct *vmcb = arch_svm->vmcb;
-    u32 *iopm, *msrpm;
-
-    /* mask off all general 1 intercepts except those listed here */
+    segment_attributes_t attrib;
+    unsigned long dr7;
+
+    /* SVM intercepts. */
     vmcb->general1_intercepts = 
         GENERAL1_INTERCEPT_INTR         | GENERAL1_INTERCEPT_NMI         |
         GENERAL1_INTERCEPT_SMI          | GENERAL1_INTERCEPT_INIT        |
@@ -100,74 +101,43 @@ static int construct_vmcb_controls(struc
         GENERAL1_INTERCEPT_HLT          | GENERAL1_INTERCEPT_INVLPG      | 
         GENERAL1_INTERCEPT_INVLPGA      | GENERAL1_INTERCEPT_IOIO_PROT   |
         GENERAL1_INTERCEPT_MSR_PROT     | GENERAL1_INTERCEPT_SHUTDOWN_EVT;
-
-    /* turn on the general 2 intercepts */
     vmcb->general2_intercepts = 
         GENERAL2_INTERCEPT_VMRUN  | GENERAL2_INTERCEPT_VMMCALL | 
         GENERAL2_INTERCEPT_VMLOAD | GENERAL2_INTERCEPT_VMSAVE  |
         GENERAL2_INTERCEPT_STGI   | GENERAL2_INTERCEPT_CLGI    |
         GENERAL2_INTERCEPT_SKINIT | GENERAL2_INTERCEPT_RDTSCP;
 
-    /* read or write all debug registers 0 - 15 */
+    /* Intercept all debug-register writes. */
     vmcb->dr_intercepts = DR_INTERCEPT_ALL_WRITES;
 
-    /* RD/WR all control registers 0 - 15, but not read CR2 */
+    /* Intercept all control-register accesses, except to CR2. */
     vmcb->cr_intercepts = ~(CR_INTERCEPT_CR2_READ | CR_INTERCEPT_CR2_WRITE);
 
-    /* The following is for I/O and MSR permision map */
-    iopm = alloc_xenheap_pages(get_order_from_bytes(IOPM_SIZE));
-    if ( iopm != NULL )
-    {
-        memset(iopm, 0xff, IOPM_SIZE);
-        clear_bit(PC_DEBUG_PORT, iopm);
-    }
-    msrpm = alloc_xenheap_pages(get_order_from_bytes(MSRPM_SIZE));
-    if ( msrpm != NULL )
-        memset(msrpm, 0xff, MSRPM_SIZE);
-
-    arch_svm->iopm = iopm;
-    arch_svm->msrpm = msrpm;
-
-    if ( !iopm || !msrpm )
-        return 1;
-
-    vmcb->iopm_base_pa = (u64) virt_to_maddr(iopm);
-    vmcb->msrpm_base_pa = (u64) virt_to_maddr(msrpm);
-
-    return 0;
-}
-
-
-/*
- * Initially set the same environement as host.
- */
-static int construct_init_vmcb_guest(struct arch_svm_struct *arch_svm, 
-                                     struct cpu_user_regs *regs )
-{
-    int error = 0;
-    unsigned long crn;
-    segment_attributes_t attrib;
-    unsigned long dr7;
-    unsigned long shadow_cr;
-    struct vmcb_struct *vmcb = arch_svm->vmcb;
-
-    /* Allows IRQs to be shares */
+    /* I/O and MSR permission bitmaps. */
+    arch_svm->iopm  = alloc_xenheap_pages(get_order_from_bytes(IOPM_SIZE));
+    arch_svm->msrpm = alloc_xenheap_pages(get_order_from_bytes(MSRPM_SIZE));
+    if ( (arch_svm->iopm == NULL) || (arch_svm->msrpm == NULL) )
+    {
+        free_xenheap_pages(arch_svm->iopm,  get_order_from_bytes(IOPM_SIZE));
+        free_xenheap_pages(arch_svm->msrpm, get_order_from_bytes(MSRPM_SIZE));
+        return -ENOMEM;
+    }
+    memset(arch_svm->iopm, 0xff, IOPM_SIZE);
+    clear_bit(PC_DEBUG_PORT, arch_svm->iopm);
+    memset(arch_svm->msrpm, 0xff, MSRPM_SIZE);
+    vmcb->iopm_base_pa = (u64)virt_to_maddr(arch_svm->iopm);
+    vmcb->msrpm_base_pa = (u64)virt_to_maddr(arch_svm->msrpm);
+
+    /* Virtualise EFLAGS.IF and LAPIC TPR (CR8). */
     vmcb->vintr.fields.intr_masking = 1;
   
-    /* Set up event injection entry in VMCB. Just clear it. */
+    /* Initialise event injection to no-op. */
     vmcb->eventinj.bytes = 0;
 
-    /* TSC */
+    /* TSC. */
     vmcb->tsc_offset = 0;
     
-    vmcb->cs.sel = regs->cs;
-    vmcb->es.sel = regs->es;
-    vmcb->ss.sel = regs->ss;
-    vmcb->ds.sel = regs->ds;
-    vmcb->fs.sel = regs->fs;
-    vmcb->gs.sel = regs->gs;
-
-    /* Guest segment Limits. 64K for real mode*/
+    /* Guest segment limits. */
     vmcb->cs.limit = GUEST_SEGMENT_LIMIT;
     vmcb->es.limit = GUEST_SEGMENT_LIMIT;
     vmcb->ss.limit = GUEST_SEGMENT_LIMIT;
@@ -175,7 +145,7 @@ static int construct_init_vmcb_guest(str
     vmcb->fs.limit = GUEST_SEGMENT_LIMIT;
     vmcb->gs.limit = GUEST_SEGMENT_LIMIT;
 
-    /* Base address for segments */
+    /* Guest segment bases. */
     vmcb->cs.base = 0;
     vmcb->es.base = 0;
     vmcb->ss.base = 0;
@@ -183,74 +153,88 @@ static int construct_init_vmcb_guest(str
     vmcb->fs.base = 0;
     vmcb->gs.base = 0;
 
-    /* Guest Interrupt descriptor table */
-    vmcb->idtr.base = 0;
-    vmcb->idtr.limit = 0;
-
-    /* Set up segment attributes */
+    /* Guest segment AR bytes. */
     attrib.bytes = 0;
     attrib.fields.type = 0x3; /* type = 3 */
-    attrib.fields.s = 1; /* code or data, i.e. not system */
-    attrib.fields.dpl = 0; /* DPL = 0 */
-    attrib.fields.p = 1; /* segment present */
-    attrib.fields.db = 1; /* 32-bit */
-    attrib.fields.g = 1; /* 4K pages in limit */
-
-    /* Data selectors */
+    attrib.fields.s = 1;      /* code or data, i.e. not system */
+    attrib.fields.dpl = 0;    /* DPL = 0 */
+    attrib.fields.p = 1;      /* segment present */
+    attrib.fields.db = 1;     /* 32-bit */
+    attrib.fields.g = 1;      /* 4K pages in limit */
     vmcb->es.attributes = attrib;
     vmcb->ss.attributes = attrib;
     vmcb->ds.attributes = attrib;
     vmcb->fs.attributes = attrib;
     vmcb->gs.attributes = attrib;
-
-    /* Code selector */
-    attrib.fields.type = 0xb;   /* type=0xb -> executable/readable, accessed */
+    attrib.fields.type = 0xb; /* type=0xb -> executable/readable, accessed */
     vmcb->cs.attributes = attrib;
 
-    /* Guest Global descriptor table */
+    /* Guest IDT. */
+    vmcb->idtr.base = 0;
+    vmcb->idtr.limit = 0;
+
+    /* Guest GDT. */
     vmcb->gdtr.base = 0;
     vmcb->gdtr.limit = 0;
 
-    /* Guest Local Descriptor Table */
-    attrib.fields.s = 0; /* not code or data segement */
+    /* Guest LDT. */
+    attrib.fields.s = 0;      /* not code or data segement */
     attrib.fields.type = 0x2; /* LDT */
-    attrib.fields.db = 0; /* 16-bit */
-    attrib.fields.g = 0;   
+    attrib.fields.db = 0;     /* 16-bit */
+    attrib.fields.g = 0;
     vmcb->ldtr.attributes = attrib;
 
+    /* Guest TSS. */
     attrib.fields.type = 0xb; /* 32-bit TSS (busy) */
     vmcb->tr.attributes = attrib;
     vmcb->tr.base = 0;
     vmcb->tr.limit = 0xff;
 
-    __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (crn) :);
-    vmcb->cr0 = crn;
-
-    /* Initally PG, PE are not set*/
-    shadow_cr = vmcb->cr0;
-    shadow_cr &= ~X86_CR0_PG;
-    arch_svm->cpu_shadow_cr0 = shadow_cr;
-
-    /* CR3 is set in svm_final_setup_guest */
-
-    __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) :);
-    crn &= ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE);
-    arch_svm->cpu_shadow_cr4 = crn;
-    vmcb->cr4 = crn | SVM_CR4_HOST_MASK;
-
-    vmcb->rsp = 0;
-    vmcb->rip = regs->eip;
-
-    vmcb->rflags = regs->eflags | 2UL; /* inc. reserved bit */
-
+    /* Guest CR0. */
+    vmcb->cr0 = read_cr0();
+    arch_svm->cpu_shadow_cr0 = vmcb->cr0 & ~(X86_CR0_PG | X86_CR0_TS);
+
+    /* Guest CR4. */
+    arch_svm->cpu_shadow_cr4 =
+        read_cr4() & ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE);
+    vmcb->cr4 = arch_svm->cpu_shadow_cr4 | SVM_CR4_HOST_MASK;
+
+    /* Guest DR7. */
     __asm__ __volatile__ ("mov %%dr7, %0\n" : "=r" (dr7));
     vmcb->dr7 = dr7;
 
-    return error;
-}
-
-void destroy_vmcb(struct arch_svm_struct *arch_svm)
-{
+    arch_svm->vmcb->exception_intercepts = MONITOR_DEFAULT_EXCEPTION_BITMAP;
+
+    return 0;
+}
+
+int svm_create_vmcb(struct vcpu *v)
+{
+    struct arch_svm_struct *arch_svm = &v->arch.hvm_svm;
+    int rc;
+
+    if ( (arch_svm->vmcb = alloc_vmcb()) == NULL )
+    {
+        printk("Failed to create a new VMCB\n");
+        return -ENOMEM;
+    }
+
+    if ( (rc = construct_vmcb(v)) != 0 )
+    {
+        free_vmcb(arch_svm->vmcb);
+        arch_svm->vmcb = NULL;
+        return rc;
+    }
+
+    arch_svm->vmcb_pa = virt_to_maddr(arch_svm->vmcb);
+
+    return 0;
+}
+
+void svm_destroy_vmcb(struct vcpu *v)
+{
+    struct arch_svm_struct *arch_svm = &v->arch.hvm_svm;
+
     if ( arch_svm->vmcb != NULL )
     {
         asidpool_retire(arch_svm->vmcb, arch_svm->asid_core);
@@ -273,31 +257,6 @@ void destroy_vmcb(struct arch_svm_struct
 
     arch_svm->vmcb = NULL;
 }
-
-int construct_vmcb(struct arch_svm_struct *arch_svm, 
-                   struct cpu_user_regs *regs)
-{
-    if ( construct_vmcb_controls(arch_svm) != 0 )
-    {
-        printk("construct_vmcb: construct_vmcb_controls failed\n");
-        return -EINVAL;
-    }
-
-    if ( construct_init_vmcb_guest(arch_svm, regs) != 0 )
-    {
-        printk("construct_vmcb: construct_vmcb_guest failed\n");
-        return -EINVAL;
-    }
-
-    arch_svm->vmcb->exception_intercepts = MONITOR_DEFAULT_EXCEPTION_BITMAP;
-    if ( regs->eflags & EF_TF )
-        arch_svm->vmcb->exception_intercepts |= EXCEPTION_BITMAP_DB;
-    else
-        arch_svm->vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_DB;
-
-    return 0;
-}
-
 
 void svm_do_launch(struct vcpu *v)
 {
diff -r f8ffeb540ec1 -r 81c451bd398e xen/include/asm-x86/hvm/svm/vmcb.h
--- a/xen/include/asm-x86/hvm/svm/vmcb.h        Mon Nov 06 18:57:33 2006 +0000
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h        Mon Nov 06 20:23:08 2006 +0000
@@ -23,7 +23,7 @@
 #include <asm/config.h>
 #include <asm/hvm/hvm.h>
 
-extern int start_svm(void);
+int start_svm(void);
 
 /* general 1 intercepts */
 enum GenericIntercept1bits
@@ -496,15 +496,15 @@ struct arch_svm_struct {
     unsigned long       cpu_state;
 };
 
-extern struct vmcb_struct *alloc_vmcb(void);
-extern struct host_save_area *alloc_host_save_area(void);
-extern void free_vmcb(struct vmcb_struct *vmcb);
-extern void free_host_save_area(struct host_save_area *hsa);
-
-extern int  construct_vmcb(struct arch_svm_struct *, struct cpu_user_regs *);
-extern void destroy_vmcb(struct arch_svm_struct *);
-
-extern void setup_vmcb_dump(void);
+struct vmcb_struct *alloc_vmcb(void);
+struct host_save_area *alloc_host_save_area(void);
+void free_vmcb(struct vmcb_struct *vmcb);
+void free_host_save_area(struct host_save_area *hsa);
+
+int  svm_create_vmcb(struct vcpu *v);
+void svm_destroy_vmcb(struct vcpu *v);
+
+void setup_vmcb_dump(void);
 
 #define VMCB_USE_HOST_ENV       1
 #define VMCB_USE_SEPARATE_ENV   0

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.