lkml.org 
[lkml]   [2022]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.16 1032/1039] KVM: x86: Do runtime CPUID update before updating vcpu->arch.cpuid_entries
    Date
    From: Vitaly Kuznetsov <vkuznets@redhat.com>

    commit ee3a5f9e3d9bf94159f3cc80da542fbe83502dd8 upstream.

    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>
    Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    arch/x86/kvm/cpuid.c | 54 ++++++++++++++++++++++++++++++++-------------------
    1 file changed, 34 insertions(+), 20 deletions(-)

    --- a/arch/x86/kvm/cpuid.c
    +++ b/arch/x86/kvm/cpuid.c
    @@ -125,14 +125,21 @@ static void kvm_update_kvm_cpuid_base(st
    }
    }

    -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)
    @@ -147,11 +154,12 @@ void kvm_update_pv_runtime(struct kvm_vc
    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))
    @@ -162,33 +170,38 @@ void kvm_update_cpuid_runtime(struct kvm
    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)
    @@ -276,21 +289,22 @@ u64 kvm_vcpu_reserved_gpa_bits_raw(struc
    static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2,
    int nent)
    {
    - int r;
    + int r;
    +
    + __kvm_update_cpuid_runtime(vcpu, e2, nent);

    - r = kvm_check_cpuid(e2, nent);
    - if (r)
    - return r;
    + r = kvm_check_cpuid(e2, nent);
    + if (r)
    + return r;

    - kvfree(vcpu->arch.cpuid_entries);
    - vcpu->arch.cpuid_entries = e2;
    - vcpu->arch.cpuid_nent = nent;
    + kvfree(vcpu->arch.cpuid_entries);
    + vcpu->arch.cpuid_entries = e2;
    + vcpu->arch.cpuid_nent = nent;

    - kvm_update_kvm_cpuid_base(vcpu);
    - kvm_update_cpuid_runtime(vcpu);
    - kvm_vcpu_after_set_cpuid(vcpu);
    + kvm_update_kvm_cpuid_base(vcpu);
    + kvm_vcpu_after_set_cpuid(vcpu);

    - return 0;
    + return 0;
    }

    /* when an old userspace process fills a new kernel module */

    \
     
     \ /
      Last update: 2022-01-25 03:48    [W:4.140 / U:0.052 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site