Skip to content

Commit d468d94

Browse files
Sean Christophersonbonzini
authored andcommitted
KVM: x86: Dynamically calculate TDP level from max level and MAXPHYADDR
Calculate the desired TDP level on the fly using the max TDP level and MAXPHYADDR instead of doing the same when CPUID is updated. This avoids the hidden dependency on cpuid_maxphyaddr() in vmx_get_tdp_level() and also standardizes the "use 5-level paging iff MAXPHYADDR > 48" behavior across x86. Suggested-by: Paolo Bonzini <[email protected]> Signed-off-by: Sean Christopherson <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent f83a4a6 commit d468d94

File tree

6 files changed

+21
-14
lines changed

6 files changed

+21
-14
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ struct kvm_vcpu_arch {
639639
struct kvm_cpuid_entry2 cpuid_entries[KVM_MAX_CPUID_ENTRIES];
640640

641641
int maxphyaddr;
642-
int tdp_level;
642+
int max_tdp_level;
643643

644644
/* emulate context */
645645

@@ -1133,7 +1133,7 @@ struct kvm_x86_ops {
11331133
int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu);
11341134
int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
11351135
int (*set_identity_map_addr)(struct kvm *kvm, u64 ident_addr);
1136-
int (*get_tdp_level)(struct kvm_vcpu *vcpu);
1136+
int (*get_max_tdp_level)(void);
11371137
u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio);
11381138

11391139
void (*load_mmu_pgd)(struct kvm_vcpu *vcpu, unsigned long pgd,

arch/x86/kvm/cpuid.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,7 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
140140
vcpu->arch.guest_supported_xcr0 =
141141
(best->eax | ((u64)best->edx << 32)) & supported_xcr0;
142142

143-
/* Note, maxphyaddr must be updated before tdp_level. */
144143
vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
145-
vcpu->arch.tdp_level = kvm_x86_ops.get_tdp_level(vcpu);
146144
kvm_mmu_reset_context(vcpu);
147145

148146
kvm_pmu_refresh(vcpu);

arch/x86/kvm/mmu/mmu.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4846,13 +4846,22 @@ static union kvm_mmu_role kvm_calc_mmu_role_common(struct kvm_vcpu *vcpu,
48464846
return role;
48474847
}
48484848

4849+
static inline int kvm_mmu_get_tdp_level(struct kvm_vcpu *vcpu)
4850+
{
4851+
/* Use 5-level TDP if and only if it's useful/necessary. */
4852+
if (vcpu->arch.max_tdp_level == 5 && cpuid_maxphyaddr(vcpu) <= 48)
4853+
return 4;
4854+
4855+
return vcpu->arch.max_tdp_level;
4856+
}
4857+
48494858
static union kvm_mmu_role
48504859
kvm_calc_tdp_mmu_root_page_role(struct kvm_vcpu *vcpu, bool base_only)
48514860
{
48524861
union kvm_mmu_role role = kvm_calc_mmu_role_common(vcpu, base_only);
48534862

48544863
role.base.ad_disabled = (shadow_accessed_mask == 0);
4855-
role.base.level = vcpu->arch.tdp_level;
4864+
role.base.level = kvm_mmu_get_tdp_level(vcpu);
48564865
role.base.direct = true;
48574866
role.base.gpte_is_8_bytes = true;
48584867

@@ -4873,7 +4882,7 @@ static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
48734882
context->sync_page = nonpaging_sync_page;
48744883
context->invlpg = NULL;
48754884
context->update_pte = nonpaging_update_pte;
4876-
context->shadow_root_level = vcpu->arch.tdp_level;
4885+
context->shadow_root_level = kvm_mmu_get_tdp_level(vcpu);
48774886
context->direct_map = true;
48784887
context->get_guest_pgd = get_cr3;
48794888
context->get_pdptr = kvm_pdptr_read;
@@ -4973,7 +4982,7 @@ kvm_calc_shadow_npt_root_page_role(struct kvm_vcpu *vcpu)
49734982
kvm_calc_shadow_root_page_role_common(vcpu, false);
49744983

49754984
role.base.direct = false;
4976-
role.base.level = vcpu->arch.tdp_level;
4985+
role.base.level = kvm_mmu_get_tdp_level(vcpu);
49774986

49784987
return role;
49794988
}
@@ -5683,7 +5692,7 @@ static int alloc_mmu_pages(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu)
56835692
* SVM's 32-bit NPT support, TDP paging doesn't use PAE paging and can
56845693
* skip allocating the PDP table.
56855694
*/
5686-
if (tdp_enabled && vcpu->arch.tdp_level > PT32E_ROOT_LEVEL)
5695+
if (tdp_enabled && kvm_mmu_get_tdp_level(vcpu) > PT32E_ROOT_LEVEL)
56875696
return 0;
56885697

56895698
page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_DMA32);

arch/x86/kvm/svm/svm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ static inline void invlpga(unsigned long addr, u32 asid)
254254
asm volatile (__ex("invlpga %1, %0") : : "c"(asid), "a"(addr));
255255
}
256256

257-
static int get_npt_level(struct kvm_vcpu *vcpu)
257+
static int get_max_npt_level(void)
258258
{
259259
#ifdef CONFIG_X86_64
260260
return PT64_ROOT_4LEVEL;
@@ -4109,7 +4109,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
41094109

41104110
.set_tss_addr = svm_set_tss_addr,
41114111
.set_identity_map_addr = svm_set_identity_map_addr,
4112-
.get_tdp_level = get_npt_level,
4112+
.get_max_tdp_level = get_max_npt_level,
41134113
.get_mt_mask = svm_get_mt_mask,
41144114

41154115
.get_exit_info = svm_get_exit_info,

arch/x86/kvm/vmx/vmx.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3065,9 +3065,9 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
30653065
vmx->emulation_required = emulation_required(vcpu);
30663066
}
30673067

3068-
static int vmx_get_tdp_level(struct kvm_vcpu *vcpu)
3068+
static int vmx_get_max_tdp_level(void)
30693069
{
3070-
if (cpu_has_vmx_ept_5levels() && (cpuid_maxphyaddr(vcpu) > 48))
3070+
if (cpu_has_vmx_ept_5levels())
30713071
return 5;
30723072
return 4;
30733073
}
@@ -7959,7 +7959,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
79597959

79607960
.set_tss_addr = vmx_set_tss_addr,
79617961
.set_identity_map_addr = vmx_set_identity_map_addr,
7962-
.get_tdp_level = vmx_get_tdp_level,
7962+
.get_max_tdp_level = vmx_get_max_tdp_level,
79637963
.get_mt_mask = vmx_get_mt_mask,
79647964

79657965
.get_exit_info = vmx_get_exit_info,

arch/x86/kvm/x86.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9520,7 +9520,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
95209520
fx_init(vcpu);
95219521

95229522
vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
9523-
vcpu->arch.tdp_level = kvm_x86_ops.get_tdp_level(vcpu);
9523+
vcpu->arch.max_tdp_level = kvm_x86_ops.get_max_tdp_level();
95249524

95259525
vcpu->arch.pat = MSR_IA32_CR_PAT_DEFAULT;
95269526

0 commit comments

Comments
 (0)