diff options
-rw-r--r-- | arch/x86/include/asm/kvm_emulate.h | 6 | ||||
-rw-r--r-- | arch/x86/kvm/emulate.c | 56 |
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 { | |||
143 | struct operand { | 143 | struct 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 | ||
149 | struct fetch_cache { | 153 | struct 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 | ||
97 | enum { | 95 | enum { |
@@ -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 | |||
579 | static inline unsigned long ad_mask(struct decode_cache *c) | 584 | static 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); |