aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAvi Kivity <avi.kivity@gmail.com>2013-02-09 04:31:49 -0500
committerGleb Natapov <gleb@redhat.com>2013-05-21 08:43:21 -0400
commitb8c0b6ae498fe5c3f29966bd2a2d9882911b887b (patch)
treed3bc70c893d6623f4b1b70edf9cf1419accfea50 /arch
parentb9fa409b00a1ed2a372758fd09f3f5df70f8d59a (diff)
KVM: x86 emulator: convert DIV/IDIV to fastop
Since DIV and IDIV can generate exceptions, we need an additional output parameter indicating whether an execption has occured. To avoid increasing register pressure on i386, we use %rsi, which is already allocated for the fastop code pointer. Gleb: added comment about fop usage as exception indication. Signed-off-by: Avi Kivity <avi.kivity@gmail.com> Signed-off-by: Gleb Natapov <gleb@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/emulate.c51
1 files changed, 26 insertions, 25 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 3a3542a88289..8404dc350988 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -183,6 +183,7 @@
183 * src: rdx (in/out) 183 * src: rdx (in/out)
184 * src2: rcx (in) 184 * src2: rcx (in)
185 * flags: rflags (in/out) 185 * flags: rflags (in/out)
186 * ex: rsi (in:fastop pointer, out:zero if exception)
186 * 187 *
187 * Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for 188 * Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for
188 * different operand sizes can be reached by calculation, rather than a jump 189 * different operand sizes can be reached by calculation, rather than a jump
@@ -470,7 +471,10 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
470#define FOPNOP() FOP_ALIGN FOP_RET 471#define FOPNOP() FOP_ALIGN FOP_RET
471 472
472#define FOP1E(op, dst) \ 473#define FOP1E(op, dst) \
473 FOP_ALIGN #op " %" #dst " \n\t" FOP_RET 474 FOP_ALIGN "10: " #op " %" #dst " \n\t" FOP_RET
475
476#define FOP1EEX(op, dst) \
477 FOP1E(op, dst) _ASM_EXTABLE(10b, kvm_fastop_exception)
474 478
475#define FASTOP1(op) \ 479#define FASTOP1(op) \
476 FOP_START(op) \ 480 FOP_START(op) \
@@ -489,6 +493,15 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
489 ON64(FOP1E(op, rcx)) \ 493 ON64(FOP1E(op, rcx)) \
490 FOP_END 494 FOP_END
491 495
496/* 1-operand, using src2 (for MUL/DIV r/m), with exceptions */
497#define FASTOP1SRC2EX(op, name) \
498 FOP_START(name) \
499 FOP1EEX(op, cl) \
500 FOP1EEX(op, cx) \
501 FOP1EEX(op, ecx) \
502 ON64(FOP1EEX(op, rcx)) \
503 FOP_END
504
492#define FOP2E(op, dst, src) \ 505#define FOP2E(op, dst, src) \
493 FOP_ALIGN #op " %" #src ", %" #dst " \n\t" FOP_RET 506 FOP_ALIGN #op " %" #src ", %" #dst " \n\t" FOP_RET
494 507
@@ -533,6 +546,9 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
533/* Special case for SETcc - 1 instruction per cc */ 546/* Special case for SETcc - 1 instruction per cc */
534#define FOP_SETCC(op) ".align 4; " #op " %al; ret \n\t" 547#define FOP_SETCC(op) ".align 4; " #op " %al; ret \n\t"
535 548
549asm(".global kvm_fastop_exception \n"
550 "kvm_fastop_exception: xor %esi, %esi; ret");
551
536FOP_START(setcc) 552FOP_START(setcc)
537FOP_SETCC(seto) 553FOP_SETCC(seto)
538FOP_SETCC(setno) 554FOP_SETCC(setno)
@@ -1007,6 +1023,8 @@ FASTOP2(test);
1007 1023
1008FASTOP1SRC2(mul, mul_ex); 1024FASTOP1SRC2(mul, mul_ex);
1009FASTOP1SRC2(imul, imul_ex); 1025FASTOP1SRC2(imul, imul_ex);
1026FASTOP1SRC2EX(div, div_ex);
1027FASTOP1SRC2EX(idiv, idiv_ex);
1010 1028
1011FASTOP3WCL(shld); 1029FASTOP3WCL(shld);
1012FASTOP3WCL(shrd); 1030FASTOP3WCL(shrd);
@@ -2131,26 +2149,6 @@ static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
2131 return X86EMUL_CONTINUE; 2149 return X86EMUL_CONTINUE;
2132} 2150}
2133 2151
2134static int em_div_ex(struct x86_emulate_ctxt *ctxt)
2135{
2136 u8 de = 0;
2137
2138 emulate_1op_rax_rdx(ctxt, "div", de);
2139 if (de)
2140 return emulate_de(ctxt);
2141 return X86EMUL_CONTINUE;
2142}
2143
2144static int em_idiv_ex(struct x86_emulate_ctxt *ctxt)
2145{
2146 u8 de = 0;
2147
2148 emulate_1op_rax_rdx(ctxt, "idiv", de);
2149 if (de)
2150 return emulate_de(ctxt);
2151 return X86EMUL_CONTINUE;
2152}
2153
2154static int em_grp45(struct x86_emulate_ctxt *ctxt) 2152static int em_grp45(struct x86_emulate_ctxt *ctxt)
2155{ 2153{
2156 int rc = X86EMUL_CONTINUE; 2154 int rc = X86EMUL_CONTINUE;
@@ -3734,8 +3732,8 @@ static const struct opcode group3[] = {
3734 F(DstMem | SrcNone | Lock, em_neg), 3732 F(DstMem | SrcNone | Lock, em_neg),
3735 F(DstXacc | Src2Mem, em_mul_ex), 3733 F(DstXacc | Src2Mem, em_mul_ex),
3736 F(DstXacc | Src2Mem, em_imul_ex), 3734 F(DstXacc | Src2Mem, em_imul_ex),
3737 I(DstXacc | Src2Mem, em_div_ex), 3735 F(DstXacc | Src2Mem, em_div_ex),
3738 I(DstXacc | Src2Mem, em_idiv_ex), 3736 F(DstXacc | Src2Mem, em_idiv_ex),
3739}; 3737};
3740 3738
3741static const struct opcode group4[] = { 3739static const struct opcode group4[] = {
@@ -4571,9 +4569,12 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *))
4571 if (!(ctxt->d & ByteOp)) 4569 if (!(ctxt->d & ByteOp))
4572 fop += __ffs(ctxt->dst.bytes) * FASTOP_SIZE; 4570 fop += __ffs(ctxt->dst.bytes) * FASTOP_SIZE;
4573 asm("push %[flags]; popf; call *%[fastop]; pushf; pop %[flags]\n" 4571 asm("push %[flags]; popf; call *%[fastop]; pushf; pop %[flags]\n"
4574 : "+a"(ctxt->dst.val), "+d"(ctxt->src.val), [flags]"+D"(flags) 4572 : "+a"(ctxt->dst.val), "+d"(ctxt->src.val), [flags]"+D"(flags),
4575 : "c"(ctxt->src2.val), [fastop]"S"(fop)); 4573 [fastop]"+S"(fop)
4574 : "c"(ctxt->src2.val));
4576 ctxt->eflags = (ctxt->eflags & ~EFLAGS_MASK) | (flags & EFLAGS_MASK); 4575 ctxt->eflags = (ctxt->eflags & ~EFLAGS_MASK) | (flags & EFLAGS_MASK);
4576 if (!fop) /* exception is returned in fop variable */
4577 return emulate_de(ctxt);
4577 return X86EMUL_CONTINUE; 4578 return X86EMUL_CONTINUE;
4578} 4579}
4579 4580