1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Paolo Bonzini <pbonzini@redhat.com>
3 Date: Thu, 21 Dec 2017 00:49:14 +0100
4 Subject: [PATCH] kvm: x86: fix RSM when PCID is non-zero
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
11 rsm_load_state_64() and rsm_enter_protected_mode() load CR3, then
12 CR4 & ~PCIDE, then CR0, then CR4.
14 However, setting CR4.PCIDE fails if CR3[11:0] != 0. It's probably easier
15 in the long run to replace rsm_enter_protected_mode() with an emulator
16 callback that sets all the special registers (like KVM_SET_SREGS would
17 do). For now, set the PCID field of CR3 only after CR4.PCIDE is 1.
19 Reported-by: Laszlo Ersek <lersek@redhat.com>
20 Tested-by: Laszlo Ersek <lersek@redhat.com>
21 Fixes: 660a5d517aaab9187f93854425c4c63f4a09195c
22 Cc: stable@vger.kernel.org
23 Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
24 (cherry picked from commit fae1a3e775cca8c3a9e0eb34443b310871a15a92)
25 Signed-off-by: Andy Whitcroft <apw@canonical.com>
26 Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
27 (cherry picked from commit dba4ceb9a91ed2d11a47722436b3c0be15e791d4)
28 Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
30 arch/x86/kvm/emulate.c | 32 +++++++++++++++++++++++++-------
31 1 file changed, 25 insertions(+), 7 deletions(-)
33 diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
34 index fb0055953fbc..155f2af2cb39 100644
35 --- a/arch/x86/kvm/emulate.c
36 +++ b/arch/x86/kvm/emulate.c
37 @@ -2399,9 +2399,21 @@ static int rsm_load_seg_64(struct x86_emulate_ctxt *ctxt, u64 smbase, int n)
40 static int rsm_enter_protected_mode(struct x86_emulate_ctxt *ctxt,
42 + u64 cr0, u64 cr3, u64 cr4)
47 + /* In order to later set CR4.PCIDE, CR3[11:0] must be zero. */
49 + if (cr4 & X86_CR4_PCIDE) {
54 + bad = ctxt->ops->set_cr(ctxt, 3, cr3);
56 + return X86EMUL_UNHANDLEABLE;
59 * First enable PAE, long mode needs it before CR0.PG = 1 is set.
60 @@ -2420,6 +2432,12 @@ static int rsm_enter_protected_mode(struct x86_emulate_ctxt *ctxt,
61 bad = ctxt->ops->set_cr(ctxt, 4, cr4);
63 return X86EMUL_UNHANDLEABLE;
65 + bad = ctxt->ops->set_cr(ctxt, 3, cr3 | pcid);
67 + return X86EMUL_UNHANDLEABLE;
72 return X86EMUL_CONTINUE;
73 @@ -2430,11 +2448,11 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase)
74 struct desc_struct desc;
78 + u32 val, cr0, cr3, cr4;
81 cr0 = GET_SMSTATE(u32, smbase, 0x7ffc);
82 - ctxt->ops->set_cr(ctxt, 3, GET_SMSTATE(u32, smbase, 0x7ff8));
83 + cr3 = GET_SMSTATE(u32, smbase, 0x7ff8);
84 ctxt->eflags = GET_SMSTATE(u32, smbase, 0x7ff4) | X86_EFLAGS_FIXED;
85 ctxt->_eip = GET_SMSTATE(u32, smbase, 0x7ff0);
87 @@ -2476,14 +2494,14 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase)
89 ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smbase, 0x7ef8));
91 - return rsm_enter_protected_mode(ctxt, cr0, cr4);
92 + return rsm_enter_protected_mode(ctxt, cr0, cr3, cr4);
95 static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
97 struct desc_struct desc;
100 + u64 val, cr0, cr3, cr4;
104 @@ -2500,7 +2518,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
105 ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1);
107 cr0 = GET_SMSTATE(u64, smbase, 0x7f58);
108 - ctxt->ops->set_cr(ctxt, 3, GET_SMSTATE(u64, smbase, 0x7f50));
109 + cr3 = GET_SMSTATE(u64, smbase, 0x7f50);
110 cr4 = GET_SMSTATE(u64, smbase, 0x7f48);
111 ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smbase, 0x7f00));
112 val = GET_SMSTATE(u64, smbase, 0x7ed0);
113 @@ -2528,7 +2546,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
114 dt.address = GET_SMSTATE(u64, smbase, 0x7e68);
115 ctxt->ops->set_gdt(ctxt, &dt);
117 - r = rsm_enter_protected_mode(ctxt, cr0, cr4);
118 + r = rsm_enter_protected_mode(ctxt, cr0, cr3, cr4);
119 if (r != X86EMUL_CONTINUE)