KVM: guest_memfd: Add hook for invalidating memory
In some cases, like with SEV-SNP, guest memory needs to be updated in a platform-specific manner before it can be safely freed back to the host. Wire up arch-defined hooks to the .free_folio kvm_gmem_aops callback to allow for special handling of this sort when freeing memory in response to FALLOC_FL_PUNCH_HOLE operations and when releasing the inode, and go ahead and define an arch-specific hook for x86 since it will be needed for handling memory used for SEV-SNP guests. Signed-off-by: Michael Roth <michael.roth@amd.com> Message-Id: <20231230172351.574091-6-michael.roth@amd.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
1f6c06b177
commit
a90764f0e4
@ -140,6 +140,7 @@ KVM_X86_OP_OPTIONAL_RET0(vcpu_get_apicv_inhibit_reasons);
|
||||
KVM_X86_OP_OPTIONAL(get_untagged_addr)
|
||||
KVM_X86_OP_OPTIONAL(alloc_apic_backing_page)
|
||||
KVM_X86_OP_OPTIONAL_RET0(gmem_prepare)
|
||||
KVM_X86_OP_OPTIONAL(gmem_invalidate)
|
||||
|
||||
#undef KVM_X86_OP
|
||||
#undef KVM_X86_OP_OPTIONAL
|
||||
|
@ -1813,6 +1813,7 @@ struct kvm_x86_ops {
|
||||
gva_t (*get_untagged_addr)(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags);
|
||||
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);
|
||||
};
|
||||
|
||||
struct kvm_x86_nested_ops {
|
||||
|
@ -13605,6 +13605,13 @@ int kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_ord
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HAVE_KVM_GMEM_INVALIDATE
|
||||
void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end)
|
||||
{
|
||||
static_call_cond(kvm_x86_gmem_invalidate)(start, end);
|
||||
}
|
||||
#endif
|
||||
|
||||
int kvm_spec_ctrl_test_value(u64 value)
|
||||
{
|
||||
/*
|
||||
|
@ -2475,4 +2475,8 @@ typedef int (*kvm_gmem_populate_cb)(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
|
||||
long kvm_gmem_populate(struct kvm *kvm, gfn_t gfn, void __user *src, long npages,
|
||||
kvm_gmem_populate_cb post_populate, void *opaque);
|
||||
|
||||
#ifdef CONFIG_HAVE_KVM_GMEM_INVALIDATE
|
||||
void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -113,3 +113,7 @@ config KVM_GENERIC_PRIVATE_MEM
|
||||
config HAVE_KVM_GMEM_PREPARE
|
||||
bool
|
||||
depends on KVM_PRIVATE_MEM
|
||||
|
||||
config HAVE_KVM_GMEM_INVALIDATE
|
||||
bool
|
||||
depends on KVM_PRIVATE_MEM
|
||||
|
@ -343,10 +343,24 @@ static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *fol
|
||||
return MF_DELAYED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_KVM_GMEM_INVALIDATE
|
||||
static void kvm_gmem_free_folio(struct folio *folio)
|
||||
{
|
||||
struct page *page = folio_page(folio, 0);
|
||||
kvm_pfn_t pfn = page_to_pfn(page);
|
||||
int order = folio_order(folio);
|
||||
|
||||
kvm_arch_gmem_invalidate(pfn, pfn + (1ul << order));
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct address_space_operations kvm_gmem_aops = {
|
||||
.dirty_folio = noop_dirty_folio,
|
||||
.migrate_folio = kvm_gmem_migrate_folio,
|
||||
.error_remove_folio = kvm_gmem_error_folio,
|
||||
#ifdef CONFIG_HAVE_KVM_GMEM_INVALIDATE
|
||||
.free_folio = kvm_gmem_free_folio,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int kvm_gmem_getattr(struct mnt_idmap *idmap, const struct path *path,
|
||||
|
Loading…
Reference in New Issue
Block a user