]> git.baikalelectronics.ru Git - kernel.git/commitdiff
KVM: x86: Do runtime CPUID update before updating vcpu->arch.cpuid_entries
authorVitaly Kuznetsov <vkuznets@redhat.com>
Mon, 17 Jan 2022 15:05:39 +0000 (16:05 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 17 Jan 2022 17:25:46 +0000 (12:25 -0500)
kvm_update_cpuid_runtime() mangles CPUID data coming from userspace
VMM after updating 'vcpu->arch.cpuid_entries', this makes it
impossible to compare an update with what was previously
supplied. Introduce __kvm_update_cpuid_runtime() version which can be
used to tweak the input before it goes to 'vcpu->arch.cpuid_entries'
so the upcoming update check can compare tweaked data.

No functional change intended.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Message-Id: <20220117150542.2176196-2-vkuznets@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/cpuid.c

index c55e57b30e81585fd78d4180f51bdb3f2ce0b67c..812190a707f62f11dab7e066693ddbf14492cdeb 100644 (file)
@@ -145,14 +145,21 @@ static void kvm_update_kvm_cpuid_base(struct kvm_vcpu *vcpu)
        }
 }
 
-static struct kvm_cpuid_entry2 *kvm_find_kvm_cpuid_features(struct kvm_vcpu *vcpu)
+static struct kvm_cpuid_entry2 *__kvm_find_kvm_cpuid_features(struct kvm_vcpu *vcpu,
+                                             struct kvm_cpuid_entry2 *entries, int nent)
 {
        u32 base = vcpu->arch.kvm_cpuid_base;
 
        if (!base)
                return NULL;
 
-       return kvm_find_cpuid_entry(vcpu, base | KVM_CPUID_FEATURES, 0);
+       return cpuid_entry2_find(entries, nent, base | KVM_CPUID_FEATURES, 0);
+}
+
+static struct kvm_cpuid_entry2 *kvm_find_kvm_cpuid_features(struct kvm_vcpu *vcpu)
+{
+       return __kvm_find_kvm_cpuid_features(vcpu, vcpu->arch.cpuid_entries,
+                                            vcpu->arch.cpuid_nent);
 }
 
 void kvm_update_pv_runtime(struct kvm_vcpu *vcpu)
@@ -167,11 +174,12 @@ void kvm_update_pv_runtime(struct kvm_vcpu *vcpu)
                vcpu->arch.pv_cpuid.features = best->eax;
 }
 
-void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu)
+static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *entries,
+                                      int nent)
 {
        struct kvm_cpuid_entry2 *best;
 
-       best = kvm_find_cpuid_entry(vcpu, 1, 0);
+       best = cpuid_entry2_find(entries, nent, 1, 0);
        if (best) {
                /* Update OSXSAVE bit */
                if (boot_cpu_has(X86_FEATURE_XSAVE))
@@ -182,33 +190,38 @@ void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu)
                           vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE);
        }
 
-       best = kvm_find_cpuid_entry(vcpu, 7, 0);
+       best = cpuid_entry2_find(entries, nent, 7, 0);
        if (best && boot_cpu_has(X86_FEATURE_PKU) && best->function == 0x7)
                cpuid_entry_change(best, X86_FEATURE_OSPKE,
                                   kvm_read_cr4_bits(vcpu, X86_CR4_PKE));
 
-       best = kvm_find_cpuid_entry(vcpu, 0xD, 0);
+       best = cpuid_entry2_find(entries, nent, 0xD, 0);
        if (best)
                best->ebx = xstate_required_size(vcpu->arch.xcr0, false);
 
-       best = kvm_find_cpuid_entry(vcpu, 0xD, 1);
+       best = cpuid_entry2_find(entries, nent, 0xD, 1);
        if (best && (cpuid_entry_has(best, X86_FEATURE_XSAVES) ||
                     cpuid_entry_has(best, X86_FEATURE_XSAVEC)))
                best->ebx = xstate_required_size(vcpu->arch.xcr0, true);
 
-       best = kvm_find_kvm_cpuid_features(vcpu);
+       best = __kvm_find_kvm_cpuid_features(vcpu, entries, nent);
        if (kvm_hlt_in_guest(vcpu->kvm) && best &&
                (best->eax & (1 << KVM_FEATURE_PV_UNHALT)))
                best->eax &= ~(1 << KVM_FEATURE_PV_UNHALT);
 
        if (!kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT)) {
-               best = kvm_find_cpuid_entry(vcpu, 0x1, 0);
+               best = cpuid_entry2_find(entries, nent, 0x1, 0);
                if (best)
                        cpuid_entry_change(best, X86_FEATURE_MWAIT,
                                           vcpu->arch.ia32_misc_enable_msr &
                                           MSR_IA32_MISC_ENABLE_MWAIT);
        }
 }
+
+void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu)
+{
+       __kvm_update_cpuid_runtime(vcpu, vcpu->arch.cpuid_entries, vcpu->arch.cpuid_nent);
+}
 EXPORT_SYMBOL_GPL(kvm_update_cpuid_runtime);
 
 static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
@@ -298,6 +311,8 @@ static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2,
 {
        int r;
 
+       __kvm_update_cpuid_runtime(vcpu, e2, nent);
+
        r = kvm_check_cpuid(vcpu, e2, nent);
        if (r)
                return r;
@@ -307,7 +322,6 @@ static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2,
        vcpu->arch.cpuid_nent = nent;
 
        kvm_update_kvm_cpuid_base(vcpu);
-       kvm_update_cpuid_runtime(vcpu);
        kvm_vcpu_after_set_cpuid(vcpu);
 
        return 0;