]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: x86/mmu: Extend guest_memfd's max mapping level to shared mappings
authorSean Christopherson <seanjc@google.com>
Tue, 29 Jul 2025 22:54:46 +0000 (15:54 -0700)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 27 Aug 2025 08:35:01 +0000 (04:35 -0400)
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@google.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
Message-ID: <20250729225455.670324-16-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/svm/sev.c
arch/x86/kvm/svm/svm.h
arch/x86/kvm/vmx/main.c
arch/x86/kvm/vmx/tdx.c
arch/x86/kvm/vmx/x86_ops.h

index c0a739bf38296326b4cf883ae122b40a681ef6b0..c56cc54d682a6038f688124cf5e71049767f51c5 100644 (file)
@@ -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 {
index 61eb9f723675a73f0774964c99ab400877f26e33..e83d666f32ad52ed06bf62c6d7ee1f9f8f6ad5e2 100644 (file)
@@ -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);
index b926a053b8cfb2f399ffe906f2295ad692cfba52..5bac4d20aec04203429e55a130623eb7b6ebf50f 100644 (file)
@@ -4943,7 +4943,7 @@ next_pfn:
        }
 }
 
-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;
index d84a83ae18a1ff99e4bdc7fde9bd18781e59f755..70df7c6413cf9b671ee31f86e0aad142dfb7d31a 100644 (file)
@@ -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;
 }
index dd7687ef7e2d8560fef5d6fef521352b4177012b..bb5f182f67884a726883fa7fa7c060d865f07f2f 100644 (file)
@@ -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;
 }
index b444714e8e8aa50e77ba68c31a8939b7d749b985..ca9c8ec7dd01a3c1faebfe618a1a203c56d11bc5 100644 (file)
@@ -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;
 }
 
index 6037d17084856c99aadff7ad4a7e397a36168aa7..4c70f56c57c8d71e78f9d8b28ed3b12100028116 100644 (file)
@@ -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 */