aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/x86_emulate.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2007-11-25 18:05:10 +0000
committerKeir Fraser <keir.fraser@citrix.com>2007-11-25 18:05:10 +0000
commitb8e219e001243b570045935b0476ee026e9c43b9 (patch)
treeb14abfae1418deaf3b400b921c4bbfd6b2379358 /xen/arch/x86/x86_emulate.c
parentd0b01f6dd89534b49fa92645fe560908e7e1bfbb (diff)
downloadxen-b8e219e001243b570045935b0476ee026e9c43b9.tar.gz
xen-b8e219e001243b570045935b0476ee026e9c43b9.tar.bz2
xen-b8e219e001243b570045935b0476ee026e9c43b9.zip
x86_emulate: Allow emulated injection of exceptions and interrupts.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'xen/arch/x86/x86_emulate.c')
-rw-r--r--xen/arch/x86/x86_emulate.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
index 54ea38f581..60b00eebe1 100644
--- a/xen/arch/x86/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate.c
@@ -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;
@@ -2292,6 +2324,10 @@ x86_emulate(
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;
break;