public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [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