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] x86 hvm: Allow cross-vendor migration

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86 hvm: Allow cross-vendor migration
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 27 May 2009 04:30:44 -0700
Delivery-date: Wed, 27 May 2009 04:31:47 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
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/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/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 Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1243346496 -3600
# Node ID f0e2df69a8eb2f560af5626807b81ca4f41afd39
# Parent  1c627434605e7747689047e1761c193ceb4f9ef0
x86 hvm: Allow cross-vendor migration

Intercept #UD and emulate SYSCALL/SYSENTER/SYSEXIT as necessary.

Signed-off-by: Christoph Egger <Christoph.Egger@xxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/hvm/svm/svm.c             |  100 ++++++++++++++-
 xen/arch/x86/hvm/svm/vmcb.c            |    8 -
 xen/arch/x86/hvm/vmx/vmcs.c            |    3 
 xen/arch/x86/hvm/vmx/vmx.c             |   36 +++++
 xen/arch/x86/x86_emulate/x86_emulate.c |  212 ++++++++++++++++++++++++++++++++-
 xen/include/asm-x86/hvm/svm/vmcb.h     |    9 +
 xen/include/public/arch-x86/hvm/save.h |    4 
 7 files changed, 354 insertions(+), 18 deletions(-)

diff -r 1c627434605e -r f0e2df69a8eb xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Tue May 26 11:52:31 2009 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Tue May 26 15:01:36 2009 +0100
@@ -37,6 +37,7 @@
 #include <asm/debugreg.h>
 #include <asm/msr.h>
 #include <asm/spinlock.h>
+#include <asm/hvm/emulate.h>
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/support.h>
 #include <asm/hvm/io.h>
