From: Jing Zhang <jingzhangos@google.com>
To: KVM <kvm@vger.kernel.org>, KVMARM <kvmarm@lists.linux.dev>,
Marc Zyngier <maz@kernel.org>, Joey Gouly <joey.gouly@arm.com>,
Wei-Lin Chang <weilin.chang@arm.com>,
Yao Yuan <yaoyuan@linux.alibaba.com>
Cc: Oliver Upton <oliver.upton@linux.dev>,
Andrew Jones <andrew.jones@linux.dev>,
Alexandru Elisei <alexandru.elisei@arm.com>,
Mingwei Zhang <mizhang@google.com>,
Raghavendra Rao Ananta <rananta@google.com>,
Colton Lewis <coltonlewis@google.com>,
Jing Zhang <jingzhangos@google.com>
Subject: [kvm-unit-tests PATCH v2 7/7] arm64: Add Stage-2 MMU demand paging test
Date: Mon, 13 Apr 2026 13:46:30 -0700 [thread overview]
Message-ID: <20260413204630.1149038-8-jingzhangos@google.com> (raw)
In-Reply-To: <20260413204630.1149038-1-jingzhangos@google.com>
Introduce a new test case to validate Stage-2 MMU fault handling. The
test verifies that the hypervisor correctly identifies and handles
Stage-2 data aborts triggered by a guest accessing unmapped memory.
The test performs the following:
- Sets up a guest with Stage-1 disabled, using identity-mapped host
code and shared data in the Stage-2 page tables.
- Triggers a Stage-2 data abort by accessing a specific unmapped IPA.
- Catches the exception in the host, verifies the fault address,
and dynamically maps a new page to resolve the fault.
- Resumes the guest to confirm the memory access completes successfully
and the fault handler functioned as expected.
Signed-off-by: Jing Zhang <jingzhangos@google.com>
---
arm/Makefile.arm64 | 1 +
arm/stage2-mmu-test.c | 107 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 108 insertions(+)
create mode 100644 arm/stage2-mmu-test.c
diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64
index 9026fd71..e547f92d 100644
--- a/arm/Makefile.arm64
+++ b/arm/Makefile.arm64
@@ -67,6 +67,7 @@ tests += $(TEST_DIR)/cache.$(exe)
tests += $(TEST_DIR)/debug.$(exe)
tests += $(TEST_DIR)/fpu.$(exe)
tests += $(TEST_DIR)/mte.$(exe)
+tests += $(TEST_DIR)/stage2-mmu-test.$(exe)
include $(SRCDIR)/$(TEST_DIR)/Makefile.common
diff --git a/arm/stage2-mmu-test.c b/arm/stage2-mmu-test.c
new file mode 100644
index 00000000..0df4704b
--- /dev/null
+++ b/arm/stage2-mmu-test.c
@@ -0,0 +1,107 @@
+/*
+ * ARM64 Stage-2 MMU Demand Paging Test
+ *
+ * This test validates stage-2 data abort handling by purposefully
+ * accessing unmapped memory in the guest and verifying that the
+ * host correctly handles the fault by mapping the page.
+ *
+ * Copyright (C) 2026 Google LLC.
+ * Author: Jing Zhang <jingzhangos@google.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+#include <libcflat.h>
+#include <alloc_page.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/guest.h>
+#include <asm/stage2_mmu.h>
+
+#define TEST_PAGE_IPA 0x40000000UL
+#define FAULT_ADDR_IPA 0x50000000UL
+#define TEST_DATA 0xBEEFCAFEUL
+
+static volatile bool handled = false;
+
+static void guest_code(void)
+{
+ volatile unsigned long *test_va = (void *)TEST_PAGE_IPA;
+ volatile unsigned long *fault_va = (void *)FAULT_ADDR_IPA;
+
+ *fault_va = *test_va;
+
+ if (*fault_va == *test_va)
+ handled = true;
+
+ asm("hvc #0");
+}
+
+static enum guest_handler_result guest_exception_handler(struct guest *guest)
+{
+ unsigned long far, ec;
+ unsigned long *fixup_page;
+
+ ec = guest->esr_el2 >> ESR_ELx_EC_SHIFT;
+
+ if (ec == ESR_ELx_EC_HVC64) {
+ report_info("CPU%d: Guest exited via HVC.", smp_processor_id());
+ return GUEST_ACTION_EXIT;
+ }
+
+ if (ec == ESR_ELx_EC_DABT_LOW) {
+ far = guest->far_el2;
+ if (far == FAULT_ADDR_IPA) {
+ fixup_page = alloc_page();
+ s2mmu_map(guest->s2mmu, FAULT_ADDR_IPA,
+ virt_to_phys(fixup_page), PAGE_SIZE, S2_MAP_RW);
+ report(true, "Caught stage-2 fault at 0x%lx", far);
+ } else {
+ report(false, "Unexpected fault address: 0x%lx", far);
+ }
+ } else {
+ report(false, "Unexpected exception class: 0x%lx", ec);
+ }
+
+ return GUEST_ACTION_RESUME;
+}
+
+int main(int argc, char **argv)
+{
+ struct guest *guest;
+ unsigned long *test_page;
+ unsigned long code_va_base, code_pa_base, data_base;
+
+ report_prefix_push("stage2-mmu");
+
+ guest = guest_create(smp_processor_id(), guest_code, S2_PAGE_4K);
+
+ /* Map host code: IPA(VA) -> PA */
+ /* We use the host VA as the Guest IPA because guest stage 1 is disabled. */
+ code_va_base = (unsigned long)guest_code;
+ code_pa_base = virt_to_phys((void *)guest_code);
+
+ /* Align to 2MB to use block descriptors where possible */
+ code_va_base = code_va_base & ~(SZ_2M - 1);
+ code_pa_base = code_pa_base & ~(SZ_2M - 1);
+ s2mmu_map(guest->s2mmu, code_va_base, code_pa_base, SZ_2M, S2_MAP_RW);
+
+ /* Identity map the shared variable */
+ data_base = virt_to_phys((void *)&handled) & PAGE_MASK;
+ s2mmu_map(guest->s2mmu, data_base, data_base, PAGE_SIZE, S2_MAP_RW);
+
+ /* Map test data page */
+ test_page = alloc_page();
+ *test_page = TEST_DATA;
+ s2mmu_map(guest->s2mmu, TEST_PAGE_IPA, virt_to_phys(test_page), PAGE_SIZE, S2_MAP_RW);
+
+ guest_install_handler(guest, ELx_LOW_SYNC_64, guest_exception_handler);
+
+ report_info("CPU%d: entering guest...", smp_processor_id());
+
+ guest_run(guest);
+
+ report(handled, "Stage-2 fault handling test completed");
+ guest_destroy(guest);
+
+ return report_summary();
+}
--
2.53.0.1213.gd9a14994de-goog
prev parent reply other threads:[~2026-04-13 20:46 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-13 20:46 [kvm-unit-tests PATCH v2 0/7] arm64: Add Stage-2 MMU and Nested Guest Framework Jing Zhang
2026-04-13 20:46 ` [kvm-unit-tests PATCH v2 1/7] lib: arm64: Generalize ESR exception class definitions for EL2 support Jing Zhang
2026-04-16 15:27 ` Joey Gouly
2026-04-13 20:46 ` [kvm-unit-tests PATCH v2 2/7] lib: arm64: Add stage2 page table management library Jing Zhang
2026-04-16 15:19 ` Joey Gouly
2026-04-13 20:46 ` [kvm-unit-tests PATCH v2 3/7] lib: arm64: Generalize exception vector definitions for EL2 support Jing Zhang
2026-04-13 20:46 ` [kvm-unit-tests PATCH v2 4/7] lib: arm64: Add foundational guest execution framework Jing Zhang
2026-04-16 16:16 ` Joey Gouly
2026-04-13 20:46 ` [kvm-unit-tests PATCH v2 5/7] lib: arm64: Add support for guest exit exception handling Jing Zhang
2026-04-13 20:46 ` [kvm-unit-tests PATCH v2 6/7] lib: arm64: Add guest-internal exception handling (EL1) Jing Zhang
2026-04-13 20:46 ` Jing Zhang [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260413204630.1149038-8-jingzhangos@google.com \
--to=jingzhangos@google.com \
--cc=alexandru.elisei@arm.com \
--cc=andrew.jones@linux.dev \
--cc=coltonlewis@google.com \
--cc=joey.gouly@arm.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=maz@kernel.org \
--cc=mizhang@google.com \
--cc=oliver.upton@linux.dev \
--cc=rananta@google.com \
--cc=weilin.chang@arm.com \
--cc=yaoyuan@linux.alibaba.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox