Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions resources/hiding_ci/build_and_install_kernel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,7 @@ apply_patch_or_series() {
*.patch) apply_patch_file $1 ;;
*.mbox) apply_series_mbox $1 ;;
*.lore) apply_series_link $1 ;;
*)
echo "Uknown patch file: "$1
exit 1
;;
*) echo "Skipping non-patch file" $1 ;;
esac
}

Expand Down Expand Up @@ -146,7 +143,7 @@ update_boot_config() {

KERNEL_URL=$(cat kernel_url)
KERNEL_COMMIT_HASH=$(cat kernel_commit_hash)
KERNEL_PATCHES_DIR=$(pwd)/patches
KERNEL_PATCHES_DIR=$(pwd)/linux_patches
KERNEL_CONFIG_OVERRIDES=$(pwd)/kernel_config_overrides

TMP_BUILD_DIR=$(mktemp -d -t kernel-build-XXXX)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
From f9ca710b51263ce8317cc2fa02232e456fa1f39c Mon Sep 17 00:00:00 2001
From: Fuad Tabba <[email protected]>
Date: Tue, 18 Mar 2025 16:18:15 +0000
Subject: [PATCH 01/34] mm: Consolidate freeing of typed folios on final
folio_put()

Some folio types, such as hugetlb, handle freeing their own
folios. Moreover, guest_memfd will require being notified once a
folio's reference count reaches 0 to facilitate shared to private
folio conversion, without the folio actually being freed at that
point.

As a first step towards that, this patch consolidates freeing
folios that have a type. The first user is hugetlb folios. Later
in this patch series, guest_memfd will become the second user of
this.

Suggested-by: David Hildenbrand <[email protected]>
Acked-by: Vlastimil Babka <[email protected]>
Acked-by: David Hildenbrand <[email protected]>
Signed-off-by: Fuad Tabba <[email protected]>
---
include/linux/page-flags.h | 15 +++++++++++++++
mm/swap.c | 23 ++++++++++++++++++-----
2 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 36d283552f80..6dc2494bd002 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -953,6 +953,21 @@ static inline bool page_has_type(const struct page *page)
return page_mapcount_is_type(data_race(page->page_type));
}

+static inline int page_get_type(const struct page *page)
+{
+ return page->page_type >> 24;
+}
+
+static inline bool folio_has_type(const struct folio *folio)
+{
+ return page_has_type(&folio->page);
+}
+
+static inline int folio_get_type(const struct folio *folio)
+{
+ return page_get_type(&folio->page);
+}
+
#define FOLIO_TYPE_OPS(lname, fname) \
static __always_inline bool folio_test_##fname(const struct folio *folio) \
{ \
diff --git a/mm/swap.c b/mm/swap.c
index fc8281ef4241..47bc1bb919cc 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -94,6 +94,19 @@ static void page_cache_release(struct folio *folio)
unlock_page_lruvec_irqrestore(lruvec, flags);
}

