[PATCH v2 3/3] KVM: arm64: selftests: Test 52-bit guest virtual addresses
From: Itaru Kitayama
Date: Mon Sep 14 2026 - 03:40:25 EST
Exercise reads and writes through low and high guest virtual addresses
in the 52-bit VA modes with 4K, 16K and 64K pages. Verify that mappings
to the same GPA share data and mappings to distinct GPAs remain
independent.
Signed-off-by: Itaru Kitayama <itaru.kitayama@xxxxxxxxxxx>
---
tools/testing/selftests/kvm/Makefile.kvm | 1 +
tools/testing/selftests/kvm/arm64/lpa_test.c | 124 +++++++++++++++++++++++++++
2 files changed, 125 insertions(+)
diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 96bab7002d39..1e9d059ffb24 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -179,6 +179,7 @@ TEST_GEN_PROGS_arm64 += arm64/hello_el2
TEST_GEN_PROGS_arm64 += arm64/host_sve
TEST_GEN_PROGS_arm64 += arm64/hypercalls
TEST_GEN_PROGS_arm64 += arm64/external_aborts
+TEST_GEN_PROGS_arm64 += arm64/lpa_test
TEST_GEN_PROGS_arm64 += arm64/mmio_sign_ext
TEST_GEN_PROGS_arm64 += arm64/page_fault_test
TEST_GEN_PROGS_arm64 += arm64/psci_test
diff --git a/tools/testing/selftests/kvm/arm64/lpa_test.c b/tools/testing/selftests/kvm/arm64/lpa_test.c
new file mode 100644
index 000000000000..8fe6f254db28
--- /dev/null
+++ b/tools/testing/selftests/kvm/arm64/lpa_test.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Higher virtual addresses read/write test
+ */
+#include <test_util.h>
+
+#include "kvm_syscalls.h"
+#include "kvm_util.h"
+#include "ucall_common.h"
+#include "guest_modes.h"
+#include "processor.h"
+
+#define LOW_GVA 0xc0000000
+#define HIGH_GVA (LOW_GVA | BIT(48))
+
+static void guest_code(void)
+{
+ u64 *low = (u64 *)LOW_GVA;
+ u64 *high = (u64 *)HIGH_GVA;
+
+ WRITE_ONCE(*low, 1);
+ GUEST_ASSERT_EQ(READ_ONCE(*high), 1);
+ WRITE_ONCE(*high, 2);
+ GUEST_ASSERT_EQ(READ_ONCE(*low), 2);
+
+ GUEST_SYNC(0);
+
+ asm volatile("dsb sy\n\t"
+ "tlbi vmalle1is\n\t"
+ "dsb sy\n\t"
+ "isb"
+ : : : "memory");
+
+ GUEST_SYNC(1); /* Host installs HIGH_GVA -> gpa_b. */
+
+ asm volatile("dsb sy\n\t"
+ "isb\n\t"
+ : : : "memory");
+
+ /* low and high map to different GPAs. */
+ WRITE_ONCE(*low, 1);
+ WRITE_ONCE(*high, 2);
+
+ /* Check both after both writes to detect accidental aliasing. */
+ GUEST_ASSERT_EQ(READ_ONCE(*low), 1);
+ GUEST_ASSERT_EQ(READ_ONCE(*high), 2);
+
+ /* Updating the low mapping must not change the high mapping. */
+ WRITE_ONCE(*low, 3);
+
+ GUEST_ASSERT_EQ(READ_ONCE(*low), 3);
+ GUEST_ASSERT_EQ(READ_ONCE(*high), 2);
+
+ GUEST_DONE();
+}
+
+static void run_test(enum vm_guest_mode mode, void *arg)
+{
+ unsigned int *nr_tests = arg;
+ struct kvm_vcpu_init init;
+ struct kvm_vm *vm;
+ struct kvm_vcpu *vcpu;
+ struct ucall uc;
+
+ if (mode != VM_MODE_P52V52_4K &&
+ mode != VM_MODE_P52V52_16K &&
+ mode != VM_MODE_P52V52_64K)
+ return;
+
+ vm = __vm_create(VM_SHAPE(mode), 1, 0);
+ kvm_get_default_vcpu_target(vm, &init);
+ vcpu = aarch64_vcpu_add(vm, 0, &init, guest_code);
+ kvm_arch_vm_finalize_vcpus(vm);
+
+ vm_init_descriptor_tables(vm);
+ vcpu_init_descriptor_tables(vcpu);
+
+ u64 gpa_a = vm_phy_pages_alloc(vm, 1, 0, 0);
+ u64 gpa_b = vm_phy_pages_alloc(vm, 1, 0, 0);
+
+ virt_pg_map(vm, LOW_GVA, gpa_a);
+ virt_pg_map(vm, HIGH_GVA, gpa_a);
+
+ for (;;) {
+ vcpu_run(vcpu);
+ switch (get_ucall(vcpu, &uc)) {
+ case UCALL_DONE:
+ goto done;
+ case UCALL_ABORT:
+ REPORT_GUEST_ASSERT(uc);
+ break;
+ case UCALL_SYNC:
+ switch (uc.args[1]) {
+ case 0:
+ WRITE_ONCE(*virt_get_pte_hva(vm, HIGH_GVA), 0);
+ break;
+ case 1:
+ virt_pg_map(vm, HIGH_GVA, gpa_b);
+ break;
+ default:
+ TEST_FAIL("Unexpected sync stage: %lu\n", uc.args[1]);
+ }
+ /* Complete the host's PTE store before resuming the guest. */
+ asm volatile("dsb sy" : : : "memory");
+ break;
+ default:
+ TEST_FAIL("Unhandled ucall: %ld\n", uc.cmd);
+ }
+ }
+
+done:
+ kvm_vm_free(vm);
+ (*nr_tests)++;
+}
+
+int main(int argc, char **argv)
+{
+ unsigned int nr_tests = 0;
+
+ for_each_guest_mode(run_test, &nr_tests);
+ if (!nr_tests)
+ ksft_exit_skip("No supported 52-bit VA guest mode; skipping test\n");
+ return 0;
+}
--
2.43.0