[PATCH 0/8] More fastop patches

2013-01-12 Thread Avi Kivity
After this, only the diffult MUL and DIV case remains.

Avi Kivity (8):
  KVM: x86 emulator: Streamline SHLD, SHRD
  KVM: x86 emulator: convert shift/rotate instructions to fastop
  KVM: x86 emulator: covert SETCC to fastop
  KVM: x86 emulator: convert INC/DEC to fastop
  KVM: x86 emulator: convert BT/BTS/BTR/BTC/BSF/BSR to fastop
  KVM: x86 emulator: convert 2-operand IMUL to fastop
  KVM: x86 emulator: rearrange fastop definitions
  KVM: x86 emulator: convert a few freestanding emulations to fastop

 arch/x86/kvm/emulate.c | 311 +
 1 file changed, 136 insertions(+), 175 deletions(-)

-- 
1.8.0.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/8] KVM: x86 emulator: Streamline SHLD, SHRD

2013-01-12 Thread Avi Kivity
Signed-off-by: Avi Kivity avi.kiv...@gmail.com
---
 arch/x86/kvm/emulate.c | 33 +
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 619a33d..2189c6a 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -454,6 +454,8 @@ static void invalidate_registers(struct x86_emulate_ctxt 
*ctxt)
 #define FOP_END \
.popsection)
 
+#define FOPNOP() FOP_ALIGN FOP_RET
+
 #define FOP1E(op,  dst) \
FOP_ALIGN #op  % #dst  \n\t FOP_RET
 
