|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH XTF 6/6] Add test mmu-pt-update-swap
Test for new mmu_update subop MMU_PT_UPDATE_SWAP
Signed-off-by: Kevin Lampis <kevin.lampis@xxxxxxxxxx>
---
Changes in v5:
- New patch
---
include/xen/version.h | 8 +++
include/xen/xen.h | 1 +
tests/mmu-pt-update-swap/Makefile | 9 +++
tests/mmu-pt-update-swap/main.c | 114 ++++++++++++++++++++++++++++++
4 files changed, 132 insertions(+)
create mode 100644 tests/mmu-pt-update-swap/Makefile
create mode 100644 tests/mmu-pt-update-swap/main.c
diff --git a/include/xen/version.h b/include/xen/version.h
index 45ce490b4b8f..73719a358c9a 100644
--- a/include/xen/version.h
+++ b/include/xen/version.h
@@ -24,6 +24,14 @@ typedef struct xen_compile_info xen_compile_info_t;
#define XENVER_changeset 4
typedef char xen_changeset_info_t[64];
+#define XENVER_get_features 6
+struct xen_feature_info {
+ uint32_t submap_idx; /* IN: which 32-bit submap to return */
+ uint32_t submap; /* OUT: 32-bit submap */
+};
+typedef struct xen_feature_info xen_feature_info_t;
+#define XENFEAT_mmu_pt_update_swap 21
+
#endif /* __XEN_PUBLIC_VERSION_H__ */
/*
diff --git a/include/xen/xen.h b/include/xen/xen.h
index 11af167702cd..8a239ea2b046 100644
--- a/include/xen/xen.h
+++ b/include/xen/xen.h
@@ -246,6 +246,7 @@ struct mmu_update {
#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */
#define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */
#define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */
+#define MMU_PT_UPDATE_SWAP 4 /* Update and return the old value. */
uint64_t ptr; /* Machine address of PTE. */
uint64_t val; /* New contents of PTE. */
};
diff --git a/tests/mmu-pt-update-swap/Makefile
b/tests/mmu-pt-update-swap/Makefile
new file mode 100644
index 000000000000..9e01c6bace63
--- /dev/null
+++ b/tests/mmu-pt-update-swap/Makefile
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME := mmu-pt-update-swap
+CATEGORY := functional
+TEST-ENVS := $(PV_ENVIRONMENTS)
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/mmu-pt-update-swap/main.c b/tests/mmu-pt-update-swap/main.c
new file mode 100644
index 000000000000..b43fcef57ed1
--- /dev/null
+++ b/tests/mmu-pt-update-swap/main.c
@@ -0,0 +1,114 @@
+/**
+ * @file tests/mmu-pt-update-swap/main.c
+ * @ref mmu-pt-update-swap
+ *
+ * Test new mmu_update subop MMU_PT_UPDATE_SWAP
+ * - Create a minimal l1 page table
+ * - Create a page table entry for a test page
+ * - Swap the page table entry with 0 using the new subop
+ * - If the feature is supported by Xen then
+ * - Test the new page table entry is zero
+ * - Test the old page table entry was returned by the hypercall
+ * - If the feature is not supported by Xen then
+ * - Test the hypercall failed
+ *
+ * @see tests/mmu-pt-update-swap/main.c
+ */
+#include <xtf.h>
+
+const char test_title[] = "mmu-pt-update-swap";
+
+static intpte_t nl1t[L1_PT_ENTRIES] __page_aligned_bss;
+static uint8_t target_page[PAGE_SIZE] __page_aligned_bss;
+
+static bool check_pte(intpte_t value, intpte_t expected)
+{
+ const intpte_t v = value & PADDR_MASK & PAGE_MASK;
+ const intpte_t e = expected & PADDR_MASK & PAGE_MASK;
+ if ( v != e )
+ {
+ xtf_failure("Fail: PTE mismatch got %"PRIpte" expected %"PRIpte"\n",
v, e);
+ return false;
+ }
+
+ return true;
+}
+
+void test_main(void)
+{
+ long rc = 0;
+
+ rc = hypercall_update_va_mapping(_u(nl1t),
+ pte_from_virt(nl1t, PF_SYM(AD, P)),
+ UVMF_INVLPG | UVMF_LOCAL);
+ if ( rc )
+ return xtf_failure("Failed to remap nl1t as readonly: %ld\n", rc);
+
+ /* Turn nl1t into a L1 page table page */
+ mmuext_op_t pin = {
+ .cmd = MMUEXT_PIN_L1_TABLE,
+ .arg1.mfn = virt_to_mfn(nl1t),
+ };
+ rc = hypercall_mmuext_op(&pin, 1, NULL, DOMID_SELF);
+ if ( rc )
+ return xtf_failure("Failed to pin nl1t: %ld\n", rc);
+
+ /* Add target_page into our new nl1t */
+ intpte_t test_pte = pte_from_virt(target_page, PF_SYM(AD, RW, P));
+ mmu_update_t req = {
+ .ptr = virt_to_maddr(&nl1t[0]),
+ .val = test_pte,
+ };
+ unsigned int done = 0;
+ rc = hypercall_mmu_update(&req, 1, &done, DOMID_SELF);
+ if ( rc || done != 1 )
+ return xtf_failure("Failed mmu_update: rc %ld, done %u\n", rc, done);
+
+ /* Confirm target_page was added correctly */
+ if ( !check_pte(nl1t[0], test_pte) )
+ return;
+
+ /* Try to swap the target_page PTE with 0 using the new subop */
+ req.ptr = virt_to_maddr(&nl1t[0]) | MMU_PT_UPDATE_SWAP;
+ req.val = 0;
+ rc = hypercall_mmu_update(&req, 1, &done, DOMID_SELF);
+
+ /* Check if Xen supports the new subop */
+ xen_feature_info_t fi = { .submap_idx = 0 };
+ if ( hypercall_xen_version(XENVER_get_features, &fi) )
+ return xtf_failure("Failed to run hypercall_xen_version\n");
+
+ if ( fi.submap & (1 << XENFEAT_mmu_pt_update_swap) )
+ {
+ if ( rc )
+ return xtf_failure("Fail: MMU_PT_UPDATE_SWAP rc=%ld expected
%d\n", rc, 0);
+
+ if ( done != 1 )
+ return xtf_failure("Fail: MMU_PT_UPDATE_SWAP done=%d expected
%d\n", done, 1);
+
+ /* Check the new PTE value is 0 */
+ if ( !check_pte(nl1t[0], 0) )
+ return;
+
+ /* Check the old PTE value was returned by the hypercall */
+ if ( !check_pte(req.val, test_pte) )
+ return;
+ }
+ else
+ {
+ if ( !rc )
+ return xtf_failure("Fail: MMU_PT_UPDATE_SWAP unsupported but
didn't fail rc=%ld\n", rc);
+ }
+
+ xtf_success(NULL);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.52.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |