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] [SVM] Move VMCB construction to VCPU crea

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [SVM] Move VMCB construction to VCPU creation time.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 07 Nov 2006 12:30:16 +0000
Delivery-date: Tue, 07 Nov 2006 04:30:10 -0800
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@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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [SVM] Move VMCB construction to VCPU creation time., Xen patchbot-unstable <=