@@ -476,6 +478,18 @@ static void invalidate_registers(struct x86_emulate_ctxt 
*ctxt)
ON64(FOP2E(op##q, rax, rbx)) \
FOP_END
 
+#define FOP3E(op,  dst, src, src2) \
+   FOP_ALIGN #op  % #src2 , % #src , % #dst  \n\t FOP_RET
+
+/* 3-operand, word-only, src2=cl */
+#define FASTOP3WCL(op) \
+   FOP_START(op) \
+   FOPNOP() \
+   FOP3E(op, ax, bx, cl) \
+   FOP3E(op, eax, ebx, cl) \
+   ON64(FOP3E(op, rax, rbx, cl)) \
+   FOP_END
+
 #define __emulate_1op_rax_rdx(ctxt, _op, _suffix, _ex) \
do {\
unsigned long _tmp; \
@@ -3036,6 +3050,9 @@ FASTOP2(xor);
 FASTOP2(cmp);
 FASTOP2(test);
 
+FASTOP3WCL(shld);
+FASTOP3WCL(shrd);
+
 static int em_xchg(struct x86_emulate_ctxt *ctxt)
 {
/* Write back the register source. */
@@ -4015,14 +4032,14 @@ static const struct opcode twobyte_table[256] = {
/* 0xA0 - 0xA7 */
I(Stack | Src2FS, em_push_sreg), I(Stack | Src2FS, em_pop_sreg),
II(ImplicitOps, em_cpuid, cpuid), I(DstMem | SrcReg | ModRM | BitOp, 
em_bt),
-   D(DstMem | SrcReg | Src2ImmByte | ModRM),
-   D(DstMem | SrcReg | Src2CL | ModRM), N, N,
+   F(DstMem | SrcReg | Src2ImmByte | ModRM, em_shld),
+   F(DstMem | SrcReg | Src2CL | ModRM, em_shld), N, N,
/* 0xA8 - 0xAF */
I(Stack | Src2GS, em_push_sreg), I(Stack | Src2GS, em_pop_sreg),
DI(ImplicitOps, rsm),
I(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_bts),
-   D(DstMem | SrcReg | Src2ImmByte | ModRM),
-   D(DstMem | SrcReg | Src2CL | ModRM),
+   F(DstMem | SrcReg | Src2ImmByte | ModRM, em_shrd),
+   F(DstMem | SrcReg | Src2CL | ModRM, em_shrd),
D(ModRM), I(DstReg | SrcMem | ModRM, em_imul),
/* 0xB0 - 0xB7 */
I2bv(DstMem | SrcReg | ModRM | Lock | PageTable, em_cmpxchg),
@@ -4834,14 +4851,6 @@ twobyte_insn:
case 0x90 ... 0x9f: /* setcc r/m8 */
ctxt-dst.val = test_cc(ctxt-b, ctxt-eflags);
break;
-   case 0xa4: /* shld imm8, r, r/m */
-   case 0xa5: /* shld cl, r, r/m */
-   emulate_2op_cl(ctxt, shld);
-   break;
-   case 0xac: /* shrd imm8, r, r/m */
-   case 0xad: /* shrd cl, r, r/m */
-   emulate_2op_cl(ctxt, shrd);
-   break;
case 0xae:  /* clflush */
break;
case 0xb6 ... 0xb7: /* movzx */
-- 
1.8.0.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/8] KVM: x86 emulator: convert shift/rotate instructions to fastop

2013-01-12 Thread Avi Kivity
SHL, SHR, ROL, ROR, RCL, RCR, SAR, SAL

Signed-off-by: Avi Kivity avi.kiv...@gmail.com
---
 arch/x86/kvm/emulate.c | 72 ++
 1 file changed, 31 insertions(+), 41 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 2189c6a..d641178 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -478,6 +478,15 @@ static void invalidate_registers(struct x86_emulate_ctxt 
*ctxt)
ON64(FOP2E(op##q, rax, rbx)) \
FOP_END
 
+/* 2 operand, src is CL */
+#define FASTOP2CL(op) \
+   FOP_START(op) \
+   FOP2E(op##b, al, cl) \
+   FOP2E(op##w, ax, cl) \
+   FOP2E(op##l, eax, cl) \
+   ON64(FOP2E(op##q, rax, cl)) \
+   FOP_END
+
 #define FOP3E(op,  dst, src, src2) \
FOP_ALIGN #op  % #src2 , % #src , % #dst  \n\t FOP_RET
 
@@ -2046,38 +2055,17 @@ static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
return X86EMUL_CONTINUE;
 }
 
-static int em_grp2(struct x86_emulate_ctxt *ctxt)
-{
-   switch (ctxt-modrm_reg) {
-   case 0: /* rol */
-   emulate_2op_SrcB(ctxt, rol);
-   break;
-   case 1: /* ror */
-   emulate_2op_SrcB(ctxt, ror);
-   break;
-   case 2: /* rcl */
-   emulate_2op_SrcB(ctxt, rcl);
-   break;
-   case 3: /* rcr */
-   emulate_2op_SrcB(ctxt, rcr);
-   break;
-   case 4: /* sal/shl */
-   case 6: /* sal/shl */
-   emulate_2op_SrcB(ctxt, sal);
-   break;
-   case 5: /* shr */
-   emulate_2op_SrcB(ctxt, shr);
-   break;
-   case 7: /* sar */
-   emulate_2op_SrcB(ctxt, sar);
-   break;
-   }
-   return X86EMUL_CONTINUE;
-}
-
 FASTOP1(not);
 FASTOP1(neg);
 
+FASTOP2CL(rol);
+FASTOP2CL(ror);
+FASTOP2CL(rcl);
+FASTOP2CL(rcr);
+FASTOP2CL(shl);
+FASTOP2CL(shr);
+FASTOP2CL(sar);
+
 static int em_mul_ex(struct x86_emulate_ctxt *ctxt)
 {
u8 ex = 0;
@@ -3726,6 +3714,17 @@ static const struct opcode group1A[] = {
I(DstMem | SrcNone | Mov | Stack, em_pop), N, N, N, N, N, N, N,
 };
 
+static const struct opcode group2[] = {
+   F(DstMem | ModRM, em_rol),
+   F(DstMem | ModRM, em_ror),
+   F(DstMem | ModRM, em_rcl),
+   F(DstMem | ModRM, em_rcr),
+   F(DstMem | ModRM, em_shl),
+   F(DstMem | ModRM, em_shr),
+   F(DstMem | ModRM, em_shl),
+   F(DstMem | ModRM, em_sar),
+};
+
 static const struct opcode group3[] = {
F(DstMem | SrcImm | NoWrite, em_test),
F(DstMem | SrcImm | NoWrite, em_test),
@@ -3949,7 +3948,7 @@ static const struct opcode opcode_table[256] = {
/* 0xB8 - 0xBF */
X8(I(DstReg | SrcImm64 | Mov, em_mov)),
/* 0xC0 - 0xC7 */
-   D2bv(DstMem | SrcImmByte | ModRM),
+   G(ByteOp | Src2ImmByte, group2), G(Src2ImmByte, group2),
I(ImplicitOps | Stack | SrcImmU16, em_ret_near_imm),
I(ImplicitOps | Stack, em_ret),
I(DstReg | SrcMemFAddr | ModRM | No64 | Src2ES, em_lseg),
@@ -3961,7 +3960,8 @@ static const struct opcode opcode_table[256] = {
D(ImplicitOps), DI(SrcImmByte, intn),
D(ImplicitOps | No64), II(ImplicitOps, em_iret, iret),
/* 0xD0 - 0xD7 */
-   D2bv(DstMem | SrcOne | ModRM), D2bv(DstMem | ModRM),
+   G(Src2One | ByteOp, group2), G(Src2One, group2),
+   G(Src2CL | ByteOp, group2), G(Src2CL, group2),
N, I(DstAcc | SrcImmByte | No64, em_aad), N, N,
/* 0xD8 - 0xDF */
N, E(0, escape_d9), N, E(0, escape_db), N, E(0, escape_dd), N, N,
@@ -4713,9 +4713,6 @@ special_insn:
case 8: ctxt-dst.val = (s32)ctxt-dst.val; break;
}
break;
-   case 0xc0 ... 0xc1:
-   rc = em_grp2(ctxt);
-   break;
case 0xcc:  /* int3 */
rc = emulate_int(ctxt, 3);
break;
@@ -4726,13 +4723,6 @@ special_insn:
if (ctxt-eflags  EFLG_OF)
rc = emulate_int(ctxt, 4);
break;
-   case 0xd0 ... 0xd1: /* Grp2 */
-   rc = em_grp2(ctxt);
-   break;
-   case 0xd2 ... 0xd3: /* Grp2 */
-   ctxt-src.val = reg_read(ctxt, VCPU_REGS_RCX);
-   rc = em_grp2(ctxt);
-   break;
case 0xe9: /* jmp rel */
case 0xeb: /* jmp rel short */
jmp_rel(ctxt, ctxt-src.val);
-- 
1.8.0.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/8] KVM: x86 emulator: convert INC/DEC to fastop

2013-01-12 Thread Avi Kivity
Signed-off-by: Avi Kivity avi.kiv...@gmail.com
---
 arch/x86/kvm/emulate.c | 24 +++-
 1 file changed, 7 insertions(+), 17 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index f6f615e..d89e88f 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2055,6 +2055,8 @@ static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
 
 FASTOP1(not);
 FASTOP1(neg);
+FASTOP1(inc);
+FASTOP1(dec);
 
 FASTOP2CL(rol);
 FASTOP2CL(ror);
@@ -2105,12 +2107,6 @@ static int em_grp45(struct x86_emulate_ctxt *ctxt)
int rc = X86EMUL_CONTINUE;
 
switch (ctxt-modrm_reg) {
-   case 0: /* inc */
-   emulate_1op(ctxt, inc);
-   break;
-   case 1: /* dec */
-   emulate_1op(ctxt, dec);
-   break;
case 2: /* call near abs */ {
long int old_eip;
old_eip = ctxt-_eip;
@@ -3735,14 +3731,14 @@ static const struct opcode group3[] = {
 };
 
 static const struct opcode group4[] = {
-   I(ByteOp | DstMem | SrcNone | Lock, em_grp45),
-   I(ByteOp | DstMem | SrcNone | Lock, em_grp45),
+   F(ByteOp | DstMem | SrcNone | Lock, em_inc),
+   F(ByteOp | DstMem | SrcNone | Lock, em_dec),
N, N, N, N, N, N,
 };
 
 static const struct opcode group5[] = {
-   I(DstMem | SrcNone | Lock,  em_grp45),
-   I(DstMem | SrcNone | Lock,  em_grp45),
+   F(DstMem | SrcNone | Lock,  em_inc),
+   F(DstMem | SrcNone | Lock,  em_dec),
I(SrcMem | Stack,   em_grp45),
I(SrcMemFAddr | ImplicitOps | Stack,em_call_far),
I(SrcMem | Stack,   em_grp45),
@@ -3891,7 +3887,7 @@ static const struct opcode opcode_table[256] = {
/* 0x38 - 0x3F */
F6ALU(NoWrite, em_cmp), N, N,
/* 0x40 - 0x4F */
-   X16(D(DstReg)),
+   X8(F(DstReg, em_inc)), X8(F(DstReg, em_dec)),
/* 0x50 - 0x57 */
X8(I(SrcReg | Stack, em_push)),
/* 0x58 - 0x5F */
@@ -4681,12 +4677,6 @@ special_insn:
goto twobyte_insn;
 
switch (ctxt-b) {
-   case 0x40 ... 0x47: /* inc r16/r32 */
-   emulate_1op(ctxt, inc);
-   break;
-   case 0x48 ... 0x4f: /* dec r16/r32 */
-   emulate_1op(ctxt, dec);
-   break;
case 0x63:  /* movsxd */
if (ctxt-mode != X86EMUL_MODE_PROT64)
goto cannot_emulate;
-- 
1.8.0.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 8/8] KVM: x86 emulator: convert a few freestanding emulations to fastop

2013-01-12 Thread Avi Kivity
---
 arch/x86/kvm/emulate.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index da2b903..1bb0af2 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2209,7 +2209,7 @@ static int em_cmpxchg(struct x86_emulate_ctxt *ctxt)
/* Save real source value, then compare EAX against destination. */
ctxt-src.orig_val = ctxt-src.val;
ctxt-src.val = reg_read(ctxt, VCPU_REGS_RAX);
-   emulate_2op_SrcV(ctxt, cmp);
+   fastop(ctxt, em_cmp);
 
if (ctxt-eflags  EFLG_ZF) {
/* Success: write back to memory. */
@@ -2977,7 +2977,7 @@ static int em_das(struct x86_emulate_ctxt *ctxt)
ctxt-src.type = OP_IMM;
ctxt-src.val = 0;
ctxt-src.bytes = 1;
-   emulate_2op_SrcV(ctxt, or);
+   fastop(ctxt, em_or);
ctxt-eflags = ~(X86_EFLAGS_AF | X86_EFLAGS_CF);
if (cf)
ctxt-eflags |= X86_EFLAGS_CF;
@@ -4816,7 +4816,7 @@ twobyte_insn:
(s16) ctxt-src.val;
break;
case 0xc0 ... 0xc1: /* xadd */
-   emulate_2op_SrcV(ctxt, add);
+   fastop(ctxt, em_add);
/* Write back the register source. */
ctxt-src.val = ctxt-dst.orig_val;
write_register_operand(ctxt-src);
-- 
1.8.0.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/8] KVM: x86 emulator: covert SETCC to fastop

2013-01-12 Thread Avi Kivity
This is a bit of a special case since we don't have the usual
byte/word/long/quad switch; instead we switch on the condition code embedded
in the instruction.

Signed-off-by: Avi Kivity avi.kiv...@gmail.com
---
 arch/x86/kvm/emulate.c | 60 --
 1 file changed, 29 insertions(+), 31 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index d641178..f6f615e 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -499,6 +499,28 @@ static void invalidate_registers(struct x86_emulate_ctxt 
*ctxt)
ON64(FOP3E(op, rax, rbx, cl)) \
FOP_END
 
+/* Special case for SETcc - 1 instruction per cc */
+#define FOP_SETCC(op) .align 4;  #op  %al; ret \n\t
+
+FOP_START(setcc)
+FOP_SETCC(seto)
+FOP_SETCC(setc)
+FOP_SETCC(setz)
+FOP_SETCC(setbe)
+FOP_SETCC(sets)
+FOP_SETCC(setp)
+FOP_SETCC(setl)
+FOP_SETCC(setle)
+FOP_SETCC(setno)
+FOP_SETCC(setnc)
+FOP_SETCC(setnz)
+FOP_SETCC(setnbe)
+FOP_SETCC(setns)
+FOP_SETCC(setnp)
+FOP_SETCC(setnl)
+FOP_SETCC(setnle)
+FOP_END;
+
 #define __emulate_1op_rax_rdx(ctxt, _op, _suffix, _ex) \
do {\
unsigned long _tmp; \
@@ -939,39 +961,15 @@ static int read_descriptor(struct x86_emulate_ctxt *ctxt,
return rc;
 }
 
-static int test_cc(unsigned int condition, unsigned int flags)
+static u8 test_cc(unsigned int condition, unsigned long flags)
 {
-   int rc = 0;
+   u8 rc;
+   void (*fop)(void) = (void *)em_setcc + 4 * (condition  0xf);
 
-   switch ((condition  15)  1) {
-   case 0: /* o */
-   rc |= (flags  EFLG_OF);
-   break;
-   case 1: /* b/c/nae */
-   rc |= (flags  EFLG_CF);
-   break;
-   case 2: /* z/e */
-   rc |= (flags  EFLG_ZF);
-   break;
-   case 3: /* be/na */
-   rc |= (flags  (EFLG_CF|EFLG_ZF));
-   break;
-   case 4: /* s */
-   rc |= (flags  EFLG_SF);
-   break;
-   case 5: /* p/pe */
-   rc |= (flags  EFLG_PF);
-   break;
-   case 7: /* le/ng */
-   rc |= (flags  EFLG_ZF);
-   /* fall through */
-   case 6: /* l/nge */
-   rc |= (!(flags  EFLG_SF) != !(flags  EFLG_OF));
-   break;
-   }
-
-   /* Odd condition identifiers (lsb == 1) have inverted sense. */
-   return (!!rc ^ (condition  1));
+   flags = (flags  EFLAGS_MASK) | X86_EFLAGS_IF;
+   asm(pushq %[flags]; popf; call *%[fastop]
+   : =a(rc) : [fastop]r(fop), [flags]r(flags));
+   return rc;
 }
 
 static void fetch_register_operand(struct operand *op)
-- 
1.8.0.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 7/8] KVM: x86 emulator: rearrange fastop definitions

2013-01-12 Thread Avi Kivity
Make fastop opcodes usable in other emulations.

Signed-off-by: Avi Kivity avi.kiv...@gmail.com
---
 arch/x86/kvm/emulate.c | 70 +-
 1 file changed, 35 insertions(+), 35 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index c7578d0..da2b903 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -972,6 +972,41 @@ static int read_descriptor(struct x86_emulate_ctxt *ctxt,
return rc;
 }
 
+FASTOP2(add);
+FASTOP2(or);
+FASTOP2(adc);
+FASTOP2(sbb);
+FASTOP2(and);
+FASTOP2(sub);
+FASTOP2(xor);
+FASTOP2(cmp);
+FASTOP2(test);
+
+FASTOP3WCL(shld);
+FASTOP3WCL(shrd);
+
+FASTOP2W(imul);
+
+FASTOP1(not);
+FASTOP1(neg);
+FASTOP1(inc);
+FASTOP1(dec);
+
+FASTOP2CL(rol);
+FASTOP2CL(ror);
+FASTOP2CL(rcl);
+FASTOP2CL(rcr);
+FASTOP2CL(shl);
+FASTOP2CL(shr);
+FASTOP2CL(sar);
+
+FASTOP2W(bsf);
+FASTOP2W(bsr);
+FASTOP2W(bt);
+FASTOP2W(bts);
+FASTOP2W(btr);
+FASTOP2W(btc);
+
 static u8 test_cc(unsigned int condition, unsigned long flags)
 {
u8 rc;
@@ -2064,26 +2099,6 @@ static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
return X86EMUL_CONTINUE;
 }
 
-FASTOP1(not);
-FASTOP1(neg);
-FASTOP1(inc);
-FASTOP1(dec);
-
-FASTOP2CL(rol);
-FASTOP2CL(ror);
-FASTOP2CL(rcl);
-FASTOP2CL(rcr);
-FASTOP2CL(shl);
-FASTOP2CL(shr);
-FASTOP2CL(sar);
-
-FASTOP2W(bsf);
-FASTOP2W(bsr);
-FASTOP2W(bt);
-FASTOP2W(bts);
-FASTOP2W(btr);
-FASTOP2W(btc);
-
 static int em_mul_ex(struct x86_emulate_ctxt *ctxt)
 {
u8 ex = 0;
@@ -3040,21 +3055,6 @@ static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
return X86EMUL_CONTINUE;
 }
 
-FASTOP2(add);
-FASTOP2(or);
-FASTOP2(adc);
-FASTOP2(sbb);
-FASTOP2(and);
-FASTOP2(sub);
-FASTOP2(xor);
-FASTOP2(cmp);
-FASTOP2(test);
-
-FASTOP3WCL(shld);
-FASTOP3WCL(shrd);
-
-FASTOP2W(imul);
-
 static int em_xchg(struct x86_emulate_ctxt *ctxt)
 {
/* Write back the register source. */
-- 
1.8.0.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/8] KVM: x86 emulator: convert 2-operand IMUL to fastop

2013-01-12 Thread Avi Kivity
Signed-off-by: Avi Kivity avi.kiv...@gmail.com
---
 arch/x86/kvm/emulate.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 7ff83d9..c7578d0 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -441,6 +441,8 @@ static void invalidate_registers(struct x86_emulate_ctxt 
*ctxt)
}   \
} while (0)
 
+static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
+
 #define FOP_ALIGN .align  __stringify(FASTOP_SIZE)  \n\t
 #define FOP_RET   ret \n\t
 
@@ -3051,6 +3053,8 @@ FASTOP2(test);
 FASTOP3WCL(shld);
 FASTOP3WCL(shrd);
 
+FASTOP2W(imul);
+
 static int em_xchg(struct x86_emulate_ctxt *ctxt)
 {
/* Write back the register source. */
@@ -3063,16 +3067,10 @@ static int em_xchg(struct x86_emulate_ctxt *ctxt)
return X86EMUL_CONTINUE;
 }
 
-static int em_imul(struct x86_emulate_ctxt *ctxt)
-{
-   emulate_2op_SrcV_nobyte(ctxt, imul);
-   return X86EMUL_CONTINUE;
-}
-
 static int em_imul_3op(struct x86_emulate_ctxt *ctxt)
 {
ctxt-dst.val = ctxt-src2.val;
-   return em_imul(ctxt);
+   return fastop(ctxt, em_imul);
 }
 
 static int em_cwd(struct x86_emulate_ctxt *ctxt)
@@ -4010,7 +4008,7 @@ static const struct opcode twobyte_table[256] = {
F(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_bts),
F(DstMem | SrcReg | Src2ImmByte | ModRM, em_shrd),
F(DstMem | SrcReg | Src2CL | ModRM, em_shrd),
-   D(ModRM), I(DstReg | SrcMem | ModRM, em_imul),
+   D(ModRM), F(DstReg | SrcMem | ModRM, em_imul),
/* 0xB0 - 0xB7 */
I2bv(DstMem | SrcReg | ModRM | Lock | PageTable, em_cmpxchg),
I(DstReg | SrcMemFAddr | ModRM | Src2SS, em_lseg),
-- 
1.8.0.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/8] KVM: x86 emulator: convert BT/BTS/BTR/BTC/BSF/BSR to fastop

2013-01-12 Thread Avi Kivity
Signed-off-by: Avi Kivity avi.kiv...@gmail.com
---
 arch/x86/kvm/emulate.c | 76 +-
 1 file changed, 26 insertions(+), 50 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index d89e88f..7ff83d9 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -478,6 +478,15 @@ static void invalidate_registers(struct x86_emulate_ctxt 
*ctxt)
ON64(FOP2E(op##q, rax, rbx)) \
FOP_END
 
+/* 2 operand, word only */
+#define FASTOP2W(op) \
+   FOP_START(op) \
+   FOPNOP() \
+   FOP2E(op##w, ax, bx) \
+   FOP2E(op##l, eax, ebx) \
+   ON64(FOP2E(op##q, rax, rbx)) \
+   FOP_END
+
 /* 2 operand, src is CL */
 #define FASTOP2CL(op) \
FOP_START(op) \
@@ -2066,6 +2075,13 @@ FASTOP2CL(shl);
 FASTOP2CL(shr);
 FASTOP2CL(sar);
 
+FASTOP2W(bsf);
+FASTOP2W(bsr);
+FASTOP2W(bt);
+FASTOP2W(bts);
+FASTOP2W(btr);
+FASTOP2W(btc);
+
 static int em_mul_ex(struct x86_emulate_ctxt *ctxt)
 {
u8 ex = 0;
@@ -3377,47 +3393,6 @@ static int em_sti(struct x86_emulate_ctxt *ctxt)
return X86EMUL_CONTINUE;
 }
 
-static int em_bt(struct x86_emulate_ctxt *ctxt)
-{
-   /* Disable writeback. */
-   ctxt-dst.type = OP_NONE;
-   /* only subword offset */
-   ctxt-src.val = (ctxt-dst.bytes  3) - 1;
-
-   emulate_2op_SrcV_nobyte(ctxt, bt);
-   return X86EMUL_CONTINUE;
-}
-
-static int em_bts(struct x86_emulate_ctxt *ctxt)
-{
-   emulate_2op_SrcV_nobyte(ctxt, bts);
-   return X86EMUL_CONTINUE;
-}
-
-static int em_btr(struct x86_emulate_ctxt *ctxt)
-{
-   emulate_2op_SrcV_nobyte(ctxt, btr);
-   return X86EMUL_CONTINUE;
-}
-
-static int em_btc(struct x86_emulate_ctxt *ctxt)
-{
-   emulate_2op_SrcV_nobyte(ctxt, btc);
-   return X86EMUL_CONTINUE;
-}
-
-static int em_bsf(struct x86_emulate_ctxt *ctxt)
-{
-   emulate_2op_SrcV_nobyte(ctxt, bsf);
-   return X86EMUL_CONTINUE;
-}
-
-static int em_bsr(struct x86_emulate_ctxt *ctxt)
-{
-   emulate_2op_SrcV_nobyte(ctxt, bsr);
-   return X86EMUL_CONTINUE;
-}
-
 static int em_cpuid(struct x86_emulate_ctxt *ctxt)
 {
u32 eax, ebx, ecx, edx;
@@ -3773,10 +3748,10 @@ static const struct group_dual group7 = { {
 
 static const struct opcode group8[] = {
N, N, N, N,
-   I(DstMem | SrcImmByte,  em_bt),
-   I(DstMem | SrcImmByte | Lock | PageTable,   em_bts),
-   I(DstMem | SrcImmByte | Lock,   em_btr),
-   I(DstMem | SrcImmByte | Lock | PageTable,   em_btc),
+   F(DstMem | SrcImmByte | NoWrite,em_bt),
+   F(DstMem | SrcImmByte | Lock | PageTable,   em_bts),
+   F(DstMem | SrcImmByte | Lock,   em_btr),
+   F(DstMem | SrcImmByte | Lock | PageTable,   em_btc),
 };
 
 static const struct group_dual group9 = { {
@@ -4025,28 +4000,29 @@ static const struct opcode twobyte_table[256] = {
X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)),
/* 0xA0 - 0xA7 */
I(Stack | Src2FS, em_push_sreg), I(Stack | Src2FS, em_pop_sreg),
-   II(ImplicitOps, em_cpuid, cpuid), I(DstMem | SrcReg | ModRM | BitOp, 
em_bt),
+   II(ImplicitOps, em_cpuid, cpuid),
+   F(DstMem | SrcReg | ModRM | BitOp | NoWrite, em_bt),
F(DstMem | SrcReg | Src2ImmByte | ModRM, em_shld),
F(DstMem | SrcReg | Src2CL | ModRM, em_shld), N, N,
/* 0xA8 - 0xAF */
I(Stack | Src2GS, em_push_sreg), I(Stack | Src2GS, em_pop_sreg),
DI(ImplicitOps, rsm),
-   I(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_bts),
+   F(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_bts),
F(DstMem | SrcReg | Src2ImmByte | ModRM, em_shrd),
F(DstMem | SrcReg | Src2CL | ModRM, em_shrd),
D(ModRM), I(DstReg | SrcMem | ModRM, em_imul),
/* 0xB0 - 0xB7 */
I2bv(DstMem | SrcReg | ModRM | Lock | PageTable, em_cmpxchg),
I(DstReg | SrcMemFAddr | ModRM | Src2SS, em_lseg),
-   I(DstMem | SrcReg | ModRM | BitOp | Lock, em_btr),
+   F(DstMem | SrcReg | ModRM | BitOp | Lock, em_btr),
I(DstReg | SrcMemFAddr | ModRM | Src2FS, em_lseg),
I(DstReg | SrcMemFAddr | ModRM | Src2GS, em_lseg),
D(DstReg | SrcMem8 | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
/* 0xB8 - 0xBF */
N, N,
G(BitOp, group8),
-   I(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_btc),
-   I(DstReg | SrcMem | ModRM, em_bsf), I(DstReg | SrcMem | ModRM, em_bsr),
+   F(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_btc),
+   F(DstReg | SrcMem | ModRM, em_bsf), F(DstReg | SrcMem | ModRM, em_bsr),
D(DstReg | SrcMem8 | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
/* 0xC0 - 0xC7 */
D2bv(DstMem | SrcReg | ModRM | Lock),
-- 
1.8.0.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  

Re: [PATCH] tcm_vhost: Use llist for cmd completion list

2013-01-12 Thread Paolo Bonzini
Il 06/01/2013 07:36, Asias He ha scritto:
 This drops the cmd completion list spin lock and makes the cmd
 completion queue lock-less.
 
 Signed-off-by: Asias He as...@redhat.com
 ---
  drivers/vhost/tcm_vhost.c | 46 +-
  drivers/vhost/tcm_vhost.h |  2 +-
  2 files changed, 14 insertions(+), 34 deletions(-)
 
 diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
 index b20df5c..3720604 100644
 --- a/drivers/vhost/tcm_vhost.c
 +++ b/drivers/vhost/tcm_vhost.c
 @@ -47,6 +47,7 @@
  #include linux/vhost.h
  #include linux/virtio_net.h /* TODO vhost.h currently depends on this */
  #include linux/virtio_scsi.h
 +#include linux/llist.h
  
  #include vhost.c
  #include vhost.h
 @@ -64,8 +65,7 @@ struct vhost_scsi {
   struct vhost_virtqueue vqs[3];
  
   struct vhost_work vs_completion_work; /* cmd completion work item */
 - struct list_head vs_completion_list;  /* cmd completion queue */
 - spinlock_t vs_completion_lock;/* protects s_completion_list */
 + struct llist_head vs_completion_list; /* cmd completion queue */
  };
  
  /* Local pointer to allocated TCM configfs fabric module */
 @@ -301,9 +301,7 @@ static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd 
 *tv_cmd)
  {
   struct vhost_scsi *vs = tv_cmd-tvc_vhost;
  
 - spin_lock_bh(vs-vs_completion_lock);
 - list_add_tail(tv_cmd-tvc_completion_list, vs-vs_completion_list);
 - spin_unlock_bh(vs-vs_completion_lock);
 + llist_add(tv_cmd-tvc_completion_list, vs-vs_completion_list);
  
   vhost_work_queue(vs-dev, vs-vs_completion_work);
  }
 @@ -347,27 +345,6 @@ static void vhost_scsi_free_cmd(struct tcm_vhost_cmd 
 *tv_cmd)
   kfree(tv_cmd);
  }
  
 -/* Dequeue a command from the completion list */
 -static struct tcm_vhost_cmd *vhost_scsi_get_cmd_from_completion(
 - struct vhost_scsi *vs)
 -{
 - struct tcm_vhost_cmd *tv_cmd = NULL;
 -
 - spin_lock_bh(vs-vs_completion_lock);
 - if (list_empty(vs-vs_completion_list)) {
 - spin_unlock_bh(vs-vs_completion_lock);
 - return NULL;
 - }
 -
 - list_for_each_entry(tv_cmd, vs-vs_completion_list,
 - tvc_completion_list) {
 - list_del(tv_cmd-tvc_completion_list);
 - break;
 - }
 - spin_unlock_bh(vs-vs_completion_lock);
 - return tv_cmd;
 -}
 -
  /* Fill in status and signal that we are done processing this command
   *
   * This is scheduled in the vhost work queue so we are called with the owner
 @@ -377,12 +354,18 @@ static void vhost_scsi_complete_cmd_work(struct 
 vhost_work *work)
  {
   struct vhost_scsi *vs = container_of(work, struct vhost_scsi,
   vs_completion_work);
 + struct virtio_scsi_cmd_resp v_rsp;
   struct tcm_vhost_cmd *tv_cmd;
 + struct llist_node *llnode;
 + struct se_cmd *se_cmd;
 + int ret;
  
 - while ((tv_cmd = vhost_scsi_get_cmd_from_completion(vs))) {
 - struct virtio_scsi_cmd_resp v_rsp;
 - struct se_cmd *se_cmd = tv_cmd-tvc_se_cmd;
 - int ret;
 + llnode = llist_del_all(vs-vs_completion_list);
 + while (llnode) {
 + tv_cmd = llist_entry(llnode, struct tcm_vhost_cmd,
 +  tvc_completion_list);
 + llnode = llist_next(llnode);
 + se_cmd = tv_cmd-tvc_se_cmd;
  
   pr_debug(%s tv_cmd %p resid %u status %#02x\n, __func__,
   tv_cmd, se_cmd-residual_count, se_cmd-scsi_status);
 @@ -426,7 +409,6 @@ static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd(
   pr_err(Unable to allocate struct tcm_vhost_cmd\n);
   return ERR_PTR(-ENOMEM);
   }
 - INIT_LIST_HEAD(tv_cmd-tvc_completion_list);
   tv_cmd-tvc_tag = v_req-tag;
   tv_cmd-tvc_task_attr = v_req-task_attr;
   tv_cmd-tvc_exp_data_len = exp_data_len;
 @@ -859,8 +841,6 @@ static int vhost_scsi_open(struct inode *inode, struct 
 file *f)
   return -ENOMEM;
  
   vhost_work_init(s-vs_completion_work, vhost_scsi_complete_cmd_work);
 - INIT_LIST_HEAD(s-vs_completion_list);
 - spin_lock_init(s-vs_completion_lock);
  
   s-vqs[VHOST_SCSI_VQ_CTL].handle_kick = vhost_scsi_ctl_handle_kick;
   s-vqs[VHOST_SCSI_VQ_EVT].handle_kick = vhost_scsi_evt_handle_kick;
 diff --git a/drivers/vhost/tcm_vhost.h b/drivers/vhost/tcm_vhost.h
 index 7e87c63..47ee80b 100644
 --- a/drivers/vhost/tcm_vhost.h
 +++ b/drivers/vhost/tcm_vhost.h
 @@ -34,7 +34,7 @@ struct tcm_vhost_cmd {
   /* Sense buffer that will be mapped into outgoing status */
   unsigned char tvc_sense_buf[TRANSPORT_SENSE_BUFFER];
   /* Completed commands list, serviced from vhost worker thread */
 - struct list_head tvc_completion_list;
 + struct llist_node tvc_completion_list;
  };
  
  struct tcm_vhost_nexus {
 

Reviewed-by: Paolo Bonzini pbonz...@redhat.com
--
To unsubscribe from this list: