Commit b7d97f69 authored by Sean Christopherson's avatar Sean Christopherson Committed by Paolo Bonzini
Browse files

KVM: x86/mmu: Extend guest_memfd's max mapping level to shared mappings



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: default avatarAckerley Tng <ackerleytng@google.com>
Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
Reviewed-by: default avatarDavid Hildenbrand <david@redhat.com>
Reviewed-by: default avatarFuad Tabba <tabba@google.com>
Reviewed-by: default avatarXiaoyao Li <xiaoyao.li@intel.com>
Message-ID: <20250729225455.670324-16-seanjc@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent a3522ac7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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 {
+7 −5
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -4943,7 +4943,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;
+2 −2
Original line number Diff line number Diff line
@@ -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;
}
+3 −2
Original line number Diff line number Diff line
@@ -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;
}
Loading