diff options
author | Mohammed Gamal <m.gamal005@gmail.com> | 2009-09-01 09:28:11 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-12-03 02:32:09 -0500 |
commit | abcf14b560a4ba62c659e6f5aafc8f9934d8c130 (patch) | |
tree | 8a150ee04c05b09d5429252b5563b2e142d5283d /arch/x86/kvm/emulate.c | |
parent | 94677e61fdcf4cdae11a1b7c8974d7034ef9bd1b (diff) |
KVM: x86 emulator: Add pusha and popa instructions
This adds pusha and popa instructions (opcodes 0x60-0x61), this enables booting
MINIX with invalid guest state emulation on.
[marcelo: remove unused variable]
Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r-- | arch/x86/kvm/emulate.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index db0820dfbffe..d226dff47d77 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -139,7 +139,8 @@ static u32 opcode_table[256] = { | |||
139 | DstReg | Stack, DstReg | Stack, DstReg | Stack, DstReg | Stack, | 139 | DstReg | Stack, DstReg | Stack, DstReg | Stack, DstReg | Stack, |
140 | DstReg | Stack, DstReg | Stack, DstReg | Stack, DstReg | Stack, | 140 | DstReg | Stack, DstReg | Stack, DstReg | Stack, DstReg | Stack, |
141 | /* 0x60 - 0x67 */ | 141 | /* 0x60 - 0x67 */ |
142 | 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ , | 142 | ImplicitOps | Stack | No64, ImplicitOps | Stack | No64, |
143 | 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ , | ||
143 | 0, 0, 0, 0, | 144 | 0, 0, 0, 0, |
144 | /* 0x68 - 0x6F */ | 145 | /* 0x68 - 0x6F */ |
145 | SrcImm | Mov | Stack, 0, SrcImmByte | Mov | Stack, 0, | 146 | SrcImm | Mov | Stack, 0, SrcImmByte | Mov | Stack, 0, |
@@ -1225,6 +1226,43 @@ static int emulate_pop_sreg(struct x86_emulate_ctxt *ctxt, | |||
1225 | return rc; | 1226 | return rc; |
1226 | } | 1227 | } |
1227 | 1228 | ||
1229 | static void emulate_pusha(struct x86_emulate_ctxt *ctxt) | ||
1230 | { | ||
1231 | struct decode_cache *c = &ctxt->decode; | ||
1232 | unsigned long old_esp = c->regs[VCPU_REGS_RSP]; | ||
1233 | int reg = VCPU_REGS_RAX; | ||
1234 | |||
1235 | while (reg <= VCPU_REGS_RDI) { | ||
1236 | (reg == VCPU_REGS_RSP) ? | ||
1237 | (c->src.val = old_esp) : (c->src.val = c->regs[reg]); | ||
1238 | |||
1239 | emulate_push(ctxt); | ||
1240 | ++reg; | ||
1241 | } | ||
1242 | } | ||
1243 | |||
1244 | static int emulate_popa(struct x86_emulate_ctxt *ctxt, | ||
1245 | struct x86_emulate_ops *ops) | ||
1246 | { | ||
1247 | struct decode_cache *c = &ctxt->decode; | ||
1248 | int rc = 0; | ||
1249 | int reg = VCPU_REGS_RDI; | ||
1250 | |||
1251 | while (reg >= VCPU_REGS_RAX) { | ||
1252 | if (reg == VCPU_REGS_RSP) { | ||
1253 | register_address_increment(c, &c->regs[VCPU_REGS_RSP], | ||
1254 | c->op_bytes); | ||
1255 | --reg; | ||
1256 | } | ||
1257 | |||
1258 | rc = emulate_pop(ctxt, ops, &c->regs[reg], c->op_bytes); | ||
1259 | if (rc != 0) | ||
1260 | break; | ||
1261 | --reg; | ||
1262 | } | ||
1263 | return rc; | ||
1264 | } | ||
1265 | |||
1228 | static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt, | 1266 | static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt, |
1229 | struct x86_emulate_ops *ops) | 1267 | struct x86_emulate_ops *ops) |
1230 | { | 1268 | { |
@@ -1816,6 +1854,14 @@ special_insn: | |||
1816 | if (rc != 0) | 1854 | if (rc != 0) |
1817 | goto done; | 1855 | goto done; |
1818 | break; | 1856 | break; |
1857 | case 0x60: /* pusha */ | ||
1858 | emulate_pusha(ctxt); | ||
1859 | break; | ||
1860 | case 0x61: /* popa */ | ||
1861 | rc = emulate_popa(ctxt, ops); | ||
1862 | if (rc != 0) | ||
1863 | goto done; | ||
1864 | break; | ||
1819 | case 0x63: /* movsxd */ | 1865 | case 0x63: /* movsxd */ |
1820 | if (ctxt->mode != X86EMUL_MODE_PROT64) | 1866 | if (ctxt->mode != X86EMUL_MODE_PROT64) |
1821 | goto cannot_emulate; | 1867 | goto cannot_emulate; |