]> git.ipfire.org Git - thirdparty/kernel/linux.git/commit
clocksource/drivers/arm_arch_timer: Default to EL2 virtual timer when running VHE
authorMarc Zyngier <maz@kernel.org>
Sat, 23 May 2026 14:02:28 +0000 (15:02 +0100)
committerDaniel Lezcano <daniel.lezcano@kernel.org>
Wed, 3 Jun 2026 07:53:21 +0000 (09:53 +0200)
commitd87773de9efe1df6fe2ba379926f9df92f1a5913
tree20013abcdd35a06475023cf48bc13e135578b1e9
parentfe15af3e75298533056ce73f8e66cd3da31f2b4a
clocksource/drivers/arm_arch_timer: Default to EL2 virtual timer when running VHE

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@kernel.org>
Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
Link: https://patch.msgid.link/20260523140242.586031-4-maz@kernel.org
drivers/clocksource/arm_arch_timer.c