On Tue, 29 Jul 2025 at 23:55, Sean Christopherson <seanjc@xxxxxxxxxx> wrote: > > Rework kvm_mmu_max_mapping_level() to consult guest_memfd for all mappings, > not just private mappings, so that hugepage support plays nice with the > upcoming support for backing non-private memory with guest_memfd. > > In addition to getting the max order from guest_memfd for gmem-only > memslots, update TDX's hook to effectively ignore shared mappings, as TDX's > restrictions on page size only apply to Secure EPT mappings. Do nothing > for SNP, as RMP restrictions apply to both private and shared memory. > > Suggested-by: Ackerley Tng <ackerleytng@xxxxxxxxxx> > Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> > --- Reviewed-by: Fuad Tabba <tabba@xxxxxxxxxx> Cheers, /fuad > arch/x86/include/asm/kvm_host.h | 2 +- > arch/x86/kvm/mmu/mmu.c | 12 +++++++----- > arch/x86/kvm/svm/sev.c | 2 +- > arch/x86/kvm/svm/svm.h | 4 ++-- > arch/x86/kvm/vmx/main.c | 5 +++-- > arch/x86/kvm/vmx/tdx.c | 5 ++++- > arch/x86/kvm/vmx/x86_ops.h | 2 +- > 7 files changed, 19 insertions(+), 13 deletions(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index c0a739bf3829..c56cc54d682a 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -1922,7 +1922,7 @@ struct kvm_x86_ops { > void *(*alloc_apic_backing_page)(struct kvm_vcpu *vcpu); > int (*gmem_prepare)(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order); > void (*gmem_invalidate)(kvm_pfn_t start, kvm_pfn_t end); > - int (*gmem_max_mapping_level)(struct kvm *kvm, kvm_pfn_t pfn); > + int (*gmem_max_mapping_level)(struct kvm *kvm, kvm_pfn_t pfn, bool is_private); > }; > > struct kvm_x86_nested_ops { > diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c > index 61eb9f723675..e83d666f32ad 100644 > --- a/arch/x86/kvm/mmu/mmu.c > +++ b/arch/x86/kvm/mmu/mmu.c > @@ -3302,8 +3302,9 @@ static u8 kvm_max_level_for_order(int order) > return PG_LEVEL_4K; > } > > -static u8 kvm_max_private_mapping_level(struct kvm *kvm, struct kvm_page_fault *fault, > - const struct kvm_memory_slot *slot, gfn_t gfn) > +static u8 kvm_gmem_max_mapping_level(struct kvm *kvm, struct kvm_page_fault *fault, > + const struct kvm_memory_slot *slot, gfn_t gfn, > + bool is_private) > { > u8 max_level, coco_level; > kvm_pfn_t pfn; > @@ -3327,7 +3328,7 @@ static u8 kvm_max_private_mapping_level(struct kvm *kvm, struct kvm_page_fault * > * restrictions. A return of '0' means "no additional restrictions", to > * allow for using an optional "ret0" static call. > */ > - coco_level = kvm_x86_call(gmem_max_mapping_level)(kvm, pfn); > + coco_level = kvm_x86_call(gmem_max_mapping_level)(kvm, pfn, is_private); > if (coco_level) > max_level = min(max_level, coco_level); > > @@ -3361,8 +3362,9 @@ int kvm_mmu_max_mapping_level(struct kvm *kvm, struct kvm_page_fault *fault, > if (max_level == PG_LEVEL_4K) > return PG_LEVEL_4K; > > - if (is_private) > - host_level = kvm_max_private_mapping_level(kvm, fault, slot, gfn); > + if (is_private || kvm_memslot_is_gmem_only(slot)) > + host_level = kvm_gmem_max_mapping_level(kvm, fault, slot, gfn, > + is_private); > else > host_level = host_pfn_mapping_level(kvm, gfn, slot); > return min(host_level, max_level); > diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c > index be1c80d79331..807d4b70327a 100644 > --- a/arch/x86/kvm/svm/sev.c > +++ b/arch/x86/kvm/svm/sev.c > @@ -4947,7 +4947,7 @@ void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end) > } > } > > -int sev_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn) > +int sev_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn, bool is_private) > { > int level, rc; > bool assigned; > diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h > index d84a83ae18a1..70df7c6413cf 100644 > --- a/arch/x86/kvm/svm/svm.h > +++ b/arch/x86/kvm/svm/svm.h > @@ -866,7 +866,7 @@ void sev_handle_rmp_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code); > void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu); > int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order); > void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end); > -int sev_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn); > +int sev_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn, bool is_private); > struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu); > void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa); > #else > @@ -895,7 +895,7 @@ static inline int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, in > return 0; > } > static inline void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end) {} > -static inline int sev_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn) > +static inline int sev_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn, bool is_private) > { > return 0; > } > diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c > index dd7687ef7e2d..bb5f182f6788 100644 > --- a/arch/x86/kvm/vmx/main.c > +++ b/arch/x86/kvm/vmx/main.c > @@ -831,10 +831,11 @@ static int vt_vcpu_mem_enc_ioctl(struct kvm_vcpu *vcpu, void __user *argp) > return tdx_vcpu_ioctl(vcpu, argp); > } > > -static int vt_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn) > +static int vt_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn, > + bool is_private) > { > if (is_td(kvm)) > - return tdx_gmem_max_mapping_level(kvm, pfn); > + return tdx_gmem_max_mapping_level(kvm, pfn, is_private); > > return 0; > } > diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c > index b444714e8e8a..ca9c8ec7dd01 100644 > --- a/arch/x86/kvm/vmx/tdx.c > +++ b/arch/x86/kvm/vmx/tdx.c > @@ -3318,8 +3318,11 @@ int tdx_vcpu_ioctl(struct kvm_vcpu *vcpu, void __user *argp) > return ret; > } > > -int tdx_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn) > +int tdx_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn, bool is_private) > { > + if (!is_private) > + return 0; > + > return PG_LEVEL_4K; > } > > diff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h > index 6037d1708485..4c70f56c57c8 100644 > --- a/arch/x86/kvm/vmx/x86_ops.h > +++ b/arch/x86/kvm/vmx/x86_ops.h > @@ -153,7 +153,7 @@ int tdx_vcpu_ioctl(struct kvm_vcpu *vcpu, void __user *argp); > void tdx_flush_tlb_current(struct kvm_vcpu *vcpu); > void tdx_flush_tlb_all(struct kvm_vcpu *vcpu); > void tdx_load_mmu_pgd(struct kvm_vcpu *vcpu, hpa_t root_hpa, int root_level); > -int tdx_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn); > +int tdx_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn, bool is_private); > #endif > > #endif /* __KVM_X86_VMX_X86_OPS_H */ > -- > 2.50.1.552.g942d659e1b-goog >