Skip to content

Commit

Permalink
KVM: x86: Explicitly do runtime CPUID updates "after" initial setup
Browse files Browse the repository at this point in the history
Explicitly perform runtime CPUID adjustments as part of the "after set
CPUID" flow to guard against bugs where KVM consumes stale vCPU/CPUID
state during kvm_update_cpuid_runtime().  E.g. see commit 4736d85
("KVM: x86: Use actual kvm_cpuid.base for clearing KVM_FEATURE_PV_UNHALT").

Whacking each mole individually is not sustainable or robust, e.g. while
the aforemention commit fixed KVM's PV features, the same issue lurks for
Xen and Hyper-V features, Xen and Hyper-V simply don't have any runtime
features (though spoiler alert, neither should KVM).

Updating runtime features in the "full" path will also simplify adding a
snapshot of the guest's capabilities, i.e. of caching the intersection of
guest CPUID and kvm_cpu_caps (modulo a few edge cases).

Link: https://lore.kernel.org/r/20241128013424.4096668-5-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
  • Loading branch information
sean-jc committed Dec 18, 2024
1 parent 85e5ba8 commit ec3d444
Showing 1 changed file with 16 additions and 2 deletions.
18 changes: 16 additions & 2 deletions arch/x86/kvm/cpuid.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,27 @@ static int kvm_check_cpuid(struct kvm_vcpu *vcpu,
return fpu_enable_guest_xfd_features(&vcpu->arch.guest_fpu, xfeatures);
}

static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *entries,
int nent);

/* Check whether the supplied CPUID data is equal to what is already set for the vCPU. */
static int kvm_cpuid_check_equal(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2,
int nent)
{
struct kvm_cpuid_entry2 *orig;
int i;

/*
* Apply runtime CPUID updates to the incoming CPUID entries to avoid
* false positives due mismatches on KVM-owned feature flags. Note,
* runtime CPUID updates may consume other CPUID-driven vCPU state,
* e.g. KVM or Xen CPUID bases. Updating runtime state before full
* CPUID processing is functionally correct only because any change in
* CPUID is disallowed, i.e. using stale data is ok because the below
* checks will reject the change.
*/
__kvm_update_cpuid_runtime(vcpu, e2, nent);

if (nent != vcpu->arch.cpuid_nent)
return -EINVAL;

Expand Down Expand Up @@ -369,6 +383,8 @@ void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
bitmap_zero(vcpu->arch.governed_features.enabled,
KVM_MAX_NR_GOVERNED_FEATURES);

kvm_update_cpuid_runtime(vcpu);

/*
* If TDP is enabled, let the guest use GBPAGES if they're supported in
* hardware. The hardware page walker doesn't let KVM disable GBPAGES,
Expand Down Expand Up @@ -450,8 +466,6 @@ static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2,
{
int r;

__kvm_update_cpuid_runtime(vcpu, e2, nent);

/*
* KVM does not correctly handle changing guest CPUID after KVM_RUN, as
* MAXPHYADDR, GBPAGES support, AMD reserved bit behavior, etc.. aren't
Expand Down

0 comments on commit ec3d444

Please sign in to comment.