aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2010-04-28 12:15:26 -0400
committerAvi Kivity <avi@redhat.com>2010-08-01 03:35:30 -0400
commit414e6277fd148f6470261cef50a7fed0d88a2825 (patch)
treec105f8a33e9f744695d0ffd2172f6d2a9e859258
parentb8a98945ea5b735e083eaf92906aa0ff9ece92e8 (diff)
KVM: x86 emulator: handle "far address" source operand
ljmp/lcall instruction operand contains address and segment. It can be 10 bytes long. Currently we decode it as two different operands. Fix it by introducing new kind of operand that can hold entire far address. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-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);