@@ -199,9 +200,9 @@ static int svm_vmcb_save(struct vcpu *v,
     c->cr3 = v->arch.hvm_vcpu.guest_cr[3];
     c->cr4 = v->arch.hvm_vcpu.guest_cr[4];
 
-    c->sysenter_cs = vmcb->sysenter_cs;
-    c->sysenter_esp = vmcb->sysenter_esp;
-    c->sysenter_eip = vmcb->sysenter_eip;
+    c->sysenter_cs = v->arch.hvm_svm.guest_sysenter_cs;
+    c->sysenter_esp = v->arch.hvm_svm.guest_sysenter_esp;
+    c->sysenter_eip = v->arch.hvm_svm.guest_sysenter_eip;
 
     c->pending_event = 0;
     c->error_code = 0;
@@ -258,9 +259,9 @@ static int svm_vmcb_restore(struct vcpu 
     svm_update_guest_cr(v, 2);
     svm_update_guest_cr(v, 4);
 
-    vmcb->sysenter_cs =  c->sysenter_cs;
-    vmcb->sysenter_esp = c->sysenter_esp;
-    vmcb->sysenter_eip = c->sysenter_eip;
+    v->arch.hvm_svm.guest_sysenter_cs = c->sysenter_cs;
+    v->arch.hvm_svm.guest_sysenter_esp = c->sysenter_esp;
+    v->arch.hvm_svm.guest_sysenter_eip = c->sysenter_eip;
 
     if ( paging_mode_hap(v->domain) )
     {
@@ -286,7 +287,7 @@ static int svm_vmcb_restore(struct vcpu 
     return 0;
 }
 
-        
+
 static void svm_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
@@ -985,6 +986,16 @@ static int svm_msr_read_intercept(struct
         msr_content = v->arch.hvm_vcpu.guest_efer;
         break;
 
+    case MSR_IA32_SYSENTER_CS:
+        msr_content = v->arch.hvm_svm.guest_sysenter_cs;
+        break;
+    case MSR_IA32_SYSENTER_ESP:
+        msr_content = v->arch.hvm_svm.guest_sysenter_esp;
+        break;
+    case MSR_IA32_SYSENTER_EIP:
+        msr_content = v->arch.hvm_svm.guest_sysenter_eip;
+        break;
+
     case MSR_IA32_MC4_MISC: /* Threshold register */
     case MSR_F10_MC4_MISC1 ... MSR_F10_MC4_MISC3:
         /*
@@ -1067,6 +1078,16 @@ static int svm_msr_write_intercept(struc
     case MSR_K8_VM_HSAVE_PA:
         goto gpf;
 
+    case MSR_IA32_SYSENTER_CS:
+        v->arch.hvm_svm.guest_sysenter_cs = msr_content;
+        break;
+    case MSR_IA32_SYSENTER_ESP:
+        v->arch.hvm_svm.guest_sysenter_esp = msr_content;
+        break;
+    case MSR_IA32_SYSENTER_EIP:
+        v->arch.hvm_svm.guest_sysenter_eip = msr_content;
+        break;
+
     case MSR_IA32_DEBUGCTLMSR:
         vmcb->debugctlmsr = msr_content;
         if ( !msr_content || !cpu_has_svm_lbrv )
@@ -1165,6 +1186,66 @@ static void svm_vmexit_do_rdtsc(struct c
     hvm_rdtsc_intercept(regs);
 }
 
+static void svm_dump_regs(const char *from, struct cpu_user_regs *regs)
+{
+    printk("Dumping guest's current registers at %s...\n", from);
+    printk("Size of regs = 0x%lx, address = %p\n",
+           sizeof(struct cpu_user_regs), regs);
+
+    printk("r15 = 0x%016"PRIx64", r14 = 0x%016"PRIx64"\n",
+           regs->r15, regs->r14);
+    printk("r13 = 0x%016"PRIx64", r12 = 0x%016"PRIx64"\n",
+           regs->r13, regs->r12);
+    printk("rbp = 0x%016"PRIx64", rbx = 0x%016"PRIx64"\n",
+           regs->rbp, regs->rbx);
+    printk("r11 = 0x%016"PRIx64", r10 = 0x%016"PRIx64"\n",
+           regs->r11, regs->r10);
+    printk("r9  = 0x%016"PRIx64", r8  = 0x%016"PRIx64"\n",
+           regs->r9, regs->r8);
+    printk("rax = 0x%016"PRIx64", rcx = 0x%016"PRIx64"\n",
+           regs->rax, regs->rcx);
+    printk("rdx = 0x%016"PRIx64", rsi = 0x%016"PRIx64"\n",
+           regs->rdx, regs->rsi);
+    printk("rdi = 0x%016"PRIx64", rsp = 0x%016"PRIx64"\n",
+           regs->rdi, regs->rsp);
+    printk("error code = 0x%08"PRIx32", entry_vector = 0x%08"PRIx32"\n",
+           regs->error_code, regs->entry_vector);
+    printk("rip = 0x%016"PRIx64", rflags = 0x%016"PRIx64"\n",
+           regs->rip, regs->rflags);
+}
+
+static void svm_vmexit_ud_intercept(struct cpu_user_regs *regs)
+{
+    struct hvm_emulate_ctxt ctxt;
+    int rc;
+
+    hvm_emulate_prepare(&ctxt, regs);
+
+    rc = hvm_emulate_one(&ctxt);
+
+    switch ( rc )
+    {
+    case X86EMUL_UNHANDLEABLE:
+        gdprintk(XENLOG_WARNING,
+                 "instruction emulation failed @ %04x:%lx: "
+                 "%02x %02x %02x %02x %02x %02x\n",
+                 hvmemul_get_seg_reg(x86_seg_cs, &ctxt)->sel,
+                 ctxt.insn_buf_eip,
+                 ctxt.insn_buf[0], ctxt.insn_buf[1],
+                 ctxt.insn_buf[2], ctxt.insn_buf[3],
+                 ctxt.insn_buf[4], ctxt.insn_buf[5]);
+         return;
+    case X86EMUL_EXCEPTION:
+        if ( ctxt.exn_pending )
+            hvm_inject_exception(ctxt.exn_vector, ctxt.exn_error_code, 0);
+        break;
+    default:
+        break;
+    }
+
+    hvm_emulate_writeback(&ctxt);
+}
+
 static void wbinvd_ipi(void *info)
 {
     wbinvd();
@@ -1229,6 +1310,7 @@ asmlinkage void svm_vmexit_handler(struc
     if ( unlikely(exit_reason == VMEXIT_INVALID) )
     {
         svm_dump_vmcb(__func__, vmcb);
+        svm_dump_regs(__func__, regs);
         goto exit_and_crash;
     }
 
@@ -1304,6 +1386,10 @@ asmlinkage void svm_vmexit_handler(struc
         svm_inject_exception(TRAP_page_fault, regs->error_code, va);
         break;
     }
+
+    case VMEXIT_EXCEPTION_UD:
+        svm_vmexit_ud_intercept(regs);
+        break;
 
     /* Asynchronous event, handled when we STGI'd after the VMEXIT. */
     case VMEXIT_EXCEPTION_MC:
diff -r 1c627434605e -r f0e2df69a8eb xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Tue May 26 11:52:31 2009 +0100
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Tue May 26 15:01:36 2009 +0100
@@ -150,9 +150,6 @@ static int construct_vmcb(struct vcpu *v
     svm_disable_intercept_for_msr(v, MSR_LSTAR);
     svm_disable_intercept_for_msr(v, MSR_STAR);
     svm_disable_intercept_for_msr(v, MSR_SYSCALL_MASK);
-    svm_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_CS);
-    svm_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_ESP);
-    svm_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_EIP);
 
     vmcb->msrpm_base_pa = (u64)virt_to_maddr(arch_svm->msrpm);
     vmcb->iopm_base_pa  = (u64)virt_to_maddr(hvm_io_bitmap);
@@ -222,7 +219,10 @@ static int construct_vmcb(struct vcpu *v
 
     paging_update_paging_modes(v);
 
-    vmcb->exception_intercepts = HVM_TRAP_MASK | (1U << TRAP_no_device);
+    vmcb->exception_intercepts =
+        HVM_TRAP_MASK
+        | (1U << TRAP_no_device)
+        | (1U << TRAP_invalid_op);
 
     if ( paging_mode_hap(v->domain) )
     {
diff -r 1c627434605e -r f0e2df69a8eb xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Tue May 26 11:52:31 2009 +0100
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Tue May 26 15:01:36 2009 +0100
@@ -668,7 +668,8 @@ static int construct_vmcs(struct vcpu *v
     __vmwrite(EXCEPTION_BITMAP,
               HVM_TRAP_MASK
               | (paging_mode_hap(d) ? 0 : (1U << TRAP_page_fault))
-              | (1U << TRAP_no_device));
+              | (1U << TRAP_no_device)
+              | (1U << TRAP_invalid_op));
 
     v->arch.hvm_vcpu.guest_cr[0] = X86_CR0_PE | X86_CR0_ET;
     hvm_update_guest_cr(v, 0);
diff -r 1c627434605e -r f0e2df69a8eb xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Tue May 26 11:52:31 2009 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Tue May 26 15:01:36 2009 +0100
@@ -37,6 +37,7 @@
 #include <asm/spinlock.h>
 #include <asm/paging.h>
 #include <asm/p2m.h>
+#include <asm/hvm/emulate.h>
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/support.h>
 #include <asm/hvm/vmx/vmx.h>
@@ -2248,6 +2249,38 @@ asmlinkage void vmx_enter_realmode(struc
     regs->eflags |= (X86_EFLAGS_VM | X86_EFLAGS_IOPL);
 }
 
+static void vmx_vmexit_ud_intercept(struct cpu_user_regs *regs)
+{
+     struct hvm_emulate_ctxt ctxt;
+     int rc;
+ 
+     hvm_emulate_prepare(&ctxt, regs);
+ 
+     rc = hvm_emulate_one(&ctxt);
+ 
+     switch ( rc )
+     {
+     case X86EMUL_UNHANDLEABLE:
+         gdprintk(XENLOG_WARNING,
+                  "instruction emulation failed @ %04x:%lx: "
+                  "%02x %02x %02x %02x %02x %02x\n",
+                  hvmemul_get_seg_reg(x86_seg_cs, &ctxt)->sel,
+                  ctxt.insn_buf_eip,
+                  ctxt.insn_buf[0], ctxt.insn_buf[1],
+                  ctxt.insn_buf[2], ctxt.insn_buf[3],
+                  ctxt.insn_buf[4], ctxt.insn_buf[5]);
+          return;
+     case X86EMUL_EXCEPTION:
+         if ( ctxt.exn_pending )
+             hvm_inject_exception(ctxt.exn_vector, ctxt.exn_error_code, 0);
+         break;
+     default:
+         break;
+     }
+ 
+     hvm_emulate_writeback(&ctxt);
+}
+
 asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
 {
     unsigned int exit_reason, idtv_info;
@@ -2434,6 +2467,9 @@ asmlinkage void vmx_vmexit_handler(struc
             HVMTRACE_0D(MCE);
             do_machine_check(regs);
             break;
+        case TRAP_invalid_op:
+            vmx_vmexit_ud_intercept(regs);
+            break;
         default:
             goto exit_and_crash;
         }
diff -r 1c627434605e -r f0e2df69a8eb xen/arch/x86/x86_emulate/x86_emulate.c
--- a/xen/arch/x86/x86_emulate/x86_emulate.c    Tue May 26 11:52:31 2009 +0100
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c    Tue May 26 15:01:36 2009 +0100
@@ -172,7 +172,7 @@ static uint8_t opcode_table[256] = {
 
 static uint8_t twobyte_table[256] = {
     /* 0x00 - 0x07 */
-    SrcMem16|ModRM, ImplicitOps|ModRM, 0, 0, 0, 0, ImplicitOps, 0,
+    SrcMem16|ModRM, ImplicitOps|ModRM, 0, 0, 0, ImplicitOps, ImplicitOps, 0,
     /* 0x08 - 0x0F */
     ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps|ModRM, 0, 0,
     /* 0x10 - 0x17 */
@@ -186,7 +186,8 @@ static uint8_t twobyte_table[256] = {
     /* 0x28 - 0x2F */
     0, 0, 0, 0, 0, 0, 0, 0,
     /* 0x30 - 0x37 */
-    ImplicitOps, ImplicitOps, ImplicitOps, 0, 0, 0, 0, 0,
+    ImplicitOps, ImplicitOps, ImplicitOps, 0,
+    ImplicitOps, ImplicitOps, 0, 0,
     /* 0x38 - 0x3F */
     0, 0, 0, 0, 0, 0, 0, 0,
     /* 0x40 - 0x47 */
@@ -280,7 +281,17 @@ struct operand {
 };
 
 /* MSRs. */
-#define MSR_TSC   0x10
+#define MSR_TSC          0x00000010
+#define MSR_SYSENTER_CS  0x00000174
+#define MSR_SYSENTER_ESP 0x00000175
+#define MSR_SYSENTER_EIP 0x00000176
+#define MSR_EFER         0xc0000080
+#define EFER_SCE         (1u<<0)
+#define EFER_LMA         (1u<<10)
+#define MSR_STAR         0xc0000081
+#define MSR_LSTAR        0xc0000082
+#define MSR_CSTAR        0xc0000083
+#define MSR_FMASK        0xc0000084
 
 /* Control register flags. */
 #define CR0_PE    (1<<0)
@@ -942,6 +953,20 @@ in_protmode(
 }
 
 static int
+in_longmode(
+    struct x86_emulate_ctxt *ctxt,
+    struct x86_emulate_ops *ops)
+{
+    uint64_t efer;
+
+    if (ops->read_msr == NULL)
+        return -1;
+
+    ops->read_msr(MSR_EFER, &efer, ctxt);
+    return !!(efer & EFER_LMA);
+}
+
+static int
 realmode_load_seg(
     enum x86_segment seg,
     uint16_t sel,
@@ -3544,6 +3569,71 @@ x86_emulate(
         break;
     }
 
+    case 0x05: /* syscall */ {
+        uint64_t msr_content;
+        struct segment_register cs = { 0 }, ss = { 0 };
+        int rc;
+
+        fail_if(ops->read_msr == NULL);
+        fail_if(ops->read_segment == NULL);
+        fail_if(ops->write_segment == NULL);
+
+        generate_exception_if(in_realmode(ctxt, ops), EXC_UD, 0);
+        generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, 0);
+        generate_exception_if(lock_prefix, EXC_UD, 0);
+
+        /* Inject #UD if syscall/sysret are disabled. */
+        rc = ops->read_msr(MSR_EFER, &msr_content, ctxt);
+        fail_if(rc != 0);
+        generate_exception_if((msr_content & EFER_SCE) == 0, EXC_UD, 0);
+
+        rc = ops->read_msr(MSR_STAR, &msr_content, ctxt);
+        fail_if(rc != 0);
+
+        msr_content >>= 32;
+        cs.sel = (uint16_t)(msr_content & 0xfffc);
+        ss.sel = (uint16_t)(msr_content + 8);
+
+        cs.base = ss.base = 0; /* flat segment */
+        cs.limit = ss.limit = ~0u;  /* 4GB limit */
+        cs.attr.bytes = 0xc9b; /* G+DB+P+S+Code */
+        ss.attr.bytes = 0xc93; /* G+DB+P+S+Data */
+
+        if ( in_longmode(ctxt, ops) )
+        {
+            cs.attr.fields.db = 0;
+            cs.attr.fields.l = 1;
+
+            _regs.rcx = _regs.rip;
+            _regs.r11 = _regs.eflags & ~EFLG_RF;
+
+            rc = ops->read_msr(mode_64bit() ? MSR_LSTAR : MSR_CSTAR,
+                               &msr_content, ctxt);
+            fail_if(rc != 0);
+
+            _regs.rip = msr_content;
+
+            rc = ops->read_msr(MSR_FMASK, &msr_content, ctxt);
+            fail_if(rc != 0);
+            _regs.eflags &= ~(msr_content | EFLG_RF);
+        }
+        else
+        {
+            rc = ops->read_msr(MSR_STAR, &msr_content, ctxt);
+            fail_if(rc != 0);
+
+            _regs.rcx = _regs.rip;
+            _regs.eip = (uint32_t)msr_content;
+            _regs.eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
+        }
+
+        if ( (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) ||
+             (rc = ops->write_segment(x86_seg_ss, &ss, ctxt)) )
+            goto done;
+
+        break;
+    }
+
     case 0x06: /* clts */
         generate_exception_if(!mode_ring0(), EXC_GP, 0);
         fail_if((ops->read_cr == NULL) || (ops->write_cr == NULL));
@@ -3644,6 +3734,122 @@ x86_emulate(
         if ( !test_cc(b, _regs.eflags) )
             dst.type = OP_NONE;
         break;
+
+    case 0x34: /* sysenter */ {
+        uint64_t msr_content;
+        struct segment_register cs, ss;
+        int rc;
+
+        fail_if(ops->read_msr == NULL);
+        fail_if(ops->read_segment == NULL);
+        fail_if(ops->write_segment == NULL);
+
+        generate_exception_if(mode_ring0(), EXC_GP, 0);
+        generate_exception_if(in_realmode(ctxt, ops), EXC_GP, 0);
+        generate_exception_if(!in_protmode(ctxt, ops), EXC_GP, 0);
+        generate_exception_if(lock_prefix, EXC_UD, 0);
+
+        rc = ops->read_msr(MSR_SYSENTER_CS, &msr_content, ctxt);
+        fail_if(rc != 0);
+
+        if ( mode_64bit() )
+            generate_exception_if(msr_content == 0, EXC_GP, 0);
+        else
+            generate_exception_if((msr_content & 0xfffc) == 0, EXC_GP, 0);
+
+        _regs.eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
+
+        ops->read_segment(x86_seg_cs, &cs, ctxt);
+        cs.sel = (uint16_t)msr_content & ~3; /* SELECTOR_RPL_MASK */
+        cs.base = 0;   /* flat segment */
+        cs.limit = ~0u;  /* 4GB limit */
+        cs.attr.bytes = 0xc9b; /* G+DB+P+S+Code */
+
+        ss.sel = cs.sel + 8;
+        ss.base = 0;   /* flat segment */
+        ss.limit = ~0u;  /* 4GB limit */
+        ss.attr.bytes = 0xc93; /* G+DB+P+S+Data */
+
+        if ( in_longmode(ctxt, ops) )
+        {
+            cs.attr.fields.db = 0;
+            cs.attr.fields.l = 1;
+        }
+
+        rc = ops->write_segment(x86_seg_cs, &cs, ctxt);
+        fail_if(rc != 0);
+        rc = ops->write_segment(x86_seg_ss, &ss, ctxt);
+        fail_if(rc != 0);
+
+        rc = ops->read_msr(MSR_SYSENTER_EIP, &msr_content, ctxt);
+        fail_if(rc != 0);
+        _regs.rip = msr_content;
+
+        rc = ops->read_msr(MSR_SYSENTER_ESP, &msr_content, ctxt);
+        fail_if(rc != 0);
+        _regs.rsp = msr_content;
+
+        break;
+    }
+
+    case 0x35: /* sysexit */ {
+        uint64_t msr_content;
+        struct segment_register cs, ss;
+        int user64 = !!(rex_prefix & 8); /* REX.W */
+        int rc;
+
+        fail_if(ops->read_msr == NULL);
+        fail_if(ops->read_segment == NULL);
+        fail_if(ops->write_segment == NULL);
+
+        generate_exception_if(!mode_ring0(), EXC_GP, 0);
+        generate_exception_if(in_realmode(ctxt, ops), EXC_GP, 0);
+        generate_exception_if(!in_protmode(ctxt, ops), EXC_GP, 0);
+        generate_exception_if(lock_prefix, EXC_UD, 0);
+
+        rc = ops->read_msr(MSR_SYSENTER_CS, &msr_content, ctxt);
+        fail_if(rc != 0);
+        rc = ops->read_segment(x86_seg_cs, &cs, ctxt);
+        fail_if(rc != 0);
+
+        if ( user64 )
+        {
+            cs.sel = (uint16_t)(msr_content + 32);
+            ss.sel = (cs.sel + 8);
+            generate_exception_if(msr_content == 0, EXC_GP, 0);
+        }
+        else
+        {
+            cs.sel = (uint16_t)(msr_content + 16);
+            ss.sel = (uint16_t)(msr_content + 24);
+            generate_exception_if((msr_content & 0xfffc) == 0, EXC_GP, 0);
+        }
+
+        cs.sel |= 0x3;   /* SELECTOR_RPL_MASK */
+        cs.base = 0;   /* flat segment */
+        cs.limit = ~0u;  /* 4GB limit */
+        cs.attr.bytes = 0xcfb; /* G+DB+P+DPL3+S+Code */
+
+        ss.sel |= 0x3;   /* SELECTOR_RPL_MASK */
+        ss.base = 0;   /* flat segment */
+        ss.limit = ~0u;  /* 4GB limit */
+        ss.attr.bytes = 0xcf3; /* G+DB+P+DPL3+S+Data */
+
+        if ( user64 )
+        {
+            cs.attr.fields.db = 0;
+            cs.attr.fields.l = 1;
+        }
+
+        rc = ops->write_segment(x86_seg_cs, &cs, ctxt);
+        fail_if(rc != 0);
+        rc = ops->write_segment(x86_seg_ss, &ss, ctxt);
+        fail_if(rc != 0);
+
+        _regs.rip = _regs.rdx;
+        _regs.rsp = _regs.rcx;
+        break;
+    }
 
     case 0x6f: /* movq mm/m64,mm */ {
         uint8_t stub[] = { 0x0f, 0x6f, modrm, 0xc3 };
diff -r 1c627434605e -r f0e2df69a8eb xen/include/asm-x86/hvm/svm/vmcb.h
--- a/xen/include/asm-x86/hvm/svm/vmcb.h        Tue May 26 11:52:31 2009 +0100
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h        Tue May 26 15:01:36 2009 +0100
@@ -459,6 +459,15 @@ struct arch_svm_struct {
     unsigned long *msrpm;
     int    launch_core;
     bool_t vmcb_in_sync;    /* VMCB sync'ed with VMSAVE? */
+
+    /* Upper four bytes are undefined in the VMCB, therefore we can't
+     * use the fields in the VMCB. Write a 64bit value and then read a 64bit
+     * value is fine unless there's a VMRUN/VMEXIT in between which clears
+     * the upper four bytes.
+     */
+    uint64_t guest_sysenter_cs;
+    uint64_t guest_sysenter_esp;
+    uint64_t guest_sysenter_eip;
 };
 
 struct vmcb_struct *alloc_vmcb(void);
diff -r 1c627434605e -r f0e2df69a8eb xen/include/public/arch-x86/hvm/save.h
--- a/xen/include/public/arch-x86/hvm/save.h    Tue May 26 11:52:31 2009 +0100
+++ b/xen/include/public/arch-x86/hvm/save.h    Tue May 26 15:01:36 2009 +0100
@@ -123,9 +123,7 @@ struct hvm_hw_cpu {
     uint32_t tr_arbytes;
     uint32_t ldtr_arbytes;
 
-    uint32_t sysenter_cs;
-    uint32_t padding0;
-
+    uint64_t sysenter_cs;
     uint64_t sysenter_esp;
     uint64_t sysenter_eip;
 

_______________________________________________
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] x86 hvm: Allow cross-vendor migration, Xen patchbot-unstable <=