|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 2/2] tests/paging-mempool: Extend to test P2M relocation
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@xxxxxxxxxx>
---
CC: Anthony PERARD <anthony.perard@xxxxxxxxxx>
CC: Michal Orzel <michal.orzel@xxxxxxx>
CC: Jan Beulich <jbeulich@xxxxxxxx>
CC: Julien Grall <julien@xxxxxxx>
CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
CC: Stefano Stabellini <sstabellini@xxxxxxxxxx>
CC: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |