From: Ackerley Tng <ackerleytng@google.com>
To: tabba@google.com, quic_eberman@quicinc.com, roypat@amazon.co.uk,
jgg@nvidia.com, peterx@redhat.com, david@redhat.com,
rientjes@google.com, fvdl@google.com, jthoughton@google.com,
seanjc@google.com, pbonzini@redhat.com, zhiquan1.li@intel.com,
fan.du@intel.com, jun.miao@intel.com, isaku.yamahata@intel.com,
muchun.song@linux.dev, mike.kravetz@oracle.com
Cc: erdemaktas@google.com, vannapurve@google.com,
ackerleytng@google.com, qperret@google.com, jhubbard@nvidia.com,
willy@infradead.org, shuah@kernel.org, brauner@kernel.org,
bfoster@redhat.com, kent.overstreet@linux.dev, pvorel@suse.cz,
rppt@kernel.org, richard.weiyang@gmail.com, anup@brainfault.org,
haibo1.xu@intel.com, ajones@ventanamicro.com,
vkuznets@redhat.com, maciej.wieczor-retman@intel.com,
pgonda@google.com, oliver.upton@linux.dev,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
kvm@vger.kernel.org, linux-kselftest@vger.kernel.org,
linux-fsdevel@kvack.org
Subject: [RFC PATCH 30/39] KVM: guest_memfd: Handle folio preparation for guest_memfd mmap
Date: Tue, 10 Sep 2024 23:44:01 +0000 [thread overview]
Message-ID: <24cf7a9b1ee499c4ca4da76e9945429072014d1e.1726009989.git.ackerleytng@google.com> (raw)
In-Reply-To: <cover.1726009989.git.ackerleytng@google.com>
Since guest_memfd now supports mmap(), folios have to be prepared
before they are faulted into userspace.
When memory attributes are switched between shared and private, the
up-to-date flags will be cleared.
Use the folio's up-to-date flag to indicate being ready for the guest
usage and can be used to mark whether the folio is ready for shared OR
private use.
Signed-off-by: Ackerley Tng <ackerleytng@google.com>
---
virt/kvm/guest_memfd.c | 131 ++++++++++++++++++++++++++++++++++++++++-
virt/kvm/kvm_main.c | 2 +
virt/kvm/kvm_mm.h | 7 +++
3 files changed, 139 insertions(+), 1 deletion(-)
diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index 110c4bbb004b..fb292e542381 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -129,13 +129,29 @@ static int __kvm_gmem_prepare_folio(struct kvm *kvm, struct kvm_memory_slot *slo
}
/**
- * Use the uptodate flag to indicate that the folio is prepared for KVM's usage.
+ * Use folio's up-to-date flag to indicate that this folio is prepared for usage
+ * by the guest.
+ *
+ * This flag can be used whether the folio is prepared for PRIVATE or SHARED
+ * usage.
*/
static inline void kvm_gmem_mark_prepared(struct folio *folio)
{
folio_mark_uptodate(folio);
}
+/**
+ * Use folio's up-to-date flag to indicate that this folio is not yet prepared for
+ * usage by the guest.
+ *
+ * This flag can be used whether the folio is prepared for PRIVATE or SHARED
+ * usage.
+ */
+static inline void kvm_gmem_clear_prepared(struct folio *folio)
+{
+ folio_clear_uptodate(folio);
+}
+
/*
* 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.
@@ -148,6 +164,12 @@ static int kvm_gmem_prepare_folio(struct kvm *kvm, struct kvm_memory_slot *slot,
pgoff_t index;
int r;
+ /*
+ * Defensively zero folio to avoid leaking kernel memory in
+ * uninitialized pages. This is important since pages can now be mapped
+ * into userspace, where hardware (e.g. TDX) won't be clearing those
+ * pages.
+ */
if (folio_test_hugetlb(folio)) {
folio_zero_user(folio, folio->index << PAGE_SHIFT);
} else {
@@ -1017,6 +1039,7 @@ static vm_fault_t kvm_gmem_fault(struct vm_fault *vmf)
{
struct inode *inode;
struct folio *folio;
+ bool is_prepared;
inode = file_inode(vmf->vma->vm_file);
if (!kvm_gmem_is_faultable(inode, vmf->pgoff))
@@ -1026,6 +1049,31 @@ static vm_fault_t kvm_gmem_fault(struct vm_fault *vmf)
if (!folio)
return VM_FAULT_SIGBUS;
+ is_prepared = folio_test_uptodate(folio);
+ if (!is_prepared) {
+ unsigned long nr_pages;
+ unsigned long i;
+
+ if (folio_test_hugetlb(folio)) {
+ folio_zero_user(folio, folio->index << PAGE_SHIFT);
+ } else {
+ /*
+ * Defensively zero folio to avoid leaking kernel memory in
+ * uninitialized pages. This is important since pages can now be
+ * mapped into userspace, where hardware (e.g. TDX) won't be
+ * clearing those pages.
+ *
+ * Will probably need a version of kvm_gmem_prepare_folio() to
+ * prepare the page for SHARED use.
+ */
+ nr_pages = folio_nr_pages(folio);
+ for (i = 0; i < nr_pages; i++)
+ clear_highpage(folio_page(folio, i));
+ }
+
+ kvm_gmem_mark_prepared(folio);
+ }
+
vmf->page = folio_file_page(folio, vmf->pgoff);
return VM_FAULT_LOCKED;
}
@@ -1593,6 +1641,87 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long
}
EXPORT_SYMBOL_GPL(kvm_gmem_populate);
+static void kvm_gmem_clear_prepared_range(struct inode *inode, pgoff_t start,
+ pgoff_t end)
+{
+ pgoff_t index;
+
+ filemap_invalidate_lock_shared(inode->i_mapping);
+
+ /* TODO: replace iteration with filemap_get_folios() for efficiency. */
+ for (index = start; index < end;) {
+ struct folio *folio;
+
+ /* Don't use kvm_gmem_get_folio to avoid allocating */
+ folio = filemap_lock_folio(inode->i_mapping, index);
+ if (IS_ERR(folio)) {
+ ++index;
+ continue;
+ }
+
+ kvm_gmem_clear_prepared(folio);
+
+ index = folio_next_index(folio);
+ folio_unlock(folio);
+ folio_put(folio);
+ }
+
+ filemap_invalidate_unlock_shared(inode->i_mapping);
+}
+
+/**
+ * Clear the prepared flag for all folios in gfn range [@start, @end) in memslot
+ * @slot.
+ */
+static void kvm_gmem_clear_prepared_slot(struct kvm_memory_slot *slot, gfn_t start,
+ gfn_t end)
+{
+ pgoff_t start_offset;
+ pgoff_t end_offset;
+ struct file *file;
+
+ file = kvm_gmem_get_file(slot);
+ if (!file)
+ return;
+
+ start_offset = start - slot->base_gfn + slot->gmem.pgoff;
+ end_offset = end - slot->base_gfn + slot->gmem.pgoff;
+
+ kvm_gmem_clear_prepared_range(file_inode(file), start_offset, end_offset);
+
+ fput(file);
+}
+
+/**
+ * Clear the prepared flag for all folios for any slot in gfn range
+ * [@start, @end) in @kvm.
+ */
+void kvm_gmem_clear_prepared_vm(struct kvm *kvm, gfn_t start, gfn_t end)
+{
+ int i;
+
+ lockdep_assert_held(&kvm->slots_lock);
+
+ for (i = 0; i < kvm_arch_nr_memslot_as_ids(kvm); i++) {
+ struct kvm_memslot_iter iter;
+ struct kvm_memslots *slots;
+
+ slots = __kvm_memslots(kvm, i);
+ kvm_for_each_memslot_in_gfn_range(&iter, slots, start, end) {
+ struct kvm_memory_slot *slot;
+ gfn_t gfn_start;
+ gfn_t gfn_end;
+
+ slot = iter.slot;
+ gfn_start = max(start, slot->base_gfn);
+ gfn_end = min(end, slot->base_gfn + slot->npages);
+
+ if (iter.slot->flags & KVM_MEM_GUEST_MEMFD)
+ kvm_gmem_clear_prepared_slot(iter.slot, gfn_start, gfn_end);
+ }
+ }
+}
+
/**
* Returns true if pages in range [@start, @end) in inode @inode have no
* userspace mappings.
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 1a7bbcc31b7e..255d27df7f5c 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2565,6 +2565,8 @@ static int kvm_vm_set_mem_attributes(struct kvm *kvm, gfn_t start, gfn_t end,
KVM_BUG_ON(r, kvm);
}
+ kvm_gmem_clear_prepared_vm(kvm, start, end);
+
kvm_handle_gfn_range(kvm, &post_set_range);
out_unlock:
diff --git a/virt/kvm/kvm_mm.h b/virt/kvm/kvm_mm.h
index d8ff2b380d0e..25fd0d9f66cc 100644
--- a/virt/kvm/kvm_mm.h
+++ b/virt/kvm/kvm_mm.h
@@ -43,6 +43,7 @@ int kvm_gmem_bind(struct kvm *kvm, struct kvm_memory_slot *slot,
void kvm_gmem_unbind(struct kvm_memory_slot *slot);
int kvm_gmem_should_set_attributes(struct kvm *kvm, gfn_t start, gfn_t end,
unsigned long attrs);
+void kvm_gmem_clear_prepared_vm(struct kvm *kvm, gfn_t start, gfn_t end);
#else
static inline void kvm_gmem_init(struct module *module)
{
@@ -68,6 +69,12 @@ static inline int kvm_gmem_should_set_attributes(struct kvm *kvm, gfn_t start,
return 0;
}
+static inline void kvm_gmem_clear_prepared_slots(struct kvm *kvm,
+ gfn_t start, gfn_t end)
+{
+ WARN_ON_ONCE(1);
+}
+
#endif /* CONFIG_KVM_PRIVATE_MEM */
#endif /* __KVM_MM_H__ */
--
2.46.0.598.g6f2099f65c-goog
next prev parent reply other threads:[~2024-09-10 23:46 UTC|newest]
Thread overview: 130+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-10 23:43 [RFC PATCH 00/39] 1G page support for guest_memfd Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 01/39] mm: hugetlb: Simplify logic in dequeue_hugetlb_folio_vma() Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 02/39] mm: hugetlb: Refactor vma_has_reserves() to should_use_hstate_resv() Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 03/39] mm: hugetlb: Remove unnecessary check for avoid_reserve Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 04/39] mm: mempolicy: Refactor out policy_node_nodemask() Ackerley Tng
2024-09-11 16:46 ` Gregory Price
2024-09-10 23:43 ` [RFC PATCH 05/39] mm: hugetlb: Refactor alloc_buddy_hugetlb_folio_with_mpol() to interpret mempolicy instead of vma Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 06/39] mm: hugetlb: Refactor dequeue_hugetlb_folio_vma() to use mpol Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 07/39] mm: hugetlb: Refactor out hugetlb_alloc_folio Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 08/39] mm: truncate: Expose preparation steps for truncate_inode_pages_final Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 09/39] mm: hugetlb: Expose hugetlb_subpool_{get,put}_pages() Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 10/39] mm: hugetlb: Add option to create new subpool without using surplus Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 11/39] mm: hugetlb: Expose hugetlb_acct_memory() Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 12/39] mm: hugetlb: Move and expose hugetlb_zero_partial_page() Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 13/39] KVM: guest_memfd: Make guest mem use guest mem inodes instead of anonymous inodes Ackerley Tng
2025-04-02 4:01 ` Yan Zhao
2025-04-23 20:22 ` Ackerley Tng
2025-04-24 3:53 ` Yan Zhao
2024-09-10 23:43 ` [RFC PATCH 14/39] KVM: guest_memfd: hugetlb: initialization and cleanup Ackerley Tng
2024-09-20 9:17 ` Vishal Annapurve
2024-10-01 23:00 ` Ackerley Tng
2024-12-01 17:59 ` Peter Xu
2025-02-13 9:47 ` Ackerley Tng
2025-02-26 18:55 ` Ackerley Tng
2025-03-06 17:33 ` Peter Xu
2024-09-10 23:43 ` [RFC PATCH 15/39] KVM: guest_memfd: hugetlb: allocate and truncate from hugetlb Ackerley Tng
2024-09-13 22:26 ` Elliot Berman
2024-10-03 20:23 ` Ackerley Tng
2024-10-30 9:01 ` Jun Miao
2025-02-11 1:21 ` Ackerley Tng
2024-12-01 17:55 ` Peter Xu
2025-02-13 7:52 ` Ackerley Tng
2025-02-13 16:48 ` Peter Xu
2024-09-10 23:43 ` [RFC PATCH 16/39] KVM: guest_memfd: Add page alignment check for hugetlb guest_memfd Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 17/39] KVM: selftests: Add basic selftests for hugetlb-backed guest_memfd Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 18/39] KVM: selftests: Support various types of backing sources for private memory Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 19/39] KVM: selftests: Update test for various private memory backing source types Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 20/39] KVM: selftests: Add private_mem_conversions_test.sh Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 21/39] KVM: selftests: Test that guest_memfd usage is reported via hugetlb Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 22/39] mm: hugetlb: Expose vmemmap optimization functions Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 23/39] mm: hugetlb: Expose HugeTLB functions for promoting/demoting pages Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 24/39] mm: hugetlb: Add functions to add/move/remove from hugetlb lists Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 25/39] KVM: guest_memfd: Split HugeTLB pages for guest_memfd use Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 26/39] KVM: guest_memfd: Track faultability within a struct kvm_gmem_private Ackerley Tng
2024-10-10 16:06 ` Peter Xu
2024-10-11 23:32 ` Ackerley Tng
2024-10-15 21:34 ` Peter Xu
2024-10-15 23:42 ` Ackerley Tng
2024-10-16 8:45 ` David Hildenbrand
2024-10-16 20:16 ` Peter Xu
2024-10-16 22:51 ` Jason Gunthorpe
2024-10-16 23:49 ` Peter Xu
2024-10-16 23:54 ` Jason Gunthorpe
2024-10-17 14:58 ` Peter Xu
2024-10-17 16:47 ` Jason Gunthorpe
2024-10-17 17:05 ` Peter Xu
2024-10-17 17:10 ` Jason Gunthorpe
2024-10-17 19:11 ` Peter Xu
2024-10-17 19:18 ` Jason Gunthorpe
2024-10-17 19:29 ` David Hildenbrand
2024-10-18 7:15 ` Patrick Roy
2024-10-18 7:50 ` David Hildenbrand
2024-10-18 9:34 ` Patrick Roy
2024-10-17 17:11 ` David Hildenbrand
2024-10-17 17:16 ` Jason Gunthorpe
2024-10-17 17:55 ` David Hildenbrand
2024-10-17 18:26 ` Vishal Annapurve
2024-10-17 14:56 ` David Hildenbrand
2024-10-17 15:02 ` David Hildenbrand
2024-10-16 8:50 ` David Hildenbrand
2024-10-16 10:48 ` Vishal Annapurve
2024-10-16 11:54 ` David Hildenbrand
2024-10-16 11:57 ` Jason Gunthorpe
2025-02-25 20:37 ` Peter Xu
2025-04-23 22:07 ` Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 27/39] KVM: guest_memfd: Allow mmapping guest_memfd files Ackerley Tng
2025-01-20 22:42 ` Peter Xu
2025-04-23 20:25 ` Ackerley Tng
2025-03-04 23:24 ` Peter Xu
2025-04-02 4:07 ` Yan Zhao
2025-04-23 20:28 ` Ackerley Tng
2024-09-10 23:43 ` [RFC PATCH 28/39] KVM: guest_memfd: Use vm_type to determine default faultability Ackerley Tng
2024-09-10 23:44 ` [RFC PATCH 29/39] KVM: Handle conversions in the SET_MEMORY_ATTRIBUTES ioctl Ackerley Tng
2024-09-10 23:44 ` Ackerley Tng [this message]
2024-09-16 20:00 ` [RFC PATCH 30/39] KVM: guest_memfd: Handle folio preparation for guest_memfd mmap Elliot Berman
2024-10-03 21:32 ` Ackerley Tng
2024-10-03 23:43 ` Ackerley Tng
2024-10-08 19:30 ` Sean Christopherson
2024-10-07 15:56 ` Patrick Roy
2024-10-08 18:07 ` Ackerley Tng
2024-10-08 19:56 ` Sean Christopherson
2024-10-09 3:51 ` Manwaring, Derek
2024-10-09 13:52 ` Andrew Cooper
2024-10-10 16:21 ` Patrick Roy
2024-10-10 19:27 ` Manwaring, Derek
2024-10-17 23:16 ` Ackerley Tng
2024-10-18 7:10 ` Patrick Roy
2024-09-10 23:44 ` [RFC PATCH 31/39] KVM: selftests: Allow vm_set_memory_attributes to be used without asserting return value of 0 Ackerley Tng
2024-09-10 23:44 ` [RFC PATCH 32/39] KVM: selftests: Test using guest_memfd memory from userspace Ackerley Tng
2024-09-10 23:44 ` [RFC PATCH 33/39] KVM: selftests: Test guest_memfd memory sharing between guest and host Ackerley Tng
2024-09-10 23:44 ` [RFC PATCH 34/39] KVM: selftests: Add notes in private_mem_kvm_exits_test for mmap-able guest_memfd Ackerley Tng
2024-09-10 23:44 ` [RFC PATCH 35/39] KVM: selftests: Test that pinned pages block KVM from setting memory attributes to PRIVATE Ackerley Tng
2024-09-10 23:44 ` [RFC PATCH 36/39] KVM: selftests: Refactor vm_mem_add to be more flexible Ackerley Tng
2024-09-10 23:44 ` [RFC PATCH 37/39] KVM: selftests: Add helper to perform madvise by memslots Ackerley Tng
2024-09-10 23:44 ` [RFC PATCH 38/39] KVM: selftests: Update private_mem_conversions_test for mmap()able guest_memfd Ackerley Tng
2024-09-10 23:44 ` [RFC PATCH 39/39] KVM: guest_memfd: Dynamically split/reconstruct HugeTLB page Ackerley Tng
2025-04-03 12:33 ` Yan Zhao
2025-04-23 22:02 ` Ackerley Tng
2025-04-24 1:09 ` Yan Zhao
2025-04-24 4:25 ` Yan Zhao
2025-04-24 5:55 ` Chenyi Qiang
2025-04-24 8:13 ` Yan Zhao
2025-04-24 14:10 ` Vishal Annapurve
2025-04-24 18:15 ` Ackerley Tng
2025-04-25 4:02 ` Yan Zhao
2025-04-25 22:45 ` Ackerley Tng
2025-04-28 1:05 ` Yan Zhao
2025-04-28 19:02 ` Vishal Annapurve
2025-04-30 20:09 ` Ackerley Tng
2025-05-06 1:23 ` Yan Zhao
2025-05-06 19:22 ` Ackerley Tng
2025-05-07 3:15 ` Yan Zhao
2025-05-13 17:33 ` Ackerley Tng
2024-09-11 6:56 ` [RFC PATCH 00/39] 1G page support for guest_memfd Michal Hocko
2024-09-14 1:08 ` Du, Fan
2024-09-14 13:34 ` Vishal Annapurve
2025-01-28 9:42 ` Amit Shah
2025-02-03 8:35 ` Ackerley Tng
2025-02-06 11:07 ` Amit Shah
2025-02-07 6:25 ` Ackerley Tng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=24cf7a9b1ee499c4ca4da76e9945429072014d1e.1726009989.git.ackerleytng@google.com \
--to=ackerleytng@google.com \
--cc=ajones@ventanamicro.com \
--cc=anup@brainfault.org \
--cc=bfoster@redhat.com \
--cc=brauner@kernel.org \
--cc=david@redhat.com \
--cc=erdemaktas@google.com \
--cc=fan.du@intel.com \
--cc=fvdl@google.com \
--cc=haibo1.xu@intel.com \
--cc=isaku.yamahata@intel.com \
--cc=jgg@nvidia.com \
--cc=jhubbard@nvidia.com \
--cc=jthoughton@google.com \
--cc=jun.miao@intel.com \
--cc=kent.overstreet@linux.dev \
--cc=kvm@vger.kernel.org \
--cc=linux-fsdevel@kvack.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=maciej.wieczor-retman@intel.com \
--cc=mike.kravetz@oracle.com \
--cc=muchun.song@linux.dev \
--cc=oliver.upton@linux.dev \
--cc=pbonzini@redhat.com \
--cc=peterx@redhat.com \
--cc=pgonda@google.com \
--cc=pvorel@suse.cz \
--cc=qperret@google.com \
--cc=quic_eberman@quicinc.com \
--cc=richard.weiyang@gmail.com \
--cc=rientjes@google.com \
--cc=roypat@amazon.co.uk \
--cc=rppt@kernel.org \
--cc=seanjc@google.com \
--cc=shuah@kernel.org \
--cc=tabba@google.com \
--cc=vannapurve@google.com \
--cc=vkuznets@redhat.com \
--cc=willy@infradead.org \
--cc=zhiquan1.li@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox