]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.9.104/kvm-x86-update-cpuid-properly-when-cr4.osxave-or-cr4.pke-is-changed.patch
Linux 4.9.178
[thirdparty/kernel/stable-queue.git] / releases / 4.9.104 / kvm-x86-update-cpuid-properly-when-cr4.osxave-or-cr4.pke-is-changed.patch
CommitLineData
eab49e0f
GKH
1From c4d2188206bafa177ea58e9a25b952baa0bf7712 Mon Sep 17 00:00:00 2001
2From: Wei Huang <wei@redhat.com>
3Date: Tue, 1 May 2018 09:49:54 -0500
4Subject: KVM: x86: Update cpuid properly when CR4.OSXAVE or CR4.PKE is changed
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9From: Wei Huang <wei@redhat.com>
10
11commit c4d2188206bafa177ea58e9a25b952baa0bf7712 upstream.
12
13The CPUID bits of OSXSAVE (function=0x1) and OSPKE (func=0x7, leaf=0x0)
14allows user apps to detect if OS has set CR4.OSXSAVE or CR4.PKE. KVM is
15supposed to update these CPUID bits when CR4 is updated. Current KVM
16code doesn't handle some special cases when updates come from emulator.
17Here is one example:
18
19 Step 1: guest boots
20 Step 2: guest OS enables XSAVE ==> CR4.OSXSAVE=1 and CPUID.OSXSAVE=1
21 Step 3: guest hot reboot ==> QEMU reset CR4 to 0, but CPUID.OSXAVE==1
22 Step 4: guest os checks CPUID.OSXAVE, detects 1, then executes xgetbv
23
24Step 4 above will cause an #UD and guest crash because guest OS hasn't
25turned on OSXAVE yet. This patch solves the problem by comparing the the
26old_cr4 with cr4. If the related bits have been changed,
27kvm_update_cpuid() needs to be called.
28
29Signed-off-by: Wei Huang <wei@redhat.com>
30Reviewed-by: Bandan Das <bsd@redhat.com>
31Cc: stable@vger.kernel.org
32Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
33Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
34
35---
36 arch/x86/kvm/x86.c | 5 ++++-
37 1 file changed, 4 insertions(+), 1 deletion(-)
38
39--- a/arch/x86/kvm/x86.c
40+++ b/arch/x86/kvm/x86.c
41@@ -7258,6 +7258,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct
42 {
43 struct msr_data apic_base_msr;
44 int mmu_reset_needed = 0;
45+ int cpuid_update_needed = 0;
46 int pending_vec, max_bits, idx;
47 struct desc_ptr dt;
48
49@@ -7289,8 +7290,10 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct
50 vcpu->arch.cr0 = sregs->cr0;
51
52 mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4;
53+ cpuid_update_needed |= ((kvm_read_cr4(vcpu) ^ sregs->cr4) &
54+ (X86_CR4_OSXSAVE | X86_CR4_PKE));
55 kvm_x86_ops->set_cr4(vcpu, sregs->cr4);
56- if (sregs->cr4 & (X86_CR4_OSXSAVE | X86_CR4_PKE))
57+ if (cpuid_update_needed)
58 kvm_update_cpuid(vcpu);
59
60 idx = srcu_read_lock(&vcpu->kvm->srcu);