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_emulate: Allow emulated injection of

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86_emulate: Allow emulated injection of exceptions and interrupts.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 26 Nov 2007 22:40:06 -0800
Delivery-date: Mon, 26 Nov 2007 22:40:25 -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 1196013910 0
# Node ID f6a587e3d5c981b7cea8c3e97d234e14e3ca81bb
# Parent  d40788f07a4f40ac95c1f297f808c63b85baa3ff
x86_emulate: Allow emulated injection of exceptions and interrupts.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/hvm/vmx/realmode.c   |  182 +++++++++++++++++++++++++-------------
 xen/arch/x86/x86_emulate.c        |   46 ++++++++-
 xen/include/asm-x86/x86_emulate.h |   11 ++
 3 files changed, 174 insertions(+), 65 deletions(-)

diff -r d40788f07a4f -r f6a587e3d5c9 xen/arch/x86/hvm/vmx/realmode.c
--- a/xen/arch/x86/hvm/vmx/realmode.c   Sun Nov 25 12:43:13 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/realmode.c   Sun Nov 25 18:05:10 2007 +0000
@@ -13,6 +13,7 @@
 #include <xen/init.h>
 #include <xen/lib.h>
 #include <xen/sched.h>
+#include <asm/event.h>
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/support.h>
 #include <asm/hvm/vmx/vmx.h>
