diff options
author | Avi Kivity <avi@qumranet.com> | 2008-04-14 15:40:50 +0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-04-27 19:21:34 +0400 |
commit | 16286d082d99cb41e16938fa6ba84604229f4b77 (patch) | |
tree | 4320f07eea5e48e617c03d732b178d9d99f81f41 /arch | |
parent | 66b85505736dbd3a3a0ed5ae38c12bb218b231c0 (diff) | |
download | linux-16286d082d99cb41e16938fa6ba84604229f4b77.tar.xz |
KVM: x86 emulator: fix smsw and lmsw with a memory operand
lmsw and smsw were implemented only with a register operand. Extend them
to support a memory operand as well. Fixes Windows running some display
compatibility test on AMD hosts.
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/x86_emulate.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index 8e1b32f2cd5e..46ef78f8bb35 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c @@ -275,12 +275,15 @@ static u16 group_table[] = { SrcMem | ModRM, 0, SrcMem | ModRM | Stack, 0, [Group7*8] = 0, 0, ModRM | SrcMem, ModRM | SrcMem, - SrcNone | ModRM | DstMem, 0, SrcMem | ModRM, SrcMem | ModRM | ByteOp, + SrcNone | ModRM | DstMem | Mov, 0, + SrcMem16 | ModRM | Mov, SrcMem | ModRM | ByteOp, }; static u16 group2_table[] = { [Group7*8] = - SrcNone | ModRM, 0, 0, 0, SrcNone | ModRM | DstMem, 0, SrcMem | ModRM, 0, + SrcNone | ModRM, 0, 0, 0, + SrcNone | ModRM | DstMem | Mov, 0, + SrcMem16 | ModRM | Mov, 0, }; /* EFLAGS bit definitions. */ @@ -1722,6 +1725,8 @@ twobyte_insn: goto done; kvm_emulate_hypercall(ctxt->vcpu); + /* Disable writeback. */ + c->dst.type = OP_NONE; break; case 2: /* lgdt */ rc = read_descriptor(ctxt, ops, c->src.ptr, @@ -1729,6 +1734,8 @@ twobyte_insn: if (rc) goto done; realmode_lgdt(ctxt->vcpu, size, address); + /* Disable writeback. */ + c->dst.type = OP_NONE; break; case 3: /* lidt/vmmcall */ if (c->modrm_mod == 3 && c->modrm_rm == 1) { @@ -1744,27 +1751,25 @@ twobyte_insn: goto done; realmode_lidt(ctxt->vcpu, size, address); } + /* Disable writeback. */ + c->dst.type = OP_NONE; break; case 4: /* smsw */ - if (c->modrm_mod != 3) - goto cannot_emulate; - *(u16 *)&c->regs[c->modrm_rm] - = realmode_get_cr(ctxt->vcpu, 0); + c->dst.bytes = 2; + c->dst.val = realmode_get_cr(ctxt->vcpu, 0); break; case 6: /* lmsw */ - if (c->modrm_mod != 3) - goto cannot_emulate; - realmode_lmsw(ctxt->vcpu, (u16)c->modrm_val, - &ctxt->eflags); + realmode_lmsw(ctxt->vcpu, (u16)c->src.val, + &ctxt->eflags); break; case 7: /* invlpg*/ emulate_invlpg(ctxt->vcpu, memop); + /* Disable writeback. */ + c->dst.type = OP_NONE; break; default: goto cannot_emulate; } - /* Disable writeback. */ - c->dst.type = OP_NONE; break; case 0x06: emulate_clts(ctxt->vcpu); |