Skip to content

Commit 75d4642

Browse files
committed
KVM: x86: Update guest cpu_caps at runtime for dynamic CPUID-based features
When updating guest CPUID entries to emulate runtime behavior, e.g. when the guest enables a CR4-based feature that is tied to a CPUID flag, also update the vCPU's cpu_caps accordingly. This will allow replacing all usage of guest_cpuid_has() with guest_cpu_cap_has(). Note, this relies on kvm_set_cpuid() taking a snapshot of cpu_caps before invoking kvm_update_cpuid_runtime(), i.e. when KVM is updating CPUID entries that *may* become the vCPU's CPUID, so that unwinding to the old cpu_caps is possible if userspace tries to set bogus CPUID information. Note #2, none of the features in question use guest_cpu_cap_has() at this time, i.e. aside from settings bits in cpu_caps, this is a glorified nop. Cc: Yang Weijiang <[email protected]> Cc: Robert Hoo <[email protected]> Reviewed-by: Binbin Wu <[email protected]> Reviewed-by: Maxim Levitsky <[email protected]> Reviewed-by: Xiaoyao Li <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Sean Christopherson <[email protected]>
1 parent 1f66590 commit 75d4642

File tree

1 file changed

+19
-9
lines changed

1 file changed

+19
-9
lines changed

arch/x86/kvm/cpuid.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -291,28 +291,38 @@ static u64 cpuid_get_supported_xcr0(struct kvm_vcpu *vcpu)
291291
return (best->eax | ((u64)best->edx << 32)) & kvm_caps.supported_xcr0;
292292
}
293293

294+
static __always_inline void kvm_update_feature_runtime(struct kvm_vcpu *vcpu,
295+
struct kvm_cpuid_entry2 *entry,
296+
unsigned int x86_feature,
297+
bool has_feature)
298+
{
299+
cpuid_entry_change(entry, x86_feature, has_feature);
300+
guest_cpu_cap_change(vcpu, x86_feature, has_feature);
301+
}
302+
294303
void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu)
295304
{
296305
struct kvm_cpuid_entry2 *best;
297306

298307
best = kvm_find_cpuid_entry(vcpu, 1);
299308
if (best) {
300-
cpuid_entry_change(best, X86_FEATURE_OSXSAVE,
301-
kvm_is_cr4_bit_set(vcpu, X86_CR4_OSXSAVE));
309+
kvm_update_feature_runtime(vcpu, best, X86_FEATURE_OSXSAVE,
310+
kvm_is_cr4_bit_set(vcpu, X86_CR4_OSXSAVE));
302311

303-
cpuid_entry_change(best, X86_FEATURE_APIC,
304-
vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE);
312+
kvm_update_feature_runtime(vcpu, best, X86_FEATURE_APIC,
313+
vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE);
305314

306315
if (!kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT))
307-
cpuid_entry_change(best, X86_FEATURE_MWAIT,
308-
vcpu->arch.ia32_misc_enable_msr &
309-
MSR_IA32_MISC_ENABLE_MWAIT);
316+
kvm_update_feature_runtime(vcpu, best, X86_FEATURE_MWAIT,
317+
vcpu->arch.ia32_misc_enable_msr &
318+
MSR_IA32_MISC_ENABLE_MWAIT);
310319
}
311320

312321
best = kvm_find_cpuid_entry_index(vcpu, 7, 0);
313322
if (best)
314-
cpuid_entry_change(best, X86_FEATURE_OSPKE,
315-
kvm_is_cr4_bit_set(vcpu, X86_CR4_PKE));
323+
kvm_update_feature_runtime(vcpu, best, X86_FEATURE_OSPKE,
324+
kvm_is_cr4_bit_set(vcpu, X86_CR4_PKE));
325+
316326

317327
best = kvm_find_cpuid_entry_index(vcpu, 0xD, 0);
318328
if (best)

0 commit comments

Comments
 (0)