Skip to content

Commit

Permalink
KVM: x86/mmu: Use KVM-governed feature framework to track "GBPAGES en…
Browse files Browse the repository at this point in the history
…abled"

Use the governed feature framework to track whether or not the guest can
use 1GiB pages, and drop the one-off helper that wraps the surprisingly
non-trivial logic surrounding 1GiB page usage in the guest.

No functional change intended.

Reviewed-by: Yuan Yao <yuan.yao@intel.com>
Link: https://lore.kernel.org/r/20230815203653.519297-3-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
  • Loading branch information
sean-jc committed Aug 17, 2023
1 parent 4276441 commit ccf31d6
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 17 deletions.
17 changes: 17 additions & 0 deletions arch/x86/kvm/cpuid.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,11 +312,28 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
{
struct kvm_lapic *apic = vcpu->arch.apic;
struct kvm_cpuid_entry2 *best;
bool allow_gbpages;

BUILD_BUG_ON(KVM_NR_GOVERNED_FEATURES > KVM_MAX_NR_GOVERNED_FEATURES);
bitmap_zero(vcpu->arch.governed_features.enabled,
KVM_MAX_NR_GOVERNED_FEATURES);

/*
* 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,
* i.e. won't treat them as reserved, and KVM doesn't redo the GVA->GPA
* walk for performance and complexity reasons. Not to mention KVM
* _can't_ solve the problem because GVA->GPA walks aren't visible to
* KVM once a TDP translation is installed. Mimic hardware behavior so
* that KVM's is at least consistent, i.e. doesn't randomly inject #PF.
* If TDP is disabled, honor *only* guest CPUID as KVM has full control
* and can install smaller shadow pages if the host lacks 1GiB support.
*/
allow_gbpages = tdp_enabled ? boot_cpu_has(X86_FEATURE_GBPAGES) :
guest_cpuid_has(vcpu, X86_FEATURE_GBPAGES);
if (allow_gbpages)
kvm_governed_feature_set(vcpu, X86_FEATURE_GBPAGES);

best = kvm_find_cpuid_entry(vcpu, 1);
if (best && apic) {
if (cpuid_entry_has(best, X86_FEATURE_TSC_DEADLINE_TIMER))
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/kvm/governed_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ BUILD_BUG()

#define KVM_GOVERNED_X86_FEATURE(x) KVM_GOVERNED_FEATURE(X86_FEATURE_##x)

KVM_GOVERNED_X86_FEATURE(GBPAGES)

#undef KVM_GOVERNED_X86_FEATURE
#undef KVM_GOVERNED_FEATURE
20 changes: 3 additions & 17 deletions arch/x86/kvm/mmu/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -4808,28 +4808,13 @@ static void __reset_rsvds_bits_mask(struct rsvd_bits_validate *rsvd_check,
}
}

static bool guest_can_use_gbpages(struct kvm_vcpu *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,
* i.e. won't treat them as reserved, and KVM doesn't redo the GVA->GPA
* walk for performance and complexity reasons. Not to mention KVM
* _can't_ solve the problem because GVA->GPA walks aren't visible to
* KVM once a TDP translation is installed. Mimic hardware behavior so
* that KVM's is at least consistent, i.e. doesn't randomly inject #PF.
*/
return tdp_enabled ? boot_cpu_has(X86_FEATURE_GBPAGES) :
guest_cpuid_has(vcpu, X86_FEATURE_GBPAGES);
}

static void reset_guest_rsvds_bits_mask(struct kvm_vcpu *vcpu,
struct kvm_mmu *context)
{
__reset_rsvds_bits_mask(&context->guest_rsvd_check,
vcpu->arch.reserved_gpa_bits,
context->cpu_role.base.level, is_efer_nx(context),
guest_can_use_gbpages(vcpu),
guest_can_use(vcpu, X86_FEATURE_GBPAGES),
is_cr4_pse(context),
guest_cpuid_is_amd_or_hygon(vcpu));
}
Expand Down Expand Up @@ -4906,7 +4891,8 @@ static void reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu,
__reset_rsvds_bits_mask(shadow_zero_check, reserved_hpa_bits(),
context->root_role.level,
context->root_role.efer_nx,
guest_can_use_gbpages(vcpu), is_pse, is_amd);
guest_can_use(vcpu, X86_FEATURE_GBPAGES),
is_pse, is_amd);

if (!shadow_me_mask)
return;
Expand Down

0 comments on commit ccf31d6

Please sign in to comment.