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] vmx: Initial framework for real-mode emul

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] vmx: Initial framework for real-mode emulation (disabled by default).
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Sat, 24 Nov 2007 19:00:26 -0800
Delivery-date: Sat, 24 Nov 2007 19:01:40 -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 Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1195940774 0
# Node ID 51082cf273d426b6443e729e8141be24f0bdc850
# Parent  d5c3961288970acd963855b12c84ede7d8ebabfc
vmx: Initial framework for real-mode emulation (disabled by default).
Still plenty to do:
 - i/o emulation
 - more instructions
 - interrupt/exception delivery
 - vm86 fast path
At this stage we can get three instructions into the rombios.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/hvm/vmx/Makefile     |    3 
 xen/arch/x86/hvm/vmx/realmode.c   |  274 ++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/hvm/vmx/vmx.c        |    7 
 xen/include/asm-x86/hvm/vmx/vmx.h |    1 
 4 files changed, 278 insertions(+), 7 deletions(-)

diff -r d5c396128897 -r 51082cf273d4 xen/arch/x86/hvm/vmx/Makefile
--- a/xen/arch/x86/hvm/vmx/Makefile     Sat Nov 24 21:40:19 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/Makefile     Sat Nov 24 21:46:14 2007 +0000
@@ -4,5 +4,8 @@ subdir-$(x86_64) += x86_64
 subdir-$(x86_64) += x86_64
 
 obj-y += intr.o
+ifneq ($(vmxassist),y)
+obj-y += realmode.o
+endif
 obj-y += vmcs.o
 obj-y += vmx.o
