From: Marc Zyngier Subject: [PATCH 3/4] Pick the correct timer interrupt for the running EL To: tech@openbsd.org Cc: kettenis@openbsd.org Date: Sun, 12 Apr 2026 11:18:23 +0100 When running at EL2, the kernel is using the virtual EL2 timer, and therefore uses a different interrupt from the one driven by the virtual EL0 timer which gets used when running at EL1. Pick the correct interrupt depending on the EL the kernel runs at. Signed-off-by: Marc Zyngier --- sys/arch/arm64/dev/agtimer.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/sys/arch/arm64/dev/agtimer.c b/sys/arch/arm64/dev/agtimer.c index d5700a13f..1f008662d 100644 --- a/sys/arch/arm64/dev/agtimer.c +++ b/sys/arch/arm64/dev/agtimer.c @@ -286,10 +286,38 @@ agtimer_set_clockrate(int32_t new_frequency) sc->sc_ticks_per_second / 1000); } +static int +agtimer_get_intr_idx(int node) +{ + const char *intr_name; + int intr_idx; + uint32_t el; + + __asm volatile("mrs %x0, CurrentEL" : "=r" (el)); + el >>= 2; + + /* Pick the currect PPI depending on the running EL */ + switch (el) { + case 1: + intr_name = "virt"; + break; + case 2: + intr_name = "hyp-virt"; + break; + } + + intr_idx = OF_getindex(node, intr_name, "interrupt-names"); + if (intr_idx >= 0) + return intr_idx; + + return (el == 2) ? 4 : 2; +} + void agtimer_cpu_initclocks(void) { struct agtimer_softc *sc = agtimer_cd.cd_devs[0]; + int ppi_idx; stathz = hz; profhz = stathz * 10; @@ -299,8 +327,10 @@ agtimer_cpu_initclocks(void) agtimer_set_clockrate(agtimer_frequency); } + ppi_idx = agtimer_get_intr_idx(sc->sc_node); + /* configure virtual timer interrupt */ - sc->sc_ih = arm_intr_establish_fdt_idx(sc->sc_node, 2, + sc->sc_ih = arm_intr_establish_fdt_idx(sc->sc_node, ppi_idx, IPL_CLOCK|IPL_MPSAFE, agtimer_intr, NULL, "tick"); } -- 2.51.0