aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2010-08-26 04:59:01 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:51:42 -0400
commit34d1f4905eb66478a890ea808ec58bc842e6e589 (patch)
tree14062e3dbc2430bc74d29d02fce2c305310b1b34 /arch/x86/kvm/emulate.c
parentf6b3597bded9ed261b42fdcb5e741489cb5ccbfe (diff)
KVM: x86 emulator: trap and propagate #DE from DIV and IDIV
Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index e96cce170228..917b9b50fab0 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -504,6 +504,12 @@ static void emulate_ts(struct x86_emulate_ctxt *ctxt, int err)
504 emulate_exception(ctxt, TS_VECTOR, err, true); 504 emulate_exception(ctxt, TS_VECTOR, err, true);
505} 505}
506 506
507static int emulate_de(struct x86_emulate_ctxt *ctxt)
508{
509 emulate_exception(ctxt, DE_VECTOR, 0, false);
510 return X86EMUL_PROPAGATE_FAULT;
511}
512
507static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt, 513static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
508 struct x86_emulate_ops *ops, 514 struct x86_emulate_ops *ops,
509 unsigned long eip, u8 *dest) 515 unsigned long eip, u8 *dest)
@@ -1458,6 +1464,7 @@ static inline int emulate_grp3(struct x86_emulate_ctxt *ctxt,
1458 struct decode_cache *c = &ctxt->decode; 1464 struct decode_cache *c = &ctxt->decode;
1459 unsigned long *rax = &c->regs[VCPU_REGS_RAX]; 1465 unsigned long *rax = &c->regs[VCPU_REGS_RAX];
1460 unsigned long *rdx = &c->regs[VCPU_REGS_RDX]; 1466 unsigned long *rdx = &c->regs[VCPU_REGS_RDX];
1467 u8 de = 0;
1461 1468
1462 switch (c->modrm_reg) { 1469 switch (c->modrm_reg) {
1463 case 0 ... 1: /* test */ 1470 case 0 ... 1: /* test */
@@ -1476,14 +1483,18 @@ static inline int emulate_grp3(struct x86_emulate_ctxt *ctxt,
1476 emulate_1op_rax_rdx("imul", c->src, *rax, *rdx, ctxt->eflags); 1483 emulate_1op_rax_rdx("imul", c->src, *rax, *rdx, ctxt->eflags);
1477 break; 1484 break;
1478 case 6: /* div */ 1485 case 6: /* div */
1479 emulate_1op_rax_rdx("div", c->src, *rax, *rdx, ctxt->eflags); 1486 emulate_1op_rax_rdx_ex("div", c->src, *rax, *rdx,
1487 ctxt->eflags, de);
1480 break; 1488 break;
1481 case 7: /* idiv */ 1489 case 7: /* idiv */
1482 emulate_1op_rax_rdx("idiv", c->src, *rax, *rdx, ctxt->eflags); 1490 emulate_1op_rax_rdx_ex("idiv", c->src, *rax, *rdx,
1491 ctxt->eflags, de);
1483 break; 1492 break;
1484 default: 1493 default:
1485 return X86EMUL_UNHANDLEABLE; 1494 return X86EMUL_UNHANDLEABLE;
1486 } 1495 }
1496 if (de)
1497 return emulate_de(ctxt);
1487 return X86EMUL_CONTINUE; 1498 return X86EMUL_CONTINUE;
1488} 1499}
1489 1500
@@ -3413,8 +3424,9 @@ special_insn:
3413 ctxt->eflags ^= EFLG_CF; 3424 ctxt->eflags ^= EFLG_CF;
3414 break; 3425 break;
3415 case 0xf6 ... 0xf7: /* Grp3 */ 3426 case 0xf6 ... 0xf7: /* Grp3 */
3416 if (emulate_grp3(ctxt, ops) != X86EMUL_CONTINUE) 3427 rc = emulate_grp3(ctxt, ops);
3417 goto cannot_emulate; 3428 if (rc != X86EMUL_CONTINUE)
3429 goto done;
3418 break; 3430 break;
3419 case 0xf8: /* clc */ 3431 case 0xf8: /* clc */
3420 ctxt->eflags &= ~EFLG_CF; 3432 ctxt->eflags &= ~EFLG_CF;