* [PATCH 0/2] tests/paging-mempool: Testing for P2M relocation
@ 2026-05-12 15:55 Andrew Cooper
2026-05-12 15:55 ` [PATCH 1/2] tests/paging-mempool: Misc cleanup Andrew Cooper
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Andrew Cooper @ 2026-05-12 15:55 UTC (permalink / raw)
To: Xen-devel
Cc: Andrew Cooper, Anthony PERARD, Michal Orzel, Jan Beulich,
Julien Grall, Roger Pau Monné, Stefano Stabellini,
Oleksii Kurochko
Andrew Cooper (2):
tests/paging-mempool: Misc cleanup
tests/paging-mempool: Extend to test P2M relocation
tools/tests/paging-mempool/Makefile | 4 +
.../paging-mempool/test-paging-mempool.c | 222 +++++++++++++++++-
xen/common/memory.c | 2 +-
3 files changed, 223 insertions(+), 5 deletions(-)
--
2.39.5
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] tests/paging-mempool: Misc cleanup
2026-05-12 15:55 [PATCH 0/2] tests/paging-mempool: Testing for P2M relocation Andrew Cooper
@ 2026-05-12 15:55 ` Andrew Cooper
2026-05-12 15:55 ` [PATCH 2/2] tests/paging-mempool: Extend to test P2M relocation Andrew Cooper
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Andrew Cooper @ 2026-05-12 15:55 UTC (permalink / raw)
To: Xen-devel
Cc: Andrew Cooper, Anthony PERARD, Michal Orzel, Jan Beulich,
Julien Grall, Roger Pau Monné, Stefano Stabellini,
Oleksii Kurochko
... ahead of extending it with a second test.
Rename run_tests() to test_paging_mempool_size() and have it return int so the
newly wrapping run_tests() can decide whether to run the next or not.
Comment the parameters to xc_domain_populate_physmap_exact() to make it
clearer what's going on, and remove the page added to the physmap when the
test is done.
No practical change.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Anthony PERARD <anthony.perard@vates.tech>
CC: Michal Orzel <michal.orzel@amd.com>
CC: Jan Beulich <jbeulich@suse.com>
CC: Julien Grall <julien@xen.org>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
.../paging-mempool/test-paging-mempool.c | 25 ++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/tools/tests/paging-mempool/test-paging-mempool.c b/tools/tests/paging-mempool/test-paging-mempool.c
index 1ebc13455ac2..d1207d26d3fc 100644
--- a/tools/tests/paging-mempool/test-paging-mempool.c
+++ b/tools/tests/paging-mempool/test-paging-mempool.c
@@ -15,6 +15,7 @@ static unsigned int nr_failures;
({ \
nr_failures++; \
(void)printf(fmt, ##__VA_ARGS__); \
+ -1; \
})
static xc_interface *xch;
@@ -40,7 +41,7 @@ static uint64_t default_mempool_size_bytes =
16 << 12;
#endif
-static void run_tests(void)
+static int test_paging_mempool_size(void)
{
xen_pfn_t physmap[] = { 0 };
uint64_t size_bytes, old_size_bytes;
@@ -80,7 +81,8 @@ static void run_tests(void)
return fail(" Fail: setmaxmem: : %d - %s\n",
errno, strerror(errno));
- rc = xc_domain_populate_physmap_exact(xch, domid, 1, 0, 0, physmap);
+ rc = xc_domain_populate_physmap_exact(xch, domid, ARRAY_SIZE(physmap),
+ 0 /* order 4k */, 0 /* flags */, physmap);
if ( rc )
return fail(" Fail: populate physmap: %d - %s\n",
errno, strerror(errno));
@@ -98,6 +100,11 @@ static void run_tests(void)
return fail(" Fail: mempool size changed %"PRIu64" => %"PRIu64"\n",
old_size_bytes, size_bytes);
+ /* We added one 4k page. Check we can remove it. */
+ rc = xc_domain_remove_from_physmap(xch, domid, physmap[0]);
+ if ( rc )
+ return fail(" Fail: remove from physmap: %d - %s\n",
+ errno, strerror(errno));
printf("Test bad set size\n");
@@ -134,6 +141,19 @@ static void run_tests(void)
if ( size_bytes != 64 << 20 )
return fail(" Fail: expected mempool size %u, got %"PRIu64"\n",
64 << 20, size_bytes);
+
+ return 0;
+}
+
+static int run_tests(void)
+{
+ int rc;
+
+ rc = test_paging_mempool_size();
+ if ( rc )
+ return rc;
+
+ return 0;
}
int main(int argc, char **argv)
@@ -143,7 +163,6 @@ int main(int argc, char **argv)
printf("Paging mempool tests\n");
xch = xc_interface_open(NULL, NULL, 0);
-
if ( !xch )
err(1, "xc_interface_open");
--
2.39.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] tests/paging-mempool: Extend to test P2M relocation
2026-05-12 15:55 [PATCH 0/2] tests/paging-mempool: Testing for P2M relocation Andrew Cooper
2026-05-12 15:55 ` [PATCH 1/2] tests/paging-mempool: Misc cleanup Andrew Cooper
@ 2026-05-12 15:55 ` Andrew Cooper
2026-05-13 8:06 ` [PATCH 0/2] tests/paging-mempool: Testing for " Jan Beulich
2026-05-14 7:23 ` Oleksii Kurochko
3 siblings, 0 replies; 5+ messages in thread
From: Andrew Cooper @ 2026-05-12 15:55 UTC (permalink / raw)
To: Xen-devel
Cc: Andrew Cooper, Anthony PERARD, Michal Orzel, Jan Beulich,
Julien Grall, Roger Pau Monné, Stefano Stabellini,
Oleksii Kurochko
XENMAPSPACE_gmfn_range was found to be buggy with overlapping ranges, and the
fix is sufficiently far from clear that yours truely decided a test was in
order.
XENMAPSPACE_gmfn_range is exposed by xendevicemodel_relocate_memory() so take
the opportunity to create a better example for others to copy.
The test works as follows. Populate 2M of RAM in the guest, marking the pages
so they can be identified later. Then construct four relocation test
cases (overlapping vs non-overlapping, forwards vs backwards) using the marks
in the guest pages to confirm that the P2M was adjusted correctly.
The use of XEN_DOMCTL_CDF_iommu forces xenmem_add_to_physmap() to limit the
iteration count to a maximum of 16. Use this to force a continuation and
exercise more of the logic.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Anthony PERARD <anthony.perard@vates.tech>
CC: Michal Orzel <michal.orzel@amd.com>
CC: Jan Beulich <jbeulich@suse.com>
CC: Julien Grall <julien@xen.org>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Oleksii Kurochko <oleksii.kurochko@gmail.com>
paging-mempool isn't necessary the best named test to put this in, but it's
the one with the best structure to fit it. We are going to want to shuffle
the testing structure a bit when we've got a couple more examples to draw good
lines between.
Without "memory: overlapping XENMAPSPACE_gmfn_range requests", this fails:
...
Test p2m memory relocation
Test forward, no overlap: GFNs [3e0...3ff] -> [400...41f]
Test forward, overlapping: GFNs [3c0...3df] -> [3c1...3e0]
Fail: check mark unable to map 003c1: -22
Fail: check mark unable to map 003c2: -22
Fail: check mark unable to map 003c3: -22
Fail: check mark unable to map 003c4: -22
Fail: check mark unable to map 003c5: -22
Fail: check mark unable to map 003c6: -22
Fail: check mark unable to map 003c7: -22
Fail: check mark unable to map 003c8: -22
Fail: check mark unable to map 003c9: -22
Fail: check mark unable to map 003ca: -22
Fail: check mark unable to map 003cb: -22
Fail: check mark unable to map 003cc: -22
Fail: check mark unable to map 003cd: -22
Fail: check mark unable to map 003ce: -22
Fail: check mark unable to map 003cf: -22
Fail: check mark unable to map 003d0: -22
Fail: check mark unable to map 003d1: -22
Fail: check mark unable to map 003d2: -22
Fail: check mark unable to map 003d3: -22
Fail: check mark unable to map 003d4: -22
Fail: check mark unable to map 003d5: -22
Fail: check mark unable to map 003d6: -22
Fail: check mark unable to map 003d7: -22
Fail: check mark unable to map 003d8: -22
Fail: check mark unable to map 003d9: -22
Fail: check mark unable to map 003da: -22
Fail: check mark unable to map 003db: -22
Fail: check mark unable to map 003dc: -22
Fail: check mark unable to map 003dd: -22
Fail: check mark unable to map 003de: -22
Fail: check mark unable to map 003df: -22
Fail: check mark: gfn 003e0 expecting fffffe20 (479), got fffffe3f (448)
With the fix in place, the test passes:
...
Test p2m memory relocation
Test forward, no overlap: GFNs [3e0...3ff] -> [400...41f]
Test forward, overlapping: GFNs [3c0...3df] -> [3c1...3e0]
Test backwards, no overlap: GFNs [200...21f] -> [1e0...1ff]
Test backwards, no overlap: GFNs [220...23f] -> [21f...23e]
---
tools/tests/paging-mempool/Makefile | 4 +
.../paging-mempool/test-paging-mempool.c | 197 +++++++++++++++++-
xen/common/memory.c | 2 +-
3 files changed, 201 insertions(+), 2 deletions(-)
diff --git a/tools/tests/paging-mempool/Makefile b/tools/tests/paging-mempool/Makefile
index a1e12584ce80..7444d81b8460 100644
--- a/tools/tests/paging-mempool/Makefile
+++ b/tools/tests/paging-mempool/Makefile
@@ -25,9 +25,13 @@ uninstall:
CFLAGS += $(CFLAGS_xeninclude)
CFLAGS += $(CFLAGS_libxenctrl)
+CFLAGS += $(CFLAGS_libxendevicemodel)
+CFLAGS += $(CFLAGS_libxenforeignmemory)
CFLAGS += $(APPEND_CFLAGS)
LDFLAGS += $(LDLIBS_libxenctrl)
+LDFLAGS += $(LDLIBS_libxendevicemodel)
+LDFLAGS += $(LDLIBS_libxenforeignmemory)
LDFLAGS += $(APPEND_LDFLAGS)
%.o: Makefile
diff --git a/tools/tests/paging-mempool/test-paging-mempool.c b/tools/tests/paging-mempool/test-paging-mempool.c
index d1207d26d3fc..fc0375358324 100644
--- a/tools/tests/paging-mempool/test-paging-mempool.c
+++ b/tools/tests/paging-mempool/test-paging-mempool.c
@@ -6,6 +6,7 @@
#include <sys/mman.h>
#include <xenctrl.h>
+#include <xendevicemodel.h>
#include <xenforeignmemory.h>
#include <xengnttab.h>
#include <xen-tools/common-macros.h>
@@ -19,10 +20,15 @@ static unsigned int nr_failures;
})
static xc_interface *xch;
+static xendevicemodel_handle *dh;
+static xenforeignmemory_handle *fh;
static uint32_t domid;
static struct xen_domctl_createdomain create = {
- .flags = XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap,
+ .flags = (XEN_DOMCTL_CDF_hvm |
+ XEN_DOMCTL_CDF_hap |
+ XEN_DOMCTL_CDF_iommu |
+ 0),
.max_vcpus = 1,
.max_grant_frames = 1,
.grant_opts = XEN_DOMCTL_GRANT_version(1),
@@ -145,6 +151,183 @@ static int test_paging_mempool_size(void)
return 0;
}
+static int mark_guest_mem(xen_pfn_t gfn, size_t count)
+{
+ xen_pfn_t gfns[count];
+ uint32_t *mem;
+ size_t i;
+ int rc;
+
+ for ( i = 0; i < count; ++i )
+ gfns[i] = gfn + i;
+
+ mem = xenforeignmemory_map(fh, domid, PROT_READ | PROT_WRITE,
+ count, gfns, NULL);
+ if ( !mem )
+ return fail(" Fail: mark mem foreign map: %d - %s\n",
+ errno, strerror(errno));
+
+ for ( i = 0; i < count; ++i )
+ {
+ uint32_t *mark = &mem[i << 10];
+
+ *mark = ~i;
+ }
+
+ rc = xenforeignmemory_unmap(fh, mem, count);
+ if ( rc )
+ return fail(" Fail: mark mem foreign unmap: %d - %s\n",
+ errno, strerror(errno));
+
+ return 0;
+}
+
+static int check_guest_marks(xen_pfn_t gfn, uint32_t mark_start, size_t count)
+{
+ xen_pfn_t gfns[count];
+ int errs[count];
+ uint32_t *mem;
+ size_t i;
+ int rc = 0;
+
+ for ( i = 0; i < count; ++i )
+ gfns[i] = gfn + i;
+
+ mem = xenforeignmemory_map(fh, domid, PROT_READ,
+ count, gfns, errs);
+ if ( !mem )
+ return fail(" Fail: check mark foreign map: %d - %s\n",
+ errno, strerror(errno));
+
+ for ( i = 0; i < count; ++i )
+ {
+ uint32_t *mark = &mem[i << 10];
+ uint32_t exp = ~(mark_start + i);
+
+ if ( errs[i] )
+ {
+ rc = -1;
+ fail(" Fail: check mark unable to map %05lx: %d\n", gfns[i], errs[i]);
+ continue;
+ }
+
+ if ( *mark == exp )
+ continue;
+
+ fail(" Fail: check mark: gfn %05lx expecting %08x (%u), got %08x (%u)\n",
+ gfns[i], exp, ~exp, *mark, ~*mark);
+ rc = -1;
+ }
+
+ if ( xenforeignmemory_unmap(fh, mem, count) )
+ return fail(" Fail: check marks foreign unmap: %d - %s\n",
+ errno, strerror(errno));
+
+ return rc;
+}
+
+static int test_p2m_relocate_memory(void)
+{
+#define GFN_2M ((2UL << 20) >> 12)
+#define GFN_4M ((4UL << 20) >> 12)
+
+ xen_pfn_t physmap[] = { GFN_2M };
+ int rc;
+
+ /*
+ * Inherited state of the domain:
+ * - Unlimited allocation
+ *
+ * Construction of the test:
+ * - Populate 2M at 2M, mark the pages.
+ */
+ printf("Test p2m memory relocation\n");
+
+ rc = xc_domain_populate_physmap_exact(xch, domid, ARRAY_SIZE(physmap),
+ 9 /* order 2M */, 0 /* flags */, physmap);
+ if ( rc )
+ return fail(" Fail: populate physmap: %d - %s\n",
+ errno, strerror(errno));
+
+ rc = mark_guest_mem(GFN_2M, 1 << 9 /* order 2M */);
+ if ( rc )
+ return rc;
+
+ /* Sanity check the start and end markers. */
+ if ( (rc = check_guest_marks(GFN_2M, 0, 8)) ||
+ (rc = check_guest_marks(GFN_4M - 8, 512 - 8, 8)) )
+ return rc;
+
+
+#define GFN_PAIR(g, c) (g), ((g) + (c) - 1)
+
+ /*
+ * Move the final 32 pages below 4M forward by 32 pages. All destination
+ * GFNs free, and no overlap.
+ */
+ printf(" Test forward, no overlap: GFNs [%lx...%lx] -> [%lx...%lx]\n",
+ GFN_PAIR(GFN_4M - 32, 32), GFN_PAIR(GFN_4M, 32));
+
+ rc = xendevicemodel_relocate_memory(dh, domid, 32, GFN_4M - 32, GFN_4M);
+ if ( rc )
+ return fail(" Fail: relocate memory: %d - %s\n",
+ errno, strerror(errno));
+
+ rc = check_guest_marks(GFN_4M, 512 - 32, 32);
+ if ( rc )
+ return rc;
+
+ /*
+ * Move the next 32 pages below 4M forward by 1 page. The region is
+ * almost completely overlapping.
+ */
+ printf(" Test forward, overlapping: GFNs [%lx...%lx] -> [%lx...%lx]\n",
+ GFN_PAIR(GFN_4M - 64, 32), GFN_PAIR(GFN_4M - 63, 32));
+
+ rc = xendevicemodel_relocate_memory(dh, domid, 32, GFN_4M - 64, GFN_4M - 63);
+ if ( rc )
+ return fail(" Fail: relocate memory: %d - %s\n",
+ errno, strerror(errno));
+
+ rc = check_guest_marks(GFN_4M - 63, 512 - 64, 32);
+ if ( rc )
+ return rc;
+
+ /*
+ * Move the first 32 pages above 2M backwards by 32 pages. All
+ * destination GFNs free, and no overlap.
+ */
+ printf(" Test backwards, no overlap: GFNs [%lx...%lx] -> [%lx...%lx]\n",
+ GFN_PAIR(GFN_2M, 32), GFN_PAIR(GFN_2M - 32, 32));
+
+ rc = xendevicemodel_relocate_memory(dh, domid, 32, GFN_2M, GFN_2M - 32);
+ if ( rc )
+ return fail(" Fail: relocate memory: %d - %s\n",
+ errno, strerror(errno));
+
+ rc = check_guest_marks(GFN_2M - 32, 0, 32);
+ if ( rc )
+ return rc;
+
+ /*
+ * Move the next 32 pages above 2M backwards by 1 page. The region is
+ * almost completely overlapping.
+ */
+ printf(" Test backwards, no overlap: GFNs [%lx...%lx] -> [%lx...%lx]\n",
+ GFN_PAIR(GFN_2M + 32, 32), GFN_PAIR(GFN_2M + 31, 32));
+
+ rc = xendevicemodel_relocate_memory(dh, domid, 32, GFN_2M + 32, GFN_2M + 31);
+ if ( rc )
+ return fail(" Fail: relocate memory: %d - %s\n",
+ errno, strerror(errno));
+
+ rc = check_guest_marks(GFN_2M + 31, 32, 32);
+ if ( rc )
+ return rc;
+
+ return 0;
+}
+
static int run_tests(void)
{
int rc;
@@ -153,6 +336,10 @@ static int run_tests(void)
if ( rc )
return rc;
+ rc = test_p2m_relocate_memory();
+ if ( rc )
+ return rc;
+
return 0;
}
@@ -166,6 +353,14 @@ int main(int argc, char **argv)
if ( !xch )
err(1, "xc_interface_open");
+ dh = xendevicemodel_open(NULL, 0);
+ if ( !dh )
+ err(1, "xendevicemodel_open");
+
+ fh = xenforeignmemory_open(NULL, 0);
+ if ( !fh )
+ err(1, "xenforeignmemory_open");
+
rc = xc_domain_create(xch, &domid, &create);
if ( rc )
{
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 1ad4b51c5b02..c6109dc7d664 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -962,7 +962,7 @@ int xenmem_add_to_physmap(struct domain *d, struct xen_add_to_physmap *xatp,
unsigned int done = 0;
long rc = 0;
union add_to_physmap_extra extra = {};
- struct page_info *pages[16];
+ struct page_info *pages[16]; /* If changing this, adjust test-paging-mempool too */
if ( !paging_mode_translate(d) )
{
--
2.39.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] tests/paging-mempool: Testing for P2M relocation
2026-05-12 15:55 [PATCH 0/2] tests/paging-mempool: Testing for P2M relocation Andrew Cooper
2026-05-12 15:55 ` [PATCH 1/2] tests/paging-mempool: Misc cleanup Andrew Cooper
2026-05-12 15:55 ` [PATCH 2/2] tests/paging-mempool: Extend to test P2M relocation Andrew Cooper
@ 2026-05-13 8:06 ` Jan Beulich
2026-05-14 7:23 ` Oleksii Kurochko
3 siblings, 0 replies; 5+ messages in thread
From: Jan Beulich @ 2026-05-13 8:06 UTC (permalink / raw)
To: Andrew Cooper
Cc: Anthony PERARD, Michal Orzel, Julien Grall, Roger Pau Monné,
Stefano Stabellini, Oleksii Kurochko, Xen-devel
On 12.05.2026 17:55, Andrew Cooper wrote:
> Andrew Cooper (2):
> tests/paging-mempool: Misc cleanup
> tests/paging-mempool: Extend to test P2M relocation
>
> tools/tests/paging-mempool/Makefile | 4 +
> .../paging-mempool/test-paging-mempool.c | 222 +++++++++++++++++-
> xen/common/memory.c | 2 +-
> 3 files changed, 223 insertions(+), 5 deletions(-)
Acked-by: Jan Beulich <jbeulich@suse.com>
ideally with line length of 80 chars not exceeded, as looks to be the case
in both of the patches.
Jan
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] tests/paging-mempool: Testing for P2M relocation
2026-05-12 15:55 [PATCH 0/2] tests/paging-mempool: Testing for P2M relocation Andrew Cooper
` (2 preceding siblings ...)
2026-05-13 8:06 ` [PATCH 0/2] tests/paging-mempool: Testing for " Jan Beulich
@ 2026-05-14 7:23 ` Oleksii Kurochko
3 siblings, 0 replies; 5+ messages in thread
From: Oleksii Kurochko @ 2026-05-14 7:23 UTC (permalink / raw)
To: Andrew Cooper, Xen-devel
Cc: Anthony PERARD, Michal Orzel, Jan Beulich, Julien Grall,
Roger Pau Monné, Stefano Stabellini
On 5/12/26 5:55 PM, Andrew Cooper wrote:
> Andrew Cooper (2):
> tests/paging-mempool: Misc cleanup
> tests/paging-mempool: Extend to test P2M relocation
>
> tools/tests/paging-mempool/Makefile | 4 +
> .../paging-mempool/test-paging-mempool.c | 222 +++++++++++++++++-
> xen/common/memory.c | 2 +-
> 3 files changed, 223 insertions(+), 5 deletions(-)
>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
~ Oleksii
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-05-14 7:23 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-12 15:55 [PATCH 0/2] tests/paging-mempool: Testing for P2M relocation Andrew Cooper
2026-05-12 15:55 ` [PATCH 1/2] tests/paging-mempool: Misc cleanup Andrew Cooper
2026-05-12 15:55 ` [PATCH 2/2] tests/paging-mempool: Extend to test P2M relocation Andrew Cooper
2026-05-13 8:06 ` [PATCH 0/2] tests/paging-mempool: Testing for " Jan Beulich
2026-05-14 7:23 ` Oleksii Kurochko
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.