1 From stefan.bader@canonical.com Wed Apr 7 14:42:41 2010
2 From: Gleb Natapov <gleb@redhat.com>
3 Date: Fri, 19 Mar 2010 15:47:33 +0100
4 Subject: KVM: x86 emulator: Fix popf emulation
6 Cc: Marcelo Tosatti <mtosatti@redhat.com>, Avi Kivity <avi@redhat.com>, Gleb Natapov <gleb@redhat.com>
7 Message-ID: <1269010059-25309-6-git-send-email-stefan.bader@canonical.com>
10 From: Gleb Natapov <gleb@redhat.com>
12 commit d4c6a1549c056f1d817e8f6f2f97d8b44933472f upstream
14 POPF behaves differently depending on current CPU mode. Emulate correct
15 logic to prevent guest from changing flags that it can't change otherwise.
17 Signed-off-by: Gleb Natapov <gleb@redhat.com>
18 Signed-off-by: Avi Kivity <avi@redhat.com>
19 Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
20 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
22 arch/x86/kvm/emulate.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++-
23 1 file changed, 54 insertions(+), 1 deletion(-)
25 --- a/arch/x86/kvm/emulate.c
26 +++ b/arch/x86/kvm/emulate.c
27 @@ -339,11 +339,18 @@ static u32 group2_table[] = {
30 /* EFLAGS bit definitions. */
31 +#define EFLG_ID (1<<21)
32 +#define EFLG_VIP (1<<20)
33 +#define EFLG_VIF (1<<19)
34 +#define EFLG_AC (1<<18)
35 #define EFLG_VM (1<<17)
36 #define EFLG_RF (1<<16)
37 +#define EFLG_IOPL (3<<12)
38 +#define EFLG_NT (1<<14)
39 #define EFLG_OF (1<<11)
40 #define EFLG_DF (1<<10)
41 #define EFLG_IF (1<<9)
42 +#define EFLG_TF (1<<8)
43 #define EFLG_SF (1<<7)
44 #define EFLG_ZF (1<<6)
45 #define EFLG_AF (1<<4)
46 @@ -1205,6 +1212,49 @@ static int emulate_pop(struct x86_emulat
50 +static int emulate_popf(struct x86_emulate_ctxt *ctxt,
51 + struct x86_emulate_ops *ops,
52 + void *dest, int len)
55 + unsigned long val, change_mask;
56 + int iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
57 + int cpl = kvm_x86_ops->get_cpl(ctxt->vcpu);
59 + rc = emulate_pop(ctxt, ops, &val, len);
60 + if (rc != X86EMUL_CONTINUE)
63 + change_mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_OF
64 + | EFLG_TF | EFLG_DF | EFLG_NT | EFLG_RF | EFLG_AC | EFLG_ID;
66 + switch(ctxt->mode) {
67 + case X86EMUL_MODE_PROT64:
68 + case X86EMUL_MODE_PROT32:
69 + case X86EMUL_MODE_PROT16:
71 + change_mask |= EFLG_IOPL;
73 + change_mask |= EFLG_IF;
75 + case X86EMUL_MODE_VM86:
77 + kvm_inject_gp(ctxt->vcpu, 0);
78 + return X86EMUL_PROPAGATE_FAULT;
80 + change_mask |= EFLG_IF;
82 + default: /* real mode */
83 + change_mask |= (EFLG_IOPL | EFLG_IF);
87 + *(unsigned long *)dest =
88 + (ctxt->eflags & ~change_mask) | (val & change_mask);
93 static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
94 struct x86_emulate_ops *ops)
96 @@ -1995,7 +2045,10 @@ special_insn:
98 c->dst.ptr = (unsigned long *) &ctxt->eflags;
99 c->dst.bytes = c->op_bytes;
100 - goto pop_instruction;
101 + rc = emulate_popf(ctxt, ops, &c->dst.val, c->op_bytes);
102 + if (rc != X86EMUL_CONTINUE)
105 case 0xa0 ... 0xa1: /* mov */
106 c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
107 c->dst.val = c->src.val;