[PATCH v3 03/17] clocksource/drivers/arm_arch_timer: Default to EL2 virtual timer when running VHE

Marek Szyprowski m.szyprowski at samsung.com
Tue Jun 9 03:35:24 PDT 2026


On 09.06.2026 12:21, Marc Zyngier wrote:
> On Tue, 09 Jun 2026 11:03:21 +0100,
> Marek Szyprowski <m.szyprowski at samsung.com> wrote:
>> On 23.05.2026 16:02, Marc Zyngier wrote:
>>> When running with at EL2 with VHE enabled, the architecture provides
>>> two EL2 timer/counters, dubbed physical and virtual. Apart from their
>>> names, they are strictly identical.
>>>
>>> However, they don't get virtualised the same way, specially when
>>> it comes to adding arbitrary offsets to the timers. When running as
>>> a guest, the host CNTVOFF_EL2 does apply to the guest's view of
>>> CNTHV*_El2. This is not true for CNTPOFF_EL2 and CNTHP*_EL2, as
>>> the architecture is broken past the first level of virtualisation
>>> (it lacks some essential mechanisms to be usable, despite what
>>> the ARM ARM pretends).
>>>
>>> This means that when running as a L2 guest hypervisor, using the
>>> physical timer results in traps to L0, which are then forwarded to
>>> L1 in order to emulate the offset, leading to even worse performance
>>> due to massive trap amplification (the combination of register and
>>> ERET trapping is absolutely lethal).
>>>
>>> Switch the arch timer code to using the virtual timer when running
>>> in VHE by default, only using the physical timer if the interrupt
>>> is not correctly described in the firmware tables (which seems
>>> to be an unfortunately common case). This comes as no impact on
>>> bare-metal, and slightly improves the situation in the virtualised
>>> case.
>>>
>>> Signed-off-by: Marc Zyngier <maz at kernel.org>
>> This patch landed recently in linux-next as commit d87773de9efe
>> ("clocksource/drivers/arm_arch_timer: Default to EL2 virtual timer when
>> running VHE"). In my tests I found that it breaks booting of RaspberryPi5
>> board. Reverting it on top of linux-next fixes the issue. Here is a boot
>> log:
> Huh.
>
> [...]
>
>> arch_timer: cp15 timer running at 54.00MHz (hyp-virt).
>> clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0xc743ce346, max_idle_ns: 440795203123 ns
>> sched_clock: 56 bits at 54MHz, resolution 18ns, wraps every 4398046511102ns
> The interrupt appears to be advertised in the DT, but doesn't seem to
> fire. That's obviously not going to end well. My suspicion is that
> either the interrupt isn't wired (that'd be hilariously abd), or is
> left as Group-0 by the firmware (copy-paste from RPi4).
>
> Can you try the following hack and let me know if the kernel shouts at
> you?
>
> Thanks,
>
> 	M.
>
> diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
> index ec70c84e9f91d..d05791e6cc0db 100644
> --- a/drivers/irqchip/irq-gic.c
> +++ b/drivers/irqchip/irq-gic.c
> @@ -213,6 +213,7 @@ static void gic_eoimode1_mask_irq(struct irq_data *d)
>  static void gic_unmask_irq(struct irq_data *d)
>  {
>  	gic_poke_irq(d, GIC_DIST_ENABLE_SET);
> +	WARN_ON(!gic_peek_irq(d, GIC_DIST_ENABLE_SET));
>  }
>  
>  static void gic_eoi_irq(struct irq_data *d)

I've applied this change, but it doesn't trigger any warning in the boot log.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland




More information about the linux-arm-kernel mailing list