@@ -23,35 +24,78 @@ struct realmode_emulate_ctxt {
 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;
+    /* Cache of 16 bytes of instruction. */
+    uint8_t insn_buf[16];
     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 void realmode_deliver_exception(
+    unsigned int vector,
+    unsigned int insn_len,
+    struct realmode_emulate_ctxt *rm_ctxt)
+{
+    struct segment_register *idtr = &rm_ctxt->seg_reg[x86_seg_idtr];
+    struct segment_register *csr = &rm_ctxt->seg_reg[x86_seg_cs];
+    struct cpu_user_regs *regs = rm_ctxt->ctxt.regs;
+    uint32_t cs_eip, pstk;
+    uint16_t frame[3];
+    unsigned int last_byte;
+
+ again:
+    last_byte = (vector * 4) + 3;
+    if ( idtr->limit < last_byte )
+    {
+        /* Software interrupt? */
+        if ( insn_len != 0 )
+        {
+            insn_len = 0;
+            vector = TRAP_gp_fault;
+            goto again;
+        }
+
+        /* Exception or hardware interrupt. */
+        switch ( vector )
+        {
+        case TRAP_double_fault:
+            hvm_triple_fault();
+            return;
+        case TRAP_gp_fault:
+            vector = TRAP_double_fault;
+            goto again;
+        default:
+            vector = TRAP_gp_fault;
+            goto again;
+        }
+    }
+
+    (void)hvm_copy_from_guest_phys(&cs_eip, idtr->base + vector * 4, 4);
+
+    frame[0] = regs->eip + insn_len;
+    frame[1] = csr->sel;
+    frame[2] = regs->eflags & ~X86_EFLAGS_RF;
+
+    if ( rm_ctxt->ctxt.addr_size == 32 )
+    {
+        regs->esp -= 4;
+        pstk = regs->esp;
+    }
+    else
+    {
+        pstk = (uint16_t)(regs->esp - 4);
+        regs->esp &= ~0xffff;
+        regs->esp |= pstk;
+    }
+
+    pstk += rm_ctxt->seg_reg[x86_seg_ss].base;
+    (void)hvm_copy_to_guest_phys(pstk, frame, sizeof(frame));
+
+    csr->sel  = cs_eip >> 16;
+    csr->base = (uint32_t)csr->sel << 4;
+    regs->eip = (uint16_t)cs_eip;
+    regs->eflags &= ~(X86_EFLAGS_AC | X86_EFLAGS_TF |
+                      X86_EFLAGS_AC | X86_EFLAGS_RF);
 }
 
 static int
@@ -63,14 +107,7 @@ realmode_read(
     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;
-
+    uint32_t addr = rm_ctxt->seg_reg[seg].base + offset;
     *val = 0;
     (void)hvm_copy_from_guest_phys(val, addr, bytes);
     return X86EMUL_OKAY;
@@ -102,7 +139,7 @@ realmode_emulate_insn_fetch(
     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) )
+    if ( unlikely((insn_off + bytes) > sizeof(rm_ctxt->insn_buf)) )
         return realmode_read(
             seg, offset, val, bytes,
             hvm_access_insn_fetch, rm_ctxt);
@@ -123,14 +160,7 @@ realmode_emulate_write(
 {
     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;
-
+    uint32_t addr = rm_ctxt->seg_reg[seg].base + offset;
     (void)hvm_copy_to_guest_phys(addr, &val, bytes);
     return X86EMUL_OKAY;
 }
@@ -254,6 +284,31 @@ static int realmode_write_rflags(
         intr_shadow ^= VMX_INTR_SHADOW_STI;
         __vmwrite(GUEST_INTERRUPTIBILITY_INFO, intr_shadow);
     }
+
+    return X86EMUL_OKAY;
+}
+
+static int realmode_inject_hw_exception(
+    uint8_t vector,
+    struct x86_emulate_ctxt *ctxt)
+{
+    struct realmode_emulate_ctxt *rm_ctxt =
+        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
+
+    realmode_deliver_exception(vector, 0, rm_ctxt);
+
+    return X86EMUL_OKAY;
+}
+
+static int realmode_inject_sw_interrupt(
+    uint8_t vector,
+    uint8_t insn_len,
+    struct x86_emulate_ctxt *ctxt)
+{
+    struct realmode_emulate_ctxt *rm_ctxt =
+        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
+
+    realmode_deliver_exception(vector, insn_len, rm_ctxt);
 
     return X86EMUL_OKAY;
 }
@@ -268,37 +323,44 @@ static struct x86_emulate_ops realmode_e
     .read_io       = realmode_read_io,
     .write_io      = realmode_write_io,
     .read_cr       = realmode_read_cr,
-    .write_rflags  = realmode_write_rflags
+    .write_rflags  = realmode_write_rflags,
+    .inject_hw_exception = realmode_inject_hw_exception,
+    .inject_sw_interrupt = realmode_inject_sw_interrupt
 };
 
 int vmx_realmode(struct cpu_user_regs *regs)
 {
     struct vcpu *curr = current;
     struct realmode_emulate_ctxt rm_ctxt;
-    unsigned long addr;
+    unsigned long intr_info;
     int i, rc = 0;
+
+    rm_ctxt.ctxt.regs = regs;
 
     for ( i = 0; i < 10; i++ )
         hvm_get_segment_register(curr, i, &rm_ctxt.seg_reg[i]);
 
+    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;
+
+    intr_info = __vmread(VM_ENTRY_INTR_INFO);
+    if ( intr_info & INTR_INFO_VALID_MASK )
+    {
+        __vmwrite(VM_ENTRY_INTR_INFO, 0);
+        realmode_deliver_exception((uint8_t)intr_info, 0, &rm_ctxt);
+    }
+
     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;
-
+            !softirq_pending(smp_processor_id()) &&
+            !hvm_local_events_need_delivery(curr) )
+    {
         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;
+        (void)hvm_copy_from_guest_phys(
+            rm_ctxt.insn_buf,
+            (uint32_t)(rm_ctxt.seg_reg[x86_seg_cs].base + regs->eip),
+            sizeof(rm_ctxt.insn_buf));
 
         rc = x86_emulate(&rm_ctxt.ctxt, &realmode_emulator_ops);
 
@@ -308,7 +370,7 @@ int vmx_realmode(struct cpu_user_regs *r
             break;
         }
 
-        if ( rc )
+        if ( rc == X86EMUL_UNHANDLEABLE )
         {
             gdprintk(XENLOG_DEBUG,
                      "RM %04x:%08lx: %02x %02x %02x %02x %02x %02x\n",
diff -r d40788f07a4f -r f6a587e3d5c9 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Sun Nov 25 12:43:13 2007 +0000
+++ b/xen/arch/x86/x86_emulate.c        Sun Nov 25 18:05:10 2007 +0000
@@ -149,7 +149,7 @@ static uint8_t opcode_table[256] = {
     ImplicitOps, ImplicitOps,
     0, 0, ByteOp|DstMem|SrcImm|ModRM|Mov, DstMem|SrcImm|ModRM|Mov,
     /* 0xC8 - 0xCF */
-    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, ImplicitOps, ImplicitOps, ImplicitOps, 0,
     /* 0xD0 - 0xD7 */
     ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 
     ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 
@@ -163,7 +163,7 @@ static uint8_t opcode_table[256] = {
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     /* 0xF0 - 0xF7 */
-    0, 0, 0, 0,
+    0, ImplicitOps, 0, 0,
     0, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM,
     /* 0xF8 - 0xFF */
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
@@ -270,6 +270,7 @@ struct operand {
 #define EFLG_OF (1<<11)
 #define EFLG_DF (1<<10)
 #define EFLG_IF (1<<9)
+#define EFLG_TF (1<<8)
 #define EFLG_SF (1<<7)
 #define EFLG_ZF (1<<6)
 #define EFLG_AF (1<<4)
@@ -278,6 +279,9 @@ struct operand {
 
 /* Exception definitions. */
 #define EXC_DE  0
+#define EXC_DB  1
+#define EXC_BP  3
+#define EXC_OF  4
 #define EXC_BR  5
 #define EXC_UD  6
 #define EXC_GP 13
@@ -477,8 +481,13 @@ do {                                    
     if ( rc ) goto done;                                \
 } while (0)
 
-/* In future we will be able to generate arbitrary exceptions. */
-#define generate_exception_if(p, e) fail_if(p)
+#define generate_exception_if(p, e)                                     \
+({  if ( (p) ) {                                                        \
+        fail_if(ops->inject_hw_exception == NULL);                      \
+        rc = ops->inject_hw_exception(e, ctxt) ? : X86EMUL_EXCEPTION;   \
+        goto done;                                                      \
+    }                                                                   \
+})
 
 /* Given byte has even parity (even number of 1s)? */
 static int even_parity(uint8_t v)
@@ -1771,7 +1780,11 @@ x86_emulate(
     /* Commit shadow register state. */
     _regs.eflags &= ~EFLG_RF;
     *ctxt->regs = _regs;
-    /* FIXME generate_exception_if(_regs.eflags & EFLG_TF, EXC_DB); */
+
+    if ( (_regs.eflags & EFLG_TF) &&
+         (rc == X86EMUL_OKAY) &&
+         (ops->inject_hw_exception != NULL) )
+        rc = ops->inject_hw_exception(EXC_DB, ctxt) ? : X86EMUL_EXCEPTION;
 
  done:
     return rc;
@@ -2152,6 +2165,25 @@ x86_emulate(
         break;
     }
 
+    case 0xcc: /* int3 */
+        src.val = EXC_BP;
+        goto swint;
+
+    case 0xcd: /* int imm8 */
+        src.val = insn_fetch_type(uint8_t);
+    swint:
+        fail_if(ops->inject_sw_interrupt == NULL);
+        rc = ops->inject_sw_interrupt(src.val, _regs.eip - ctxt->regs->eip,
+                                      ctxt) ? : X86EMUL_EXCEPTION;
+        goto done;
+
+    case 0xce: /* into */
+        generate_exception_if(mode_64bit(), EXC_UD);
+        if ( !(_regs.eflags & EFLG_OF) )
+            break;
+        src.val = EXC_OF;
+        goto swint;
+
     case 0xd4: /* aam */ {
         unsigned int base = insn_fetch_type(uint8_t);
         uint8_t al = _regs.eax;
@@ -2291,6 +2323,10 @@ x86_emulate(
     case 0xeb: /* jmp (short) */
         jmp_rel(insn_fetch_type(int8_t));
         break;
+
+    case 0xf1: /* int1 (icebp) */
+        src.val = EXC_DB;
+        goto swint;
 
     case 0xf5: /* cmc */
         _regs.eflags ^= EFLG_CF;
diff -r d40788f07a4f -r f6a587e3d5c9 xen/include/asm-x86/x86_emulate.h
--- a/xen/include/asm-x86/x86_emulate.h Sun Nov 25 12:43:13 2007 +0000
+++ b/xen/include/asm-x86/x86_emulate.h Sun Nov 25 18:05:10 2007 +0000
@@ -274,6 +274,17 @@ struct x86_emulate_ops
     /* wbinvd: Write-back and invalidate cache contents. */
     int (*wbinvd)(
         struct x86_emulate_ctxt *ctxt);
+
+    /* inject_hw_exception */
+    int (*inject_hw_exception)(
+        uint8_t vector,
+        struct x86_emulate_ctxt *ctxt);
+
+    /* inject_sw_interrupt */
+    int (*inject_sw_interrupt)(
+        uint8_t vector,
+        uint8_t insn_len,
+        struct x86_emulate_ctxt *ctxt);
 };
 
 struct cpu_user_regs;

_______________________________________________
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_emulate: Allow emulated injection of exceptions and interrupts., Xen patchbot-unstable <=