+static void free_typed_folio(struct folio *folio)
+{
+ switch (folio_get_type(folio)) {
+#ifdef CONFIG_HUGETLBFS
+ case PGTY_hugetlb:
+ free_huge_folio(folio);
+ return;
+#endif
+ default:
+ WARN_ON_ONCE(1);
+ }
+}
+
void __folio_put(struct folio *folio)
{
if (unlikely(folio_is_zone_device(folio))) {
@@ -101,8 +114,8 @@ void __folio_put(struct folio *folio)
return;
}

- if (folio_test_hugetlb(folio)) {
- free_huge_folio(folio);
+ if (unlikely(folio_has_type(folio))) {
+ free_typed_folio(folio);
return;
}

@@ -966,13 +979,13 @@ void folios_put_refs(struct folio_batch *folios, unsigned int *refs)
if (!folio_ref_sub_and_test(folio, nr_refs))
continue;

- /* hugetlb has its own memcg */
- if (folio_test_hugetlb(folio)) {
+ if (unlikely(folio_has_type(folio))) {
+ /* typed folios have their own memcg, if any */
if (lruvec) {
unlock_page_lruvec_irqrestore(lruvec, flags);
lruvec = NULL;
}
- free_huge_folio(folio);
+ free_typed_folio(folio);
continue;
}
folio_unqueue_deferred_split(folio);

base-commit: 4701f33a10702d5fc577c32434eb62adde0a1ae1
--
2.47.1

Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
From 9a4d7cd855d14e1522f363e3e04ebb9fa0a90ff0 Mon Sep 17 00:00:00 2001
From: Fuad Tabba <[email protected]>
Date: Tue, 18 Mar 2025 16:18:16 +0000
Subject: [PATCH 02/34] KVM: guest_memfd: Handle final folio_put() of
guest_memfd pages

Before transitioning a guest_memfd folio to unshared, thereby
disallowing access by the host and allowing the hypervisor to
transition its view of the guest page as private, we need to be
sure that the host doesn't have any references to the folio.

This patch introduces a new type for guest_memfd folios, which
isn't activated in this series but is here as a placeholder and
to facilitate the code in the subsequent patch series. This will
be used in the future to register a callback that informs the
guest_memfd subsystem when the last reference is dropped,
therefore knowing that the host doesn't have any remaining
references.

This patch also introduces the configuration option,
KVM_GMEM_SHARED_MEM, which toggles support for mapping
guest_memfd shared memory at the host.

Signed-off-by: Fuad Tabba <[email protected]>
Acked-by: Vlastimil Babka <[email protected]>
Acked-by: David Hildenbrand <[email protected]>
---
include/linux/kvm_host.h | 4 ++++
include/linux/page-flags.h | 16 ++++++++++++++++
mm/debug.c | 1 +
mm/swap.c | 29 +++++++++++++++++++++++++++++
virt/kvm/Kconfig | 4 ++++
virt/kvm/guest_memfd.c | 8 ++++++++
6 files changed, 62 insertions(+)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index f34f4cfaa513..3ad0719bfc4f 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -2571,4 +2571,8 @@ long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu,
struct kvm_pre_fault_memory *range);
#endif

+#ifdef CONFIG_KVM_GMEM_SHARED_MEM
+void kvm_gmem_handle_folio_put(struct folio *folio);
+#endif
+
#endif
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 6dc2494bd002..daeee9a38e4c 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -933,6 +933,7 @@ enum pagetype {
PGTY_slab = 0xf5,
PGTY_zsmalloc = 0xf6,
PGTY_unaccepted = 0xf7,
+ PGTY_guestmem = 0xf8,

PGTY_mapcount_underflow = 0xff
};
@@ -1082,6 +1083,21 @@ FOLIO_TYPE_OPS(hugetlb, hugetlb)
FOLIO_TEST_FLAG_FALSE(hugetlb)
#endif

+/*
+ * guestmem folios are used to back VM memory as managed by guest_memfd. Once
+ * the last reference is put, instead of freeing these folios back to the page
+ * allocator, they are returned to guest_memfd.
+ *
+ * For now, guestmem will only be set on these folios as long as they cannot be
+ * mapped to user space ("private state"), with the plan of always setting that
+ * type once typed folios can be mapped to user space cleanly.
+ */
+#ifdef CONFIG_KVM_GMEM_SHARED_MEM
+FOLIO_TYPE_OPS(guestmem, guestmem)
+#else
+FOLIO_TEST_FLAG_FALSE(guestmem)
+#endif
+
PAGE_TYPE_OPS(Zsmalloc, zsmalloc, zsmalloc)

/*
diff --git a/mm/debug.c b/mm/debug.c
index 8d2acf432385..08bc42c6cba8 100644
--- a/mm/debug.c
+++ b/mm/debug.c
@@ -56,6 +56,7 @@ static const char *page_type_names[] = {
DEF_PAGETYPE_NAME(table),
DEF_PAGETYPE_NAME(buddy),
DEF_PAGETYPE_NAME(unaccepted),
+ DEF_PAGETYPE_NAME(guestmem),
};

static const char *page_type_name(unsigned int page_type)
diff --git a/mm/swap.c b/mm/swap.c
index 47bc1bb919cc..d8fda3948684 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -38,6 +38,10 @@
#include <linux/local_lock.h>
#include <linux/buffer_head.h>

+#ifdef CONFIG_KVM_GMEM_SHARED_MEM
+#include <linux/kvm_host.h>
+#endif
+
#include "internal.h"

#define CREATE_TRACE_POINTS
@@ -94,6 +98,26 @@ static void page_cache_release(struct folio *folio)
unlock_page_lruvec_irqrestore(lruvec, flags);
}

+#ifdef CONFIG_KVM_GMEM_SHARED_MEM
+static void gmem_folio_put(struct folio *folio)
+{
+ /*
+ * Perform the callback only as long as the KVM module is still loaded.
+ * As long as the folio mapping is set, the folio is associated with a
+ * guest_memfd inode.
+ */
+ if (folio->mapping)
+ kvm_gmem_handle_folio_put(folio);
+
+ /*
+ * If there are no references to the folio left, it's not associated
+ * with a guest_memfd inode anymore.
+ */
+ if (folio_ref_count(folio) == 0)
+ __folio_put(folio);
+}
+#endif /* CONFIG_KVM_GMEM_SHARED_MEM */
+
static void free_typed_folio(struct folio *folio)
{
switch (folio_get_type(folio)) {
@@ -101,6 +125,11 @@ static void free_typed_folio(struct folio *folio)
case PGTY_hugetlb:
free_huge_folio(folio);
return;
+#endif
+#ifdef CONFIG_KVM_GMEM_SHARED_MEM
+ case PGTY_guestmem:
+ gmem_folio_put(folio);
+ return;
#endif
default:
WARN_ON_ONCE(1);
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index 54e959e7d68f..4e759e8020c5 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -124,3 +124,7 @@ config HAVE_KVM_ARCH_GMEM_PREPARE
config HAVE_KVM_ARCH_GMEM_INVALIDATE
bool
depends on KVM_PRIVATE_MEM
+
+config KVM_GMEM_SHARED_MEM
+ select KVM_PRIVATE_MEM
+ bool
diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index b2aa6bf24d3a..5fc414becae5 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -13,6 +13,14 @@ struct kvm_gmem {
struct list_head entry;
};

+#ifdef CONFIG_KVM_GMEM_SHARED_MEM
+void kvm_gmem_handle_folio_put(struct folio *folio)
+{
+ WARN_ONCE(1, "A placeholder that shouldn't trigger. Work in progress.");
+}
+EXPORT_SYMBOL_GPL(kvm_gmem_handle_folio_put);
+#endif /* CONFIG_KVM_GMEM_SHARED_MEM */
+
/**
* folio_file_pfn - like folio_file_page, but return a pfn.
* @folio: The folio which contains this index.
--
2.47.1

Loading