aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorMohammed Gamal <m.gamal005@gmail.com>2010-07-28 05:38:40 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:50:05 -0400
commit62bd430e6d41ac84ff2fb719f5783c3692718f47 (patch)
treed4f956bb6e12a9a76d5aa724dbe12a34c7f6c4ed /arch/x86/kvm/emulate.c
parent7a190667bb316653cbb782fff95cfdfcf51ded45 (diff)
KVM: x86 emulator: Add IRET instruction
Ths patch adds IRET instruction (opcode 0xcf). Currently, only IRET in real mode is emulated. Protected mode support is to be added later if needed. Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com> Reviewed-by: Avi Kivity <avi@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 7f615c57cbad..b0f45bc63e1c 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -341,6 +341,9 @@ static u32 group2_table[] = {
341#define EFLG_PF (1<<2) 341#define EFLG_PF (1<<2)
342#define EFLG_CF (1<<0) 342#define EFLG_CF (1<<0)
343 343
344#define EFLG_RESERVED_ZEROS_MASK 0xffc0802a
345#define EFLG_RESERVED_ONE_MASK 2
346
344/* 347/*
345 * Instruction emulation: 348 * Instruction emulation:
346 * Most instructions are emulated directly via a fragment of inline assembly 349 * Most instructions are emulated directly via a fragment of inline assembly
@@ -1729,6 +1732,78 @@ static int emulate_popa(struct x86_emulate_ctxt *ctxt,
1729 return rc; 1732 return rc;
1730} 1733}
1731 1734
1735static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
1736 struct x86_emulate_ops *ops)
1737{
1738 struct decode_cache *c = &ctxt->decode;
1739 int rc = X86EMUL_CONTINUE;
1740 unsigned long temp_eip = 0;
1741 unsigned long temp_eflags = 0;
1742 unsigned long cs = 0;
1743 unsigned long mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_TF |
1744 EFLG_IF | EFLG_DF | EFLG_OF | EFLG_IOPL | EFLG_NT | EFLG_RF |
1745 EFLG_AC | EFLG_ID | (1 << 1); /* Last one is the reserved bit */
1746 unsigned long vm86_mask = EFLG_VM | EFLG_VIF | EFLG_VIP;
1747
1748 /* TODO: Add stack limit check */
1749
1750 rc = emulate_pop(ctxt, ops, &temp_eip, c->op_bytes);
1751
1752 if (rc != X86EMUL_CONTINUE)
1753 return rc;
1754
1755 if (temp_eip & ~0xffff) {
1756 emulate_gp(ctxt, 0);
1757 return X86EMUL_PROPAGATE_FAULT;
1758 }
1759
1760 rc = emulate_pop(ctxt, ops, &cs, c->op_bytes);
1761
1762 if (rc != X86EMUL_CONTINUE)
1763 return rc;
1764
1765 rc = emulate_pop(ctxt, ops, &temp_eflags, c->op_bytes);
1766
1767 if (rc != X86EMUL_CONTINUE)
1768 return rc;
1769
1770 rc = load_segment_descriptor(ctxt, ops, (u16)cs, VCPU_SREG_CS);
1771
1772 if (rc != X86EMUL_CONTINUE)
1773 return rc;
1774
1775 c->eip = temp_eip;
1776
1777
1778 if (c->op_bytes == 4)
1779 ctxt->eflags = ((temp_eflags & mask) | (ctxt->eflags & vm86_mask));
1780 else if (c->op_bytes == 2) {
1781 ctxt->eflags &= ~0xffff;
1782 ctxt->eflags |= temp_eflags;
1783 }
1784
1785 ctxt->eflags &= ~EFLG_RESERVED_ZEROS_MASK; /* Clear reserved zeros */
1786 ctxt->eflags |= EFLG_RESERVED_ONE_MASK;
1787
1788 return rc;
1789}
1790
1791static inline int emulate_iret(struct x86_emulate_ctxt *ctxt,
1792 struct x86_emulate_ops* ops)
1793{
1794 switch(ctxt->mode) {
1795 case X86EMUL_MODE_REAL:
1796 return emulate_iret_real(ctxt, ops);
1797 case X86EMUL_MODE_VM86:
1798 case X86EMUL_MODE_PROT16:
1799 case X86EMUL_MODE_PROT32:
1800 case X86EMUL_MODE_PROT64:
1801 default:
1802 /* iret from protected mode unimplemented yet */
1803 return X86EMUL_UNHANDLEABLE;
1804 }
1805}
1806
1732static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt, 1807static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
1733 struct x86_emulate_ops *ops) 1808 struct x86_emulate_ops *ops)
1734{ 1809{
@@ -2860,6 +2935,12 @@ special_insn:
2860 if (rc != X86EMUL_CONTINUE) 2935 if (rc != X86EMUL_CONTINUE)
2861 goto done; 2936 goto done;
2862 break; 2937 break;
2938 case 0xcf: /* iret */
2939 rc = emulate_iret(ctxt, ops);
2940
2941 if (rc != X86EMUL_CONTINUE)
2942 goto done;
2943 break;
2863 case 0xd0 ... 0xd1: /* Grp2 */ 2944 case 0xd0 ... 0xd1: /* Grp2 */
2864 c->src.val = 1; 2945 c->src.val = 1;
2865 emulate_grp2(ctxt); 2946 emulate_grp2(ctxt);