aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/kvm_emulate.h6
-rw-r--r--arch/x86/kvm/emulate.c56
2 files changed, 37 insertions, 25 deletions
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 288cbedcab1c..69a64a6a36f4 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -143,7 +143,11 @@ struct x86_emulate_ops {
143struct operand { 143struct operand {
144 enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type; 144 enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type;
145 unsigned int bytes; 145 unsigned int bytes;
146 unsigned long val, orig_val, *ptr; 146 unsigned long orig_val, *ptr;
147 union {
148 unsigned long val;
149 char valptr[sizeof(unsigned long) + 2];
150 };
147}; 151};
148 152
149struct fetch_cache { 153struct fetch_cache {
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 03a72912d7b9..687ea0906b79 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -67,6 +67,8 @@
67#define SrcImmUByte (8<<4) /* 8-bit unsigned immediate operand. */ 67#define SrcImmUByte (8<<4) /* 8-bit unsigned immediate operand. */
68#define SrcImmU (9<<4) /* Immediate operand, unsigned */ 68#define SrcImmU (9<<4) /* Immediate operand, unsigned */
69#define SrcSI (0xa<<4) /* Source is in the DS:RSI */ 69#define SrcSI (0xa<<4) /* Source is in the DS:RSI */
70#define SrcImmFAddr (0xb<<4) /* Source is immediate far address */
71#define SrcMemFAddr (0xc<<4) /* Source is far address in memory */
70#define SrcMask (0xf<<4) 72#define SrcMask (0xf<<4)
71/* Generic ModRM decode. */ 73/* Generic ModRM decode. */
72#define ModRM (1<<8) 74#define ModRM (1<<8)
@@ -88,10 +90,6 @@
88#define Src2CL (1<<29) 90#define Src2CL (1<<29)
89#define Src2ImmByte (2<<29) 91#define Src2ImmByte (2<<29)
90#define Src2One (3<<29) 92#define Src2One (3<<29)
91#define Src2Imm16 (4<<29)
92#define Src2Mem16 (5<<29) /* Used for Ep encoding. First argument has to be
93 in memory and second argument is located
94 immediately after the first one in memory. */
95#define Src2Mask (7<<29) 93#define Src2Mask (7<<29)
96 94
97enum { 95enum {
@@ -175,7 +173,7 @@ static u32 opcode_table[256] = {
175 /* 0x90 - 0x97 */ 173 /* 0x90 - 0x97 */
176 DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, 174 DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
177 /* 0x98 - 0x9F */ 175 /* 0x98 - 0x9F */
178 0, 0, SrcImm | Src2Imm16 | No64, 0, 176 0, 0, SrcImmFAddr | No64, 0,
179 ImplicitOps | Stack, ImplicitOps | Stack, 0, 0, 177 ImplicitOps | Stack, ImplicitOps | Stack, 0, 0,
180 /* 0xA0 - 0xA7 */ 178 /* 0xA0 - 0xA7 */
181 ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs, 179 ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs,
@@ -215,7 +213,7 @@ static u32 opcode_table[256] = {
215 ByteOp | SrcImmUByte | DstAcc, SrcImmUByte | DstAcc, 213 ByteOp | SrcImmUByte | DstAcc, SrcImmUByte | DstAcc,
216 /* 0xE8 - 0xEF */ 214 /* 0xE8 - 0xEF */
217 SrcImm | Stack, SrcImm | ImplicitOps, 215 SrcImm | Stack, SrcImm | ImplicitOps,
218 SrcImmU | Src2Imm16 | No64, SrcImmByte | ImplicitOps, 216 SrcImmFAddr | No64, SrcImmByte | ImplicitOps,
219 SrcNone | ByteOp | DstAcc, SrcNone | DstAcc, 217 SrcNone | ByteOp | DstAcc, SrcNone | DstAcc,
220 SrcNone | ByteOp | DstAcc, SrcNone | DstAcc, 218 SrcNone | ByteOp | DstAcc, SrcNone | DstAcc,
221 /* 0xF0 - 0xF7 */ 219 /* 0xF0 - 0xF7 */
@@ -350,7 +348,7 @@ static u32 group_table[] = {
350 [Group5*8] = 348 [Group5*8] =
351 DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, 349 DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM,
352 SrcMem | ModRM | Stack, 0, 350 SrcMem | ModRM | Stack, 0,
353 SrcMem | ModRM | Stack, SrcMem | ModRM | Src2Mem16 | ImplicitOps, 351 SrcMem | ModRM | Stack, SrcMemFAddr | ModRM | ImplicitOps,
354 SrcMem | ModRM | Stack, 0, 352 SrcMem | ModRM | Stack, 0,
355 [Group7*8] = 353 [Group7*8] =
356 0, 0, ModRM | SrcMem | Priv, ModRM | SrcMem | Priv, 354 0, 0, ModRM | SrcMem | Priv, ModRM | SrcMem | Priv,
@@ -576,6 +574,13 @@ static u32 group2_table[] = {
576 (_type)_x; \ 574 (_type)_x; \
577}) 575})
578 576
577#define insn_fetch_arr(_arr, _size, _eip) \
578({ rc = do_insn_fetch(ctxt, ops, (_eip), _arr, (_size)); \
579 if (rc != X86EMUL_CONTINUE) \
580 goto done; \
581 (_eip) += (_size); \
582})
583
579static inline unsigned long ad_mask(struct decode_cache *c) 584static inline unsigned long ad_mask(struct decode_cache *c)
580{ 585{
581 return (1UL << (c->ad_bytes << 3)) - 1; 586 return (1UL << (c->ad_bytes << 3)) - 1;
@@ -1160,6 +1165,17 @@ done_prefixes:
1160 c->regs[VCPU_REGS_RSI]); 1165 c->regs[VCPU_REGS_RSI]);
1161 c->src.val = 0; 1166 c->src.val = 0;
1162 break; 1167 break;
1168 case SrcImmFAddr:
1169 c->src.type = OP_IMM;
1170 c->src.ptr = (unsigned long *)c->eip;
1171 c->src.bytes = c->op_bytes + 2;
1172 insn_fetch_arr(c->src.valptr, c->src.bytes, c->eip);
1173 break;
1174 case SrcMemFAddr:
1175 c->src.type = OP_MEM;
1176 c->src.ptr = (unsigned long *)c->modrm_ea;
1177 c->src.bytes = c->op_bytes + 2;
1178 break;
1163 } 1179 }
1164 1180
1165 /* 1181 /*
@@ -1179,22 +1195,10 @@ done_prefixes:
1179 c->src2.bytes = 1; 1195 c->src2.bytes = 1;
1180 c->src2.val = insn_fetch(u8, 1, c->eip); 1196 c->src2.val = insn_fetch(u8, 1, c->eip);
1181 break; 1197 break;
1182 case Src2Imm16:
1183 c->src2.type = OP_IMM;
1184 c->src2.ptr = (unsigned long *)c->eip;
1185 c->src2.bytes = 2;
1186 c->src2.val = insn_fetch(u16, 2, c->eip);
1187 break;
1188 case Src2One: 1198 case Src2One:
1189 c->src2.bytes = 1; 1199 c->src2.bytes = 1;
1190 c->src2.val = 1; 1200 c->src2.val = 1;
1191 break; 1201 break;
1192 case Src2Mem16:
1193 c->src2.type = OP_MEM;
1194 c->src2.bytes = 2;
1195 c->src2.ptr = (unsigned long *)(c->modrm_ea + c->src.bytes);
1196 c->src2.val = 0;
1197 break;
1198 } 1202 }
1199 1203
1200 /* Decode and fetch the destination operand: register or memory. */ 1204 /* Decode and fetch the destination operand: register or memory. */
@@ -2558,7 +2562,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
2558 2562
2559 if (c->src.type == OP_MEM) { 2563 if (c->src.type == OP_MEM) {
2560 rc = read_emulated(ctxt, ops, (unsigned long)c->src.ptr, 2564 rc = read_emulated(ctxt, ops, (unsigned long)c->src.ptr,
2561 &c->src.val, c->src.bytes); 2565 c->src.valptr, c->src.bytes);
2562 if (rc != X86EMUL_CONTINUE) 2566 if (rc != X86EMUL_CONTINUE)
2563 goto done; 2567 goto done;
2564 c->src.orig_val = c->src.val; 2568 c->src.orig_val = c->src.val;
@@ -2884,14 +2888,18 @@ special_insn:
2884 } 2888 }
2885 case 0xe9: /* jmp rel */ 2889 case 0xe9: /* jmp rel */
2886 goto jmp; 2890 goto jmp;
2887 case 0xea: /* jmp far */ 2891 case 0xea: { /* jmp far */
2892 unsigned short sel;
2888 jump_far: 2893 jump_far:
2889 if (load_segment_descriptor(ctxt, ops, c->src2.val, 2894 memcpy(&sel, c->src.valptr + c->op_bytes, 2);
2890 VCPU_SREG_CS)) 2895
2896 if (load_segment_descriptor(ctxt, ops, sel, VCPU_SREG_CS))
2891 goto done; 2897 goto done;
2892 2898
2893 c->eip = c->src.val; 2899 c->eip = 0;
2900 memcpy(&c->eip, c->src.valptr, c->op_bytes);
2894 break; 2901 break;
2902 }
2895 case 0xeb: 2903 case 0xeb:
2896 jmp: /* jmp rel short */ 2904 jmp: /* jmp rel short */
2897 jmp_rel(c, c->src.val); 2905 jmp_rel(c, c->src.val);