diff -r d5c396128897 -r 51082cf273d4 xen/arch/x86/hvm/vmx/realmode.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/hvm/vmx/realmode.c   Sat Nov 24 21:46:14 2007 +0000
@@ -0,0 +1,274 @@
+/******************************************************************************
+ * arch/x86/hvm/vmx/realmode.c
+ * 
+ * Real-mode emulation for VMX.
+ * 
+ * Copyright (c) 2007 Citrix Systems, Inc.
+ * 
+ * Authors:
+ *    Keir Fraser <keir.fraser@xxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/sched.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/vmx/vmx.h>
+#include <asm/hvm/vmx/vmcs.h>
+#include <asm/hvm/vmx/cpu.h>
+#include <asm/x86_emulate.h>
+
+struct realmode_emulate_ctxt {
+    struct x86_emulate_ctxt ctxt;
+
+    /* Cache of up to 31 bytes of instruction. */
+    uint8_t insn_buf[31];
+    uint8_t insn_buf_bytes;
+    unsigned long insn_buf_eip;
+
+    struct segment_register seg_reg[10];
+};
+
+static int realmode_translate_linear_addr(
+    enum x86_segment seg,
+    unsigned long offset,
+    unsigned int bytes,
+    enum hvm_access_type access_type,
+    struct realmode_emulate_ctxt *rm_ctxt,
+    unsigned long *paddr)
+{
+    struct segment_register *reg = &rm_ctxt->seg_reg[seg];
+    int okay;
+
+    okay = hvm_virtual_to_linear_addr(
+        seg, reg, offset, bytes, access_type, rm_ctxt->ctxt.addr_size, paddr);
+
+    if ( !okay )
+    {
+        hvm_inject_exception(TRAP_gp_fault, 0, 0);
+        return X86EMUL_EXCEPTION;
+    }
+
+    return 0;
+}
+
+static int
+realmode_read(
+    enum x86_segment seg,
+    unsigned long offset,
+    unsigned long *val,
+    unsigned int bytes,
+    enum hvm_access_type access_type,
+    struct realmode_emulate_ctxt *rm_ctxt)
+{
+    unsigned long addr;
+    int rc;
+
+    rc = realmode_translate_linear_addr(
+        seg, offset, bytes, access_type, rm_ctxt, &addr);
+    if ( rc )
+        return rc;
+
+    *val = 0;
+    (void)hvm_copy_from_guest_phys(val, addr, bytes);
+    return X86EMUL_OKAY;
+}
+
+static int
+realmode_emulate_read(
+    enum x86_segment seg,
+    unsigned long offset,
+    unsigned long *val,
+    unsigned int bytes,
+    struct x86_emulate_ctxt *ctxt)
+{
+    return realmode_read(
+        seg, offset, val, bytes, hvm_access_read,
+        container_of(ctxt, struct realmode_emulate_ctxt, ctxt));
+}
+
+static int
+realmode_emulate_insn_fetch(
+    enum x86_segment seg,
+    unsigned long offset,
+    unsigned long *val,
+    unsigned int bytes,
+    struct x86_emulate_ctxt *ctxt)
+{
+    struct realmode_emulate_ctxt *rm_ctxt =
+        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
+    unsigned int insn_off = offset - rm_ctxt->insn_buf_eip;
+
+    /* Fall back if requested bytes are not in the prefetch cache. */
+    if ( unlikely((insn_off + bytes) > rm_ctxt->insn_buf_bytes) )
+        return realmode_read(
+            seg, offset, val, bytes,
+            hvm_access_insn_fetch, rm_ctxt);
+
+    /* Hit the cache. Simple memcpy. */
+    *val = 0;
+    memcpy(val, &rm_ctxt->insn_buf[insn_off], bytes);
+    return X86EMUL_OKAY;
+}
+
+static int
+realmode_emulate_write(
+    enum x86_segment seg,
+    unsigned long offset,
+    unsigned long val,
+    unsigned int bytes,
+    struct x86_emulate_ctxt *ctxt)
+{
+    struct realmode_emulate_ctxt *rm_ctxt =
+        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
+    unsigned long addr;
+    int rc;
+
+    rc = realmode_translate_linear_addr(
+        seg, offset, bytes, hvm_access_write, rm_ctxt, &addr);
+    if ( rc )
+        return rc;
+
+    (void)hvm_copy_to_guest_phys(addr, &val, bytes);
+    return X86EMUL_OKAY;
+}
+
+static int 
+realmode_emulate_cmpxchg(
+    enum x86_segment seg,
+    unsigned long offset,
+    unsigned long old,
+    unsigned long new,
+    unsigned int bytes,
+    struct x86_emulate_ctxt *ctxt)
+{
+    return X86EMUL_UNHANDLEABLE;
+}
+
+static int
+realmode_read_segment(
+    enum x86_segment seg,
+    struct segment_register *reg,
+    struct x86_emulate_ctxt *ctxt)
+{
+    struct realmode_emulate_ctxt *rm_ctxt =
+        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
+    memcpy(reg, &rm_ctxt->seg_reg[seg], sizeof(struct segment_register));
+    return X86EMUL_OKAY;
+}
+
+static int
+realmode_write_segment(
+    enum x86_segment seg,
+    struct segment_register *reg,
+    struct x86_emulate_ctxt *ctxt)
+{
+    struct realmode_emulate_ctxt *rm_ctxt =
+        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
+    memcpy(&rm_ctxt->seg_reg[seg], reg, sizeof(struct segment_register));
+    return X86EMUL_OKAY;
+}
+
+static int
+realmode_read_io(
+    unsigned int port,
+    unsigned int bytes,
+    unsigned long *val,
+    struct x86_emulate_ctxt *ctxt)
+{
+    return X86EMUL_UNHANDLEABLE;
+}
+
+static int realmode_write_io(
+    unsigned int port,
+    unsigned int bytes,
+    unsigned long val,
+    struct x86_emulate_ctxt *ctxt)
+{
+    return X86EMUL_UNHANDLEABLE;
+}
+
+static int
+realmode_read_cr(
+    unsigned int reg,
+    unsigned long *val,
+    struct x86_emulate_ctxt *ctxt)
+{
+    switch ( reg )
+    {
+    case 0:
+    case 2:
+    case 3:
+    case 4:
+        *val = current->arch.hvm_vcpu.guest_cr[reg];
+        break;
+    default:
+        return X86EMUL_UNHANDLEABLE;
+    }
+
+    return X86EMUL_OKAY;
+}
+
+static struct x86_emulate_ops realmode_emulator_ops = {
+    .read          = realmode_emulate_read,
+    .insn_fetch    = realmode_emulate_insn_fetch,
+    .write         = realmode_emulate_write,
+    .cmpxchg       = realmode_emulate_cmpxchg,
+    .read_segment  = realmode_read_segment,
+    .write_segment = realmode_write_segment,
+    .read_io       = realmode_read_io,
+    .write_io      = realmode_write_io,
+    .read_cr       = realmode_read_cr
+};
+
+int vmx_realmode(struct cpu_user_regs *regs)
+{
+    struct vcpu *curr = current;
+    struct realmode_emulate_ctxt rm_ctxt;
+    unsigned long addr;
+    int i, rc = 0;
+
+    for ( i = 0; i < 10; i++ )
+        hvm_get_segment_register(curr, i, &rm_ctxt.seg_reg[i]);
+
+    while ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) &&
+            !softirq_pending(smp_processor_id()) )
+    {
+        rm_ctxt.ctxt.regs = regs;
+        rm_ctxt.ctxt.addr_size =
+            rm_ctxt.seg_reg[x86_seg_cs].attr.fields.db ? 32 : 16;
+        rm_ctxt.ctxt.sp_size =
+            rm_ctxt.seg_reg[x86_seg_ss].attr.fields.db ? 32 : 16;
+
+        rm_ctxt.insn_buf_eip = regs->eip;
+        rm_ctxt.insn_buf_bytes =
+            (hvm_virtual_to_linear_addr(
+                x86_seg_cs, &rm_ctxt.seg_reg[x86_seg_cs],
+                regs->eip, sizeof(rm_ctxt.insn_buf),
+                hvm_access_insn_fetch, rm_ctxt.ctxt.addr_size, &addr) &&
+             !hvm_copy_from_guest_virt(
+                 rm_ctxt.insn_buf, addr, sizeof(rm_ctxt.insn_buf)))
+            ? sizeof(rm_ctxt.insn_buf) : 0;
+
+        gdprintk(XENLOG_DEBUG,
+                 "RM %04x:%08lx: %02x %02x %02x %02x %02x %02x\n",
+                 rm_ctxt.seg_reg[x86_seg_cs].sel, regs->eip,
+                 rm_ctxt.insn_buf[0], rm_ctxt.insn_buf[1],
+                 rm_ctxt.insn_buf[2], rm_ctxt.insn_buf[3],
+                 rm_ctxt.insn_buf[4], rm_ctxt.insn_buf[5]);
+
+        if ( x86_emulate(&rm_ctxt.ctxt, &realmode_emulator_ops) )
+        {            
+            gdprintk(XENLOG_ERR, "Emulation failed\n");
+            rc = -EINVAL;
+            break;
+        }
+    }
+
+    for ( i = 0; i < 10; i++ )
+        hvm_set_segment_register(curr, i, &rm_ctxt.seg_reg[i]);
+
+    return rc;
+}
diff -r d5c396128897 -r 51082cf273d4 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Sat Nov 24 21:40:19 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Sat Nov 24 21:46:14 2007 +0000
@@ -2078,13 +2078,6 @@ static int vmx_set_cr0(unsigned long val
 
 #define vmx_set_cr0(v) hvm_set_cr0(v)
 
-static int vmx_realmode(struct cpu_user_regs *regs)
-{
-    gdprintk(XENLOG_ERR, "Attempt to enter real mode on VCPU %d\n",
-             current->vcpu_id);
-    return -EINVAL;
-}
-
 #endif
 
 #define CASE_SET_REG(REG, reg)      \
diff -r d5c396128897 -r 51082cf273d4 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Sat Nov 24 21:40:19 2007 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Sat Nov 24 21:46:14 2007 +0000
@@ -33,6 +33,7 @@ void vmx_do_resume(struct vcpu *);
 void vmx_do_resume(struct vcpu *);
 void set_guest_time(struct vcpu *v, u64 gtime);
 void vmx_vlapic_msr_changed(struct vcpu *v);
+int vmx_realmode(struct cpu_user_regs *regs);
 
 /*
  * Exit Reasons

_______________________________________________
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] vmx: Initial framework for real-mode emulation (disabled by default)., Xen patchbot-unstable <=