[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 04:32:24 PDT 2026
On 09.06.2026 12:46, Marc Zyngier wrote:
> On Tue, 09 Jun 2026 11:35:24 +0100,
> Marek Szyprowski <m.szyprowski at samsung.com> wrote:
>> 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.
> [+ Florian]
>
> Huh. So that really points at the timer not being wired into the GIC,
> Samsung style... Can you confirm that removing the EL2 virtual timer
> from the DT results in a booting machine?
With the following diff the board boots again:
diff --git a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
index 761c59d90ffc..09ff5e9959d3 100644
--- a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
+++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
@@ -678,8 +678,6 @@ IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
- IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 12 (GIC_CPU_MASK_SIMPLE(4) |
IRQ_TYPE_LEVEL_LOW)>;
};
> Florian, can you please check whether PPI12 is actually the EL2
> virtual timer on the RPI5 SoC?
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
More information about the linux-arm-kernel
mailing list