mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:09:29 +02:00
Merge tag 'kvm-x86-coco-7.3' of https://github.com/kvm-x86/linux into HEAD
KVM guest_memfd and x86 CoCo changes for 7.3 - Forcefully invalidate SNP VMSA pages if their backing guest_memfd page is zapped/invalidated, e.g. due to a PUNCH_HOLE in response to a Page-State Change request. - Rework the so called "prepare" and "invalidate" guest_memfd hooks to prepare for in-place private<=>shared conversion, and clean up a few warts along the way.
This commit is contained in:
+5
-1
@@ -107,7 +107,11 @@ config KVM_GUEST_MEMFD
|
||||
select XARRAY_MULTI
|
||||
bool
|
||||
|
||||
config HAVE_KVM_ARCH_GMEM_PREPARE
|
||||
config HAVE_KVM_ARCH_GMEM_CONVERT
|
||||
bool
|
||||
depends on KVM_GUEST_MEMFD
|
||||
|
||||
config HAVE_KVM_ARCH_GMEM_RECLAIM
|
||||
bool
|
||||
depends on KVM_GUEST_MEMFD
|
||||
|
||||
|
||||
+20
-52
@@ -61,52 +61,14 @@ static pgoff_t kvm_gmem_get_index(struct kvm_memory_slot *slot, gfn_t gfn)
|
||||
return gfn - slot->base_gfn + slot->gmem.pgoff;
|
||||
}
|
||||
|
||||
static int __kvm_gmem_prepare_folio(struct kvm *kvm, struct kvm_memory_slot *slot,
|
||||
pgoff_t index, struct folio *folio)
|
||||
static bool kvm_gmem_is_private_mem(struct inode *inode, pgoff_t index)
|
||||
{
|
||||
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE
|
||||
kvm_pfn_t pfn = folio_file_pfn(folio, index);
|
||||
gfn_t gfn = slot->base_gfn + index - slot->gmem.pgoff;
|
||||
int rc = kvm_arch_gmem_prepare(kvm, gfn, pfn, folio_order(folio));
|
||||
if (rc) {
|
||||
pr_warn_ratelimited("gmem: Failed to prepare folio for index %lx GFN %llx PFN %llx error %d.\n",
|
||||
index, gfn, pfn, rc);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return !(GMEM_I(inode)->flags & GUEST_MEMFD_FLAG_INIT_SHARED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process @folio, which contains @gfn, so that the guest can use it.
|
||||
* The folio must be locked and the gfn must be contained in @slot.
|
||||
* On successful return the guest sees a zero page so as to avoid
|
||||
* leaking host data and the up-to-date flag is set.
|
||||
*/
|
||||
static int kvm_gmem_prepare_folio(struct kvm *kvm, struct kvm_memory_slot *slot,
|
||||
gfn_t gfn, struct folio *folio)
|
||||
static bool kvm_gmem_is_shared_mem(struct inode *inode, pgoff_t index)
|
||||
{
|
||||
pgoff_t index;
|
||||
|
||||
/*
|
||||
* Preparing huge folios should always be safe, since it should
|
||||
* be possible to split them later if needed.
|
||||
*
|
||||
* Right now the folio order is always going to be zero, but the
|
||||
* code is ready for huge folios. The only assumption is that
|
||||
* the base pgoff of memslots is naturally aligned with the
|
||||
* requested page order, ensuring that huge folios can also use
|
||||
* huge page table entries for GPA->HPA mapping.
|
||||
*
|
||||
* The order will be passed when creating the guest_memfd, and
|
||||
* checked when creating memslots.
|
||||
*/
|
||||
WARN_ON(!IS_ALIGNED(slot->gmem.pgoff, folio_nr_pages(folio)));
|
||||
index = kvm_gmem_get_index(slot, gfn);
|
||||
index = ALIGN_DOWN(index, folio_nr_pages(folio));
|
||||
|
||||
return __kvm_gmem_prepare_folio(kvm, slot, index, folio);
|
||||
return !kvm_gmem_is_private_mem(inode, index);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -186,6 +148,10 @@ static void __kvm_gmem_invalidate_start(struct gmem_file *f, pgoff_t start,
|
||||
}
|
||||
|
||||
flush |= kvm_mmu_unmap_gfn_range(kvm, &gfn_range);
|
||||
|
||||
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
|
||||
kvm_arch_gmem_invalidate_range(kvm, &gfn_range);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (flush)
|
||||
@@ -398,7 +364,7 @@ static vm_fault_t kvm_gmem_fault_user_mapping(struct vm_fault *vmf)
|
||||
if (((loff_t)vmf->pgoff << PAGE_SHIFT) >= i_size_read(inode))
|
||||
return VM_FAULT_SIGBUS;
|
||||
|
||||
if (!(GMEM_I(inode)->flags & GUEST_MEMFD_FLAG_INIT_SHARED))
|
||||
if (!kvm_gmem_is_shared_mem(inode, vmf->pgoff))
|
||||
return VM_FAULT_SIGBUS;
|
||||
|
||||
folio = kvm_gmem_get_folio(inode, vmf->pgoff);
|
||||
@@ -524,14 +490,10 @@ static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *fol
|
||||
return MF_DELAYED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
|
||||
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM
|
||||
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));
|
||||
kvm_arch_gmem_reclaim(folio_file_pfn(folio, 0), folio_nr_pages(folio));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -539,7 +501,7 @@ 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_ARCH_GMEM_INVALIDATE
|
||||
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM
|
||||
.free_folio = kvm_gmem_free_folio,
|
||||
#endif
|
||||
};
|
||||
@@ -794,7 +756,9 @@ int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
|
||||
{
|
||||
pgoff_t index = kvm_gmem_get_index(slot, gfn);
|
||||
struct folio *folio;
|
||||
int r = 0;
|
||||
int r = 0, __order;
|
||||
|
||||
max_order = max_order ?: &__order;
|
||||
|
||||
CLASS(gmem_get_file, file)(slot);
|
||||
if (!file)
|
||||
@@ -809,7 +773,11 @@ int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
|
||||
folio_mark_uptodate(folio);
|
||||
}
|
||||
|
||||
r = kvm_gmem_prepare_folio(kvm, slot, gfn, folio);
|
||||
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT
|
||||
if (kvm_gmem_is_private_mem(file_inode(file), index))
|
||||
r = kvm_arch_gmem_make_private(kvm, gfn, *pfn,
|
||||
(kvm_pfn_t)1 << *max_order);
|
||||
#endif
|
||||
|
||||
folio_unlock(folio);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user