Skip to content

Commit e451779

Browse files
kalyazinroypat
authored andcommitted
chore(hiding_ci): add userfault Linux patches
Include the following patch series rebased on top of the v7 of "KVM: Mapping guest_memfd backed memory at the host for software protected VMs" (https://<lor>/kvm/20250318161823.4005529-1-tabba@google.com/, replace "<lor>" with "lore.kernel.org" in this and the following links): - v4 "Direct Map Removal for guest_memfd" (https://<lor>/kvm/20250221160728.1584559-1-roypat@amazon.co.uk/), with fixups - v2 "KVM: Introduce KVM Userfault" (https://<lor>/kvm/20250109204929.1106563-1-jthoughton@google.com/) - v3 "KVM: guest_memfd: use write for population" (https://<lor>/kvm/20250303130838.28812-1-kalyazin@amazon.com/) - v3 "KVM: guest_memfd: support for uffd minor" (https://<lor>/kvm/20250404154352.23078-1-kalyazin@amazon.com/), with fixups After this change all patches are represented as plain text files, meaning no patches are required to be fetched via a lore link. Signed-off-by: Nikita Kalyazin <kalyazin@amazon.com>
1 parent b968ca5 commit e451779

File tree

35 files changed

+3228
-7
lines changed

35 files changed

+3228
-7
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
From f9ca710b51263ce8317cc2fa02232e456fa1f39c Mon Sep 17 00:00:00 2001
2+
From: Fuad Tabba <tabba@google.com>
3+
Date: Tue, 18 Mar 2025 16:18:15 +0000
4+
Subject: [PATCH 01/34] mm: Consolidate freeing of typed folios on final
5+
folio_put()
6+
7+
Some folio types, such as hugetlb, handle freeing their own
8+
folios. Moreover, guest_memfd will require being notified once a
9+
folio's reference count reaches 0 to facilitate shared to private
10+
folio conversion, without the folio actually being freed at that
11+
point.
12+
13+
As a first step towards that, this patch consolidates freeing
14+
folios that have a type. The first user is hugetlb folios. Later
15+
in this patch series, guest_memfd will become the second user of
16+
this.
17+
18+
Suggested-by: David Hildenbrand <david@redhat.com>
19+
Acked-by: Vlastimil Babka <vbabka@suse.cz>
20+
Acked-by: David Hildenbrand <david@redhat.com>
21+
Signed-off-by: Fuad Tabba <tabba@google.com>
22+
---
23+
include/linux/page-flags.h | 15 +++++++++++++++
24+
mm/swap.c | 23 ++++++++++++++++++-----
25+
2 files changed, 33 insertions(+), 5 deletions(-)
26+
27+
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
28+
index 36d283552f80..6dc2494bd002 100644
29+
--- a/include/linux/page-flags.h
30+
+++ b/include/linux/page-flags.h
31+
@@ -953,6 +953,21 @@ static inline bool page_has_type(const struct page *page)
32+
return page_mapcount_is_type(data_race(page->page_type));
33+
}
34+
35+
+static inline int page_get_type(const struct page *page)
36+
+{
37+
+ return page->page_type >> 24;
38+
+}
39+
+
40+
+static inline bool folio_has_type(const struct folio *folio)
41+
+{
42+
+ return page_has_type(&folio->page);
43+
+}
44+
+
45+
+static inline int folio_get_type(const struct folio *folio)
46+
+{
47+
+ return page_get_type(&folio->page);
48+
+}
49+
+
50+
#define FOLIO_TYPE_OPS(lname, fname) \
51+
static __always_inline bool folio_test_##fname(const struct folio *folio) \
52+
{ \
53+
diff --git a/mm/swap.c b/mm/swap.c
54+
index fc8281ef4241..47bc1bb919cc 100644
55+
--- a/mm/swap.c
56+
+++ b/mm/swap.c
57+
@@ -94,6 +94,19 @@ static void page_cache_release(struct folio *folio)
58+
unlock_page_lruvec_irqrestore(lruvec, flags);
59+
}
60+
61+
+static void free_typed_folio(struct folio *folio)
62+
+{
63+
+ switch (folio_get_type(folio)) {
64+
+#ifdef CONFIG_HUGETLBFS
65+
+ case PGTY_hugetlb:
66+
+ free_huge_folio(folio);
67+
+ return;
68+
+#endif
69+
+ default:
70+
+ WARN_ON_ONCE(1);
71+
+ }
72+
+}
73+
+
74+
void __folio_put(struct folio *folio)
75+
{
76+
if (unlikely(folio_is_zone_device(folio))) {
77+
@@ -101,8 +114,8 @@ void __folio_put(struct folio *folio)
78+
return;
79+
}
80+
81+
- if (folio_test_hugetlb(folio)) {
82+
- free_huge_folio(folio);
83+
+ if (unlikely(folio_has_type(folio))) {
84+
+ free_typed_folio(folio);
85+
return;
86+
}
87+
88+
@@ -966,13 +979,13 @@ void folios_put_refs(struct folio_batch *folios, unsigned int *refs)
89+
if (!folio_ref_sub_and_test(folio, nr_refs))
90+
continue;
91+
92+
- /* hugetlb has its own memcg */
93+
- if (folio_test_hugetlb(folio)) {
94+
+ if (unlikely(folio_has_type(folio))) {
95+
+ /* typed folios have their own memcg, if any */
96+
if (lruvec) {
97+
unlock_page_lruvec_irqrestore(lruvec, flags);
98+
lruvec = NULL;
99+
}
100+
- free_huge_folio(folio);
101+
+ free_typed_folio(folio);
102+
continue;
103+
}
104+
folio_unqueue_deferred_split(folio);
105+
106+
base-commit: 4701f33a10702d5fc577c32434eb62adde0a1ae1
107+
--
108+
2.47.1
109+

resources/hiding_ci/patches/0001.lore

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
From 9a4d7cd855d14e1522f363e3e04ebb9fa0a90ff0 Mon Sep 17 00:00:00 2001
2+
From: Fuad Tabba <tabba@google.com>
3+
Date: Tue, 18 Mar 2025 16:18:16 +0000
4+
Subject: [PATCH 02/34] KVM: guest_memfd: Handle final folio_put() of
5+
guest_memfd pages
6+
7+
Before transitioning a guest_memfd folio to unshared, thereby
8+
disallowing access by the host and allowing the hypervisor to
9+
transition its view of the guest page as private, we need to be
10+
sure that the host doesn't have any references to the folio.
11+
12+
This patch introduces a new type for guest_memfd folios, which
13+
isn't activated in this series but is here as a placeholder and
14+
to facilitate the code in the subsequent patch series. This will
15+
be used in the future to register a callback that informs the
16+
guest_memfd subsystem when the last reference is dropped,
17+
therefore knowing that the host doesn't have any remaining
18+
references.
19+
20+
This patch also introduces the configuration option,
21+
KVM_GMEM_SHARED_MEM, which toggles support for mapping
22+
guest_memfd shared memory at the host.
23+
24+
Signed-off-by: Fuad Tabba <tabba@google.com>
25+
Acked-by: Vlastimil Babka <vbabka@suse.cz>
26+
Acked-by: David Hildenbrand <david@redhat.com>
27+
---
28+
include/linux/kvm_host.h | 4 ++++
29+
include/linux/page-flags.h | 16 ++++++++++++++++
30+
mm/debug.c | 1 +
31+
mm/swap.c | 29 +++++++++++++++++++++++++++++
32+
virt/kvm/Kconfig | 4 ++++
33+
virt/kvm/guest_memfd.c | 8 ++++++++
34+
6 files changed, 62 insertions(+)
35+
36+
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
37+
index f34f4cfaa513..3ad0719bfc4f 100644
38+
--- a/include/linux/kvm_host.h
39+
+++ b/include/linux/kvm_host.h
40+
@@ -2571,4 +2571,8 @@ long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu,
41+
struct kvm_pre_fault_memory *range);
42+
#endif
43+
44+
+#ifdef CONFIG_KVM_GMEM_SHARED_MEM
45+
+void kvm_gmem_handle_folio_put(struct folio *folio);
46+
+#endif
47+
+
48+
#endif
49+
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
50+
index 6dc2494bd002..daeee9a38e4c 100644
51+
--- a/include/linux/page-flags.h
52+
+++ b/include/linux/page-flags.h
53+
@@ -933,6 +933,7 @@ enum pagetype {
54+
PGTY_slab = 0xf5,
55+
PGTY_zsmalloc = 0xf6,
56+
PGTY_unaccepted = 0xf7,
57+
+ PGTY_guestmem = 0xf8,
58+
59+
PGTY_mapcount_underflow = 0xff
60+
};
61+
@@ -1082,6 +1083,21 @@ FOLIO_TYPE_OPS(hugetlb, hugetlb)
62+
FOLIO_TEST_FLAG_FALSE(hugetlb)
63+
#endif
64+
65+
+/*
66+
+ * guestmem folios are used to back VM memory as managed by guest_memfd. Once
67+
+ * the last reference is put, instead of freeing these folios back to the page
68+
+ * allocator, they are returned to guest_memfd.
69+
+ *
70+
+ * For now, guestmem will only be set on these folios as long as they cannot be
71+
+ * mapped to user space ("private state"), with the plan of always setting that
72+
+ * type once typed folios can be mapped to user space cleanly.
73+
+ */
74+
+#ifdef CONFIG_KVM_GMEM_SHARED_MEM
75+
+FOLIO_TYPE_OPS(guestmem, guestmem)
76+
+#else
77+
+FOLIO_TEST_FLAG_FALSE(guestmem)
78+
+#endif
79+
+
80+
PAGE_TYPE_OPS(Zsmalloc, zsmalloc, zsmalloc)
81+
82+
/*
83+
diff --git a/mm/debug.c b/mm/debug.c
84+
index 8d2acf432385..08bc42c6cba8 100644
85+
--- a/mm/debug.c
86+
+++ b/mm/debug.c
87+
@@ -56,6 +56,7 @@ static const char *page_type_names[] = {
88+
DEF_PAGETYPE_NAME(table),
89+
DEF_PAGETYPE_NAME(buddy),
90+
DEF_PAGETYPE_NAME(unaccepted),
91+
+ DEF_PAGETYPE_NAME(guestmem),
92+
};
93+
94+
static const char *page_type_name(unsigned int page_type)
95+
diff --git a/mm/swap.c b/mm/swap.c
96+
index 47bc1bb919cc..d8fda3948684 100644
97+
--- a/mm/swap.c
98+
+++ b/mm/swap.c
99+
@@ -38,6 +38,10 @@
100+
#include <linux/local_lock.h>
101+
#include <linux/buffer_head.h>
102+
103+
+#ifdef CONFIG_KVM_GMEM_SHARED_MEM
104+
+#include <linux/kvm_host.h>
105+
+#endif
106+
+
107+
#include "internal.h"
108+
109+
#define CREATE_TRACE_POINTS
110+
@@ -94,6 +98,26 @@ static void page_cache_release(struct folio *folio)
111+
unlock_page_lruvec_irqrestore(lruvec, flags);
112+
}
113+
114+
+#ifdef CONFIG_KVM_GMEM_SHARED_MEM
115+
+static void gmem_folio_put(struct folio *folio)
116+
+{
117+
+ /*
118+
+ * Perform the callback only as long as the KVM module is still loaded.
119+
+ * As long as the folio mapping is set, the folio is associated with a
120+
+ * guest_memfd inode.
121+
+ */
122+
+ if (folio->mapping)
123+
+ kvm_gmem_handle_folio_put(folio);
124+
+
125+
+ /*
126+
+ * If there are no references to the folio left, it's not associated
127+
+ * with a guest_memfd inode anymore.
128+
+ */
129+
+ if (folio_ref_count(folio) == 0)
130+
+ __folio_put(folio);
131+
+}
132+
+#endif /* CONFIG_KVM_GMEM_SHARED_MEM */
133+
+
134+
static void free_typed_folio(struct folio *folio)
135+
{
136+
switch (folio_get_type(folio)) {
137+
@@ -101,6 +125,11 @@ static void free_typed_folio(struct folio *folio)
138+
case PGTY_hugetlb:
139+
free_huge_folio(folio);
140+
return;
141+
+#endif
142+
+#ifdef CONFIG_KVM_GMEM_SHARED_MEM
143+
+ case PGTY_guestmem:
144+
+ gmem_folio_put(folio);
145+
+ return;
146+
#endif
147+
default:
148+
WARN_ON_ONCE(1);
149+
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
150+
index 54e959e7d68f..4e759e8020c5 100644
151+
--- a/virt/kvm/Kconfig
152+
+++ b/virt/kvm/Kconfig
153+
@@ -124,3 +124,7 @@ config HAVE_KVM_ARCH_GMEM_PREPARE
154+
config HAVE_KVM_ARCH_GMEM_INVALIDATE
155+
bool
156+
depends on KVM_PRIVATE_MEM
157+
+
158+
+config KVM_GMEM_SHARED_MEM
159+
+ select KVM_PRIVATE_MEM
160+
+ bool
161+
diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
162+
index b2aa6bf24d3a..5fc414becae5 100644
163+
--- a/virt/kvm/guest_memfd.c
164+
+++ b/virt/kvm/guest_memfd.c
165+
@@ -13,6 +13,14 @@ struct kvm_gmem {
166+
struct list_head entry;
167+
};
168+
169+
+#ifdef CONFIG_KVM_GMEM_SHARED_MEM
170+
+void kvm_gmem_handle_folio_put(struct folio *folio)
171+
+{
172+
+ WARN_ONCE(1, "A placeholder that shouldn't trigger. Work in progress.");
173+
+}
174+
+EXPORT_SYMBOL_GPL(kvm_gmem_handle_folio_put);
175+
+#endif /* CONFIG_KVM_GMEM_SHARED_MEM */
176+
+
177+
/**
178+
* folio_file_pfn - like folio_file_page, but return a pfn.
179+
* @folio: The folio which contains this index.
180+
--
181+
2.47.1
182+

0 commit comments

Comments
 (0)