aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2008-04-14 07:40:50 -0400
committerAvi Kivity <avi@qumranet.com>2008-04-27 11:21:34 -0400
commit16286d082d99cb41e16938fa6ba84604229f4b77 (patch)
tree4320f07eea5e48e617c03d732b178d9d99f81f41 /arch
parent66b85505736dbd3a3a0ed5ae38c12bb218b231c0 (diff)
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.c29
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[] = {
275 SrcMem | ModRM, 0, SrcMem | ModRM | Stack, 0, 275 SrcMem | ModRM, 0, SrcMem | ModRM | Stack, 0,
276 [Group7*8] = 276 [Group7*8] =
277 0, 0, ModRM | SrcMem, ModRM | SrcMem, 277 0, 0, ModRM | SrcMem, ModRM | SrcMem,
278 SrcNone | ModRM | DstMem, 0, SrcMem | ModRM, SrcMem | ModRM | ByteOp, 278 SrcNone | ModRM | DstMem | Mov, 0,
279 SrcMem16 | ModRM | Mov, SrcMem | ModRM | ByteOp,
279}; 280};
280 281
281static u16 group2_table[] = { 282static u16 group2_table[] = {
282 [Group7*8] = 283 [Group7*8] =
283 SrcNone | ModRM, 0, 0, 0, SrcNone | ModRM | DstMem, 0, SrcMem | ModRM, 0, 284 SrcNone | ModRM, 0, 0, 0,
285 SrcNone | ModRM | DstMem | Mov, 0,
286 SrcMem16 | ModRM | Mov, 0,
284}; 287};
285 288
286/* EFLAGS bit definitions. */ 289/* EFLAGS bit definitions. */
@@ -1722,6 +1725,8 @@ twobyte_insn:
1722 goto done; 1725 goto done;
1723 1726
1724 kvm_emulate_hypercall(ctxt->vcpu); 1727 kvm_emulate_hypercall(ctxt->vcpu);
1728 /* Disable writeback. */
1729 c->dst.type = OP_NONE;
1725 break; 1730 break;
1726 case 2: /* lgdt */ 1731 case 2: /* lgdt */
1727 rc = read_descriptor(ctxt, ops, c->src.ptr, 1732 rc = read_descriptor(ctxt, ops, c->src.ptr,
@@ -1729,6 +1734,8 @@ twobyte_insn:
1729 if (rc) 1734 if (rc)
1730 goto done; 1735 goto done;
1731 realmode_lgdt(ctxt->vcpu, size, address); 1736 realmode_lgdt(ctxt->vcpu, size, address);
1737 /* Disable writeback. */
1738 c->dst.type = OP_NONE;
1732 break; 1739 break;
1733 case 3: /* lidt/vmmcall */ 1740 case 3: /* lidt/vmmcall */
1734 if (c->modrm_mod == 3 && c->modrm_rm == 1) { 1741 if (c->modrm_mod == 3 && c->modrm_rm == 1) {
@@ -1744,27 +1751,25 @@ twobyte_insn:
1744 goto done; 1751 goto done;
1745 realmode_lidt(ctxt->vcpu, size, address); 1752 realmode_lidt(ctxt->vcpu, size, address);
1746 } 1753 }
1754 /* Disable writeback. */
1755 c->dst.type = OP_NONE;
1747 break; 1756 break;
1748 case 4: /* smsw */ 1757 case 4: /* smsw */
1749 if (c->modrm_mod != 3) 1758 c->dst.bytes = 2;
1750 goto cannot_emulate; 1759 c->dst.val = realmode_get_cr(ctxt->vcpu, 0);
1751 *(u16 *)&c->regs[c->modrm_rm]
1752 = realmode_get_cr(ctxt->vcpu, 0);
1753 break; 1760 break;
1754 case 6: /* lmsw */ 1761 case 6: /* lmsw */
1755 if (c->modrm_mod != 3) 1762 realmode_lmsw(ctxt->vcpu, (u16)c->src.val,
1756 goto cannot_emulate; 1763 &ctxt->eflags);
1757 realmode_lmsw(ctxt->vcpu, (u16)c->modrm_val,
1758 &ctxt->eflags);
1759 break; 1764 break;
1760 case 7: /* invlpg*/ 1765 case 7: /* invlpg*/
1761 emulate_invlpg(ctxt->vcpu, memop); 1766 emulate_invlpg(ctxt->vcpu, memop);
1767 /* Disable writeback. */
1768 c->dst.type = OP_NONE;
1762 break; 1769 break;
1763 default: 1770 default:
1764 goto cannot_emulate; 1771 goto cannot_emulate;
1765 } 1772 }
1766 /* Disable writeback. */
1767 c->dst.type = OP_NONE;
1768 break; 1773 break;
1769 case 0x06: 1774 case 0x06:
1770 emulate_clts(ctxt->vcpu); 1775 emulate_clts(ctxt->vcpu);