KVM: x86 emulator: Add into, int, and int3 instructions (opcodes 0xcc-0xce)
This adds support for int instructions to the emulator. Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com> Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
parent
160ce1f1a8
commit
6e154e56b4
|
@ -1180,6 +1180,67 @@ static int emulate_popa(struct x86_emulate_ctxt *ctxt,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int emulate_int_real(struct x86_emulate_ctxt *ctxt,
|
||||||
|
struct x86_emulate_ops *ops, int irq)
|
||||||
|
{
|
||||||
|
struct decode_cache *c = &ctxt->decode;
|
||||||
|
int rc = X86EMUL_CONTINUE;
|
||||||
|
struct desc_ptr dt;
|
||||||
|
gva_t cs_addr;
|
||||||
|
gva_t eip_addr;
|
||||||
|
u16 cs, eip;
|
||||||
|
u32 err;
|
||||||
|
|
||||||
|
/* TODO: Add limit checks */
|
||||||
|
c->src.val = ctxt->eflags;
|
||||||
|
emulate_push(ctxt, ops);
|
||||||
|
|
||||||
|
ctxt->eflags &= ~(EFLG_IF | EFLG_TF | EFLG_AC);
|
||||||
|
|
||||||
|
c->src.val = ops->get_segment_selector(VCPU_SREG_CS, ctxt->vcpu);
|
||||||
|
emulate_push(ctxt, ops);
|
||||||
|
|
||||||
|
c->src.val = c->eip;
|
||||||
|
emulate_push(ctxt, ops);
|
||||||
|
|
||||||
|
ops->get_idt(&dt, ctxt->vcpu);
|
||||||
|
|
||||||
|
eip_addr = dt.address + (irq << 2);
|
||||||
|
cs_addr = dt.address + (irq << 2) + 2;
|
||||||
|
|
||||||
|
rc = ops->read_std(cs_addr, &cs, 2, ctxt->vcpu, &err);
|
||||||
|
if (rc != X86EMUL_CONTINUE)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = ops->read_std(eip_addr, &eip, 2, ctxt->vcpu, &err);
|
||||||
|
if (rc != X86EMUL_CONTINUE)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = load_segment_descriptor(ctxt, ops, cs, VCPU_SREG_CS);
|
||||||
|
if (rc != X86EMUL_CONTINUE)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
c->eip = eip;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int emulate_int(struct x86_emulate_ctxt *ctxt,
|
||||||
|
struct x86_emulate_ops *ops, int irq)
|
||||||
|
{
|
||||||
|
switch(ctxt->mode) {
|
||||||
|
case X86EMUL_MODE_REAL:
|
||||||
|
return emulate_int_real(ctxt, ops, irq);
|
||||||
|
case X86EMUL_MODE_VM86:
|
||||||
|
case X86EMUL_MODE_PROT16:
|
||||||
|
case X86EMUL_MODE_PROT32:
|
||||||
|
case X86EMUL_MODE_PROT64:
|
||||||
|
default:
|
||||||
|
/* Protected mode interrupts unimplemented yet */
|
||||||
|
return X86EMUL_UNHANDLEABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
|
static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
|
||||||
struct x86_emulate_ops *ops)
|
struct x86_emulate_ops *ops)
|
||||||
{
|
{
|
||||||
|
@ -2616,6 +2677,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
|
||||||
struct decode_cache *c = &ctxt->decode;
|
struct decode_cache *c = &ctxt->decode;
|
||||||
int rc = X86EMUL_CONTINUE;
|
int rc = X86EMUL_CONTINUE;
|
||||||
int saved_dst_type = c->dst.type;
|
int saved_dst_type = c->dst.type;
|
||||||
|
int irq; /* Used for int 3, int, and into */
|
||||||
|
|
||||||
ctxt->decode.mem_read.pos = 0;
|
ctxt->decode.mem_read.pos = 0;
|
||||||
|
|
||||||
|
@ -2960,6 +3022,22 @@ special_insn:
|
||||||
if (rc != X86EMUL_CONTINUE)
|
if (rc != X86EMUL_CONTINUE)
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
|
case 0xcc: /* int3 */
|
||||||
|
irq = 3;
|
||||||
|
goto do_interrupt;
|
||||||
|
case 0xcd: /* int n */
|
||||||
|
irq = c->src.val;
|
||||||
|
do_interrupt:
|
||||||
|
rc = emulate_int(ctxt, ops, irq);
|
||||||
|
if (rc != X86EMUL_CONTINUE)
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
|
case 0xce: /* into */
|
||||||
|
if (ctxt->eflags & EFLG_OF) {
|
||||||
|
irq = 4;
|
||||||
|
goto do_interrupt;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 0xcf: /* iret */
|
case 0xcf: /* iret */
|
||||||
rc = emulate_iret(ctxt, ops);
|
rc = emulate_iret(ctxt, ops);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue