* [PATCH 0/7] tests/tcg: more capabilities for aarch64-softmmu tests
@ 2026-04-17 16:43 Alex Bennée
2026-04-17 16:43 ` [PATCH 1/7] tests/tcg: introduce a lib dir for aarch64 system tests Alex Bennée
` (6 more replies)
0 siblings, 7 replies; 13+ messages in thread
From: Alex Bennée @ 2026-04-17 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Peter Maydell, Alex Bennée
In the process of writing the WFx code I needed to enhance the support
code so we could have interrupts in the test. To do that I needed to
map hardware into the page tables. To do that I wanted to make the
page table code easier to follow and now here we are.
It's quite a lot of code for a simple thing and of course if we keep
going down this road we'll end up with a kernel all of our own
although not big and professional like Linux.
The other option would be to build some machinery to exploit our cross
compiler support and just import kvm-unit-tests somehow and maybe
integrate it with meson more properly. It already has a more mature
set of helpers and is set up for even more architectural shenanigans
including setup for both GICs and a cleaner unit test wrappers.
While earlier versions of the tests where the result of LLM
prototyping hopefully the splitting and refactoring has made it more
human. There is an additional test for the HPFAR_EL2.NS for bug 2568
but I haven't had a chance to properly clean it up yet so I haven't
included it here.
What do people think? Should we go down this road or choose the
kvm-unit-tests option?
Alex.
Alex Bennée (7):
tests/tcg: introduce a lib dir for aarch64 system tests
tests/tcg: convert aarch64 feat-xs test to use helpers
tests/tcg: convert aarch64 asid2 test to use sysreg helpers
tests/tcg: move aarch64 page table setup to c code
tests/tcg: add HW page for aarch64 tests
tests/tcg: create a mini-gic3 library
tests/tcg: add basic test for aarch64 wf[ie][t] insns
tests/tcg/aarch64/system/lib/gicv3.h | 60 +++++++++
tests/tcg/aarch64/system/lib/pgtable.h | 80 ++++++++++++
tests/tcg/aarch64/system/lib/sysregs.h | 42 +++++++
tests/tcg/aarch64/system/asid2.c | 35 +++---
tests/tcg/aarch64/system/feat-xs.c | 4 +-
tests/tcg/aarch64/system/lib/gicv3.c | 70 +++++++++++
tests/tcg/aarch64/system/lib/pgtable.c | 70 +++++++++++
tests/tcg/aarch64/system/vtimer.c | 23 +---
tests/tcg/aarch64/system/wfx.c | 143 ++++++++++++++++++++++
tests/tcg/aarch64/Makefile.softmmu-target | 22 +++-
tests/tcg/aarch64/system/boot.S | 125 +++----------------
tests/tcg/aarch64/system/kernel.ld | 3 +
12 files changed, 521 insertions(+), 156 deletions(-)
create mode 100644 tests/tcg/aarch64/system/lib/gicv3.h
create mode 100644 tests/tcg/aarch64/system/lib/pgtable.h
create mode 100644 tests/tcg/aarch64/system/lib/sysregs.h
create mode 100644 tests/tcg/aarch64/system/lib/gicv3.c
create mode 100644 tests/tcg/aarch64/system/lib/pgtable.c
create mode 100644 tests/tcg/aarch64/system/wfx.c
--
2.47.3
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/7] tests/tcg: introduce a lib dir for aarch64 system tests
2026-04-17 16:43 [PATCH 0/7] tests/tcg: more capabilities for aarch64-softmmu tests Alex Bennée
@ 2026-04-17 16:43 ` Alex Bennée
2026-04-24 1:38 ` Richard Henderson
2026-04-17 16:43 ` [PATCH 2/7] tests/tcg: convert aarch64 feat-xs test to use helpers Alex Bennée
` (5 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Alex Bennée @ 2026-04-17 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Peter Maydell, Alex Bennée
We are about to add some more helpers but lets start by adding a
simple wrapper for reading and writing system registers.
Do note the subtle switch of ordering for write_sysreg() which matches
the change the kernel made sometime in 2021 (see 272a067df in linux.git).
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/aarch64/system/lib/sysregs.h | 22 ++++++++++++++++++++++
tests/tcg/aarch64/system/vtimer.c | 23 ++++-------------------
tests/tcg/aarch64/Makefile.softmmu-target | 3 ++-
3 files changed, 28 insertions(+), 20 deletions(-)
create mode 100644 tests/tcg/aarch64/system/lib/sysregs.h
diff --git a/tests/tcg/aarch64/system/lib/sysregs.h b/tests/tcg/aarch64/system/lib/sysregs.h
new file mode 100644
index 00000000000..b1c465e0746
--- /dev/null
+++ b/tests/tcg/aarch64/system/lib/sysregs.h
@@ -0,0 +1,22 @@
+/*
+ * AArch64 system register helpers
+ *
+ * Based on the helpers from Linux
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#define __stringify_1(x...) #x
+#define __stringify(x...) __stringify_1(x)
+
+#define read_sysreg(r) ({ \
+ uint64_t __val; \
+ asm volatile("mrs %0, " __stringify(r) : "=r" (__val)); \
+ __val; \
+})
+
+#define write_sysreg(v, r) do { \
+ uint64_t __val = (uint64_t)(v); \
+ asm volatile("msr " __stringify(r) ", %x0" \
+ : : "rZ" (__val)); \
+} while (0)
diff --git a/tests/tcg/aarch64/system/vtimer.c b/tests/tcg/aarch64/system/vtimer.c
index 7d725eced34..b6bde49ce30 100644
--- a/tests/tcg/aarch64/system/vtimer.c
+++ b/tests/tcg/aarch64/system/vtimer.c
@@ -8,22 +8,7 @@
#include <stdint.h>
#include <minilib.h>
-
-/* grabbed from Linux */
-#define __stringify_1(x...) #x
-#define __stringify(x...) __stringify_1(x)
-
-#define read_sysreg(r) ({ \
- uint64_t __val; \
- asm volatile("mrs %0, " __stringify(r) : "=r" (__val)); \
- __val; \
-})
-
-#define write_sysreg(r, v) do { \
- uint64_t __val = (uint64_t)(v); \
- asm volatile("msr " __stringify(r) ", %x0" \
- : : "rZ" (__val)); \
-} while (0)
+#include "sysregs.h"
int main(void)
{
@@ -31,9 +16,9 @@ int main(void)
ml_printf("VTimer Test\n");
- write_sysreg(cntvoff_el2, 1);
- write_sysreg(cntv_cval_el0, -1);
- write_sysreg(cntv_ctl_el0, 1);
+ write_sysreg(1, cntvoff_el2);
+ write_sysreg(-1, cntv_cval_el0);
+ write_sysreg(1, cntv_ctl_el0);
ml_printf("cntvoff_el2=%lx\n", read_sysreg(cntvoff_el2));
ml_printf("cntv_cval_el0=%lx\n", read_sysreg(cntv_cval_el0));
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
index f7a7d2b800f..c7f44803c73 100644
--- a/tests/tcg/aarch64/Makefile.softmmu-target
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
@@ -4,6 +4,7 @@
AARCH64_SRC=$(SRC_PATH)/tests/tcg/aarch64
AARCH64_SYSTEM_SRC=$(AARCH64_SRC)/system
+AARCH64_SYSTEM_LIB=$(AARCH64_SRC)/system/lib
VPATH+=$(AARCH64_SYSTEM_SRC)
@@ -24,7 +25,7 @@ LINK_SCRIPT=$(AARCH64_SYSTEM_SRC)/kernel.ld
LDFLAGS=-Wl,-T$(LINK_SCRIPT)
TESTS+=$(AARCH64_TESTS) $(MULTIARCH_TESTS)
EXTRA_RUNS+=$(MULTIARCH_RUNS)
-CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC)
+CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC) -I $(AARCH64_SYSTEM_LIB)
LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
config-cc.mak: Makefile
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/7] tests/tcg: convert aarch64 feat-xs test to use helpers
2026-04-17 16:43 [PATCH 0/7] tests/tcg: more capabilities for aarch64-softmmu tests Alex Bennée
2026-04-17 16:43 ` [PATCH 1/7] tests/tcg: introduce a lib dir for aarch64 system tests Alex Bennée
@ 2026-04-17 16:43 ` Alex Bennée
2026-04-24 1:38 ` Richard Henderson
2026-04-17 16:43 ` [PATCH 3/7] tests/tcg: convert aarch64 asid2 test to use sysreg helpers Alex Bennée
` (4 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Alex Bennée @ 2026-04-17 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Peter Maydell, Alex Bennée
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/aarch64/system/feat-xs.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/tcg/aarch64/system/feat-xs.c b/tests/tcg/aarch64/system/feat-xs.c
index f310fc837e0..e2324cef1af 100644
--- a/tests/tcg/aarch64/system/feat-xs.c
+++ b/tests/tcg/aarch64/system/feat-xs.c
@@ -8,12 +8,12 @@
#include <minilib.h>
#include <stdint.h>
+#include "sysregs.h"
int main(void)
{
- uint64_t isar1;
+ uint64_t isar1 = read_sysreg(id_aa64isar1_el1);
- asm volatile ("mrs %0, id_aa64isar1_el1" : "=r"(isar1));
if (((isar1 >> 56) & 0xf) < 1) {
ml_printf("FEAT_XS not supported by CPU");
return 1;
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 3/7] tests/tcg: convert aarch64 asid2 test to use sysreg helpers
2026-04-17 16:43 [PATCH 0/7] tests/tcg: more capabilities for aarch64-softmmu tests Alex Bennée
2026-04-17 16:43 ` [PATCH 1/7] tests/tcg: introduce a lib dir for aarch64 system tests Alex Bennée
2026-04-17 16:43 ` [PATCH 2/7] tests/tcg: convert aarch64 feat-xs test to use helpers Alex Bennée
@ 2026-04-17 16:43 ` Alex Bennée
2026-04-24 1:39 ` Richard Henderson
2026-04-17 16:43 ` [PATCH 4/7] tests/tcg: move aarch64 page table setup to c code Alex Bennée
` (3 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Alex Bennée @ 2026-04-17 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Peter Maydell, Alex Bennée
While we are at it we can reduce the number of temporary variables
needed and fix a format string error.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/aarch64/system/asid2.c | 35 ++++++++++++++------------------
1 file changed, 15 insertions(+), 20 deletions(-)
diff --git a/tests/tcg/aarch64/system/asid2.c b/tests/tcg/aarch64/system/asid2.c
index 7d5466af34a..8c93024b858 100644
--- a/tests/tcg/aarch64/system/asid2.c
+++ b/tests/tcg/aarch64/system/asid2.c
@@ -9,10 +9,11 @@
#include <stdint.h>
#include <minilib.h>
+#include "sysregs.h"
-#define ID_AA64MMFR3_EL1 "S3_0_C0_C7_3"
-#define ID_AA64MMFR4_EL1 "S3_0_C0_C7_4"
-#define TCR2_EL1 "S3_0_C2_C0_3"
+#define ID_AA64MMFR3_EL1 S3_0_C0_C7_3
+#define ID_AA64MMFR4_EL1 S3_0_C0_C7_4
+#define TCR2_EL1 S3_0_C2_C0_3
int main()
{
@@ -23,7 +24,7 @@ int main()
* not enabled and read as the written value if A2 is enabled.
*/
- uint64_t out;
+ uint64_t read_tcr2;
uint64_t idreg3;
uint64_t idreg4;
int tcr2_present;
@@ -31,11 +32,8 @@ int main()
/* Mask is FNG1, FNG0, and A2 */
const uint64_t feature_mask = (1ULL << 18 | 1ULL << 17 | 1ULL << 16);
- const uint64_t in = feature_mask;
-
- asm("mrs %[idreg3], " ID_AA64MMFR3_EL1 "\n\t"
- : [idreg3] "=r" (idreg3));
+ idreg3 = read_sysreg(ID_AA64MMFR3_EL1);
tcr2_present = ((idreg3 & 0xF) != 0);
if (!tcr2_present) {
@@ -43,33 +41,30 @@ int main()
return 0;
}
- asm("mrs %[idreg4], " ID_AA64MMFR4_EL1 "\n\t"
- : [idreg4] "=r" (idreg4));
-
+ idreg4 = read_sysreg(ID_AA64MMFR4_EL1);
asid2_present = ((idreg4 & 0xF00) != 0);
- asm("msr " TCR2_EL1 ", %[x0]\n\t"
- "mrs %[x1], " TCR2_EL1 "\n\t"
- : [x1] "=r" (out)
- : [x0] "r" (in));
+ /* write the feature mask and read back */
+ write_sysreg(feature_mask, TCR2_EL1);
+ read_tcr2 = read_sysreg(TCR2_EL1);
if (asid2_present) {
- if ((out & feature_mask) == in) {
+ if ((read_tcr2 & feature_mask) == feature_mask) {
ml_printf("OK\n");
return 0;
} else {
ml_printf("FAIL: ASID2 present, but read value %lx != "
"written value %lx\n",
- out & feature_mask, in);
+ read_tcr2 & feature_mask, feature_mask);
return 1;
}
} else {
- if (out == 0) {
+ if (read_tcr2 == 0) {
ml_printf("TCR2_EL1 reads as RES0 as expected\n");
return 0;
} else {
- ml_printf("FAIL: ASID2, missing but read value %lx != 0\n",
- out & feature_mask, in);
+ ml_printf("FAIL: ASID2, missing but read value %lx != %lx\n",
+ read_tcr2 & feature_mask, feature_mask);
return 1;
}
}
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 4/7] tests/tcg: move aarch64 page table setup to c code
2026-04-17 16:43 [PATCH 0/7] tests/tcg: more capabilities for aarch64-softmmu tests Alex Bennée
` (2 preceding siblings ...)
2026-04-17 16:43 ` [PATCH 3/7] tests/tcg: convert aarch64 asid2 test to use sysreg helpers Alex Bennée
@ 2026-04-17 16:43 ` Alex Bennée
2026-05-07 17:13 ` Jim MacArthur
2026-04-17 16:43 ` [PATCH 5/7] tests/tcg: add HW page for aarch64 tests Alex Bennée
` (2 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Alex Bennée @ 2026-04-17 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Peter Maydell, Alex Bennée
If we want more flexibility messing around with page tables lets do it
without having to rely on assembly for it.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
AJB
- a result of -O0 does mean each helper ends up with a stack frame
being needed to do the relatively simple mask and shift. I've
experimented with -O1 and trying to manually enable inlining but
couldn't get anything to work.
---
tests/tcg/aarch64/system/lib/pgtable.h | 80 ++++++++++++++++
tests/tcg/aarch64/system/lib/sysregs.h | 20 ++++
tests/tcg/aarch64/system/lib/pgtable.c | 60 ++++++++++++
tests/tcg/aarch64/Makefile.softmmu-target | 9 +-
tests/tcg/aarch64/system/boot.S | 109 +---------------------
tests/tcg/aarch64/system/kernel.ld | 3 +
6 files changed, 170 insertions(+), 111 deletions(-)
create mode 100644 tests/tcg/aarch64/system/lib/pgtable.h
create mode 100644 tests/tcg/aarch64/system/lib/pgtable.c
diff --git a/tests/tcg/aarch64/system/lib/pgtable.h b/tests/tcg/aarch64/system/lib/pgtable.h
new file mode 100644
index 00000000000..c5048c3eea1
--- /dev/null
+++ b/tests/tcg/aarch64/system/lib/pgtable.h
@@ -0,0 +1,80 @@
+/*
+ * AArch64 page table helpers
+ *
+ * Some simple helper functions for setting the page table entries.
+ *
+ * Copyright (C) 2026 Linaro Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+/*
+ * Page Table Descriptors
+ */
+#define DESC_VALID (1ULL << 0)
+#define DESC_TYPE_TABLE (1ULL << 1)
+#define DESC_TYPE_BLOCK (0ULL << 1)
+#define DESC_TYPE_PAGE (1ULL << 1)
+
+#define DESC_AF (1ULL << 10)
+#define DESC_ATTRINDX(i) ((uint64_t)(i) << 2)
+#define DESC_NS (1ULL << 5)
+#define DESC_UXN (1ULL << 53)
+#define DESC_PXN (1ULL << 54)
+
+#define DESC_ADDR_MASK 0x0000FFFFFFFFF000ULL
+#define DESC_ADDR_BLOCK_L1 0x0000FFFFC0000000ULL
+#define DESC_ADDR_BLOCK_L2 0x0000FFFFFFE00000ULL
+
+/* Stage 2 specific */
+#define DESC_S2_AP_RW (3ULL << 6)
+#define DESC_S2_MEMATTR_NORMAL (0xfULL << 2)
+
+/**
+ * pgt_map_l1_table - Setup a Level 1 table pointing to a Level 2 table
+ * @table: the level 1 table
+ * @va: the virtual address to map
+ * @next_table: the level 2 table to point to
+ */
+static inline void pgt_map_l1_table(uint64_t *table, uintptr_t va, uint64_t *next_table)
+{
+ int index = (va >> 30) & 0x1ff;
+ table[index] = ((uintptr_t)next_table & DESC_ADDR_MASK) | DESC_TYPE_TABLE | DESC_VALID;
+}
+
+/**
+ * pgt_map_l1_block - Setup a Level 1 block mapping (1GB)
+ * @table: the level 1 table
+ * @va: the virtual address to map
+ * @pa: the physical address to map to
+ * @flags: the descriptor flags (e.g. DESC_AF | ...)
+ */
+static inline void pgt_map_l1_block(uint64_t *table, uintptr_t va, uintptr_t pa, uint64_t flags)
+{
+ int index = (va >> 30) & 0x1ff;
+ table[index] = (pa & DESC_ADDR_BLOCK_L1) | flags | DESC_TYPE_BLOCK | DESC_VALID;
+}
+
+/**
+ * pgt_map_l2_block - Setup a Level 2 block mapping (2MB)
+ * @table: the level 2 table
+ * @va: the virtual address to map
+ * @pa: the physical address to map to
+ * @flags: the descriptor flags (e.g. DESC_AF | ...)
+ */
+static inline void pgt_map_l2_block(uint64_t *table, uintptr_t va, uintptr_t pa, uint64_t flags)
+{
+ int index = (va >> 21) & 0x1ff;
+ table[index] = (pa & DESC_ADDR_BLOCK_L2) | flags | DESC_TYPE_BLOCK | DESC_VALID;
+}
+
+/**
+ * flat_map_stage2 - Setup a flat (VA==PA) stage 2 mapping
+ * @table: the level 2 table
+ * @addr: the VA/PA to map
+ * @flags: the descriptor flags (e.g. DESC_AF | ...)
+ */
+static inline void flat_map_stage2(uint64_t *table, uintptr_t addr, uint64_t flags)
+{
+ pgt_map_l2_block(table, addr, addr, flags);
+}
diff --git a/tests/tcg/aarch64/system/lib/sysregs.h b/tests/tcg/aarch64/system/lib/sysregs.h
index b1c465e0746..6e714f46842 100644
--- a/tests/tcg/aarch64/system/lib/sysregs.h
+++ b/tests/tcg/aarch64/system/lib/sysregs.h
@@ -20,3 +20,23 @@
asm volatile("msr " __stringify(r) ", %x0" \
: : "rZ" (__val)); \
} while (0)
+
+#define isb() asm volatile("isb" : : : "memory")
+#define dsb(opt) asm volatile("dsb " #opt : : : "memory")
+
+/*
+ * SCTLR_EL1 Bits
+ */
+#define SCTLR_EL1_M (1ULL << 0) /* enable MMU for EL0/1 */
+#define SCTLR_EL1_C (1ULL << 2) /* Data cachability control */
+#define SCTLR_EL1_SA (1ULL << 3) /* SP alignment check */
+#define SCTLR_EL1_I (1ULL << 12) /* Instruction cachability control */
+
+/*
+ * TCR_EL1 Bits
+ */
+#define TCR_EL1_T0SZ(s) ((s) & 0x3fULL)
+#define TCR_EL1_IRGN0_WBWA (3ULL << 8)
+#define TCR_EL1_ORGN0_WBWA (3ULL << 10)
+#define TCR_EL1_IPS_40BIT (2ULL << 32)
+#define TCR_EL1_TG0_4KB (0ULL << 14)
diff --git a/tests/tcg/aarch64/system/lib/pgtable.c b/tests/tcg/aarch64/system/lib/pgtable.c
new file mode 100644
index 00000000000..a558f5f0dd5
--- /dev/null
+++ b/tests/tcg/aarch64/system/lib/pgtable.c
@@ -0,0 +1,60 @@
+#include <stdint.h>
+#include "sysregs.h"
+#include "pgtable.h"
+
+/*
+ * Page table setup for AArch64 system tests.
+ * We use a flat identity mapping.
+ */
+
+/* Symbols defined in kernel.ld */
+extern char _text_start[];
+extern char _data_start[];
+extern char _tag_start[];
+
+/* Assume these start zeroed */
+uint64_t ttb_l1[512] __attribute__((aligned(4096)));
+uint64_t ttb_l2[512] __attribute__((aligned(4096)));
+
+/*
+ * Setup a flat address mapping page-tables. Stage one simply
+ * maps RAM to the first Gb. The stage2 tables have two 2mb
+ * translation block entries covering a series of adjacent
+ * 4k pages.
+ */
+void setup_pgtables(void)
+{
+ /* L1 entry points to L2 table */
+ pgt_map_l1_table(ttb_l1, (uintptr_t)_text_start, ttb_l2);
+
+ /* L2 entries: 2MB blocks */
+ /* .text & .rodata (Read-only, executable) */
+ flat_map_stage2(ttb_l2, (uintptr_t)_text_start, DESC_AF);
+
+ /* .data & .bss (Read-write, no-execute) */
+ flat_map_stage2(ttb_l2, (uintptr_t)_data_start, DESC_AF | DESC_PXN | DESC_UXN);
+
+ /* mte_page (Read-write, no-execute, AttrIndx=1) */
+ flat_map_stage2(ttb_l2, (uintptr_t)_tag_start, DESC_AF | DESC_PXN | DESC_UXN | DESC_ATTRINDX(1));
+
+ /* Set TTBR0_EL1 */
+ write_sysreg(ttb_l1, ttbr0_el1);
+
+ /* Set MAIR_EL1 */
+ write_sysreg(0xeeULL, mair_el1);
+
+ /* Set TCR_EL1 */
+ uint64_t tcr = TCR_EL1_IPS_40BIT | TCR_EL1_TG0_4KB | TCR_EL1_ORGN0_WBWA | TCR_EL1_IRGN0_WBWA | TCR_EL1_T0SZ(25);
+ write_sysreg(tcr, tcr_el1);
+ isb();
+
+ /* Enable MMU via SCTLR_EL1 */
+ uint64_t sctlr = read_sysreg(sctlr_el1);
+ sctlr &= ~(1ULL << 1); /* Clear A (alignment check) */
+ sctlr &= ~(1ULL << 19); /* Clear WXN */
+ sctlr |= SCTLR_EL1_M | SCTLR_EL1_C | SCTLR_EL1_I | SCTLR_EL1_SA;
+
+ dsb(sy);
+ write_sysreg(sctlr, sctlr_el1);
+ isb();
+}
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
index c7f44803c73..5770ae1fb0c 100644
--- a/tests/tcg/aarch64/Makefile.softmmu-target
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
@@ -6,10 +6,10 @@ AARCH64_SRC=$(SRC_PATH)/tests/tcg/aarch64
AARCH64_SYSTEM_SRC=$(AARCH64_SRC)/system
AARCH64_SYSTEM_LIB=$(AARCH64_SRC)/system/lib
-VPATH+=$(AARCH64_SYSTEM_SRC)
+VPATH+=$(AARCH64_SYSTEM_SRC) $(AARCH64_SYSTEM_LIB)
# These objects provide the basic boot code and helper functions for all tests
-CRT_OBJS=boot.o
+CRT_OBJS=boot.o pgtable.o
AARCH64_TEST_C_SRCS=$(wildcard $(AARCH64_SYSTEM_SRC)/*.c)
AARCH64_TEST_S_SRCS=$(AARCH64_SYSTEM_SRC)/mte.S
@@ -37,9 +37,12 @@ config-cc.mak: Makefile
# building head blobs
.PRECIOUS: $(CRT_OBJS)
-%.o: $(CRT_PATH)/%.S
+%.o: %.S
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -Wa,--noexecstack -c $< -o $@
+%.o: %.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@
+
# Build and link the tests
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
diff --git a/tests/tcg/aarch64/system/boot.S b/tests/tcg/aarch64/system/boot.S
index 8bfa4e4efc7..bee8d9372e7 100644
--- a/tests/tcg/aarch64/system/boot.S
+++ b/tests/tcg/aarch64/system/boot.S
@@ -243,102 +243,7 @@ at_testel:
msr vbar_el1, x0
/* Page table setup (identity mapping). */
- adrp x0, ttb
- add x0, x0, :lo12:ttb
- msr ttbr0_el1, x0
-
- /*
- * Setup a flat address mapping page-tables. Stage one simply
- * maps RAM to the first Gb. The stage2 tables have two 2mb
- * translation block entries covering a series of adjacent
- * 4k pages.
- */
-
- /* Stage 1 entry: indexed by IA[38:30] */
- adr x1, . /* phys address */
- bic x1, x1, #(1 << 30) - 1 /* 1GB alignment*/
- add x2, x0, x1, lsr #(30 - 3) /* offset in l1 page table */
-
- /* point to stage 2 table [47:12] */
- adrp x0, ttb_stage2
- orr x1, x0, #3 /* ptr to stage 2 */
- str x1, [x2]
-
- /* Stage 2 entries: indexed by IA[29:21] */
- ldr x5, =(((1 << 9) - 1) << 21)
-
- /* First block: .text/RO/execute enabled */
- adr x1, . /* phys address */
- bic x1, x1, #(1 << 21) - 1 /* 2mb block alignment */
- and x4, x1, x5 /* IA[29:21] */
- add x2, x0, x4, lsr #(21 - 3) /* offset in l2 page table */
- ldr x3, =0x401 /* attr(AF, block) */
- orr x1, x1, x3
- str x1, [x2] /* 1st 2mb (.text & rodata) */
-
- /* Second block: .data/RW/no execute */
- adrp x1, .data
- add x1, x1, :lo12:.data
- bic x1, x1, #(1 << 21) - 1 /* 2mb block alignment */
- and x4, x1, x5 /* IA[29:21] */
- add x2, x0, x4, lsr #(21 - 3) /* offset in l2 page table */
- ldr x3, =(3 << 53) | 0x401 /* attr(AF, NX, block) */
- orr x1, x1, x3
- str x1, [x2] /* 2nd 2mb (.data & .bss)*/
-
- /* Third block: at 'mte_page', set in kernel.ld */
- adrp x1, mte_page
- add x1, x1, :lo12:mte_page
- bic x1, x1, #(1 << 21) - 1
- and x4, x1, x5
- add x2, x0, x4, lsr #(21 - 3)
- /* attr(AF, NX, block, AttrIndx=Attr1) */
- ldr x3, =(3 << 53) | 0x401 | (1 << 2)
- orr x1, x1, x3
- str x1, [x2]
-
- /* Setup/enable the MMU. */
-
- /*
- * TCR_EL1 - Translation Control Registers
- *
- * IPS[34:32] = 40-bit PA, 1TB
- * TG0[14:15] = b00 => 4kb granuale
- * ORGN0[11:10] = Outer: Normal, WB Read-Alloc No Write-Alloc Cacheable
- * IRGN0[9:8] = Inner: Normal, WB Read-Alloc No Write-Alloc Cacheable
- * T0SZ[5:0] = 2^(64 - 25)
- *
- * The size of T0SZ controls what the initial lookup level. It
- * would be nice to start at level 2 but unfortunately for a
- * flat-mapping on the virt machine we need to handle IA's
- * with at least 1gb range to see RAM. So we start with a
- * level 1 lookup.
- */
- ldr x0, = (2 << 32) | 25 | (3 << 10) | (3 << 8)
- msr tcr_el1, x0
-
- mov x0, #0xee /* Inner/outer cacheable WB */
- msr mair_el1, x0
- isb
-
- /*
- * SCTLR_EL1 - System Control Register
- *
- * WXN[19] = 0 = no effect, Write does not imply XN (execute never)
- * I[12] = Instruction cachability control
- * SA[3] = SP alignment check
- * C[2] = Data cachability control
- * M[0] = 1, enable stage 1 address translation for EL0/1
- */
- mrs x0, sctlr_el1
- ldr x1, =0x100d /* bits I(12) SA(3) C(2) M(0) */
- bic x0, x0, #(1 << 1) /* clear bit A(1) */
- bic x0, x0, #(1 << 19) /* clear WXN */
- orr x0, x0, x1 /* set bits */
-
- dsb sy
- msr sctlr_el1, x0
- isb
+ bl setup_pgtables
/*
* Enable FP/SVE registers. The standard C pre-amble will be
@@ -392,18 +297,6 @@ cmdline:
.space 128, 0
.align 12
-
- /* Translation table
- * @4k granuale: 9 bit lookup, 512 entries
- */
-ttb:
- .space 4096, 0
-
- .align 12
-ttb_stage2:
- .space 4096, 0
-
- .align 12
system_stack:
.space 4096, 0
system_stack_end:
diff --git a/tests/tcg/aarch64/system/kernel.ld b/tests/tcg/aarch64/system/kernel.ld
index aef043e31db..267ffcbe520 100644
--- a/tests/tcg/aarch64/system/kernel.ld
+++ b/tests/tcg/aarch64/system/kernel.ld
@@ -13,10 +13,12 @@ MEMORY {
SECTIONS {
.text : {
+ _text_start = .;
*(.text)
*(.rodata)
} >TXT
.data : {
+ _data_start = .;
*(.data)
*(.bss)
} >DAT
@@ -25,6 +27,7 @@ SECTIONS {
* Symbol 'mte_page' is used in boot.S to setup the PTE and in the mte.S
* test as the address that the MTE instructions operate on.
*/
+ _tag_start = .;
mte_page = .;
} >TAG
/DISCARD/ : {
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 5/7] tests/tcg: add HW page for aarch64 tests
2026-04-17 16:43 [PATCH 0/7] tests/tcg: more capabilities for aarch64-softmmu tests Alex Bennée
` (3 preceding siblings ...)
2026-04-17 16:43 ` [PATCH 4/7] tests/tcg: move aarch64 page table setup to c code Alex Bennée
@ 2026-04-17 16:43 ` Alex Bennée
2026-04-17 16:43 ` [PATCH 6/7] tests/tcg: create a mini-gic3 library Alex Bennée
2026-04-17 16:43 ` [PATCH 7/7] tests/tcg: add basic test for aarch64 wf[ie][t] insns Alex Bennée
6 siblings, 0 replies; 13+ messages in thread
From: Alex Bennée @ 2026-04-17 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Peter Maydell, Alex Bennée
If the test cases need to program items like the GIC we need to define
the region as Device-nGnRE memory. As this is for test cases just map
the whole first GB block (which is all HW in the -M virt machine).
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/aarch64/system/lib/pgtable.c | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/tests/tcg/aarch64/system/lib/pgtable.c b/tests/tcg/aarch64/system/lib/pgtable.c
index a558f5f0dd5..5e7d95fd3d7 100644
--- a/tests/tcg/aarch64/system/lib/pgtable.c
+++ b/tests/tcg/aarch64/system/lib/pgtable.c
@@ -17,14 +17,18 @@ uint64_t ttb_l1[512] __attribute__((aligned(4096)));
uint64_t ttb_l2[512] __attribute__((aligned(4096)));
/*
- * Setup a flat address mapping page-tables. Stage one simply
- * maps RAM to the first Gb. The stage2 tables have two 2mb
- * translation block entries covering a series of adjacent
- * 4k pages.
+ * Setup a flat address mapping page-tables.
+ *
+ * ttb (Level 1):
+ * - Entry 0 [0 - 1GB]: 1GB Device block (for GIC and other H/W)
+ * - Entry 1 [1GB - 2GB]: Table entry pointing to ttb_l2 (for RAM)
*/
void setup_pgtables(void)
{
- /* L1 entry points to L2 table */
+ /* L1 entry 0: 1GB Device block mapping at 0x0 */
+ pgt_map_l1_block(ttb_l1, 0, 0, DESC_AF | DESC_ATTRINDX(2));
+
+ /* L1 entry 1: points to L2 table for finer permissions */
pgt_map_l1_table(ttb_l1, (uintptr_t)_text_start, ttb_l2);
/* L2 entries: 2MB blocks */
@@ -40,8 +44,14 @@ void setup_pgtables(void)
/* Set TTBR0_EL1 */
write_sysreg(ttb_l1, ttbr0_el1);
- /* Set MAIR_EL1 */
- write_sysreg(0xeeULL, mair_el1);
+ /*
+ * Set MAIR_EL1
+ *
+ * Attr0 (0xee): Normal memory, Outer/Inner WB/WA/Read-Alloc
+ * Attr1 (0x00): MTE page
+ * Attr2 (0x04): Device-nGnRE memory (for the first 1GB)
+ */
+ write_sysreg(0x0400eeULL, mair_el1);
/* Set TCR_EL1 */
uint64_t tcr = TCR_EL1_IPS_40BIT | TCR_EL1_TG0_4KB | TCR_EL1_ORGN0_WBWA | TCR_EL1_IRGN0_WBWA | TCR_EL1_T0SZ(25);
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 6/7] tests/tcg: create a mini-gic3 library
2026-04-17 16:43 [PATCH 0/7] tests/tcg: more capabilities for aarch64-softmmu tests Alex Bennée
` (4 preceding siblings ...)
2026-04-17 16:43 ` [PATCH 5/7] tests/tcg: add HW page for aarch64 tests Alex Bennée
@ 2026-04-17 16:43 ` Alex Bennée
2026-04-17 16:43 ` [PATCH 7/7] tests/tcg: add basic test for aarch64 wf[ie][t] insns Alex Bennée
6 siblings, 0 replies; 13+ messages in thread
From: Alex Bennée @ 2026-04-17 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Peter Maydell, Alex Bennée
Just enough GIC to trigger timer interrupts.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/aarch64/system/lib/gicv3.h | 60 +++++++++++++++++++
tests/tcg/aarch64/system/lib/gicv3.c | 70 +++++++++++++++++++++++
tests/tcg/aarch64/Makefile.softmmu-target | 2 +
3 files changed, 132 insertions(+)
create mode 100644 tests/tcg/aarch64/system/lib/gicv3.h
create mode 100644 tests/tcg/aarch64/system/lib/gicv3.c
diff --git a/tests/tcg/aarch64/system/lib/gicv3.h b/tests/tcg/aarch64/system/lib/gicv3.h
new file mode 100644
index 00000000000..05c4c2f538b
--- /dev/null
+++ b/tests/tcg/aarch64/system/lib/gicv3.h
@@ -0,0 +1,60 @@
+/*
+ * GICv3 Helper Library
+ *
+ * Copyright (c) 2026 Linaro Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef GICV3_H
+#define GICV3_H
+
+/*
+ * This duplicates just the bits of hw/intc/gicv3_internal.h we
+ * need for basic functionality.
+ */
+
+/* Virt machine GICv3 base addresses */
+#define GICD_BASE 0x08000000 /* c.f. VIRT_GIC_DIST */
+#define GICR_BASE 0x080a0000 /* c.f. VIRT_GIC_REDIST */
+
+/* Distributor registers */
+#define GICD_CTLR (GICD_BASE + 0x0000)
+#define GICD_TYPER (GICD_BASE + 0x0004)
+#define GICD_IIDR (GICD_BASE + 0x0008)
+
+/* Redistributor registers (per-CPU) */
+#define GICR_SGI_OFFSET 0x00010000
+
+#define GICR_CTLR 0x0000
+#define GICR_WAKER 0x0014
+
+#define GICR_IGROUPR0 (GICR_SGI_OFFSET + 0x0080)
+#define GICR_ISENABLER0 (GICR_SGI_OFFSET + 0x0100)
+#define GICR_IPRIORITYR (GICR_SGI_OFFSET + 0x0400)
+
+/* GICD_CTLR fields */
+#define GICD_CTLR_ENA_GRP0 (1U << 0)
+#define GICD_CTLR_ENA_GRP1NS (1U << 1)
+#define GICD_CTLR_ARE_NS (1U << 5)
+
+/* GICR_WAKER bits */
+#define GICR_WAKER_ProcessorSleep (1U << 1)
+#define GICR_WAKER_ChildrenAsleep (1U << 2)
+
+/**
+ * gicv3_init:
+ *
+ * Initialize GICv3 distributor and the redistributor for the current CPU.
+ */
+void gicv3_init(void);
+
+/**
+ * gicv3_enable_irq:
+ * @irq: The IRQ number to enable
+ *
+ * Enable the specified IRQ (SPI or PPI).
+ */
+void gicv3_enable_irq(unsigned int irq);
+
+#endif /* GICV3_H */
diff --git a/tests/tcg/aarch64/system/lib/gicv3.c b/tests/tcg/aarch64/system/lib/gicv3.c
new file mode 100644
index 00000000000..9cfd033a8ec
--- /dev/null
+++ b/tests/tcg/aarch64/system/lib/gicv3.c
@@ -0,0 +1,70 @@
+/*
+ * GICv3 Helper Library Implementation
+ *
+ * Copyright (c) 2026 Linaro Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <stdint.h>
+#include "sysregs.h"
+#include "gicv3.h"
+
+static inline void write_reg(uintptr_t addr, uint32_t val)
+{
+ *(volatile uint32_t *) addr = val;
+}
+
+static inline uint32_t read_reg(uintptr_t addr)
+{
+ return *(volatile uint32_t *) addr;
+}
+
+void gicv3_init(void)
+{
+ uint32_t val;
+
+ /* 1. Enable Distributor ARE and Group 1 NS */
+ val = read_reg(GICD_CTLR);
+ val |= GICD_CTLR_ARE_NS | GICD_CTLR_ENA_GRP1NS;
+ write_reg(GICD_CTLR, val);
+
+ /* 2. Wake up Redistributor 0 and clear ProcessorSleep */
+ val = read_reg(GICR_BASE + GICR_WAKER);
+ val &= ~GICR_WAKER_ProcessorSleep;
+ write_reg(GICR_BASE + GICR_WAKER, val);
+
+ /* Wait for ChildrenAsleep to be cleared */
+ while (read_reg(GICR_BASE + GICR_WAKER) & GICR_WAKER_ChildrenAsleep) {
+ /* spin */
+ }
+
+ /* 3. Enable CPU interface */
+ /* Set Priority Mask to allow all interrupts */
+ write_sysreg(0xff, ICC_PMR_EL1);
+ /* Enable Group 1 Non-Secure interrupts */
+ write_sysreg(1, ICC_IGRPEN1_EL1);
+ isb();
+}
+
+void gicv3_enable_irq(unsigned int irq)
+{
+ if (irq < 32) {
+ /* PPI: use GICR_ISENABLER0 */
+ uintptr_t addr;
+
+ /* Set Group 1 */
+ addr = GICR_BASE + GICR_IGROUPR0;
+ write_reg(addr, read_reg(addr) | (1U << irq));
+
+ /* Set priority (0xa0) */
+ addr = GICR_BASE + GICR_IPRIORITYR + irq;
+ *(volatile uint8_t *)addr = 0xa0;
+
+ /* Enable it */
+ addr = GICR_BASE + GICR_ISENABLER0;
+ write_reg(addr, 1U << irq);
+ } else {
+ /* SPI: not implemented yet */
+ }
+}
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
index 5770ae1fb0c..543d638e819 100644
--- a/tests/tcg/aarch64/Makefile.softmmu-target
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
@@ -106,6 +106,8 @@ run-pauth-3:
$(call skip-test, "RUN of pauth-3", "not built")
endif
+gicv3.o: gicv3.c gicv3.h
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@
ifneq ($(CROSS_CC_HAS_ARMV8_MTE),)
QEMU_MTE_ENABLED_MACHINE=-M virt,mte=on -cpu max -display none
QEMU_OPTS_WITH_MTE_ON = $(QEMU_MTE_ENABLED_MACHINE) $(QEMU_BASE_ARGS) -kernel
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 7/7] tests/tcg: add basic test for aarch64 wf[ie][t] insns
2026-04-17 16:43 [PATCH 0/7] tests/tcg: more capabilities for aarch64-softmmu tests Alex Bennée
` (5 preceding siblings ...)
2026-04-17 16:43 ` [PATCH 6/7] tests/tcg: create a mini-gic3 library Alex Bennée
@ 2026-04-17 16:43 ` Alex Bennée
2026-04-23 15:57 ` Jim MacArthur
6 siblings, 1 reply; 13+ messages in thread
From: Alex Bennée @ 2026-04-17 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Peter Maydell, Alex Bennée
This is based on a generated test case which I've since refined and
cleaned up.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/aarch64/system/wfx.c | 143 ++++++++++++++++++++++
tests/tcg/aarch64/Makefile.softmmu-target | 8 ++
tests/tcg/aarch64/system/boot.S | 16 ++-
3 files changed, 164 insertions(+), 3 deletions(-)
create mode 100644 tests/tcg/aarch64/system/wfx.c
diff --git a/tests/tcg/aarch64/system/wfx.c b/tests/tcg/aarch64/system/wfx.c
new file mode 100644
index 00000000000..fa4c6761215
--- /dev/null
+++ b/tests/tcg/aarch64/system/wfx.c
@@ -0,0 +1,143 @@
+/*
+ * WFX Instructions Test (WFI, WFE, WFIT, WFET)
+ *
+ * Copyright (c) 2026 Linaro Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <minilib.h>
+#include "sysregs.h"
+#include "gicv3.h"
+
+#define TIMEOUT 200000
+
+#define sev() asm volatile("sev" : : : "memory")
+#define sevl() asm volatile("sevl" : : : "memory")
+#define wfi() asm volatile("wfi" : : : "memory")
+#define wfe() asm volatile("wfe" : : : "memory")
+#define wfit(reg) asm volatile("wfit %0" : : "r" (reg) : "memory")
+#define wfet(reg) asm volatile("wfet %0" : : "r" (reg) : "memory")
+
+#define enable_irq() asm volatile("msr daifclr, #2" : : : "memory")
+#define disable_irq() asm volatile("msr daifset, #2" : : : "memory")
+
+static bool check_elapsed(uint64_t start, uint64_t threshold, const char *test, bool more)
+{
+ uint64_t end = read_sysreg(cntvct_el0);
+ uint64_t elapsed = end - start;
+ if (more ? elapsed < threshold : elapsed > threshold) {
+ ml_printf("FAILED: %s %s (%ld ticks)\n", test,
+ more ? "woke too early" : "slept despite SEV",
+ elapsed);
+ return false;
+ }
+ ml_printf("PASSED (%ld ticks)\n", elapsed);
+ return true;
+}
+
+int main(void)
+{
+ uint64_t start, timeout;
+
+ gicv3_init();
+ gicv3_enable_irq(27); /* Virtual Timer PPI */
+
+ ml_printf("WFx[T] Tests\n");
+
+ /*
+ * 1. Test WFI with timer interrupt
+ *
+ * We don't have a full interrupt handler, but WFI should wake up
+ * when the interrupt is pending even if we have it masked at the CPU.
+ * PSTATE.I is set by boot code.
+ *
+ * We unmask interrupts here to ensure the CPU can take the minimal
+ * exception handler defined in boot.S.
+ */
+ ml_printf("Testing WFI...");
+
+ start = read_sysreg(cntvct_el0);
+ write_sysreg(TIMEOUT, cntv_tval_el0);
+ write_sysreg(1, cntv_ctl_el0); /* Enable timer, no mask */
+ isb();
+
+ enable_irq();
+ wfi();
+ disable_irq();
+
+ if (!check_elapsed(start, TIMEOUT, "WFI", true)) {
+ return 1;
+ }
+
+ /* Validate the timer fired and then disable for future tests */
+ if (!read_sysreg(cntv_ctl_el0) & 0x4) {
+ ml_printf("Time ISTATUS not set!\n");
+ return 1;
+ }
+ write_sysreg(0, cntv_ctl_el0);
+
+ /*
+ * 2. Test WFE and SEV[L]
+ *
+ * There are two SEV instructions, the normal one is a broadcast
+ * from any PE on the system, the other is local only.
+ * Functionally they have the same effect (setting the event
+ * register) and should be immediately consumed by the WFE.
+ *
+ * As we want to detect an early exit the sense of the timeout
+ * check is reversed.
+ */
+ ml_printf("Testing WFE/SEV...");
+ sev();
+ start = read_sysreg(cntvct_el0);
+ wfe();
+ if (!check_elapsed(start, TIMEOUT, "WFE", false)) {
+ return 1;
+ }
+
+ ml_printf("Testing WFE/SEVL...");
+ sevl();
+ start = read_sysreg(cntvct_el0);
+ wfe();
+ if (!check_elapsed(start, TIMEOUT, "WFE", false)) {
+ return 1;
+ }
+
+ /*
+ * 3. Test WFIT
+ *
+ * With the timer now disabled and no other IRQ sources firing the
+ * WFIT instruction should timeout. Although the architecture
+ * permits this being treated as a NOP we have enabled it.
+ */
+ ml_printf("Testing WFIT...");
+ start = read_sysreg(cntvct_el0);
+ timeout = start + TIMEOUT;
+ wfit(timeout);
+ if (!check_elapsed(start, TIMEOUT, "WFIT", true)) {
+ return 1;
+ }
+
+ /*
+ * 4. Test WFET
+ *
+ * Much like WFIT there are no IRQs to wake us up. However the
+ * event_register is a latch so we must first consume the event
+ * register with a normal WFE before we do the timeout version.
+ */
+ ml_printf("Testing WFET...");
+ sev();
+ wfe();
+ start = read_sysreg(cntvct_el0);
+ timeout = start + TIMEOUT;
+ wfet(timeout);
+ if (!check_elapsed(start, TIMEOUT, "WFET", true)) {
+ return 1;
+ }
+
+ ml_printf("ALL WFX TESTS PASSED\n");
+ return 0;
+}
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
index 543d638e819..6a1e867fba0 100644
--- a/tests/tcg/aarch64/Makefile.softmmu-target
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
@@ -108,6 +108,14 @@ endif
gicv3.o: gicv3.c gicv3.h
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@
+
+wfx: CFLAGS += -march=armv8.7-a
+wfx: LDFLAGS += gicv3.o
+wfx: gicv3.o
+
+QEMU_GICV3_MACHINE=-M virt,gic-version=3 -cpu max -display none
+run-wfx: QEMU_OPTS=$(QEMU_GICV3_MACHINE) $(QEMU_BASE_ARGS) -kernel
+
ifneq ($(CROSS_CC_HAS_ARMV8_MTE),)
QEMU_MTE_ENABLED_MACHINE=-M virt,mte=on -cpu max -display none
QEMU_OPTS_WITH_MTE_ON = $(QEMU_MTE_ENABLED_MACHINE) $(QEMU_BASE_ARGS) -kernel
diff --git a/tests/tcg/aarch64/system/boot.S b/tests/tcg/aarch64/system/boot.S
index bee8d9372e7..ba9000a749d 100644
--- a/tests/tcg/aarch64/system/boot.S
+++ b/tests/tcg/aarch64/system/boot.S
@@ -35,7 +35,7 @@ vector_table:
/* Current EL with SPx. */
ventry curr_spx_sync /* Synchronous */
- ventry curr_spx_irq /* IRQ/vIRQ */
+ ventry curr_spx_irq /* Basic handler for IRQ/vIRQ */
ventry curr_spx_fiq /* FIQ/vFIQ */
ventry curr_spx_serror /* SError/VSError */
@@ -54,13 +54,12 @@ vector_table:
.text
.align 4
- /* Common vector handling for now */
+ /* Apart from curr_spx_irq we error out with an unexpected exception */
curr_sp0_sync:
curr_sp0_irq:
curr_sp0_fiq:
curr_sp0_serror:
curr_spx_sync:
-curr_spx_irq:
curr_spx_fiq:
curr_spx_serror:
lower_a64_sync:
@@ -275,6 +274,17 @@ _exit:
semihosting_call
/* never returns */
+ /*
+ * IRQ handler
+ */
+ .global curr_spx_irq
+curr_spx_irq:
+ /* Minimal IRQ handler: just mask the timer and return */
+ mrs x0, cntv_ctl_el0
+ orr x0, x0, #2 /* IMASK=1 */
+ msr cntv_ctl_el0, x0
+ eret
+
/*
* Helper Functions
*/
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 7/7] tests/tcg: add basic test for aarch64 wf[ie][t] insns
2026-04-17 16:43 ` [PATCH 7/7] tests/tcg: add basic test for aarch64 wf[ie][t] insns Alex Bennée
@ 2026-04-23 15:57 ` Jim MacArthur
0 siblings, 0 replies; 13+ messages in thread
From: Jim MacArthur @ 2026-04-23 15:57 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée
On Fri, Apr 17, 2026 at 05:43:27PM +0100, Alex Bennée wrote:
> This is based on a generated test case which I've since refined and
> cleaned up.
>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> + /* Validate the timer fired and then disable for future tests */
> + if (!read_sysreg(cntv_ctl_el0) & 0x4) {
> + ml_printf("Time ISTATUS not set!\n");
> + return 1;
> + }
Should this be if (!(read_sysreg(cntv_ctl_el0) & 0x4)) ?
Jim
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/7] tests/tcg: introduce a lib dir for aarch64 system tests
2026-04-17 16:43 ` [PATCH 1/7] tests/tcg: introduce a lib dir for aarch64 system tests Alex Bennée
@ 2026-04-24 1:38 ` Richard Henderson
0 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2026-04-24 1:38 UTC (permalink / raw)
To: qemu-devel
On 4/18/26 02:43, Alex Bennée wrote:
> We are about to add some more helpers but lets start by adding a
> simple wrapper for reading and writing system registers.
>
> Do note the subtle switch of ordering for write_sysreg() which matches
> the change the kernel made sometime in 2021 (see 272a067df in linux.git).
>
> Signed-off-by: Alex Bennée<alex.bennee@linaro.org>
> ---
> tests/tcg/aarch64/system/lib/sysregs.h | 22 ++++++++++++++++++++++
> tests/tcg/aarch64/system/vtimer.c | 23 ++++-------------------
> tests/tcg/aarch64/Makefile.softmmu-target | 3 ++-
> 3 files changed, 28 insertions(+), 20 deletions(-)
> create mode 100644 tests/tcg/aarch64/system/lib/sysregs.h
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/7] tests/tcg: convert aarch64 feat-xs test to use helpers
2026-04-17 16:43 ` [PATCH 2/7] tests/tcg: convert aarch64 feat-xs test to use helpers Alex Bennée
@ 2026-04-24 1:38 ` Richard Henderson
0 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2026-04-24 1:38 UTC (permalink / raw)
To: qemu-devel
On 4/18/26 02:43, Alex Bennée wrote:
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> tests/tcg/aarch64/system/feat-xs.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/tests/tcg/aarch64/system/feat-xs.c b/tests/tcg/aarch64/system/feat-xs.c
> index f310fc837e0..e2324cef1af 100644
> --- a/tests/tcg/aarch64/system/feat-xs.c
> +++ b/tests/tcg/aarch64/system/feat-xs.c
> @@ -8,12 +8,12 @@
>
> #include <minilib.h>
> #include <stdint.h>
> +#include "sysregs.h"
>
> int main(void)
> {
> - uint64_t isar1;
> + uint64_t isar1 = read_sysreg(id_aa64isar1_el1);
>
> - asm volatile ("mrs %0, id_aa64isar1_el1" : "=r"(isar1));
> if (((isar1 >> 56) & 0xf) < 1) {
> ml_printf("FEAT_XS not supported by CPU");
> return 1;
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/7] tests/tcg: convert aarch64 asid2 test to use sysreg helpers
2026-04-17 16:43 ` [PATCH 3/7] tests/tcg: convert aarch64 asid2 test to use sysreg helpers Alex Bennée
@ 2026-04-24 1:39 ` Richard Henderson
0 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2026-04-24 1:39 UTC (permalink / raw)
To: qemu-devel
On 4/18/26 02:43, Alex Bennée wrote:
> While we are at it we can reduce the number of temporary variables
> needed and fix a format string error.
>
> Signed-off-by: Alex Bennée<alex.bennee@linaro.org>
> ---
> tests/tcg/aarch64/system/asid2.c | 35 ++++++++++++++------------------
> 1 file changed, 15 insertions(+), 20 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 4/7] tests/tcg: move aarch64 page table setup to c code
2026-04-17 16:43 ` [PATCH 4/7] tests/tcg: move aarch64 page table setup to c code Alex Bennée
@ 2026-05-07 17:13 ` Jim MacArthur
0 siblings, 0 replies; 13+ messages in thread
From: Jim MacArthur @ 2026-05-07 17:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennee
On Fri, Apr 17, 2026 at 05:43:24PM +0100, Alex Bennée wrote:
> If we want more flexibility messing around with page tables lets do it
> without having to rely on assembly for it.
>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>
> ---
> AJB
> - a result of -O0 does mean each helper ends up with a stack frame
> being needed to do the relatively simple mask and shift. I've
> experimented with -O1 and trying to manually enable inlining but
> couldn't get anything to work.
> ---
> +#define DESC_AF (1ULL << 10)
> +#define DESC_ATTRINDX(i) ((uint64_t)(i) << 2)
> +#define DESC_NS (1ULL << 5)
> +#define DESC_UXN (1ULL << 53)
> +#define DESC_PXN (1ULL << 54)
I *think* you have UXN and PXN the wrong way round? See table D8-52; UXN is always 54.
It works fine in this case as we always use them together.
Otherwise,
Reviewed-by: Jim MacArthur <jim.macarthur@linaro.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-05-07 17:13 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-17 16:43 [PATCH 0/7] tests/tcg: more capabilities for aarch64-softmmu tests Alex Bennée
2026-04-17 16:43 ` [PATCH 1/7] tests/tcg: introduce a lib dir for aarch64 system tests Alex Bennée
2026-04-24 1:38 ` Richard Henderson
2026-04-17 16:43 ` [PATCH 2/7] tests/tcg: convert aarch64 feat-xs test to use helpers Alex Bennée
2026-04-24 1:38 ` Richard Henderson
2026-04-17 16:43 ` [PATCH 3/7] tests/tcg: convert aarch64 asid2 test to use sysreg helpers Alex Bennée
2026-04-24 1:39 ` Richard Henderson
2026-04-17 16:43 ` [PATCH 4/7] tests/tcg: move aarch64 page table setup to c code Alex Bennée
2026-05-07 17:13 ` Jim MacArthur
2026-04-17 16:43 ` [PATCH 5/7] tests/tcg: add HW page for aarch64 tests Alex Bennée
2026-04-17 16:43 ` [PATCH 6/7] tests/tcg: create a mini-gic3 library Alex Bennée
2026-04-17 16:43 ` [PATCH 7/7] tests/tcg: add basic test for aarch64 wf[ie][t] insns Alex Bennée
2026-04-23 15:57 ` Jim MacArthur
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.