aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorWei Yongjun <yjwei@cn.fujitsu.com>2010-06-14 21:03:33 -0400
committerAvi Kivity <avi@redhat.com>2010-08-01 03:46:48 -0400
commitc37eda138473f8c843f2b4aa8da252fdfdaaafa3 (patch)
tree88ec34bb82c03613dd1c933f1c9f26e9b4d45901 /arch/x86/kvm/emulate.c
parentbd371396b38ffc4bd6444b0203f33b99d18cedd0 (diff)
KVM: x86 emulator: fix pusha instruction emulation
emulate pusha instruction only writeback the last EDI register, but the other registers which need to be writeback is ignored. This patch fixed it. Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c133
1 files changed, 73 insertions, 60 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index a4c2dcd10326..c990db0a3a02 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1553,6 +1553,64 @@ exception:
1553 return X86EMUL_PROPAGATE_FAULT; 1553 return X86EMUL_PROPAGATE_FAULT;
1554} 1554}
1555 1555
1556static inline int writeback(struct x86_emulate_ctxt *ctxt,
1557 struct x86_emulate_ops *ops)
1558{
1559 int rc;
1560 struct decode_cache *c = &ctxt->decode;
1561 u32 err;
1562
1563 switch (c->dst.type) {
1564 case OP_REG:
1565 /* The 4-byte case *is* correct:
1566 * in 64-bit mode we zero-extend.
1567 */
1568 switch (c->dst.bytes) {
1569 case 1:
1570 *(u8 *)c->dst.ptr = (u8)c->dst.val;
1571 break;
1572 case 2:
1573 *(u16 *)c->dst.ptr = (u16)c->dst.val;
1574 break;
1575 case 4:
1576 *c->dst.ptr = (u32)c->dst.val;
1577 break; /* 64b: zero-ext */
1578 case 8:
1579 *c->dst.ptr = c->dst.val;
1580 break;
1581 }
1582 break;
1583 case OP_MEM:
1584 if (c->lock_prefix)
1585 rc = ops->cmpxchg_emulated(
1586 (unsigned long)c->dst.ptr,
1587 &c->dst.orig_val,
1588 &c->dst.val,
1589 c->dst.bytes,
1590 &err,
1591 ctxt->vcpu);
1592 else
1593 rc = ops->write_emulated(
1594 (unsigned long)c->dst.ptr,
1595 &c->dst.val,
1596 c->dst.bytes,
1597 &err,
1598 ctxt->vcpu);
1599 if (rc == X86EMUL_PROPAGATE_FAULT)
1600 emulate_pf(ctxt,
1601 (unsigned long)c->dst.ptr, err);
1602 if (rc != X86EMUL_CONTINUE)
1603 return rc;
1604 break;
1605 case OP_NONE:
1606 /* no writeback */
1607 break;
1608 default:
1609 break;
1610 }
1611 return X86EMUL_CONTINUE;
1612}
1613
1556static inline void emulate_push(struct x86_emulate_ctxt *ctxt, 1614static inline void emulate_push(struct x86_emulate_ctxt *ctxt,
1557 struct x86_emulate_ops *ops) 1615 struct x86_emulate_ops *ops)
1558{ 1616{
@@ -1651,11 +1709,12 @@ static int emulate_pop_sreg(struct x86_emulate_ctxt *ctxt,
1651 return rc; 1709 return rc;
1652} 1710}
1653 1711
1654static void emulate_pusha(struct x86_emulate_ctxt *ctxt, 1712static int emulate_pusha(struct x86_emulate_ctxt *ctxt,
1655 struct x86_emulate_ops *ops) 1713 struct x86_emulate_ops *ops)
1656{ 1714{
1657 struct decode_cache *c = &ctxt->decode; 1715 struct decode_cache *c = &ctxt->decode;
1658 unsigned long old_esp = c->regs[VCPU_REGS_RSP]; 1716 unsigned long old_esp = c->regs[VCPU_REGS_RSP];
1717 int rc = X86EMUL_CONTINUE;
1659 int reg = VCPU_REGS_RAX; 1718 int reg = VCPU_REGS_RAX;
1660 1719
1661 while (reg <= VCPU_REGS_RDI) { 1720 while (reg <= VCPU_REGS_RDI) {
@@ -1663,8 +1722,18 @@ static void emulate_pusha(struct x86_emulate_ctxt *ctxt,
1663 (c->src.val = old_esp) : (c->src.val = c->regs[reg]); 1722 (c->src.val = old_esp) : (c->src.val = c->regs[reg]);
1664 1723
1665 emulate_push(ctxt, ops); 1724 emulate_push(ctxt, ops);
1725
1726 rc = writeback(ctxt, ops);
1727 if (rc != X86EMUL_CONTINUE)
1728 return rc;
1729
1666 ++reg; 1730 ++reg;
1667 } 1731 }
1732
1733 /* Disable writeback. */
1734 c->dst.type = OP_NONE;
1735
1736 return rc;
1668} 1737}
1669 1738
1670static int emulate_popa(struct x86_emulate_ctxt *ctxt, 1739static int emulate_popa(struct x86_emulate_ctxt *ctxt,
@@ -1817,64 +1886,6 @@ static int emulate_ret_far(struct x86_emulate_ctxt *ctxt,
1817 return rc; 1886 return rc;
1818} 1887}
1819 1888
1820static inline int writeback(struct x86_emulate_ctxt *ctxt,
1821 struct x86_emulate_ops *ops)
1822{
1823 int rc;
1824 struct decode_cache *c = &ctxt->decode;
1825 u32 err;
1826
1827 switch (c->dst.type) {
1828 case OP_REG:
1829 /* The 4-byte case *is* correct:
1830 * in 64-bit mode we zero-extend.
1831 */
1832 switch (c->dst.bytes) {
1833 case 1:
1834 *(u8 *)c->dst.ptr = (u8)c->dst.val;
1835 break;
1836 case 2:
1837 *(u16 *)c->dst.ptr = (u16)c->dst.val;
1838 break;
1839 case 4:
1840 *c->dst.ptr = (u32)c->dst.val;
1841 break; /* 64b: zero-ext */
1842 case 8:
1843 *c->dst.ptr = c->dst.val;
1844 break;
1845 }
1846 break;
1847 case OP_MEM:
1848 if (c->lock_prefix)
1849 rc = ops->cmpxchg_emulated(
1850 (unsigned long)c->dst.ptr,
1851 &c->dst.orig_val,
1852 &c->dst.val,
1853 c->dst.bytes,
1854 &err,
1855 ctxt->vcpu);
1856 else
1857 rc = ops->write_emulated(
1858 (unsigned long)c->dst.ptr,
1859 &c->dst.val,
1860 c->dst.bytes,
1861 &err,
1862 ctxt->vcpu);
1863 if (rc == X86EMUL_PROPAGATE_FAULT)
1864 emulate_pf(ctxt,
1865 (unsigned long)c->dst.ptr, err);
1866 if (rc != X86EMUL_CONTINUE)
1867 return rc;
1868 break;
1869 case OP_NONE:
1870 /* no writeback */
1871 break;
1872 default:
1873 break;
1874 }
1875 return X86EMUL_CONTINUE;
1876}
1877
1878static inline void 1889static inline void
1879setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, 1890setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
1880 struct x86_emulate_ops *ops, struct desc_struct *cs, 1891 struct x86_emulate_ops *ops, struct desc_struct *cs,
@@ -2689,7 +2700,9 @@ special_insn:
2689 goto done; 2700 goto done;
2690 break; 2701 break;
2691 case 0x60: /* pusha */ 2702 case 0x60: /* pusha */
2692 emulate_pusha(ctxt, ops); 2703 rc = emulate_pusha(ctxt, ops);
2704 if (rc != X86EMUL_CONTINUE)
2705 goto done;
2693 break; 2706 break;
2694 case 0x61: /* popa */ 2707 case 0x61: /* popa */
2695 rc = emulate_popa(ctxt, ops); 2708 rc = emulate_popa(ctxt, ops);