diff options
author | Wei Yongjun <yjwei@cn.fujitsu.com> | 2010-06-14 21:03:33 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-08-01 03:46:48 -0400 |
commit | c37eda138473f8c843f2b4aa8da252fdfdaaafa3 (patch) | |
tree | 88ec34bb82c03613dd1c933f1c9f26e9b4d45901 /arch/x86/kvm/emulate.c | |
parent | bd371396b38ffc4bd6444b0203f33b99d18cedd0 (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.c | 133 |
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 | ||
1556 | static 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 | |||
1556 | static inline void emulate_push(struct x86_emulate_ctxt *ctxt, | 1614 | static 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 | ||
1654 | static void emulate_pusha(struct x86_emulate_ctxt *ctxt, | 1712 | static 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 | ||
1670 | static int emulate_popa(struct x86_emulate_ctxt *ctxt, | 1739 | static 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 | ||
1820 | static 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 | |||
1878 | static inline void | 1889 | static inline void |
1879 | setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, | 1890 | setup_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); |