aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-12-06 11:14:14 -0500
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:53:19 -0500
commit6e3d5dfbad4d8c29bdf8ed160f91f955f0efc12b (patch)
tree914da0fb65504385c1e9e93728517585cea1f780 /drivers
parent152ff9be2ed11e76ed3014b94eacdd6bc9275518 (diff)
KVM: x86 emulator: Fix stack instructions on 64-bit mode
Stack instructions are always 64-bit on 64-bit mode; many of the emulated stack instructions did not take that into account. Fix by adding a 'Stack' bitflag and setting the operand size appropriately during the decode stage (except for 'push r/m', which is in a group with a few other instructions, so it gets its own treatment). This fixes random crashes on Vista x64. Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/kvm/x86_emulate.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index f423b0e327f4..0a6ab06fde01 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -65,6 +65,7 @@
65#define BitOp (1<<8) 65#define BitOp (1<<8)
66#define MemAbs (1<<9) /* Memory operand is absolute displacement */ 66#define MemAbs (1<<9) /* Memory operand is absolute displacement */
67#define String (1<<10) /* String instruction (rep capable) */ 67#define String (1<<10) /* String instruction (rep capable) */
68#define Stack (1<<11) /* Stack instruction (push/pop) */
68 69
69static u16 opcode_table[256] = { 70static u16 opcode_table[256] = {
70 /* 0x00 - 0x07 */ 71 /* 0x00 - 0x07 */
@@ -104,14 +105,16 @@ static u16 opcode_table[256] = {
104 /* 0x48 - 0x4F */ 105 /* 0x48 - 0x4F */
105 DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, 106 DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
106 /* 0x50 - 0x57 */ 107 /* 0x50 - 0x57 */
107 SrcReg, SrcReg, SrcReg, SrcReg, SrcReg, SrcReg, SrcReg, SrcReg, 108 SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, SrcReg | Stack,
109 SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, SrcReg | Stack,
108 /* 0x58 - 0x5F */ 110 /* 0x58 - 0x5F */
109 DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, 111 DstReg | Stack, DstReg | Stack, DstReg | Stack, DstReg | Stack,
112 DstReg | Stack, DstReg | Stack, DstReg | Stack, DstReg | Stack,
110 /* 0x60 - 0x67 */ 113 /* 0x60 - 0x67 */
111 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ , 114 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ ,
112 0, 0, 0, 0, 115 0, 0, 0, 0,
113 /* 0x68 - 0x6F */ 116 /* 0x68 - 0x6F */
114 0, 0, ImplicitOps|Mov, 0, 117 0, 0, ImplicitOps | Mov | Stack, 0,
115 SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, /* insb, insw/insd */ 118 SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, /* insb, insw/insd */
116 SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, /* outsb, outsw/outsd */ 119 SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, /* outsb, outsw/outsd */
117 /* 0x70 - 0x77 */ 120 /* 0x70 - 0x77 */
@@ -128,9 +131,10 @@ static u16 opcode_table[256] = {
128 /* 0x88 - 0x8F */ 131 /* 0x88 - 0x8F */
129 ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov, 132 ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov,
130 ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, 133 ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
131 0, ModRM | DstReg, 0, DstMem | SrcNone | ModRM | Mov, 134 0, ModRM | DstReg, 0, DstMem | SrcNone | ModRM | Mov | Stack,
132 /* 0x90 - 0x9F */ 135 /* 0x90 - 0x9F */
133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps, ImplicitOps, 0, 0, 136 0, 0, 0, 0, 0, 0, 0, 0,
137 0, 0, 0, 0, ImplicitOps | Stack, ImplicitOps | Stack, 0, 0,
134 /* 0xA0 - 0xA7 */ 138 /* 0xA0 - 0xA7 */
135 ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs, 139 ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs,
136 ByteOp | DstMem | SrcReg | Mov | MemAbs, DstMem | SrcReg | Mov | MemAbs, 140 ByteOp | DstMem | SrcReg | Mov | MemAbs, DstMem | SrcReg | Mov | MemAbs,
@@ -144,7 +148,7 @@ static u16 opcode_table[256] = {
144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
145 /* 0xC0 - 0xC7 */ 149 /* 0xC0 - 0xC7 */
146 ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, 150 ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,
147 0, ImplicitOps, 0, 0, 151 0, ImplicitOps | Stack, 0, 0,
148 ByteOp | DstMem | SrcImm | ModRM | Mov, DstMem | SrcImm | ModRM | Mov, 152 ByteOp | DstMem | SrcImm | ModRM | Mov, DstMem | SrcImm | ModRM | Mov,
149 /* 0xC8 - 0xCF */ 153 /* 0xC8 - 0xCF */
150 0, 0, 0, 0, 0, 0, 0, 0, 154 0, 0, 0, 0, 0, 0, 0, 0,
@@ -157,7 +161,8 @@ static u16 opcode_table[256] = {
157 /* 0xE0 - 0xE7 */ 161 /* 0xE0 - 0xE7 */
158 0, 0, 0, 0, 0, 0, 0, 0, 162 0, 0, 0, 0, 0, 0, 0, 0,
159 /* 0xE8 - 0xEF */ 163 /* 0xE8 - 0xEF */
160 ImplicitOps, SrcImm|ImplicitOps, 0, SrcImmByte|ImplicitOps, 0, 0, 0, 0, 164 ImplicitOps | Stack, SrcImm|ImplicitOps, 0, SrcImmByte|ImplicitOps,
165 0, 0, 0, 0,
161 /* 0xF0 - 0xF7 */ 166 /* 0xF0 - 0xF7 */
162 0, 0, 0, 0, 167 0, 0, 0, 0,
163 ImplicitOps, ImplicitOps, 168 ImplicitOps, ImplicitOps,
@@ -868,6 +873,9 @@ done_prefixes:
868 } 873 }
869 } 874 }
870 875
876 if (mode == X86EMUL_MODE_PROT64 && (c->d & Stack))
877 c->op_bytes = 8;
878
871 /* ModRM and SIB bytes. */ 879 /* ModRM and SIB bytes. */
872 if (c->d & ModRM) 880 if (c->d & ModRM)
873 rc = decode_modrm(ctxt, ops); 881 rc = decode_modrm(ctxt, ops);
@@ -988,11 +996,6 @@ static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
988 struct decode_cache *c = &ctxt->decode; 996 struct decode_cache *c = &ctxt->decode;
989 int rc; 997 int rc;
990 998
991 /* 64-bit mode: POP always pops a 64-bit operand. */
992
993 if (ctxt->mode == X86EMUL_MODE_PROT64)
994 c->dst.bytes = 8;
995
996 rc = ops->read_std(register_address(ctxt->ss_base, 999 rc = ops->read_std(register_address(ctxt->ss_base,
997 c->regs[VCPU_REGS_RSP]), 1000 c->regs[VCPU_REGS_RSP]),
998 &c->dst.val, c->dst.bytes, ctxt->vcpu); 1001 &c->dst.val, c->dst.bytes, ctxt->vcpu);