* [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support
@ 2025-09-25 14:19 Joey Gouly
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 01/10] arm64: drop to EL1 if booted at EL2 Joey Gouly
` (12 more replies)
0 siblings, 13 replies; 38+ messages in thread
From: Joey Gouly @ 2025-09-25 14:19 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Hi all,
This series is for adding support to running the kvm-unit-tests at EL2. These
have been tested with Linux 6.17-rc6 KVM nested virt.
This latest round I also tested using the run_tests.sh script with QEMU TCG,
running at EL2.
The goal is to later extend and add new tests for Nested Virtualisation,
however they should also work with bare metal as well.
Changes since v2[1]:
- Move the sctlr setup in EFI to a function.
- Decided to not re-use el2_setup.h from Linux, looked more
complicated to use than needed for KUT.
- Add EL2 env variable for testing, open to feedback for that.
This was untested with kvmtool as my testing setup only has
busybox ash currently, and the run_tests.sh script needs bash.
Issues (that I think are fine to investigate/fix later):
- Some of the debug tests fail with QEMU at EL2 and kvmtool.
- The gic ipi test times out with QEMU at EL2, but works with kvmtool.
Thanks,
Joey
[1] https://lore.kernel.org/kvmarm/20250529135557.2439500-1-joey.gouly@arm.com/
Alexandru Elisei (2):
arm64: micro-bench: use smc when at EL2
arm64: selftest: update test for running at EL2
Joey Gouly (8):
arm64: drop to EL1 if booted at EL2
arm64: efi: initialise SCTLR_ELx fully
arm64: efi: initialise the EL
arm64: timer: use hypervisor timers when at EL2
arm64: micro-bench: fix timer IRQ
arm64: pmu: count EL2 cycles
arm64: run at EL2 if supported
arm64: add EL2 environment variable
arm/cstart64.S | 56 ++++++++++++++++++++++++++++++++++++--
arm/efi/crt0-efi-aarch64.S | 5 ++++
arm/micro-bench.c | 26 ++++++++++++++++--
arm/pmu.c | 13 ++++++---
arm/run | 7 +++++
arm/selftest.c | 18 ++++++++----
arm/timer.c | 10 +++++--
lib/acpi.h | 2 ++
lib/arm/asm/setup.h | 8 ++++++
lib/arm/asm/timer.h | 11 ++++++++
lib/arm/setup.c | 4 +++
lib/arm/timer.c | 19 +++++++++++--
lib/arm64/asm/sysreg.h | 19 +++++++++++++
lib/arm64/processor.c | 12 ++++++++
14 files changed, 191 insertions(+), 19 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 38+ messages in thread
* [kvm-unit-tests PATCH v3 01/10] arm64: drop to EL1 if booted at EL2
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
@ 2025-09-25 14:19 ` Joey Gouly
2025-11-27 17:07 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 02/10] arm64: efi: initialise SCTLR_ELx fully Joey Gouly
` (11 subsequent siblings)
12 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-09-25 14:19 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
EL2 is not currently supported, drop to EL1 to conitnue booting.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
arm/cstart64.S | 47 +++++++++++++++++++++++++++++++++++++++---
lib/arm64/asm/sysreg.h | 14 +++++++++++++
2 files changed, 58 insertions(+), 3 deletions(-)
diff --git a/arm/cstart64.S b/arm/cstart64.S
index 014c9c7b..79b93dd4 100644
--- a/arm/cstart64.S
+++ b/arm/cstart64.S
@@ -15,6 +15,46 @@
#include <asm/thread_info.h>
#include <asm/sysreg.h>
+.macro init_el, tmp
+ mrs \tmp, CurrentEL
+ cmp \tmp, CurrentEL_EL2
+ b.ne 1f
+ /* EL2 setup */
+ mrs \tmp, mpidr_el1
+ msr vmpidr_el2, \tmp
+ mrs \tmp, midr_el1
+ msr vpidr_el2, \tmp
+ /* clear trap registers */
+ mrs \tmp, id_aa64mmfr0_el1
+ ubfx \tmp, \tmp, #ID_AA64MMFR0_EL1_FGT_SHIFT, #4
+ cbz \tmp, .Lskip_fgt_\@
+ mov \tmp, #0
+ msr_s SYS_HFGRTR_EL2, \tmp
+ msr_s SYS_HFGWTR_EL2, \tmp
+ msr_s SYS_HFGITR_EL2, \tmp
+ mrs \tmp, id_aa64mmfr0_el1
+ ubfx \tmp, \tmp, #ID_AA64MMFR0_EL1_FGT_SHIFT, #4
+ cmp \tmp, #ID_AA64MMFR0_EL1_FGT_FGT2
+ bne .Lskip_fgt_\@
+ mov \tmp, #0
+ msr_s SYS_HFGRTR2_EL2, \tmp
+ msr_s SYS_HFGWTR2_EL2, \tmp
+ msr_s SYS_HFGITR2_EL2, \tmp
+.Lskip_fgt_\@:
+ mov \tmp, #0
+ msr cptr_el2, \tmp
+ ldr \tmp, =(INIT_HCR_EL2_EL1_ONLY)
+ msr hcr_el2, \tmp
+ mov \tmp, PSR_MODE_EL1t
+ msr spsr_el2, \tmp
+ adrp \tmp, 1f
+ add \tmp, \tmp, :lo12:1f
+ msr elr_el2, \tmp
+ eret
+1:
+.endm
+
+
#ifdef CONFIG_EFI
#include "efi/crt0-efi-aarch64.S"
#else
@@ -56,15 +96,15 @@ start:
add x6, x6, :lo12:reloc_end
1:
cmp x5, x6
- b.hs 1f
+ b.hs reloc_done
ldr x7, [x5] // r_offset
ldr x8, [x5, #16] // r_addend
add x8, x8, x4 // val = base + r_addend
str x8, [x4, x7] // base[r_offset] = val
add x5, x5, #24
b 1b
-
-1:
+reloc_done:
+ init_el x4
/* zero BSS */
adrp x4, bss
add x4, x4, :lo12:bss
@@ -185,6 +225,7 @@ get_mmu_off:
.globl secondary_entry
secondary_entry:
+ init_el x0
/* enable FP/ASIMD and SVE */
mov x0, #(3 << 20)
orr x0, x0, #(3 << 16)
diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h
index e537bb46..ed776716 100644
--- a/lib/arm64/asm/sysreg.h
+++ b/lib/arm64/asm/sysreg.h
@@ -77,6 +77,9 @@ asm(
#define ID_AA64ISAR0_EL1_RNDR_SHIFT 60
#define ID_AA64PFR1_EL1_MTE_SHIFT 8
+#define ID_AA64MMFR0_EL1_FGT_SHIFT 56
+#define ID_AA64MMFR0_EL1_FGT_FGT2 0x2
+
#define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0)
#define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
#define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
@@ -113,6 +116,17 @@ asm(
#define SCTLR_EL1_TCF0_SHIFT 38
#define SCTLR_EL1_TCF0_MASK GENMASK_ULL(39, 38)
+#define HCR_EL2_RW _BITULL(31)
+
+#define INIT_HCR_EL2_EL1_ONLY (HCR_EL2_RW)
+
+#define SYS_HFGRTR_EL2 sys_reg(3, 4, 1, 1, 4)
+#define SYS_HFGWTR_EL2 sys_reg(3, 4, 1, 1, 5)
+#define SYS_HFGITR_EL2 sys_reg(3, 4, 1, 1, 6)
+#define SYS_HFGRTR2_EL2 sys_reg(3, 4, 3, 1, 2)
+#define SYS_HFGWTR2_EL2 sys_reg(3, 4, 3, 1, 3)
+#define SYS_HFGITR2_EL2 sys_reg(3, 4, 3, 1, 7)
+
#define INIT_SCTLR_EL1_MMU_OFF \
(SCTLR_EL1_ITD | SCTLR_EL1_SED | SCTLR_EL1_EOS | \
SCTLR_EL1_TSCXT | SCTLR_EL1_EIS | SCTLR_EL1_SPAN | \
--
2.25.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [kvm-unit-tests PATCH v3 02/10] arm64: efi: initialise SCTLR_ELx fully
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 01/10] arm64: drop to EL1 if booted at EL2 Joey Gouly
@ 2025-09-25 14:19 ` Joey Gouly
2025-11-27 16:49 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 03/10] arm64: efi: initialise the EL Joey Gouly
` (10 subsequent siblings)
12 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-09-25 14:19 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Don't rely on the value of SCTLR_ELx when booting via EFI.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
lib/arm/asm/setup.h | 6 ++++++
lib/arm/setup.c | 3 +++
lib/arm64/processor.c | 12 ++++++++++++
3 files changed, 21 insertions(+)
diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h
index 9f8ef82e..4e60d552 100644
--- a/lib/arm/asm/setup.h
+++ b/lib/arm/asm/setup.h
@@ -28,6 +28,12 @@ void setup(const void *fdt, phys_addr_t freemem_start);
#include <efi.h>
+#ifdef __aarch64__
+void setup_efi_sctlr(void);
+#else
+static inline void setup_efi_sctlr(void) {}
+#endif
+
efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo);
#endif
diff --git a/lib/arm/setup.c b/lib/arm/setup.c
index 67b5db07..0aaa1d3a 100644
--- a/lib/arm/setup.c
+++ b/lib/arm/setup.c
@@ -349,6 +349,9 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
{
efi_status_t status;
+
+ setup_efi_sctlr();
+
exceptions_init();
memregions_init(arm_mem_regions, NR_MEM_REGIONS);
diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c
index eb93fd7c..edc0ad87 100644
--- a/lib/arm64/processor.c
+++ b/lib/arm64/processor.c
@@ -8,6 +8,7 @@
#include <libcflat.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
+#include <asm/setup.h>
#include <asm/thread_info.h>
static const char *vector_names[] = {
@@ -271,3 +272,14 @@ bool __mmu_enabled(void)
{
return read_sysreg(sctlr_el1) & SCTLR_EL1_M;
}
+
+#ifdef CONFIG_EFI
+
+void setup_efi_sctlr(void)
+{
+ // EFI exits boot services with SCTLR_ELx.M=1, so keep
+ // the MMU enabled.
+ write_sysreg(INIT_SCTLR_EL1_MMU_OFF | SCTLR_EL1_M, sctlr_el1);
+}
+
+#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [kvm-unit-tests PATCH v3 03/10] arm64: efi: initialise the EL
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 01/10] arm64: drop to EL1 if booted at EL2 Joey Gouly
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 02/10] arm64: efi: initialise SCTLR_ELx fully Joey Gouly
@ 2025-09-25 14:19 ` Joey Gouly
2025-11-27 17:08 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 04/10] arm64: timer: use hypervisor timers when at EL2 Joey Gouly
` (9 subsequent siblings)
12 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-09-25 14:19 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Initialise the exception level, which may include dropping to EL1 from EL2, if
VHE is not supported.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
arm/efi/crt0-efi-aarch64.S | 5 +++++
lib/arm/asm/setup.h | 2 ++
lib/arm/setup.c | 1 +
3 files changed, 8 insertions(+)
diff --git a/arm/efi/crt0-efi-aarch64.S b/arm/efi/crt0-efi-aarch64.S
index 71ce2794..5632fee0 100644
--- a/arm/efi/crt0-efi-aarch64.S
+++ b/arm/efi/crt0-efi-aarch64.S
@@ -147,6 +147,11 @@ _start:
0: ldp x29, x30, [sp], #32
ret
+.globl do_init_el
+do_init_el:
+ init_el x16
+ ret
+
.section .data
.balign 65536
diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h
index 4e60d552..bf05ffbb 100644
--- a/lib/arm/asm/setup.h
+++ b/lib/arm/asm/setup.h
@@ -29,8 +29,10 @@ void setup(const void *fdt, phys_addr_t freemem_start);
#include <efi.h>
#ifdef __aarch64__
+void do_init_el(void);
void setup_efi_sctlr(void);
#else
+static inline void do_init_el(void) {}
static inline void setup_efi_sctlr(void) {}
#endif
diff --git a/lib/arm/setup.c b/lib/arm/setup.c
index 0aaa1d3a..5ff40b54 100644
--- a/lib/arm/setup.c
+++ b/lib/arm/setup.c
@@ -349,6 +349,7 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
{
efi_status_t status;
+ do_init_el();
setup_efi_sctlr();
--
2.25.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [kvm-unit-tests PATCH v3 04/10] arm64: timer: use hypervisor timers when at EL2
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
` (2 preceding siblings ...)
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 03/10] arm64: efi: initialise the EL Joey Gouly
@ 2025-09-25 14:19 ` Joey Gouly
2025-12-02 8:36 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 05/10] arm64: micro-bench: fix timer IRQ Joey Gouly
` (8 subsequent siblings)
12 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-09-25 14:19 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
At EL2, with VHE:
CNT{P,V}_{TVAL,CTL}_EL0 is forwarded to CNTH{P,V}_{CVAL,TVAL,CTL}_EL0.
Save the hypervisor physical and virtual timer IRQ numbers from the DT/ACPI.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
arm/timer.c | 10 ++++++++--
lib/acpi.h | 2 ++
lib/arm/asm/timer.h | 11 +++++++++++
lib/arm/timer.c | 19 +++++++++++++++++--
4 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/arm/timer.c b/arm/timer.c
index 2cb80518..c6287ca7 100644
--- a/arm/timer.c
+++ b/arm/timer.c
@@ -347,8 +347,14 @@ static void test_ptimer(void)
static void test_init(void)
{
assert(TIMER_PTIMER_IRQ != -1 && TIMER_VTIMER_IRQ != -1);
- ptimer_info.irq = TIMER_PTIMER_IRQ;
- vtimer_info.irq = TIMER_VTIMER_IRQ;
+ if (current_level() == CurrentEL_EL1) {
+ ptimer_info.irq = TIMER_PTIMER_IRQ;
+ vtimer_info.irq = TIMER_VTIMER_IRQ;
+ } else {
+ assert(TIMER_HPTIMER_IRQ != -1 && TIMER_HVTIMER_IRQ != -1);
+ ptimer_info.irq = TIMER_HPTIMER_IRQ;
+ vtimer_info.irq = TIMER_HVTIMER_IRQ;
+ }
install_exception_handler(EL1H_SYNC, ESR_EL1_EC_UNKNOWN, ptimer_unsupported_handler);
ptimer_info.read_ctl();
diff --git a/lib/acpi.h b/lib/acpi.h
index c330c877..66e3062d 100644
--- a/lib/acpi.h
+++ b/lib/acpi.h
@@ -290,6 +290,8 @@ struct acpi_table_gtdt {
u64 counter_read_block_address;
u32 platform_timer_count;
u32 platform_timer_offset;
+ u32 virtual_el2_timer_interrupt;
+ u32 virtual_el2_timer_flags;
};
/* Reset to default packing */
diff --git a/lib/arm/asm/timer.h b/lib/arm/asm/timer.h
index fd8f7796..0dcebc1c 100644
--- a/lib/arm/asm/timer.h
+++ b/lib/arm/asm/timer.h
@@ -21,12 +21,23 @@ struct timer_state {
u32 irq;
u32 irq_flags;
} vtimer;
+ struct {
+ u32 irq;
+ u32 irq_flags;
+ } hptimer;
+ struct {
+ u32 irq;
+ u32 irq_flags;
+ } hvtimer;
};
extern struct timer_state __timer_state;
#define TIMER_PTIMER_IRQ (__timer_state.ptimer.irq)
#define TIMER_VTIMER_IRQ (__timer_state.vtimer.irq)
+#define TIMER_HPTIMER_IRQ (__timer_state.hptimer.irq)
+#define TIMER_HVTIMER_IRQ (__timer_state.hvtimer.irq)
+
void timer_save_state(void);
#endif /* !__ASSEMBLER__ */
diff --git a/lib/arm/timer.c b/lib/arm/timer.c
index ae702e41..57f504e2 100644
--- a/lib/arm/timer.c
+++ b/lib/arm/timer.c
@@ -38,10 +38,11 @@ static void timer_save_state_fdt(void)
* secure timer irq
* non-secure timer irq (ptimer)
* virtual timer irq (vtimer)
- * hypervisor timer irq
+ * hypervisor timer irq (hptimer)
+ * hypervisor virtual timer irq (hvtimer)
*/
prop = fdt_get_property(fdt, node, "interrupts", &len);
- assert(prop && len == (4 * 3 * sizeof(u32)));
+ assert(prop && len >= (4 * 3 * sizeof(u32)));
data = (u32 *) prop->data;
assert(fdt32_to_cpu(data[3]) == 1 /* PPI */ );
@@ -50,6 +51,14 @@ static void timer_save_state_fdt(void)
assert(fdt32_to_cpu(data[6]) == 1 /* PPI */ );
__timer_state.vtimer.irq = PPI(fdt32_to_cpu(data[7]));
__timer_state.vtimer.irq_flags = fdt32_to_cpu(data[8]);
+ if (len == (5 * 3 * sizeof(u32))) {
+ assert(fdt32_to_cpu(data[9]) == 1 /* PPI */ );
+ __timer_state.hptimer.irq = PPI(fdt32_to_cpu(data[10]));
+ __timer_state.hptimer.irq_flags = fdt32_to_cpu(data[11]);
+ assert(fdt32_to_cpu(data[12]) == 1 /* PPI */ );
+ __timer_state.hvtimer.irq = PPI(fdt32_to_cpu(data[13]));
+ __timer_state.hvtimer.irq_flags = fdt32_to_cpu(data[14]);
+ }
}
#ifdef CONFIG_EFI
@@ -72,6 +81,12 @@ static void timer_save_state_acpi(void)
__timer_state.vtimer.irq = gtdt->virtual_timer_interrupt;
__timer_state.vtimer.irq_flags = gtdt->virtual_timer_flags;
+
+ __timer_state.hptimer.irq = gtdt->non_secure_el2_interrupt;
+ __timer_state.hptimer.irq_flags = gtdt->non_secure_el2_flags;
+
+ __timer_state.hvtimer.irq = gtdt->virtual_el2_timer_interrupt;
+ __timer_state.hvtimer.irq_flags = gtdt->virtual_el2_timer_flags;
}
#else
--
2.25.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [kvm-unit-tests PATCH v3 05/10] arm64: micro-bench: fix timer IRQ
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
` (3 preceding siblings ...)
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 04/10] arm64: timer: use hypervisor timers when at EL2 Joey Gouly
@ 2025-09-25 14:19 ` Joey Gouly
2025-12-02 8:36 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 06/10] arm64: micro-bench: use smc when at EL2 Joey Gouly
` (7 subsequent siblings)
12 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-09-25 14:19 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Enable the correct (hvtimer) IRQ when at EL2.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
arm/micro-bench.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/arm/micro-bench.c b/arm/micro-bench.c
index 22408955..f47c5fc1 100644
--- a/arm/micro-bench.c
+++ b/arm/micro-bench.c
@@ -42,7 +42,7 @@ static void gic_irq_handler(struct pt_regs *regs)
irq_received = true;
gic_write_eoir(irqstat);
- if (irqstat == TIMER_VTIMER_IRQ) {
+ if (irqstat == TIMER_VTIMER_IRQ || irqstat == TIMER_HVTIMER_IRQ) {
write_sysreg((ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE),
cntv_ctl_el0);
isb();
@@ -215,7 +215,11 @@ static bool timer_prep(void)
install_irq_handler(EL1H_IRQ, gic_irq_handler);
local_irq_enable();
- gic_enable_irq(TIMER_VTIMER_IRQ);
+ if (current_level() == CurrentEL_EL1)
+ gic_enable_irq(TIMER_VTIMER_IRQ);
+ else
+ gic_enable_irq(TIMER_HVTIMER_IRQ);
+
write_sysreg(ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
isb();
--
2.25.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [kvm-unit-tests PATCH v3 06/10] arm64: micro-bench: use smc when at EL2
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
` (4 preceding siblings ...)
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 05/10] arm64: micro-bench: fix timer IRQ Joey Gouly
@ 2025-09-25 14:19 ` Joey Gouly
2025-12-02 9:11 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 07/10] arm64: selftest: update test for running " Joey Gouly
` (6 subsequent siblings)
12 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-09-25 14:19 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
From: Alexandru Elisei <alexandru.elisei@arm.com>
At EL2, hvc would target the current EL, use smc so that it targets EL3.
Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
arm/micro-bench.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/arm/micro-bench.c b/arm/micro-bench.c
index f47c5fc1..32029c5a 100644
--- a/arm/micro-bench.c
+++ b/arm/micro-bench.c
@@ -282,6 +282,11 @@ static bool mmio_read_user_prep(void)
return true;
}
+static void smc_exec(void)
+{
+ asm volatile("mov w0, #0x4b000000; smc #0" ::: "w0");
+}
+
static void mmio_read_user_exec(void)
{
readl(userspace_emulated_addr);
@@ -300,6 +305,8 @@ static void eoi_exec(void)
write_eoir(spurious_id);
}
+static bool exec_select(void);
+
struct exit_test {
const char *name;
bool (*prep)(void);
@@ -310,7 +317,7 @@ struct exit_test {
};
static struct exit_test tests[] = {
- {"hvc", NULL, hvc_exec, NULL, 65536, true},
+ {"hyp_call", exec_select, hvc_exec, NULL, 65536, true},
{"mmio_read_user", mmio_read_user_prep, mmio_read_user_exec, NULL, 65536, true},
{"mmio_read_vgic", NULL, mmio_read_vgic_exec, NULL, 65536, true},
{"eoi", NULL, eoi_exec, NULL, 65536, true},
@@ -320,6 +327,15 @@ static struct exit_test tests[] = {
{"timer_10ms", timer_prep, timer_exec, timer_post, 256, true},
};
+static bool exec_select(void)
+{
+ if (current_level() == CurrentEL_EL2)
+ tests[0].exec = &smc_exec;
+ else
+ tests[0].exec = &hvc_exec;
+ return true;
+}
+
struct ns_time {
uint64_t ns;
uint64_t ns_frac;
--
2.25.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [kvm-unit-tests PATCH v3 07/10] arm64: selftest: update test for running at EL2
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
` (5 preceding siblings ...)
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 06/10] arm64: micro-bench: use smc when at EL2 Joey Gouly
@ 2025-09-25 14:19 ` Joey Gouly
2025-12-02 9:16 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 08/10] arm64: pmu: count EL2 cycles Joey Gouly
` (5 subsequent siblings)
12 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-09-25 14:19 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
From: Alexandru Elisei <alexandru.elisei@arm.com>
Remove some hard-coded assumptions that this test is running at EL1.
Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
arm/selftest.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/arm/selftest.c b/arm/selftest.c
index 1553ed8e..01691389 100644
--- a/arm/selftest.c
+++ b/arm/selftest.c
@@ -232,6 +232,7 @@ static void user_psci_system_off(struct pt_regs *regs)
__user_psci_system_off();
}
#elif defined(__aarch64__)
+static unsigned long expected_level;
/*
* Capture the current register state and execute an instruction
@@ -276,8 +277,7 @@ static bool check_regs(struct pt_regs *regs)
{
unsigned i;
- /* exception handlers should always run in EL1 */
- if (current_level() != CurrentEL_EL1)
+ if (current_level() != expected_level)
return false;
for (i = 0; i < ARRAY_SIZE(regs->regs); ++i) {
@@ -301,7 +301,11 @@ static enum vector check_vector_prep(void)
return EL0_SYNC_64;
asm volatile("mrs %0, daif" : "=r" (daif) ::);
- expected_regs.pstate = daif | PSR_MODE_EL1h;
+ expected_regs.pstate = daif;
+ if (current_level() == CurrentEL_EL1)
+ expected_regs.pstate |= PSR_MODE_EL1h;
+ else
+ expected_regs.pstate |= PSR_MODE_EL2h;
return EL1H_SYNC;
}
@@ -317,8 +321,8 @@ static bool check_und(void)
install_exception_handler(v, ESR_EL1_EC_UNKNOWN, unknown_handler);
- /* try to read an el2 sysreg from el0/1 */
- test_exception("", "mrs x0, sctlr_el2", "", "x0");
+ /* try to read an el3 sysreg from el0/1/2 */
+ test_exception("", "mrs x0, sctlr_el3", "", "x0");
install_exception_handler(v, ESR_EL1_EC_UNKNOWN, NULL);
@@ -429,6 +433,10 @@ int main(int argc, char **argv)
if (argc < 2)
report_abort("no test specified");
+#if defined(__aarch64__)
+ expected_level = current_level();
+#endif
+
report_prefix_push(argv[1]);
if (strcmp(argv[1], "setup") == 0) {
--
2.25.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [kvm-unit-tests PATCH v3 08/10] arm64: pmu: count EL2 cycles
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
` (6 preceding siblings ...)
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 07/10] arm64: selftest: update test for running " Joey Gouly
@ 2025-09-25 14:19 ` Joey Gouly
2025-12-02 10:31 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 09/10] arm64: run at EL2 if supported Joey Gouly
` (4 subsequent siblings)
12 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-09-25 14:19 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Count EL2 cycles if that's the EL kvm-unit-tests is running at!
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
arm/pmu.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/arm/pmu.c b/arm/pmu.c
index 2dc0822b..e6c0f05b 100644
--- a/arm/pmu.c
+++ b/arm/pmu.c
@@ -121,6 +121,8 @@ static struct pmu pmu;
#define PMINTENCLR __ACCESS_CP15(c9, 0, c14, 2)
#define PMCCNTR64 __ACCESS_CP15_64(0, c9)
+#define PMCCFILTR_EL0_DEFAULT 0
+
static inline uint32_t get_id_dfr0(void) { return read_sysreg(ID_DFR0); }
static inline uint32_t get_pmcr(void) { return read_sysreg(PMCR); }
static inline void set_pmcr(uint32_t v) { write_sysreg(v, PMCR); }
@@ -206,6 +208,9 @@ static void test_overflow_interrupt(bool overflow_at_64bits) {}
#define ID_DFR0_PMU_V3_8_5 0b0110
#define ID_DFR0_PMU_IMPDEF 0b1111
+#define PMCCFILTR_EL0_NSH BIT(27)
+#define PMCCFILTR_EL0_DEFAULT (current_level() == CurrentEL_EL2 ? PMCCFILTR_EL0_NSH : 0)
+
static inline uint32_t get_id_aa64dfr0(void) { return read_sysreg(id_aa64dfr0_el1); }
static inline uint32_t get_pmcr(void) { return read_sysreg(pmcr_el0); }
static inline void set_pmcr(uint32_t v) { write_sysreg(v, pmcr_el0); }
@@ -246,8 +251,7 @@ static inline void precise_instrs_loop(int loop, uint32_t pmcr)
#define PMCNTENSET_EL0 sys_reg(3, 3, 9, 12, 1)
#define PMCNTENCLR_EL0 sys_reg(3, 3, 9, 12, 2)
-#define PMEVTYPER_EXCLUDE_EL1 BIT(31)
-#define PMEVTYPER_EXCLUDE_EL0 BIT(30)
+#define PMEVTYPER_EXCLUDE_EL0 BIT(30) | (current_level() == CurrentEL_EL2 ? BIT(27) : 0)
static bool is_event_supported(uint32_t n, bool warn)
{
@@ -1063,7 +1067,8 @@ static bool check_cycles_increase(void)
/* init before event access, this test only cares about cycle count */
pmu_reset();
set_pmcntenset(1 << PMU_CYCLE_IDX);
- set_pmccfiltr(0); /* count cycles in EL0, EL1, but not EL2 */
+
+ set_pmccfiltr(PMCCFILTR_EL0_DEFAULT);
set_pmcr(get_pmcr() | PMU_PMCR_LC | PMU_PMCR_C | PMU_PMCR_E);
isb();
@@ -1118,7 +1123,7 @@ static bool check_cpi(int cpi)
/* init before event access, this test only cares about cycle count */
pmu_reset();
set_pmcntenset(1 << PMU_CYCLE_IDX);
- set_pmccfiltr(0); /* count cycles in EL0, EL1, but not EL2 */
+ set_pmccfiltr(PMCCFILTR_EL0_DEFAULT);
if (cpi > 0)
printf("Checking for CPI=%d.\n", cpi);
--
2.25.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [kvm-unit-tests PATCH v3 09/10] arm64: run at EL2 if supported
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
` (7 preceding siblings ...)
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 08/10] arm64: pmu: count EL2 cycles Joey Gouly
@ 2025-09-25 14:19 ` Joey Gouly
2025-12-02 10:35 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 10/10] arm64: add EL2 environment variable Joey Gouly
` (3 subsequent siblings)
12 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-09-25 14:19 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
If VHE is supported, continue booting at EL2, otherwise continue booting at
EL1.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
arm/cstart64.S | 17 +++++++++++++----
lib/arm64/asm/sysreg.h | 5 +++++
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/arm/cstart64.S b/arm/cstart64.S
index 79b93dd4..af7c81c1 100644
--- a/arm/cstart64.S
+++ b/arm/cstart64.S
@@ -18,7 +18,7 @@
.macro init_el, tmp
mrs \tmp, CurrentEL
cmp \tmp, CurrentEL_EL2
- b.ne 1f
+ b.ne 2f
/* EL2 setup */
mrs \tmp, mpidr_el1
msr vmpidr_el2, \tmp
@@ -41,17 +41,26 @@
msr_s SYS_HFGWTR2_EL2, \tmp
msr_s SYS_HFGITR2_EL2, \tmp
.Lskip_fgt_\@:
+ /* check VHE is supported */
+ mrs \tmp, ID_AA64MMFR1_EL1
+ ubfx \tmp, \tmp, ID_AA64MMFR1_EL1_VH_SHIFT, #4
+ cbz \tmp, 1f
+ ldr \tmp, =(INIT_HCR_EL2)
+ msr hcr_el2, \tmp
+ isb
+ b 2f
+1:
mov \tmp, #0
msr cptr_el2, \tmp
ldr \tmp, =(INIT_HCR_EL2_EL1_ONLY)
msr hcr_el2, \tmp
mov \tmp, PSR_MODE_EL1t
msr spsr_el2, \tmp
- adrp \tmp, 1f
- add \tmp, \tmp, :lo12:1f
+ adrp \tmp, 2f
+ add \tmp, \tmp, :lo12:2f
msr elr_el2, \tmp
eret
-1:
+2:
.endm
diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h
index ed776716..f2d05018 100644
--- a/lib/arm64/asm/sysreg.h
+++ b/lib/arm64/asm/sysreg.h
@@ -80,6 +80,8 @@ asm(
#define ID_AA64MMFR0_EL1_FGT_SHIFT 56
#define ID_AA64MMFR0_EL1_FGT_FGT2 0x2
+#define ID_AA64MMFR1_EL1_VH_SHIFT 8
+
#define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0)
#define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
#define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
@@ -116,9 +118,12 @@ asm(
#define SCTLR_EL1_TCF0_SHIFT 38
#define SCTLR_EL1_TCF0_MASK GENMASK_ULL(39, 38)
+#define HCR_EL2_TGE _BITULL(27)
#define HCR_EL2_RW _BITULL(31)
+#define HCR_EL2_E2H _BITULL(34)
#define INIT_HCR_EL2_EL1_ONLY (HCR_EL2_RW)
+#define INIT_HCR_EL2 (HCR_EL2_TGE | HCR_EL2_E2H | HCR_EL2_RW)
#define SYS_HFGRTR_EL2 sys_reg(3, 4, 1, 1, 4)
#define SYS_HFGWTR_EL2 sys_reg(3, 4, 1, 1, 5)
--
2.25.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [kvm-unit-tests PATCH v3 10/10] arm64: add EL2 environment variable
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
` (8 preceding siblings ...)
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 09/10] arm64: run at EL2 if supported Joey Gouly
@ 2025-09-25 14:19 ` Joey Gouly
2025-11-27 10:34 ` Eric Auger
2025-12-01 23:34 ` Andrew Jones
2025-11-19 13:18 ` [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
` (2 subsequent siblings)
12 siblings, 2 replies; 38+ messages in thread
From: Joey Gouly @ 2025-09-25 14:19 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
This variable when set to 1 will cause QEMU/kvmtool to start at EL2.
---
arm/run | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arm/run b/arm/run
index 858333fc..2a9c0de0 100755
--- a/arm/run
+++ b/arm/run
@@ -59,6 +59,10 @@ function arch_run_qemu()
M+=",highmem=off"
fi
+ if [ "$EL2" = "1" ]; then
+ M+=",virtualization=on"
+ fi
+
if ! $qemu $M -device '?' | grep -q virtconsole; then
echo "$qemu doesn't support virtio-console for chr-testdev. Exiting."
exit 2
@@ -116,6 +120,9 @@ function arch_run_kvmtool()
fi
command="$(timeout_cmd) $kvmtool run"
+ if [ "$EL2" = "1" ]; then
+ command+=" --nested"
+ fi
if [ "$HOST" = "aarch64" ] && [ "$ARCH" = "arm" ]; then
run_test_status $command --kernel "$@" --aarch32
else
--
2.25.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
` (9 preceding siblings ...)
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 10/10] arm64: add EL2 environment variable Joey Gouly
@ 2025-11-19 13:18 ` Joey Gouly
2025-11-19 13:48 ` Nadav Amit
2025-11-19 15:34 ` Marc Zyngier
2025-11-27 10:04 ` Eric Auger
12 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-11-19 13:18 UTC (permalink / raw)
To: kvm; +Cc: alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On Thu, Sep 25, 2025 at 03:19:48PM +0100, Joey Gouly wrote:
> Hi all,
>
> This series is for adding support to running the kvm-unit-tests at EL2. These
> have been tested with Linux 6.17-rc6 KVM nested virt.
>
> This latest round I also tested using the run_tests.sh script with QEMU TCG,
> running at EL2.
>
> The goal is to later extend and add new tests for Nested Virtualisation,
> however they should also work with bare metal as well.
Any comments on this series, would be nice to get it merged.
Thanks,
Joey
>
> Changes since v2[1]:
> - Move the sctlr setup in EFI to a function.
> - Decided to not re-use el2_setup.h from Linux, looked more
> complicated to use than needed for KUT.
> - Add EL2 env variable for testing, open to feedback for that.
> This was untested with kvmtool as my testing setup only has
> busybox ash currently, and the run_tests.sh script needs bash.
>
> Issues (that I think are fine to investigate/fix later):
> - Some of the debug tests fail with QEMU at EL2 and kvmtool.
> - The gic ipi test times out with QEMU at EL2, but works with kvmtool.
>
> Thanks,
> Joey
>
> [1] https://lore.kernel.org/kvmarm/20250529135557.2439500-1-joey.gouly@arm.com/
>
> Alexandru Elisei (2):
> arm64: micro-bench: use smc when at EL2
> arm64: selftest: update test for running at EL2
>
> Joey Gouly (8):
> arm64: drop to EL1 if booted at EL2
> arm64: efi: initialise SCTLR_ELx fully
> arm64: efi: initialise the EL
> arm64: timer: use hypervisor timers when at EL2
> arm64: micro-bench: fix timer IRQ
> arm64: pmu: count EL2 cycles
> arm64: run at EL2 if supported
> arm64: add EL2 environment variable
>
> arm/cstart64.S | 56 ++++++++++++++++++++++++++++++++++++--
> arm/efi/crt0-efi-aarch64.S | 5 ++++
> arm/micro-bench.c | 26 ++++++++++++++++--
> arm/pmu.c | 13 ++++++---
> arm/run | 7 +++++
> arm/selftest.c | 18 ++++++++----
> arm/timer.c | 10 +++++--
> lib/acpi.h | 2 ++
> lib/arm/asm/setup.h | 8 ++++++
> lib/arm/asm/timer.h | 11 ++++++++
> lib/arm/setup.c | 4 +++
> lib/arm/timer.c | 19 +++++++++++--
> lib/arm64/asm/sysreg.h | 19 +++++++++++++
> lib/arm64/processor.c | 12 ++++++++
> 14 files changed, 191 insertions(+), 19 deletions(-)
>
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support
2025-11-19 13:18 ` [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
@ 2025-11-19 13:48 ` Nadav Amit
2025-11-19 14:02 ` Joey Gouly
0 siblings, 1 reply; 38+ messages in thread
From: Nadav Amit @ 2025-11-19 13:48 UTC (permalink / raw)
To: Joey Gouly
Cc: kvm, alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
> On 19 Nov 2025, at 15:18, Joey Gouly <joey.gouly@arm.com> wrote:
>
> On Thu, Sep 25, 2025 at 03:19:48PM +0100, Joey Gouly wrote:
>> Hi all,
>>
>> This series is for adding support to running the kvm-unit-tests at EL2. These
>> have been tested with Linux 6.17-rc6 KVM nested virt.
>>
>> This latest round I also tested using the run_tests.sh script with QEMU TCG,
>> running at EL2.
>>
>> The goal is to later extend and add new tests for Nested Virtualisation,
>> however they should also work with bare metal as well.
>
> Any comments on this series, would be nice to get it merged.
I wonder, does kvm-unit-tests run on bare-metal arm64 these days?
I ran it in-house some time ago (fixing several issues on the way),
but IIRC this issue was never fixed upstream:
https://lore.kernel.org/all/C812A718-DCD6-4485-BB5A-B24DE73A0FD3@gmail.com/
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support
2025-11-19 13:48 ` Nadav Amit
@ 2025-11-19 14:02 ` Joey Gouly
2025-11-19 15:34 ` Andrew Jones
0 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-11-19 14:02 UTC (permalink / raw)
To: Nadav Amit
Cc: kvm, alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Hi Nadav,
On Wed, Nov 19, 2025 at 03:48:13PM +0200, Nadav Amit wrote:
>
>
> > On 19 Nov 2025, at 15:18, Joey Gouly <joey.gouly@arm.com> wrote:
> >
> > On Thu, Sep 25, 2025 at 03:19:48PM +0100, Joey Gouly wrote:
> >> Hi all,
> >>
> >> This series is for adding support to running the kvm-unit-tests at EL2. These
> >> have been tested with Linux 6.17-rc6 KVM nested virt.
> >>
> >> This latest round I also tested using the run_tests.sh script with QEMU TCG,
> >> running at EL2.
> >>
> >> The goal is to later extend and add new tests for Nested Virtualisation,
> >> however they should also work with bare metal as well.
> >
> > Any comments on this series, would be nice to get it merged.
>
> I wonder, does kvm-unit-tests run on bare-metal arm64 these days?
>
> I ran it in-house some time ago (fixing several issues on the way),
> but IIRC this issue was never fixed upstream:
>
> https://lore.kernel.org/all/C812A718-DCD6-4485-BB5A-B24DE73A0FD3@gmail.com/
>
I haven't tested on real bare-metal hardware, I have been booting directly in
QEMU with both .flat and .efi.
Thanks,
Joey
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support
2025-11-19 14:02 ` Joey Gouly
@ 2025-11-19 15:34 ` Andrew Jones
0 siblings, 0 replies; 38+ messages in thread
From: Andrew Jones @ 2025-11-19 15:34 UTC (permalink / raw)
To: Joey Gouly
Cc: Nadav Amit, kvm, alexandru.elisei, andrew.jones, kvmarm,
Marc Zyngier, Oliver Upton
On Wed, Nov 19, 2025 at 02:02:24PM +0000, Joey Gouly wrote:
> Hi Nadav,
>
> On Wed, Nov 19, 2025 at 03:48:13PM +0200, Nadav Amit wrote:
> >
> >
> > > On 19 Nov 2025, at 15:18, Joey Gouly <joey.gouly@arm.com> wrote:
> > >
> > > On Thu, Sep 25, 2025 at 03:19:48PM +0100, Joey Gouly wrote:
> > >> Hi all,
> > >>
> > >> This series is for adding support to running the kvm-unit-tests at EL2. These
> > >> have been tested with Linux 6.17-rc6 KVM nested virt.
> > >>
> > >> This latest round I also tested using the run_tests.sh script with QEMU TCG,
> > >> running at EL2.
> > >>
> > >> The goal is to later extend and add new tests for Nested Virtualisation,
> > >> however they should also work with bare metal as well.
> > >
> > > Any comments on this series, would be nice to get it merged.
> >
> > I wonder, does kvm-unit-tests run on bare-metal arm64 these days?
> >
> > I ran it in-house some time ago (fixing several issues on the way),
> > but IIRC this issue was never fixed upstream:
> >
> > https://lore.kernel.org/all/C812A718-DCD6-4485-BB5A-B24DE73A0FD3@gmail.com/
> >
>
> I haven't tested on real bare-metal hardware, I have been booting directly in
> QEMU with both .flat and .efi.
At one point arm64 builds worked on bare-metal - I added commit 993c37be77
("arm/arm64: Zero BSS and stack at startup") as part of that effort. I
don't know if it still works, though, since I haven't tested it in years.
As for this series, I was hoping someone more invested in arm64 would do
some reviewing and testing. Then, given we get some r-b's and t-b's, I'd
give it a quick skim and ship it.
Thanks,
drew
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
` (10 preceding siblings ...)
2025-11-19 13:18 ` [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
@ 2025-11-19 15:34 ` Marc Zyngier
2025-11-27 10:04 ` Eric Auger
12 siblings, 0 replies; 38+ messages in thread
From: Marc Zyngier @ 2025-11-19 15:34 UTC (permalink / raw)
To: Joey Gouly; +Cc: kvm, alexandru.elisei, andrew.jones, kvmarm, Oliver Upton
On Thu, 25 Sep 2025 15:19:48 +0100,
Joey Gouly <joey.gouly@arm.com> wrote:
>
> Hi all,
>
> This series is for adding support to running the kvm-unit-tests at EL2. These
> have been tested with Linux 6.17-rc6 KVM nested virt.
>
> This latest round I also tested using the run_tests.sh script with QEMU TCG,
> running at EL2.
I've eyeballed it superficially, and didn't spot anything unexpected.
Given that upstream KVM now supports NV, not having anything in KUT is
becoming a problem, and this is a first step towards proper testing.
FWIW:
Acked-by: Marc Zyngier <maz@kernel.org>
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
` (11 preceding siblings ...)
2025-11-19 15:34 ` Marc Zyngier
@ 2025-11-27 10:04 ` Eric Auger
2025-11-27 11:08 ` Joey Gouly
12 siblings, 1 reply; 38+ messages in thread
From: Eric Auger @ 2025-11-27 10:04 UTC (permalink / raw)
To: Joey Gouly, kvm
Cc: alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Hi Joey,
On 9/25/25 4:19 PM, Joey Gouly wrote:
> Hi all,
>
> This series is for adding support to running the kvm-unit-tests at EL2. These
> have been tested with Linux 6.17-rc6 KVM nested virt.
>
> This latest round I also tested using the run_tests.sh script with QEMU TCG,
> running at EL2.
>
> The goal is to later extend and add new tests for Nested Virtualisation,
> however they should also work with bare metal as well.
>
> Changes since v2[1]:
> - Move the sctlr setup in EFI to a function.
> - Decided to not re-use el2_setup.h from Linux, looked more
> complicated to use than needed for KUT.
> - Add EL2 env variable for testing, open to feedback for that.
> This was untested with kvmtool as my testing setup only has
> busybox ash currently, and the run_tests.sh script needs bash.
>
> Issues (that I think are fine to investigate/fix later):
> - Some of the debug tests fail with QEMU at EL2 and kvmtool.
> - The gic ipi test times out with QEMU at EL2, but works with kvmtool.
Have you noticed any failure with migration tests. On my end, as soon as
I set EL2=1 migration tests do fail.
Eric
>
> Thanks,
> Joey
>
> [1] https://lore.kernel.org/kvmarm/20250529135557.2439500-1-joey.gouly@arm.com/
>
> Alexandru Elisei (2):
> arm64: micro-bench: use smc when at EL2
> arm64: selftest: update test for running at EL2
>
> Joey Gouly (8):
> arm64: drop to EL1 if booted at EL2
> arm64: efi: initialise SCTLR_ELx fully
> arm64: efi: initialise the EL
> arm64: timer: use hypervisor timers when at EL2
> arm64: micro-bench: fix timer IRQ
> arm64: pmu: count EL2 cycles
> arm64: run at EL2 if supported
> arm64: add EL2 environment variable
>
> arm/cstart64.S | 56 ++++++++++++++++++++++++++++++++++++--
> arm/efi/crt0-efi-aarch64.S | 5 ++++
> arm/micro-bench.c | 26 ++++++++++++++++--
> arm/pmu.c | 13 ++++++---
> arm/run | 7 +++++
> arm/selftest.c | 18 ++++++++----
> arm/timer.c | 10 +++++--
> lib/acpi.h | 2 ++
> lib/arm/asm/setup.h | 8 ++++++
> lib/arm/asm/timer.h | 11 ++++++++
> lib/arm/setup.c | 4 +++
> lib/arm/timer.c | 19 +++++++++++--
> lib/arm64/asm/sysreg.h | 19 +++++++++++++
> lib/arm64/processor.c | 12 ++++++++
> 14 files changed, 191 insertions(+), 19 deletions(-)
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 10/10] arm64: add EL2 environment variable
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 10/10] arm64: add EL2 environment variable Joey Gouly
@ 2025-11-27 10:34 ` Eric Auger
2025-11-27 10:40 ` Joey Gouly
2025-12-01 23:34 ` Andrew Jones
1 sibling, 1 reply; 38+ messages in thread
From: Eric Auger @ 2025-11-27 10:34 UTC (permalink / raw)
To: Joey Gouly, kvm
Cc: alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Hi Joey,
On 9/25/25 4:19 PM, Joey Gouly wrote:
> This variable when set to 1 will cause QEMU/kvmtool to start at EL2.
Misses the Sob.
Besides Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
> ---
> arm/run | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/arm/run b/arm/run
> index 858333fc..2a9c0de0 100755
> --- a/arm/run
> +++ b/arm/run
> @@ -59,6 +59,10 @@ function arch_run_qemu()
> M+=",highmem=off"
> fi
>
> + if [ "$EL2" = "1" ]; then
> + M+=",virtualization=on"
> + fi
> +
> if ! $qemu $M -device '?' | grep -q virtconsole; then
> echo "$qemu doesn't support virtio-console for chr-testdev. Exiting."
> exit 2
> @@ -116,6 +120,9 @@ function arch_run_kvmtool()
> fi
>
> command="$(timeout_cmd) $kvmtool run"
> + if [ "$EL2" = "1" ]; then
> + command+=" --nested"
> + fi
> if [ "$HOST" = "aarch64" ] && [ "$ARCH" = "arm" ]; then
> run_test_status $command --kernel "$@" --aarch32
> else
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 10/10] arm64: add EL2 environment variable
2025-11-27 10:34 ` Eric Auger
@ 2025-11-27 10:40 ` Joey Gouly
0 siblings, 0 replies; 38+ messages in thread
From: Joey Gouly @ 2025-11-27 10:40 UTC (permalink / raw)
To: Eric Auger
Cc: kvm, alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On Thu, Nov 27, 2025 at 11:34:56AM +0100, Eric Auger wrote:
> Hi Joey,
>
> On 9/25/25 4:19 PM, Joey Gouly wrote:
> > This variable when set to 1 will cause QEMU/kvmtool to start at EL2.
>
> Misses the Sob.
If this counts:
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
I have fixed kvm-unit-tests to add that automatically to my commits now, thanks.
>
> Besides Reviewed-by: Eric Auger <eric.auger@redhat.com>
Thanks,
Joey
>
> Eric
>
> > ---
> > arm/run | 7 +++++++
> > 1 file changed, 7 insertions(+)
> >
> > diff --git a/arm/run b/arm/run
> > index 858333fc..2a9c0de0 100755
> > --- a/arm/run
> > +++ b/arm/run
> > @@ -59,6 +59,10 @@ function arch_run_qemu()
> > M+=",highmem=off"
> > fi
> >
> > + if [ "$EL2" = "1" ]; then
> > + M+=",virtualization=on"
> > + fi
> > +
> > if ! $qemu $M -device '?' | grep -q virtconsole; then
> > echo "$qemu doesn't support virtio-console for chr-testdev. Exiting."
> > exit 2
> > @@ -116,6 +120,9 @@ function arch_run_kvmtool()
> > fi
> >
> > command="$(timeout_cmd) $kvmtool run"
> > + if [ "$EL2" = "1" ]; then
> > + command+=" --nested"
> > + fi
> > if [ "$HOST" = "aarch64" ] && [ "$ARCH" = "arm" ]; then
> > run_test_status $command --kernel "$@" --aarch32
> > else
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support
2025-11-27 10:04 ` Eric Auger
@ 2025-11-27 11:08 ` Joey Gouly
2025-11-27 12:04 ` Eric Auger
0 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-11-27 11:08 UTC (permalink / raw)
To: Eric Auger
Cc: kvm, alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On Thu, Nov 27, 2025 at 11:04:43AM +0100, Eric Auger wrote:
> Hi Joey,
>
> On 9/25/25 4:19 PM, Joey Gouly wrote:
> > Hi all,
> >
> > This series is for adding support to running the kvm-unit-tests at EL2. These
> > have been tested with Linux 6.17-rc6 KVM nested virt.
> >
> > This latest round I also tested using the run_tests.sh script with QEMU TCG,
> > running at EL2.
> >
> > The goal is to later extend and add new tests for Nested Virtualisation,
> > however they should also work with bare metal as well.
> >
> > Changes since v2[1]:
> > - Move the sctlr setup in EFI to a function.
> > - Decided to not re-use el2_setup.h from Linux, looked more
> > complicated to use than needed for KUT.
> > - Add EL2 env variable for testing, open to feedback for that.
> > This was untested with kvmtool as my testing setup only has
> > busybox ash currently, and the run_tests.sh script needs bash.
> >
> > Issues (that I think are fine to investigate/fix later):
> > - Some of the debug tests fail with QEMU at EL2 and kvmtool.
> > - The gic ipi test times out with QEMU at EL2, but works with kvmtool.
>
> Have you noticed any failure with migration tests. On my end, as soon as
> I set EL2=1 migration tests do fail.
Yes migration also fails here, forgot to mention that.
Seems like migration completes, but then something bad happens on the first
interrupt. I will investigate a bit now and see if it's an easy fix.
Thanks,
Joey
>
> Eric
> >
> > Thanks,
> > Joey
> >
> > [1] https://lore.kernel.org/kvmarm/20250529135557.2439500-1-joey.gouly@arm.com/
> >
> > Alexandru Elisei (2):
> > arm64: micro-bench: use smc when at EL2
> > arm64: selftest: update test for running at EL2
> >
> > Joey Gouly (8):
> > arm64: drop to EL1 if booted at EL2
> > arm64: efi: initialise SCTLR_ELx fully
> > arm64: efi: initialise the EL
> > arm64: timer: use hypervisor timers when at EL2
> > arm64: micro-bench: fix timer IRQ
> > arm64: pmu: count EL2 cycles
> > arm64: run at EL2 if supported
> > arm64: add EL2 environment variable
> >
> > arm/cstart64.S | 56 ++++++++++++++++++++++++++++++++++++--
> > arm/efi/crt0-efi-aarch64.S | 5 ++++
> > arm/micro-bench.c | 26 ++++++++++++++++--
> > arm/pmu.c | 13 ++++++---
> > arm/run | 7 +++++
> > arm/selftest.c | 18 ++++++++----
> > arm/timer.c | 10 +++++--
> > lib/acpi.h | 2 ++
> > lib/arm/asm/setup.h | 8 ++++++
> > lib/arm/asm/timer.h | 11 ++++++++
> > lib/arm/setup.c | 4 +++
> > lib/arm/timer.c | 19 +++++++++++--
> > lib/arm64/asm/sysreg.h | 19 +++++++++++++
> > lib/arm64/processor.c | 12 ++++++++
> > 14 files changed, 191 insertions(+), 19 deletions(-)
> >
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support
2025-11-27 11:08 ` Joey Gouly
@ 2025-11-27 12:04 ` Eric Auger
2025-11-27 14:52 ` Joey Gouly
0 siblings, 1 reply; 38+ messages in thread
From: Eric Auger @ 2025-11-27 12:04 UTC (permalink / raw)
To: Joey Gouly
Cc: kvm, alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Hi Joey,
On 11/27/25 12:08 PM, Joey Gouly wrote:
> On Thu, Nov 27, 2025 at 11:04:43AM +0100, Eric Auger wrote:
>> Hi Joey,
>>
>> On 9/25/25 4:19 PM, Joey Gouly wrote:
>>> Hi all,
>>>
>>> This series is for adding support to running the kvm-unit-tests at EL2. These
>>> have been tested with Linux 6.17-rc6 KVM nested virt.
>>>
>>> This latest round I also tested using the run_tests.sh script with QEMU TCG,
>>> running at EL2.
>>>
>>> The goal is to later extend and add new tests for Nested Virtualisation,
>>> however they should also work with bare metal as well.
>>>
>>> Changes since v2[1]:
>>> - Move the sctlr setup in EFI to a function.
>>> - Decided to not re-use el2_setup.h from Linux, looked more
>>> complicated to use than needed for KUT.
>>> - Add EL2 env variable for testing, open to feedback for that.
>>> This was untested with kvmtool as my testing setup only has
>>> busybox ash currently, and the run_tests.sh script needs bash.
>>>
>>> Issues (that I think are fine to investigate/fix later):
>>> - Some of the debug tests fail with QEMU at EL2 and kvmtool.
>>> - The gic ipi test times out with QEMU at EL2, but works with kvmtool.
>> Have you noticed any failure with migration tests. On my end, as soon as
>> I set EL2=1 migration tests do fail.
> Yes migration also fails here, forgot to mention that.
>
> Seems like migration completes, but then something bad happens on the first
> interrupt. I will investigate a bit now and see if it's an easy fix.
while you do that I will go through the series. My apologies for the delay
Eric
>
> Thanks,
> Joey
>
>> Eric
>>> Thanks,
>>> Joey
>>>
>>> [1] https://lore.kernel.org/kvmarm/20250529135557.2439500-1-joey.gouly@arm.com/
>>>
>>> Alexandru Elisei (2):
>>> arm64: micro-bench: use smc when at EL2
>>> arm64: selftest: update test for running at EL2
>>>
>>> Joey Gouly (8):
>>> arm64: drop to EL1 if booted at EL2
>>> arm64: efi: initialise SCTLR_ELx fully
>>> arm64: efi: initialise the EL
>>> arm64: timer: use hypervisor timers when at EL2
>>> arm64: micro-bench: fix timer IRQ
>>> arm64: pmu: count EL2 cycles
>>> arm64: run at EL2 if supported
>>> arm64: add EL2 environment variable
>>>
>>> arm/cstart64.S | 56 ++++++++++++++++++++++++++++++++++++--
>>> arm/efi/crt0-efi-aarch64.S | 5 ++++
>>> arm/micro-bench.c | 26 ++++++++++++++++--
>>> arm/pmu.c | 13 ++++++---
>>> arm/run | 7 +++++
>>> arm/selftest.c | 18 ++++++++----
>>> arm/timer.c | 10 +++++--
>>> lib/acpi.h | 2 ++
>>> lib/arm/asm/setup.h | 8 ++++++
>>> lib/arm/asm/timer.h | 11 ++++++++
>>> lib/arm/setup.c | 4 +++
>>> lib/arm/timer.c | 19 +++++++++++--
>>> lib/arm64/asm/sysreg.h | 19 +++++++++++++
>>> lib/arm64/processor.c | 12 ++++++++
>>> 14 files changed, 191 insertions(+), 19 deletions(-)
>>>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support
2025-11-27 12:04 ` Eric Auger
@ 2025-11-27 14:52 ` Joey Gouly
2025-12-01 23:16 ` Andrew Jones
0 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-11-27 14:52 UTC (permalink / raw)
To: Eric Auger
Cc: kvm, alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On Thu, Nov 27, 2025 at 01:04:08PM +0100, Eric Auger wrote:
> Hi Joey,
>
> On 11/27/25 12:08 PM, Joey Gouly wrote:
> > On Thu, Nov 27, 2025 at 11:04:43AM +0100, Eric Auger wrote:
> >> Hi Joey,
> >>
> >> On 9/25/25 4:19 PM, Joey Gouly wrote:
> >>> Hi all,
> >>>
> >>> This series is for adding support to running the kvm-unit-tests at EL2. These
> >>> have been tested with Linux 6.17-rc6 KVM nested virt.
> >>>
> >>> This latest round I also tested using the run_tests.sh script with QEMU TCG,
> >>> running at EL2.
> >>>
> >>> The goal is to later extend and add new tests for Nested Virtualisation,
> >>> however they should also work with bare metal as well.
> >>>
> >>> Changes since v2[1]:
> >>> - Move the sctlr setup in EFI to a function.
> >>> - Decided to not re-use el2_setup.h from Linux, looked more
> >>> complicated to use than needed for KUT.
> >>> - Add EL2 env variable for testing, open to feedback for that.
> >>> This was untested with kvmtool as my testing setup only has
> >>> busybox ash currently, and the run_tests.sh script needs bash.
> >>>
> >>> Issues (that I think are fine to investigate/fix later):
> >>> - Some of the debug tests fail with QEMU at EL2 and kvmtool.
> >>> - The gic ipi test times out with QEMU at EL2, but works with kvmtool.
> >> Have you noticed any failure with migration tests. On my end, as soon as
> >> I set EL2=1 migration tests do fail.
> > Yes migration also fails here, forgot to mention that.
> >
> > Seems like migration completes, but then something bad happens on the first
> > interrupt. I will investigate a bit now and see if it's an easy fix.
>
> while you do that I will go through the series. My apologies for the delay
Thanks!
I found the issue, and I thought it was one I had solved before, but maybe I lost the fix somehow:
diff --git a/arm/cstart64.S b/arm/cstart64.S
index af7c81c1..fd8b6690 100644
--- a/arm/cstart64.S
+++ b/arm/cstart64.S
@@ -235,6 +235,11 @@ get_mmu_off:
.globl secondary_entry
secondary_entry:
init_el x0
+
+ /* set SCTLR_EL1 to a known value */
+ ldr x4, =INIT_SCTLR_EL1_MMU_OFF
+ msr sctlr_el1, x4
+ isb
+
/* enable FP/ASIMD and SVE */
mov x0, #(3 << 20)
orr x0, x0, #(3 << 16)
The secondary core code doesn't fully initialise SCTLR_ELx, which means that
SCTLR_ELx.SPAN=0. That's why there was a data abort after the IRQ.
This doesn't affect EL1 (only) because KVM has a different reset value for
SCTLR_EL1 and SCTLR_EL2.
I will send out a new version with this fix, missing sob/reviews/acks, after you've had a look!
Thanks,
Joey
>
> Eric
> >
> > Thanks,
> > Joey
> >
> >> Eric
> >>> Thanks,
> >>> Joey
> >>>
> >>> [1] https://lore.kernel.org/kvmarm/20250529135557.2439500-1-joey.gouly@arm.com/
> >>>
> >>> Alexandru Elisei (2):
> >>> arm64: micro-bench: use smc when at EL2
> >>> arm64: selftest: update test for running at EL2
> >>>
> >>> Joey Gouly (8):
> >>> arm64: drop to EL1 if booted at EL2
> >>> arm64: efi: initialise SCTLR_ELx fully
> >>> arm64: efi: initialise the EL
> >>> arm64: timer: use hypervisor timers when at EL2
> >>> arm64: micro-bench: fix timer IRQ
> >>> arm64: pmu: count EL2 cycles
> >>> arm64: run at EL2 if supported
> >>> arm64: add EL2 environment variable
> >>>
> >>> arm/cstart64.S | 56 ++++++++++++++++++++++++++++++++++++--
> >>> arm/efi/crt0-efi-aarch64.S | 5 ++++
> >>> arm/micro-bench.c | 26 ++++++++++++++++--
> >>> arm/pmu.c | 13 ++++++---
> >>> arm/run | 7 +++++
> >>> arm/selftest.c | 18 ++++++++----
> >>> arm/timer.c | 10 +++++--
> >>> lib/acpi.h | 2 ++
> >>> lib/arm/asm/setup.h | 8 ++++++
> >>> lib/arm/asm/timer.h | 11 ++++++++
> >>> lib/arm/setup.c | 4 +++
> >>> lib/arm/timer.c | 19 +++++++++++--
> >>> lib/arm64/asm/sysreg.h | 19 +++++++++++++
> >>> lib/arm64/processor.c | 12 ++++++++
> >>> 14 files changed, 191 insertions(+), 19 deletions(-)
> >>>
>
^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 02/10] arm64: efi: initialise SCTLR_ELx fully
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 02/10] arm64: efi: initialise SCTLR_ELx fully Joey Gouly
@ 2025-11-27 16:49 ` Eric Auger
2025-11-28 15:18 ` Joey Gouly
0 siblings, 1 reply; 38+ messages in thread
From: Eric Auger @ 2025-11-27 16:49 UTC (permalink / raw)
To: Joey Gouly, kvm
Cc: alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Hi Joey,
On 9/25/25 4:19 PM, Joey Gouly wrote:
> Don't rely on the value of SCTLR_ELx when booting via EFI.
>
> Signed-off-by: Joey Gouly <joey.gouly@arm.com>
> ---
> lib/arm/asm/setup.h | 6 ++++++
> lib/arm/setup.c | 3 +++
> lib/arm64/processor.c | 12 ++++++++++++
> 3 files changed, 21 insertions(+)
>
> diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h
> index 9f8ef82e..4e60d552 100644
> --- a/lib/arm/asm/setup.h
> +++ b/lib/arm/asm/setup.h
> @@ -28,6 +28,12 @@ void setup(const void *fdt, phys_addr_t freemem_start);
>
> #include <efi.h>
>
> +#ifdef __aarch64__
> +void setup_efi_sctlr(void);
> +#else
> +static inline void setup_efi_sctlr(void) {}
> +#endif
> +
> efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo);
>
> #endif
> diff --git a/lib/arm/setup.c b/lib/arm/setup.c
> index 67b5db07..0aaa1d3a 100644
> --- a/lib/arm/setup.c
> +++ b/lib/arm/setup.c
> @@ -349,6 +349,9 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
> {
> efi_status_t status;
>
> +
spurious line
> + setup_efi_sctlr();
> +
> exceptions_init();
>
> memregions_init(arm_mem_regions, NR_MEM_REGIONS);
> diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c
> index eb93fd7c..edc0ad87 100644
> --- a/lib/arm64/processor.c
> +++ b/lib/arm64/processor.c
> @@ -8,6 +8,7 @@
> #include <libcflat.h>
> #include <asm/ptrace.h>
> #include <asm/processor.h>
> +#include <asm/setup.h>
> #include <asm/thread_info.h>
>
> static const char *vector_names[] = {
> @@ -271,3 +272,14 @@ bool __mmu_enabled(void)
> {
> return read_sysreg(sctlr_el1) & SCTLR_EL1_M;
> }
> +
> +#ifdef CONFIG_EFI
> +
> +void setup_efi_sctlr(void)
> +{
> + // EFI exits boot services with SCTLR_ELx.M=1, so keep
> + // the MMU enabled.
I don't really understand the comment, if MMU was enabled why are we
mandated to set M bit again?
Eric
> + write_sysreg(INIT_SCTLR_EL1_MMU_OFF | SCTLR_EL1_M, sctlr_el1);
> +}
> +
> +#endif
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 01/10] arm64: drop to EL1 if booted at EL2
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 01/10] arm64: drop to EL1 if booted at EL2 Joey Gouly
@ 2025-11-27 17:07 ` Eric Auger
2025-11-28 15:11 ` Joey Gouly
0 siblings, 1 reply; 38+ messages in thread
From: Eric Auger @ 2025-11-27 17:07 UTC (permalink / raw)
To: Joey Gouly, kvm
Cc: alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Hi Joey,
On 9/25/25 4:19 PM, Joey Gouly wrote:
> EL2 is not currently supported, drop to EL1 to conitnue booting.
continue
>
> Signed-off-by: Joey Gouly <joey.gouly@arm.com>
> ---
> arm/cstart64.S | 47 +++++++++++++++++++++++++++++++++++++++---
> lib/arm64/asm/sysreg.h | 14 +++++++++++++
> 2 files changed, 58 insertions(+), 3 deletions(-)
>
> diff --git a/arm/cstart64.S b/arm/cstart64.S
> index 014c9c7b..79b93dd4 100644
> --- a/arm/cstart64.S
> +++ b/arm/cstart64.S
> @@ -15,6 +15,46 @@
> #include <asm/thread_info.h>
> #include <asm/sysreg.h>
>
> +.macro init_el, tmp
init_el2? but also likely to fall back to EL1. At least add a doc comment to explain what the function does.
> + mrs \tmp, CurrentEL
> + cmp \tmp, CurrentEL_EL2
> + b.ne 1f
> + /* EL2 setup */
> + mrs \tmp, mpidr_el1
> + msr vmpidr_el2, \tmp
> + mrs \tmp, midr_el1
> + msr vpidr_el2, \tmp
> + /* clear trap registers */
clear FGT registers if FGT feature supported
> + mrs \tmp, id_aa64mmfr0_el1
> + ubfx \tmp, \tmp, #ID_AA64MMFR0_EL1_FGT_SHIFT, #4
> + cbz \tmp, .Lskip_fgt_\@
> + mov \tmp, #0
> + msr_s SYS_HFGRTR_EL2, \tmp
> + msr_s SYS_HFGWTR_EL2, \tmp
> + msr_s SYS_HFGITR_EL2, \tmp
> + mrs \tmp, id_aa64mmfr0_el1
> + ubfx \tmp, \tmp, #ID_AA64MMFR0_EL1_FGT_SHIFT, #4
> + cmp \tmp, #ID_AA64MMFR0_EL1_FGT_FGT2
> + bne .Lskip_fgt_\@
> + mov \tmp, #0
> + msr_s SYS_HFGRTR2_EL2, \tmp
> + msr_s SYS_HFGWTR2_EL2, \tmp
> + msr_s SYS_HFGITR2_EL2, \tmp
> +.Lskip_fgt_\@:
> + mov \tmp, #0
> + msr cptr_el2, \tmp
> + ldr \tmp, =(INIT_HCR_EL2_EL1_ONLY)
> + msr hcr_el2, \tmp
> + mov \tmp, PSR_MODE_EL1t
> + msr spsr_el2, \tmp
> + adrp \tmp, 1f
> + add \tmp, \tmp, :lo12:1f
> + msr elr_el2, \tmp
> + eret
> +1:
> +.endm
I read in the coverletter you chose to not reuse include/asm/el2_setup.h
which indeed would look overkill given the reduced scope that we target
here. However compared to init_el2_state we seem to do very few things
in the EL2 setup before switching to EL1. I would give a bit more info
in the commit msg about what you keep and what you dropped and why it is
reasonable (stage2, timers, debug at least).
> +
> +
> #ifdef CONFIG_EFI
> #include "efi/crt0-efi-aarch64.S"
> #else
> @@ -56,15 +96,15 @@ start:
> add x6, x6, :lo12:reloc_end
> 1:
> cmp x5, x6
> - b.hs 1f
> + b.hs reloc_done
> ldr x7, [x5] // r_offset
> ldr x8, [x5, #16] // r_addend
> add x8, x8, x4 // val = base + r_addend
> str x8, [x4, x7] // base[r_offset] = val
> add x5, x5, #24
> b 1b
> -
> -1:
> +reloc_done:
> + init_el x4
> /* zero BSS */
> adrp x4, bss
> add x4, x4, :lo12:bss
> @@ -185,6 +225,7 @@ get_mmu_off:
>
> .globl secondary_entry
> secondary_entry:
> + init_el x0
> /* enable FP/ASIMD and SVE */
> mov x0, #(3 << 20)
> orr x0, x0, #(3 << 16)
> diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h
> index e537bb46..ed776716 100644
> --- a/lib/arm64/asm/sysreg.h
> +++ b/lib/arm64/asm/sysreg.h
> @@ -77,6 +77,9 @@ asm(
> #define ID_AA64ISAR0_EL1_RNDR_SHIFT 60
> #define ID_AA64PFR1_EL1_MTE_SHIFT 8
>
> +#define ID_AA64MMFR0_EL1_FGT_SHIFT 56
> +#define ID_AA64MMFR0_EL1_FGT_FGT2 0x2
> +
> #define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0)
> #define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
> #define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
> @@ -113,6 +116,17 @@ asm(
> #define SCTLR_EL1_TCF0_SHIFT 38
> #define SCTLR_EL1_TCF0_MASK GENMASK_ULL(39, 38)
>
> +#define HCR_EL2_RW _BITULL(31)
> +
> +#define INIT_HCR_EL2_EL1_ONLY (HCR_EL2_RW)
I don't really understand the renaming
> +
> +#define SYS_HFGRTR_EL2 sys_reg(3, 4, 1, 1, 4)
> +#define SYS_HFGWTR_EL2 sys_reg(3, 4, 1, 1, 5)
> +#define SYS_HFGITR_EL2 sys_reg(3, 4, 1, 1, 6)
> +#define SYS_HFGRTR2_EL2 sys_reg(3, 4, 3, 1, 2)
> +#define SYS_HFGWTR2_EL2 sys_reg(3, 4, 3, 1, 3)
> +#define SYS_HFGITR2_EL2 sys_reg(3, 4, 3, 1, 7)
> +
> #define INIT_SCTLR_EL1_MMU_OFF \
> (SCTLR_EL1_ITD | SCTLR_EL1_SED | SCTLR_EL1_EOS | \
> SCTLR_EL1_TSCXT | SCTLR_EL1_EIS | SCTLR_EL1_SPAN | \
Thanks
Eric
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 03/10] arm64: efi: initialise the EL
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 03/10] arm64: efi: initialise the EL Joey Gouly
@ 2025-11-27 17:08 ` Eric Auger
0 siblings, 0 replies; 38+ messages in thread
From: Eric Auger @ 2025-11-27 17:08 UTC (permalink / raw)
To: Joey Gouly, kvm
Cc: alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On 9/25/25 4:19 PM, Joey Gouly wrote:
> Initialise the exception level, which may include dropping to EL1 from EL2, if
> VHE is not supported.
>
> Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
> ---
> arm/efi/crt0-efi-aarch64.S | 5 +++++
> lib/arm/asm/setup.h | 2 ++
> lib/arm/setup.c | 1 +
> 3 files changed, 8 insertions(+)
>
> diff --git a/arm/efi/crt0-efi-aarch64.S b/arm/efi/crt0-efi-aarch64.S
> index 71ce2794..5632fee0 100644
> --- a/arm/efi/crt0-efi-aarch64.S
> +++ b/arm/efi/crt0-efi-aarch64.S
> @@ -147,6 +147,11 @@ _start:
> 0: ldp x29, x30, [sp], #32
> ret
>
> +.globl do_init_el
> +do_init_el:
> + init_el x16
> + ret
> +
> .section .data
>
> .balign 65536
> diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h
> index 4e60d552..bf05ffbb 100644
> --- a/lib/arm/asm/setup.h
> +++ b/lib/arm/asm/setup.h
> @@ -29,8 +29,10 @@ void setup(const void *fdt, phys_addr_t freemem_start);
> #include <efi.h>
>
> #ifdef __aarch64__
> +void do_init_el(void);
> void setup_efi_sctlr(void);
> #else
> +static inline void do_init_el(void) {}
> static inline void setup_efi_sctlr(void) {}
> #endif
>
> diff --git a/lib/arm/setup.c b/lib/arm/setup.c
> index 0aaa1d3a..5ff40b54 100644
> --- a/lib/arm/setup.c
> +++ b/lib/arm/setup.c
> @@ -349,6 +349,7 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
> {
> efi_status_t status;
>
> + do_init_el();
>
> setup_efi_sctlr();
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 01/10] arm64: drop to EL1 if booted at EL2
2025-11-27 17:07 ` Eric Auger
@ 2025-11-28 15:11 ` Joey Gouly
0 siblings, 0 replies; 38+ messages in thread
From: Joey Gouly @ 2025-11-28 15:11 UTC (permalink / raw)
To: Eric Auger
Cc: kvm, alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On Thu, Nov 27, 2025 at 06:07:27PM +0100, Eric Auger wrote:
> Hi Joey,
>
> On 9/25/25 4:19 PM, Joey Gouly wrote:
> > EL2 is not currently supported, drop to EL1 to conitnue booting.
> continue
> >
> > Signed-off-by: Joey Gouly <joey.gouly@arm.com>
> > ---
> > arm/cstart64.S | 47 +++++++++++++++++++++++++++++++++++++++---
> > lib/arm64/asm/sysreg.h | 14 +++++++++++++
> > 2 files changed, 58 insertions(+), 3 deletions(-)
> >
> > diff --git a/arm/cstart64.S b/arm/cstart64.S
> > index 014c9c7b..79b93dd4 100644
> > --- a/arm/cstart64.S
> > +++ b/arm/cstart64.S
> > @@ -15,6 +15,46 @@
> > #include <asm/thread_info.h>
> > #include <asm/sysreg.h>
> >
> > +.macro init_el, tmp
>
> init_el2? but also likely to fall back to EL1. At least add a doc comment to explain what the function does.
>
> > + mrs \tmp, CurrentEL
> > + cmp \tmp, CurrentEL_EL2
> > + b.ne 1f
> > + /* EL2 setup */
> > + mrs \tmp, mpidr_el1
> > + msr vmpidr_el2, \tmp
> > + mrs \tmp, midr_el1
> > + msr vpidr_el2, \tmp
> > + /* clear trap registers */
> clear FGT registers if FGT feature supported
> > + mrs \tmp, id_aa64mmfr0_el1
> > + ubfx \tmp, \tmp, #ID_AA64MMFR0_EL1_FGT_SHIFT, #4
> > + cbz \tmp, .Lskip_fgt_\@
> > + mov \tmp, #0
> > + msr_s SYS_HFGRTR_EL2, \tmp
> > + msr_s SYS_HFGWTR_EL2, \tmp
> > + msr_s SYS_HFGITR_EL2, \tmp
> > + mrs \tmp, id_aa64mmfr0_el1
> > + ubfx \tmp, \tmp, #ID_AA64MMFR0_EL1_FGT_SHIFT, #4
> > + cmp \tmp, #ID_AA64MMFR0_EL1_FGT_FGT2
> > + bne .Lskip_fgt_\@
> > + mov \tmp, #0
> > + msr_s SYS_HFGRTR2_EL2, \tmp
> > + msr_s SYS_HFGWTR2_EL2, \tmp
> > + msr_s SYS_HFGITR2_EL2, \tmp
> > +.Lskip_fgt_\@:
> > + mov \tmp, #0
> > + msr cptr_el2, \tmp
> > + ldr \tmp, =(INIT_HCR_EL2_EL1_ONLY)
> > + msr hcr_el2, \tmp
> > + mov \tmp, PSR_MODE_EL1t
> > + msr spsr_el2, \tmp
> > + adrp \tmp, 1f
> > + add \tmp, \tmp, :lo12:1f
> > + msr elr_el2, \tmp
> > + eret
> > +1:
> > +.endm
>
> I read in the coverletter you chose to not reuse include/asm/el2_setup.h
> which indeed would look overkill given the reduced scope that we target
> here. However compared to init_el2_state we seem to do very few things
> in the EL2 setup before switching to EL1. I would give a bit more info
> in the commit msg about what you keep and what you dropped and why it is
> reasonable (stage2, timers, debug at least).
>
> > +
> > +
> > #ifdef CONFIG_EFI
> > #include "efi/crt0-efi-aarch64.S"
> > #else
> > @@ -56,15 +96,15 @@ start:
> > add x6, x6, :lo12:reloc_end
> > 1:
> > cmp x5, x6
> > - b.hs 1f
> > + b.hs reloc_done
> > ldr x7, [x5] // r_offset
> > ldr x8, [x5, #16] // r_addend
> > add x8, x8, x4 // val = base + r_addend
> > str x8, [x4, x7] // base[r_offset] = val
> > add x5, x5, #24
> > b 1b
> > -
> > -1:
> > +reloc_done:
> > + init_el x4
> > /* zero BSS */
> > adrp x4, bss
> > add x4, x4, :lo12:bss
> > @@ -185,6 +225,7 @@ get_mmu_off:
> >
> > .globl secondary_entry
> > secondary_entry:
> > + init_el x0
> > /* enable FP/ASIMD and SVE */
> > mov x0, #(3 << 20)
> > orr x0, x0, #(3 << 16)
> > diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h
> > index e537bb46..ed776716 100644
> > --- a/lib/arm64/asm/sysreg.h
> > +++ b/lib/arm64/asm/sysreg.h
> > @@ -77,6 +77,9 @@ asm(
> > #define ID_AA64ISAR0_EL1_RNDR_SHIFT 60
> > #define ID_AA64PFR1_EL1_MTE_SHIFT 8
> >
> > +#define ID_AA64MMFR0_EL1_FGT_SHIFT 56
> > +#define ID_AA64MMFR0_EL1_FGT_FGT2 0x2
> > +
> > #define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0)
> > #define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
> > #define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
> > @@ -113,6 +116,17 @@ asm(
> > #define SCTLR_EL1_TCF0_SHIFT 38
> > #define SCTLR_EL1_TCF0_MASK GENMASK_ULL(39, 38)
> >
> > +#define HCR_EL2_RW _BITULL(31)
> > +
> > +#define INIT_HCR_EL2_EL1_ONLY (HCR_EL2_RW)
>
> I don't really understand the renaming
It's just a define similar to INIT_HCR_EL2, that's added in patch 9.
>
> > +
> > +#define SYS_HFGRTR_EL2 sys_reg(3, 4, 1, 1, 4)
> > +#define SYS_HFGWTR_EL2 sys_reg(3, 4, 1, 1, 5)
> > +#define SYS_HFGITR_EL2 sys_reg(3, 4, 1, 1, 6)
> > +#define SYS_HFGRTR2_EL2 sys_reg(3, 4, 3, 1, 2)
> > +#define SYS_HFGWTR2_EL2 sys_reg(3, 4, 3, 1, 3)
> > +#define SYS_HFGITR2_EL2 sys_reg(3, 4, 3, 1, 7)
> > +
> > #define INIT_SCTLR_EL1_MMU_OFF \
> > (SCTLR_EL1_ITD | SCTLR_EL1_SED | SCTLR_EL1_EOS | \
> > SCTLR_EL1_TSCXT | SCTLR_EL1_EIS | SCTLR_EL1_SPAN | \
> Thanks
>
> Eric
>
Thanks,
Joey
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 02/10] arm64: efi: initialise SCTLR_ELx fully
2025-11-27 16:49 ` Eric Auger
@ 2025-11-28 15:18 ` Joey Gouly
0 siblings, 0 replies; 38+ messages in thread
From: Joey Gouly @ 2025-11-28 15:18 UTC (permalink / raw)
To: Eric Auger
Cc: kvm, alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On Thu, Nov 27, 2025 at 05:49:45PM +0100, Eric Auger wrote:
> Hi Joey,
>
> On 9/25/25 4:19 PM, Joey Gouly wrote:
> > Don't rely on the value of SCTLR_ELx when booting via EFI.
> >
> > Signed-off-by: Joey Gouly <joey.gouly@arm.com>
> > ---
> > lib/arm/asm/setup.h | 6 ++++++
> > lib/arm/setup.c | 3 +++
> > lib/arm64/processor.c | 12 ++++++++++++
> > 3 files changed, 21 insertions(+)
> >
> > diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h
> > index 9f8ef82e..4e60d552 100644
> > --- a/lib/arm/asm/setup.h
> > +++ b/lib/arm/asm/setup.h
> > @@ -28,6 +28,12 @@ void setup(const void *fdt, phys_addr_t freemem_start);
> >
> > #include <efi.h>
> >
> > +#ifdef __aarch64__
> > +void setup_efi_sctlr(void);
> > +#else
> > +static inline void setup_efi_sctlr(void) {}
> > +#endif
> > +
> > efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo);
> >
> > #endif
> > diff --git a/lib/arm/setup.c b/lib/arm/setup.c
> > index 67b5db07..0aaa1d3a 100644
> > --- a/lib/arm/setup.c
> > +++ b/lib/arm/setup.c
> > @@ -349,6 +349,9 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
> > {
> > efi_status_t status;
> >
> > +
> spurious line
> > + setup_efi_sctlr();
> > +
> > exceptions_init();
> >
> > memregions_init(arm_mem_regions, NR_MEM_REGIONS);
> > diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c
> > index eb93fd7c..edc0ad87 100644
> > --- a/lib/arm64/processor.c
> > +++ b/lib/arm64/processor.c
> > @@ -8,6 +8,7 @@
> > #include <libcflat.h>
> > #include <asm/ptrace.h>
> > #include <asm/processor.h>
> > +#include <asm/setup.h>
> > #include <asm/thread_info.h>
> >
> > static const char *vector_names[] = {
> > @@ -271,3 +272,14 @@ bool __mmu_enabled(void)
> > {
> > return read_sysreg(sctlr_el1) & SCTLR_EL1_M;
> > }
> > +
> > +#ifdef CONFIG_EFI
> > +
> > +void setup_efi_sctlr(void)
> > +{
> > + // EFI exits boot services with SCTLR_ELx.M=1, so keep
> > + // the MMU enabled.
> I don't really understand the comment, if MMU was enabled why are we
> mandated to set M bit again?
I'm overwriting sctlr_el1 with a fully new value, rather than using a
'read-modify-write' style. So the comment is justifying why I'm using the
INIT_SCTLR_EL1_MMU_OFF define but also or-ing in the M bit.
>
> Eric
> > + write_sysreg(INIT_SCTLR_EL1_MMU_OFF | SCTLR_EL1_M, sctlr_el1);
> > +}
> > +
> > +#endif
>
Thanks,
Joey
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support
2025-11-27 14:52 ` Joey Gouly
@ 2025-12-01 23:16 ` Andrew Jones
2025-12-02 14:22 ` Joey Gouly
0 siblings, 1 reply; 38+ messages in thread
From: Andrew Jones @ 2025-12-01 23:16 UTC (permalink / raw)
To: Joey Gouly
Cc: Eric Auger, kvm, alexandru.elisei, kvmarm, Marc Zyngier,
Oliver Upton
On Thu, Nov 27, 2025 at 02:52:07PM +0000, Joey Gouly wrote:
...
> I will send out a new version with this fix, missing sob/reviews/acks, after you've had a look!
>
Also please run checkpatch on the series if you haven't already. I think
it should have complained about the C++ comments, for example. And, in
any case, please change the C++ comments to C comments and generally use
the kernel's coding style.
Thanks,
drew
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 10/10] arm64: add EL2 environment variable
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 10/10] arm64: add EL2 environment variable Joey Gouly
2025-11-27 10:34 ` Eric Auger
@ 2025-12-01 23:34 ` Andrew Jones
1 sibling, 0 replies; 38+ messages in thread
From: Andrew Jones @ 2025-12-01 23:34 UTC (permalink / raw)
To: Joey Gouly; +Cc: kvm, alexandru.elisei, kvmarm, Marc Zyngier, Oliver Upton
On Thu, Sep 25, 2025 at 03:19:58PM +0100, Joey Gouly wrote:
> This variable when set to 1 will cause QEMU/kvmtool to start at EL2.
> ---
> arm/run | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/arm/run b/arm/run
> index 858333fc..2a9c0de0 100755
> --- a/arm/run
> +++ b/arm/run
> @@ -59,6 +59,10 @@ function arch_run_qemu()
> M+=",highmem=off"
> fi
>
> + if [ "$EL2" = "1" ]; then
Please also support 'y' and 'Y', e.g. 'EL2=y run_tests.sh -g ...'
Thanks,
drew
> + M+=",virtualization=on"
> + fi
> +
> if ! $qemu $M -device '?' | grep -q virtconsole; then
> echo "$qemu doesn't support virtio-console for chr-testdev. Exiting."
> exit 2
> @@ -116,6 +120,9 @@ function arch_run_kvmtool()
> fi
>
> command="$(timeout_cmd) $kvmtool run"
> + if [ "$EL2" = "1" ]; then
> + command+=" --nested"
> + fi
> if [ "$HOST" = "aarch64" ] && [ "$ARCH" = "arm" ]; then
> run_test_status $command --kernel "$@" --aarch32
> else
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 04/10] arm64: timer: use hypervisor timers when at EL2
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 04/10] arm64: timer: use hypervisor timers when at EL2 Joey Gouly
@ 2025-12-02 8:36 ` Eric Auger
0 siblings, 0 replies; 38+ messages in thread
From: Eric Auger @ 2025-12-02 8:36 UTC (permalink / raw)
To: Joey Gouly, kvm
Cc: alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On 9/25/25 4:19 PM, Joey Gouly wrote:
> At EL2, with VHE:
> CNT{P,V}_{TVAL,CTL}_EL0 is forwarded to CNTH{P,V}_{CVAL,TVAL,CTL}_EL0.
>
> Save the hypervisor physical and virtual timer IRQ numbers from the DT/ACPI.
>
> Signed-off-by: Joey Gouly <joey.gouly@arm.com>
> Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
> ---
> arm/timer.c | 10 ++++++++--
> lib/acpi.h | 2 ++
> lib/arm/asm/timer.h | 11 +++++++++++
> lib/arm/timer.c | 19 +++++++++++++++++--
> 4 files changed, 38 insertions(+), 4 deletions(-)
>
> diff --git a/arm/timer.c b/arm/timer.c
> index 2cb80518..c6287ca7 100644
> --- a/arm/timer.c
> +++ b/arm/timer.c
> @@ -347,8 +347,14 @@ static void test_ptimer(void)
> static void test_init(void)
> {
> assert(TIMER_PTIMER_IRQ != -1 && TIMER_VTIMER_IRQ != -1);
nit: move above assert to
if (current_level() == CurrentEL_EL1) block?
> - ptimer_info.irq = TIMER_PTIMER_IRQ;
> - vtimer_info.irq = TIMER_VTIMER_IRQ;
> + if (current_level() == CurrentEL_EL1) {
> + ptimer_info.irq = TIMER_PTIMER_IRQ;
> + vtimer_info.irq = TIMER_VTIMER_IRQ;
> + } else {
> + assert(TIMER_HPTIMER_IRQ != -1 && TIMER_HVTIMER_IRQ != -1);
> + ptimer_info.irq = TIMER_HPTIMER_IRQ;
> + vtimer_info.irq = TIMER_HVTIMER_IRQ;
> + }
>
> install_exception_handler(EL1H_SYNC, ESR_EL1_EC_UNKNOWN, ptimer_unsupported_handler);
> ptimer_info.read_ctl();
> diff --git a/lib/acpi.h b/lib/acpi.h
> index c330c877..66e3062d 100644
> --- a/lib/acpi.h
> +++ b/lib/acpi.h
> @@ -290,6 +290,8 @@ struct acpi_table_gtdt {
> u64 counter_read_block_address;
> u32 platform_timer_count;
> u32 platform_timer_offset;
> + u32 virtual_el2_timer_interrupt;
> + u32 virtual_el2_timer_flags;
> };
>
> /* Reset to default packing */
> diff --git a/lib/arm/asm/timer.h b/lib/arm/asm/timer.h
> index fd8f7796..0dcebc1c 100644
> --- a/lib/arm/asm/timer.h
> +++ b/lib/arm/asm/timer.h
> @@ -21,12 +21,23 @@ struct timer_state {
> u32 irq;
> u32 irq_flags;
> } vtimer;
> + struct {
> + u32 irq;
> + u32 irq_flags;
> + } hptimer;
> + struct {
> + u32 irq;
> + u32 irq_flags;
> + } hvtimer;
> };
> extern struct timer_state __timer_state;
>
> #define TIMER_PTIMER_IRQ (__timer_state.ptimer.irq)
> #define TIMER_VTIMER_IRQ (__timer_state.vtimer.irq)
>
> +#define TIMER_HPTIMER_IRQ (__timer_state.hptimer.irq)
> +#define TIMER_HVTIMER_IRQ (__timer_state.hvtimer.irq)
> +
> void timer_save_state(void);
>
> #endif /* !__ASSEMBLER__ */
> diff --git a/lib/arm/timer.c b/lib/arm/timer.c
> index ae702e41..57f504e2 100644
> --- a/lib/arm/timer.c
> +++ b/lib/arm/timer.c
> @@ -38,10 +38,11 @@ static void timer_save_state_fdt(void)
> * secure timer irq
> * non-secure timer irq (ptimer)
> * virtual timer irq (vtimer)
> - * hypervisor timer irq
> + * hypervisor timer irq (hptimer)
> + * hypervisor virtual timer irq (hvtimer)
> */
> prop = fdt_get_property(fdt, node, "interrupts", &len);
> - assert(prop && len == (4 * 3 * sizeof(u32)));
> + assert(prop && len >= (4 * 3 * sizeof(u32)));
>
> data = (u32 *) prop->data;
> assert(fdt32_to_cpu(data[3]) == 1 /* PPI */ );
> @@ -50,6 +51,14 @@ static void timer_save_state_fdt(void)
> assert(fdt32_to_cpu(data[6]) == 1 /* PPI */ );
> __timer_state.vtimer.irq = PPI(fdt32_to_cpu(data[7]));
> __timer_state.vtimer.irq_flags = fdt32_to_cpu(data[8]);
> + if (len == (5 * 3 * sizeof(u32))) {
> + assert(fdt32_to_cpu(data[9]) == 1 /* PPI */ );
> + __timer_state.hptimer.irq = PPI(fdt32_to_cpu(data[10]));
> + __timer_state.hptimer.irq_flags = fdt32_to_cpu(data[11]);
> + assert(fdt32_to_cpu(data[12]) == 1 /* PPI */ );
> + __timer_state.hvtimer.irq = PPI(fdt32_to_cpu(data[13]));
> + __timer_state.hvtimer.irq_flags = fdt32_to_cpu(data[14]);
> + }
> }
>
> #ifdef CONFIG_EFI
> @@ -72,6 +81,12 @@ static void timer_save_state_acpi(void)
>
> __timer_state.vtimer.irq = gtdt->virtual_timer_interrupt;
> __timer_state.vtimer.irq_flags = gtdt->virtual_timer_flags;
> +
> + __timer_state.hptimer.irq = gtdt->non_secure_el2_interrupt;
> + __timer_state.hptimer.irq_flags = gtdt->non_secure_el2_flags;
> +
> + __timer_state.hvtimer.irq = gtdt->virtual_el2_timer_interrupt;
> + __timer_state.hvtimer.irq_flags = gtdt->virtual_el2_timer_flags;
> }
>
> #else
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 05/10] arm64: micro-bench: fix timer IRQ
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 05/10] arm64: micro-bench: fix timer IRQ Joey Gouly
@ 2025-12-02 8:36 ` Eric Auger
0 siblings, 0 replies; 38+ messages in thread
From: Eric Auger @ 2025-12-02 8:36 UTC (permalink / raw)
To: Joey Gouly, kvm
Cc: alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On 9/25/25 4:19 PM, Joey Gouly wrote:
> Enable the correct (hvtimer) IRQ when at EL2.
>
> Signed-off-by: Joey Gouly <joey.gouly@arm.com>
> Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
> ---
> arm/micro-bench.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/arm/micro-bench.c b/arm/micro-bench.c
> index 22408955..f47c5fc1 100644
> --- a/arm/micro-bench.c
> +++ b/arm/micro-bench.c
> @@ -42,7 +42,7 @@ static void gic_irq_handler(struct pt_regs *regs)
> irq_received = true;
> gic_write_eoir(irqstat);
>
> - if (irqstat == TIMER_VTIMER_IRQ) {
> + if (irqstat == TIMER_VTIMER_IRQ || irqstat == TIMER_HVTIMER_IRQ) {
> write_sysreg((ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE),
> cntv_ctl_el0);
> isb();
> @@ -215,7 +215,11 @@ static bool timer_prep(void)
> install_irq_handler(EL1H_IRQ, gic_irq_handler);
> local_irq_enable();
>
> - gic_enable_irq(TIMER_VTIMER_IRQ);
> + if (current_level() == CurrentEL_EL1)
> + gic_enable_irq(TIMER_VTIMER_IRQ);
> + else
> + gic_enable_irq(TIMER_HVTIMER_IRQ);
> +
> write_sysreg(ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
> isb();
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 06/10] arm64: micro-bench: use smc when at EL2
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 06/10] arm64: micro-bench: use smc when at EL2 Joey Gouly
@ 2025-12-02 9:11 ` Eric Auger
0 siblings, 0 replies; 38+ messages in thread
From: Eric Auger @ 2025-12-02 9:11 UTC (permalink / raw)
To: Joey Gouly, kvm
Cc: alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On 9/25/25 4:19 PM, Joey Gouly wrote:
> From: Alexandru Elisei <alexandru.elisei@arm.com>
>
> At EL2, hvc would target the current EL, use smc so that it targets EL3.
>
> Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
> Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
> ---
> arm/micro-bench.c | 18 +++++++++++++++++-
> 1 file changed, 17 insertions(+), 1 deletion(-)
>
> diff --git a/arm/micro-bench.c b/arm/micro-bench.c
> index f47c5fc1..32029c5a 100644
> --- a/arm/micro-bench.c
> +++ b/arm/micro-bench.c
> @@ -282,6 +282,11 @@ static bool mmio_read_user_prep(void)
> return true;
> }
>
> +static void smc_exec(void)
> +{
> + asm volatile("mov w0, #0x4b000000; smc #0" ::: "w0");
> +}
> +
> static void mmio_read_user_exec(void)
> {
> readl(userspace_emulated_addr);
> @@ -300,6 +305,8 @@ static void eoi_exec(void)
> write_eoir(spurious_id);
> }
>
> +static bool exec_select(void);
> +
> struct exit_test {
> const char *name;
> bool (*prep)(void);
> @@ -310,7 +317,7 @@ struct exit_test {
> };
>
> static struct exit_test tests[] = {
> - {"hvc", NULL, hvc_exec, NULL, 65536, true},
> + {"hyp_call", exec_select, hvc_exec, NULL, 65536, true},
> {"mmio_read_user", mmio_read_user_prep, mmio_read_user_exec, NULL, 65536, true},
> {"mmio_read_vgic", NULL, mmio_read_vgic_exec, NULL, 65536, true},
> {"eoi", NULL, eoi_exec, NULL, 65536, true},
> @@ -320,6 +327,15 @@ static struct exit_test tests[] = {
> {"timer_10ms", timer_prep, timer_exec, timer_post, 256, true},
> };
>
> +static bool exec_select(void)
> +{
> + if (current_level() == CurrentEL_EL2)
> + tests[0].exec = &smc_exec;
> + else
> + tests[0].exec = &hvc_exec;
> + return true;
> +}
> +
> struct ns_time {
> uint64_t ns;
> uint64_t ns_frac;
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 07/10] arm64: selftest: update test for running at EL2
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 07/10] arm64: selftest: update test for running " Joey Gouly
@ 2025-12-02 9:16 ` Eric Auger
2025-12-02 12:21 ` Joey Gouly
0 siblings, 1 reply; 38+ messages in thread
From: Eric Auger @ 2025-12-02 9:16 UTC (permalink / raw)
To: Joey Gouly, kvm
Cc: alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On 9/25/25 4:19 PM, Joey Gouly wrote:
> From: Alexandru Elisei <alexandru.elisei@arm.com>
>
> Remove some hard-coded assumptions that this test is running at EL1.
>
> Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
> Signed-off-by: Joey Gouly <joey.gouly@arm.com>
> ---
> arm/selftest.c | 18 +++++++++++++-----
> 1 file changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/arm/selftest.c b/arm/selftest.c
> index 1553ed8e..01691389 100644
> --- a/arm/selftest.c
> +++ b/arm/selftest.c
> @@ -232,6 +232,7 @@ static void user_psci_system_off(struct pt_regs *regs)
> __user_psci_system_off();
> }
> #elif defined(__aarch64__)
> +static unsigned long expected_level;
>
> /*
> * Capture the current register state and execute an instruction
> @@ -276,8 +277,7 @@ static bool check_regs(struct pt_regs *regs)
> {
> unsigned i;
>
> - /* exception handlers should always run in EL1 */
> - if (current_level() != CurrentEL_EL1)
> + if (current_level() != expected_level)
> return false;
>
> for (i = 0; i < ARRAY_SIZE(regs->regs); ++i) {
> @@ -301,7 +301,11 @@ static enum vector check_vector_prep(void)
> return EL0_SYNC_64;
>
> asm volatile("mrs %0, daif" : "=r" (daif) ::);
> - expected_regs.pstate = daif | PSR_MODE_EL1h;
> + expected_regs.pstate = daif;
> + if (current_level() == CurrentEL_EL1)
> + expected_regs.pstate |= PSR_MODE_EL1h;
> + else
> + expected_regs.pstate |= PSR_MODE_EL2h;
> return EL1H_SYNC;
> }
>
> @@ -317,8 +321,8 @@ static bool check_und(void)
>
> install_exception_handler(v, ESR_EL1_EC_UNKNOWN, unknown_handler);
>
> - /* try to read an el2 sysreg from el0/1 */
> - test_exception("", "mrs x0, sctlr_el2", "", "x0");
> + /* try to read an el3 sysreg from el0/1/2 */
> + test_exception("", "mrs x0, sctlr_el3", "", "x0");
>
> install_exception_handler(v, ESR_EL1_EC_UNKNOWN, NULL);
>
> @@ -429,6 +433,10 @@ int main(int argc, char **argv)
> if (argc < 2)
> report_abort("no test specified");
>
> +#if defined(__aarch64__)
> + expected_level = current_level();
nit I would directly use current_level() in the calling function,
check_regs() to avoid that #ifdef
Eric
> +#endif
> +
> report_prefix_push(argv[1]);
>
> if (strcmp(argv[1], "setup") == 0) {
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 08/10] arm64: pmu: count EL2 cycles
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 08/10] arm64: pmu: count EL2 cycles Joey Gouly
@ 2025-12-02 10:31 ` Eric Auger
0 siblings, 0 replies; 38+ messages in thread
From: Eric Auger @ 2025-12-02 10:31 UTC (permalink / raw)
To: Joey Gouly, kvm
Cc: alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On 9/25/25 4:19 PM, Joey Gouly wrote:
> Count EL2 cycles if that's the EL kvm-unit-tests is running at!
>
> Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
> ---
> arm/pmu.c | 13 +++++++++----
> 1 file changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/arm/pmu.c b/arm/pmu.c
> index 2dc0822b..e6c0f05b 100644
> --- a/arm/pmu.c
> +++ b/arm/pmu.c
> @@ -121,6 +121,8 @@ static struct pmu pmu;
> #define PMINTENCLR __ACCESS_CP15(c9, 0, c14, 2)
> #define PMCCNTR64 __ACCESS_CP15_64(0, c9)
>
> +#define PMCCFILTR_EL0_DEFAULT 0
> +
> static inline uint32_t get_id_dfr0(void) { return read_sysreg(ID_DFR0); }
> static inline uint32_t get_pmcr(void) { return read_sysreg(PMCR); }
> static inline void set_pmcr(uint32_t v) { write_sysreg(v, PMCR); }
> @@ -206,6 +208,9 @@ static void test_overflow_interrupt(bool overflow_at_64bits) {}
> #define ID_DFR0_PMU_V3_8_5 0b0110
> #define ID_DFR0_PMU_IMPDEF 0b1111
>
> +#define PMCCFILTR_EL0_NSH BIT(27)
> +#define PMCCFILTR_EL0_DEFAULT (current_level() == CurrentEL_EL2 ? PMCCFILTR_EL0_NSH : 0)
> +
> static inline uint32_t get_id_aa64dfr0(void) { return read_sysreg(id_aa64dfr0_el1); }
> static inline uint32_t get_pmcr(void) { return read_sysreg(pmcr_el0); }
> static inline void set_pmcr(uint32_t v) { write_sysreg(v, pmcr_el0); }
> @@ -246,8 +251,7 @@ static inline void precise_instrs_loop(int loop, uint32_t pmcr)
> #define PMCNTENSET_EL0 sys_reg(3, 3, 9, 12, 1)
> #define PMCNTENCLR_EL0 sys_reg(3, 3, 9, 12, 2)
>
> -#define PMEVTYPER_EXCLUDE_EL1 BIT(31)
> -#define PMEVTYPER_EXCLUDE_EL0 BIT(30)
> +#define PMEVTYPER_EXCLUDE_EL0 BIT(30) | (current_level() == CurrentEL_EL2 ? BIT(27) : 0)
>
> static bool is_event_supported(uint32_t n, bool warn)
> {
> @@ -1063,7 +1067,8 @@ static bool check_cycles_increase(void)
> /* init before event access, this test only cares about cycle count */
> pmu_reset();
> set_pmcntenset(1 << PMU_CYCLE_IDX);
> - set_pmccfiltr(0); /* count cycles in EL0, EL1, but not EL2 */
> +
> + set_pmccfiltr(PMCCFILTR_EL0_DEFAULT);
>
> set_pmcr(get_pmcr() | PMU_PMCR_LC | PMU_PMCR_C | PMU_PMCR_E);
> isb();
> @@ -1118,7 +1123,7 @@ static bool check_cpi(int cpi)
> /* init before event access, this test only cares about cycle count */
> pmu_reset();
> set_pmcntenset(1 << PMU_CYCLE_IDX);
> - set_pmccfiltr(0); /* count cycles in EL0, EL1, but not EL2 */
> + set_pmccfiltr(PMCCFILTR_EL0_DEFAULT);
>
> if (cpi > 0)
> printf("Checking for CPI=%d.\n", cpi);
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 09/10] arm64: run at EL2 if supported
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 09/10] arm64: run at EL2 if supported Joey Gouly
@ 2025-12-02 10:35 ` Eric Auger
0 siblings, 0 replies; 38+ messages in thread
From: Eric Auger @ 2025-12-02 10:35 UTC (permalink / raw)
To: Joey Gouly, kvm
Cc: alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On 9/25/25 4:19 PM, Joey Gouly wrote:
> If VHE is supported, continue booting at EL2, otherwise continue booting at
> EL1.
>
> Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
> ---
> arm/cstart64.S | 17 +++++++++++++----
> lib/arm64/asm/sysreg.h | 5 +++++
> 2 files changed, 18 insertions(+), 4 deletions(-)
>
> diff --git a/arm/cstart64.S b/arm/cstart64.S
> index 79b93dd4..af7c81c1 100644
> --- a/arm/cstart64.S
> +++ b/arm/cstart64.S
> @@ -18,7 +18,7 @@
> .macro init_el, tmp
> mrs \tmp, CurrentEL
> cmp \tmp, CurrentEL_EL2
> - b.ne 1f
> + b.ne 2f
> /* EL2 setup */
> mrs \tmp, mpidr_el1
> msr vmpidr_el2, \tmp
> @@ -41,17 +41,26 @@
> msr_s SYS_HFGWTR2_EL2, \tmp
> msr_s SYS_HFGITR2_EL2, \tmp
> .Lskip_fgt_\@:
> + /* check VHE is supported */
> + mrs \tmp, ID_AA64MMFR1_EL1
> + ubfx \tmp, \tmp, ID_AA64MMFR1_EL1_VH_SHIFT, #4
> + cbz \tmp, 1f
> + ldr \tmp, =(INIT_HCR_EL2)
> + msr hcr_el2, \tmp
> + isb
> + b 2f
> +1:
> mov \tmp, #0
> msr cptr_el2, \tmp
> ldr \tmp, =(INIT_HCR_EL2_EL1_ONLY)
> msr hcr_el2, \tmp
> mov \tmp, PSR_MODE_EL1t
> msr spsr_el2, \tmp
> - adrp \tmp, 1f
> - add \tmp, \tmp, :lo12:1f
> + adrp \tmp, 2f
> + add \tmp, \tmp, :lo12:2f
> msr elr_el2, \tmp
> eret
> -1:
> +2:
> .endm
>
>
> diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h
> index ed776716..f2d05018 100644
> --- a/lib/arm64/asm/sysreg.h
> +++ b/lib/arm64/asm/sysreg.h
> @@ -80,6 +80,8 @@ asm(
> #define ID_AA64MMFR0_EL1_FGT_SHIFT 56
> #define ID_AA64MMFR0_EL1_FGT_FGT2 0x2
>
> +#define ID_AA64MMFR1_EL1_VH_SHIFT 8
> +
> #define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0)
> #define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
> #define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
> @@ -116,9 +118,12 @@ asm(
> #define SCTLR_EL1_TCF0_SHIFT 38
> #define SCTLR_EL1_TCF0_MASK GENMASK_ULL(39, 38)
>
> +#define HCR_EL2_TGE _BITULL(27)
> #define HCR_EL2_RW _BITULL(31)
> +#define HCR_EL2_E2H _BITULL(34)
>
> #define INIT_HCR_EL2_EL1_ONLY (HCR_EL2_RW)
> +#define INIT_HCR_EL2 (HCR_EL2_TGE | HCR_EL2_E2H | HCR_EL2_RW)
>
> #define SYS_HFGRTR_EL2 sys_reg(3, 4, 1, 1, 4)
> #define SYS_HFGWTR_EL2 sys_reg(3, 4, 1, 1, 5)
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 07/10] arm64: selftest: update test for running at EL2
2025-12-02 9:16 ` Eric Auger
@ 2025-12-02 12:21 ` Joey Gouly
2025-12-02 12:30 ` Eric Auger
0 siblings, 1 reply; 38+ messages in thread
From: Joey Gouly @ 2025-12-02 12:21 UTC (permalink / raw)
To: Eric Auger
Cc: kvm, alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On Tue, Dec 02, 2025 at 10:16:42AM +0100, Eric Auger wrote:
>
>
> On 9/25/25 4:19 PM, Joey Gouly wrote:
> > From: Alexandru Elisei <alexandru.elisei@arm.com>
> >
> > Remove some hard-coded assumptions that this test is running at EL1.
> >
> > Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
> > Signed-off-by: Joey Gouly <joey.gouly@arm.com>
> > ---
> > arm/selftest.c | 18 +++++++++++++-----
> > 1 file changed, 13 insertions(+), 5 deletions(-)
> >
> > diff --git a/arm/selftest.c b/arm/selftest.c
> > index 1553ed8e..01691389 100644
> > --- a/arm/selftest.c
> > +++ b/arm/selftest.c
> > @@ -232,6 +232,7 @@ static void user_psci_system_off(struct pt_regs *regs)
> > __user_psci_system_off();
> > }
> > #elif defined(__aarch64__)
> > +static unsigned long expected_level;
> >
> > /*
> > * Capture the current register state and execute an instruction
> > @@ -276,8 +277,7 @@ static bool check_regs(struct pt_regs *regs)
> > {
> > unsigned i;
> >
> > - /* exception handlers should always run in EL1 */
> > - if (current_level() != CurrentEL_EL1)
> > + if (current_level() != expected_level)
> > return false;
> >
> > for (i = 0; i < ARRAY_SIZE(regs->regs); ++i) {
> > @@ -301,7 +301,11 @@ static enum vector check_vector_prep(void)
> > return EL0_SYNC_64;
> >
> > asm volatile("mrs %0, daif" : "=r" (daif) ::);
> > - expected_regs.pstate = daif | PSR_MODE_EL1h;
> > + expected_regs.pstate = daif;
> > + if (current_level() == CurrentEL_EL1)
> > + expected_regs.pstate |= PSR_MODE_EL1h;
> > + else
> > + expected_regs.pstate |= PSR_MODE_EL2h;
> > return EL1H_SYNC;
> > }
> >
> > @@ -317,8 +321,8 @@ static bool check_und(void)
> >
> > install_exception_handler(v, ESR_EL1_EC_UNKNOWN, unknown_handler);
> >
> > - /* try to read an el2 sysreg from el0/1 */
> > - test_exception("", "mrs x0, sctlr_el2", "", "x0");
> > + /* try to read an el3 sysreg from el0/1/2 */
> > + test_exception("", "mrs x0, sctlr_el3", "", "x0");
> >
> > install_exception_handler(v, ESR_EL1_EC_UNKNOWN, NULL);
> >
> > @@ -429,6 +433,10 @@ int main(int argc, char **argv)
> > if (argc < 2)
> > report_abort("no test specified");
> >
> > +#if defined(__aarch64__)
> > + expected_level = current_level();
> nit I would directly use current_level() in the calling function,
> check_regs() to avoid that #ifdef
I can't move it into check_regs() because that's what's checking the exception
level of the handler is what the expected_level is.
Something like this (untested) would work:
diff --git a/arm/selftest.c b/arm/selftest.c
index 01691389..f173bc99 100644
--- a/arm/selftest.c
+++ b/arm/selftest.c
@@ -215,6 +215,7 @@ static void pabt_handler(struct pt_regs *regs)
static bool check_pabt(void)
{
+ expected_level = current_level();
install_exception_handler(EXCPTN_PABT, pabt_handler);
test_exception("ldr r9, =check_pabt_invalid_paddr\n"
@@ -318,6 +319,7 @@ static void unknown_handler(struct pt_regs *regs, unsigned int esr __unused)
static bool check_und(void)
{
enum vector v = check_vector_prep();
+ expected_level = current_level();
install_exception_handler(v, ESR_EL1_EC_UNKNOWN, unknown_handler);
@@ -340,6 +342,7 @@ static void svc_handler(struct pt_regs *regs, unsigned int esr)
static bool check_svc(void)
{
enum vector v = check_vector_prep();
+ expected_level = current_level();
install_exception_handler(v, ESR_EL1_EC_SVC64, svc_handler);
@@ -433,10 +436,6 @@ int main(int argc, char **argv)
if (argc < 2)
report_abort("no test specified");
-#if defined(__aarch64__)
- expected_level = current_level();
-#endif
-
report_prefix_push(argv[1]);
if (strcmp(argv[1], "setup") == 0) {
Is that preferable than an #ifdef?
Thanks,
Joey
>
> Eric
> > +#endif
> > +
> > report_prefix_push(argv[1]);
> >
> > if (strcmp(argv[1], "setup") == 0) {
>
^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 07/10] arm64: selftest: update test for running at EL2
2025-12-02 12:21 ` Joey Gouly
@ 2025-12-02 12:30 ` Eric Auger
0 siblings, 0 replies; 38+ messages in thread
From: Eric Auger @ 2025-12-02 12:30 UTC (permalink / raw)
To: Joey Gouly
Cc: kvm, alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On 12/2/25 1:21 PM, Joey Gouly wrote:
> On Tue, Dec 02, 2025 at 10:16:42AM +0100, Eric Auger wrote:
>>
>> On 9/25/25 4:19 PM, Joey Gouly wrote:
>>> From: Alexandru Elisei <alexandru.elisei@arm.com>
>>>
>>> Remove some hard-coded assumptions that this test is running at EL1.
>>>
>>> Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
>>> Signed-off-by: Joey Gouly <joey.gouly@arm.com>
>>> ---
>>> arm/selftest.c | 18 +++++++++++++-----
>>> 1 file changed, 13 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/arm/selftest.c b/arm/selftest.c
>>> index 1553ed8e..01691389 100644
>>> --- a/arm/selftest.c
>>> +++ b/arm/selftest.c
>>> @@ -232,6 +232,7 @@ static void user_psci_system_off(struct pt_regs *regs)
>>> __user_psci_system_off();
>>> }
>>> #elif defined(__aarch64__)
>>> +static unsigned long expected_level;
>>>
>>> /*
>>> * Capture the current register state and execute an instruction
>>> @@ -276,8 +277,7 @@ static bool check_regs(struct pt_regs *regs)
>>> {
>>> unsigned i;
>>>
>>> - /* exception handlers should always run in EL1 */
>>> - if (current_level() != CurrentEL_EL1)
>>> + if (current_level() != expected_level)
>>> return false;
>>>
>>> for (i = 0; i < ARRAY_SIZE(regs->regs); ++i) {
>>> @@ -301,7 +301,11 @@ static enum vector check_vector_prep(void)
>>> return EL0_SYNC_64;
>>>
>>> asm volatile("mrs %0, daif" : "=r" (daif) ::);
>>> - expected_regs.pstate = daif | PSR_MODE_EL1h;
>>> + expected_regs.pstate = daif;
>>> + if (current_level() == CurrentEL_EL1)
>>> + expected_regs.pstate |= PSR_MODE_EL1h;
>>> + else
>>> + expected_regs.pstate |= PSR_MODE_EL2h;
>>> return EL1H_SYNC;
>>> }
>>>
>>> @@ -317,8 +321,8 @@ static bool check_und(void)
>>>
>>> install_exception_handler(v, ESR_EL1_EC_UNKNOWN, unknown_handler);
>>>
>>> - /* try to read an el2 sysreg from el0/1 */
>>> - test_exception("", "mrs x0, sctlr_el2", "", "x0");
>>> + /* try to read an el3 sysreg from el0/1/2 */
>>> + test_exception("", "mrs x0, sctlr_el3", "", "x0");
>>>
>>> install_exception_handler(v, ESR_EL1_EC_UNKNOWN, NULL);
>>>
>>> @@ -429,6 +433,10 @@ int main(int argc, char **argv)
>>> if (argc < 2)
>>> report_abort("no test specified");
>>>
>>> +#if defined(__aarch64__)
>>> + expected_level = current_level();
>> nit I would directly use current_level() in the calling function,
>> check_regs() to avoid that #ifdef
> I can't move it into check_regs() because that's what's checking the exception
> level of the handler is what the expected_level is.
>
> Something like this (untested) would work:
>
> diff --git a/arm/selftest.c b/arm/selftest.c
> index 01691389..f173bc99 100644
> --- a/arm/selftest.c
> +++ b/arm/selftest.c
> @@ -215,6 +215,7 @@ static void pabt_handler(struct pt_regs *regs)
>
> static bool check_pabt(void)
> {
> + expected_level = current_level();
> install_exception_handler(EXCPTN_PABT, pabt_handler);
>
> test_exception("ldr r9, =check_pabt_invalid_paddr\n"
> @@ -318,6 +319,7 @@ static void unknown_handler(struct pt_regs *regs, unsigned int esr __unused)
> static bool check_und(void)
> {
> enum vector v = check_vector_prep();
> + expected_level = current_level();
>
> install_exception_handler(v, ESR_EL1_EC_UNKNOWN, unknown_handler);
>
> @@ -340,6 +342,7 @@ static void svc_handler(struct pt_regs *regs, unsigned int esr)
> static bool check_svc(void)
> {
> enum vector v = check_vector_prep();
> + expected_level = current_level();
>
> install_exception_handler(v, ESR_EL1_EC_SVC64, svc_handler);
>
> @@ -433,10 +436,6 @@ int main(int argc, char **argv)
> if (argc < 2)
> report_abort("no test specified");
>
> -#if defined(__aarch64__)
> - expected_level = current_level();
> -#endif
> -
> report_prefix_push(argv[1]);
>
> if (strcmp(argv[1], "setup") == 0) {
>
> Is that preferable than an #ifdef?
OK. yes I think so
Eric
>
> Thanks,
> Joey
>> Eric
>>> +#endif
>>> +
>>> report_prefix_push(argv[1]);
>>>
>>> if (strcmp(argv[1], "setup") == 0) {
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support
2025-12-01 23:16 ` Andrew Jones
@ 2025-12-02 14:22 ` Joey Gouly
0 siblings, 0 replies; 38+ messages in thread
From: Joey Gouly @ 2025-12-02 14:22 UTC (permalink / raw)
To: Andrew Jones
Cc: Eric Auger, kvm, alexandru.elisei, kvmarm, Marc Zyngier,
Oliver Upton
On Mon, Dec 01, 2025 at 05:16:40PM -0600, Andrew Jones wrote:
> On Thu, Nov 27, 2025 at 02:52:07PM +0000, Joey Gouly wrote:
> ...
> > I will send out a new version with this fix, missing sob/reviews/acks, after you've had a look!
> >
>
> Also please run checkpatch on the series if you haven't already. I think
> it should have complained about the C++ comments, for example. And, in
> any case, please change the C++ comments to C comments and generally use
> the kernel's coding style.
I hadn't run it, have done so now, and fixed some style issues.
checkpatch doesn't actually complain about those C++/C99 comments, I guess at
some point Linux started to allow them. If you run with `--ignore
C99_COMMENT_TOLERANCE` it does complain.
I will change the one place I used them to the multiline style anyway.
Thanks,
Joey
^ permalink raw reply [flat|nested] 38+ messages in thread
end of thread, other threads:[~2025-12-02 14:22 UTC | newest]
Thread overview: 38+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-25 14:19 [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 01/10] arm64: drop to EL1 if booted at EL2 Joey Gouly
2025-11-27 17:07 ` Eric Auger
2025-11-28 15:11 ` Joey Gouly
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 02/10] arm64: efi: initialise SCTLR_ELx fully Joey Gouly
2025-11-27 16:49 ` Eric Auger
2025-11-28 15:18 ` Joey Gouly
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 03/10] arm64: efi: initialise the EL Joey Gouly
2025-11-27 17:08 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 04/10] arm64: timer: use hypervisor timers when at EL2 Joey Gouly
2025-12-02 8:36 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 05/10] arm64: micro-bench: fix timer IRQ Joey Gouly
2025-12-02 8:36 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 06/10] arm64: micro-bench: use smc when at EL2 Joey Gouly
2025-12-02 9:11 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 07/10] arm64: selftest: update test for running " Joey Gouly
2025-12-02 9:16 ` Eric Auger
2025-12-02 12:21 ` Joey Gouly
2025-12-02 12:30 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 08/10] arm64: pmu: count EL2 cycles Joey Gouly
2025-12-02 10:31 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 09/10] arm64: run at EL2 if supported Joey Gouly
2025-12-02 10:35 ` Eric Auger
2025-09-25 14:19 ` [kvm-unit-tests PATCH v3 10/10] arm64: add EL2 environment variable Joey Gouly
2025-11-27 10:34 ` Eric Auger
2025-11-27 10:40 ` Joey Gouly
2025-12-01 23:34 ` Andrew Jones
2025-11-19 13:18 ` [kvm-unit-tests PATCH v3 00/10] arm64: EL2 support Joey Gouly
2025-11-19 13:48 ` Nadav Amit
2025-11-19 14:02 ` Joey Gouly
2025-11-19 15:34 ` Andrew Jones
2025-11-19 15:34 ` Marc Zyngier
2025-11-27 10:04 ` Eric Auger
2025-11-27 11:08 ` Joey Gouly
2025-11-27 12:04 ` Eric Auger
2025-11-27 14:52 ` Joey Gouly
2025-12-01 23:16 ` Andrew Jones
2025-12-02 14:22 ` Joey Gouly
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox