]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/2.6.32.12/kvm-x86-emulator-fix-popf-emulation.patch
Remove duplicated commits
[thirdparty/kernel/stable-queue.git] / releases / 2.6.32.12 / kvm-x86-emulator-fix-popf-emulation.patch
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
5 To: stable@kernel.org
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>
8
9
10 From: Gleb Natapov <gleb@redhat.com>
11
12 commit d4c6a1549c056f1d817e8f6f2f97d8b44933472f upstream
13
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.
16
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>
21 ---
22 arch/x86/kvm/emulate.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++-
23 1 file changed, 54 insertions(+), 1 deletion(-)
24
25 --- a/arch/x86/kvm/emulate.c
26 +++ b/arch/x86/kvm/emulate.c
27 @@ -339,11 +339,18 @@ static u32 group2_table[] = {
28 };
29
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
47 return rc;
48 }
49
50 +static int emulate_popf(struct x86_emulate_ctxt *ctxt,
51 + struct x86_emulate_ops *ops,
52 + void *dest, int len)
53 +{
54 + int rc;
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);
58 +
59 + rc = emulate_pop(ctxt, ops, &val, len);
60 + if (rc != X86EMUL_CONTINUE)
61 + return rc;
62 +
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;
65 +
66 + switch(ctxt->mode) {
67 + case X86EMUL_MODE_PROT64:
68 + case X86EMUL_MODE_PROT32:
69 + case X86EMUL_MODE_PROT16:
70 + if (cpl == 0)
71 + change_mask |= EFLG_IOPL;
72 + if (cpl <= iopl)
73 + change_mask |= EFLG_IF;
74 + break;
75 + case X86EMUL_MODE_VM86:
76 + if (iopl < 3) {
77 + kvm_inject_gp(ctxt->vcpu, 0);
78 + return X86EMUL_PROPAGATE_FAULT;
79 + }
80 + change_mask |= EFLG_IF;
81 + break;
82 + default: /* real mode */
83 + change_mask |= (EFLG_IOPL | EFLG_IF);
84 + break;
85 + }
86 +
87 + *(unsigned long *)dest =
88 + (ctxt->eflags & ~change_mask) | (val & change_mask);
89 +
90 + return rc;
91 +}
92 +
93 static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
94 struct x86_emulate_ops *ops)
95 {
96 @@ -1995,7 +2045,10 @@ special_insn:
97 c->dst.type = OP_REG;
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)
103 + goto done;
104 + break;
105 case 0xa0 ... 0xa1: /* mov */
106 c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
107 c->dst.val = c->src.val;