Re: [PATCH] KVM: arm64: Fix hvhe and broken CNTVOFF_EL2
Yao Yuan <[email protected]> Fri, 7 Aug 2026 09:37:06 +0800
| Newsgroups | dev.linux.lists.kvmarm,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <gm2w76lflkw67xc4io2ornvfugvijbwotzvwmmefsfcqvrasgp@qkybjxr6lukr> |
On Thu, Aug 06, 2026 at 03:01:05PM +0800, Mostafa Saleh wrote: > When running on a setup affected with broken CNTVOFF_EL2 > (has_broken_cntvoff()) > > Booting with VHE or protected mode(nvhe) (id_aa64mmfr1.vh=0 > and arm64_sw.hvhe=0) works fine. > > However launching a protected VM with protected hvhe mode panics the > guest kernel: ... > And for non protected VMs seems to hang or progress really slowly. > > The workaround avoids setting non-zero CNTVOFF_EL2 and trapping the > virtual counter to emulate the offset. > In the VHE path (timer_set_traps()), traps are only enabled when the > guest actually has a non-zero virtual timer offset. > However, __timer_enable_traps() in hyp/nvhe/timer-sr.c unconditionally > set CNTHCTL_EL1TVT and CNTHCTL_EL1TVCT whenever has_broken_cntvoff() > was true. > > Which causes 2 issues: > 1) Protected VMs: kvm_handle_pvm_sysreg() does not find "cntv_ctl_el0" > in pvm_sys_reg_descs and injects undefined instruction exceptions. > > 2) non-protected guests are trapped all the time even with offset of > zero. > > Fix this by adding a check in __timer_enable_traps() similar to the one in > timer_set_traps() Hi Saleh, May more fix is needed for case that guest real have virtual offset, due to no cntv_ctl_el0 handler there. For current fix for virtual offset is zero: Reviewed-by: Yuan Yao <[email protected]> > > Fixes: 0bc9a9e85fcf ("KVM: arm64: Work around x1e's CNTVOFF_EL2 bogosity") > Signed-off-by: Mostafa Saleh <[email protected]> > --- > arch/arm64/kvm/hyp/nvhe/timer-sr.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/arch/arm64/kvm/hyp/nvhe/timer-sr.c b/arch/arm64/kvm/hyp/nvhe/timer-sr.c > index ff176f4ce7de..98b6e37ee8fa 100644 > --- a/arch/arm64/kvm/hyp/nvhe/timer-sr.c > +++ b/arch/arm64/kvm/hyp/nvhe/timer-sr.c > @@ -10,6 +10,7 @@ > > #include <asm/kvm_hyp.h> > #include <asm/kvm_mmu.h> > +#include <hyp/switch.h> > > void __kvm_timer_set_cntvoff(u64 cntvoff) > { > @@ -63,7 +64,7 @@ void __timer_enable_traps(struct kvm_vcpu *vcpu) > * Trap the virtual counter/timer if we have a broken cntvoff > * implementation. > */ > - if (has_broken_cntvoff()) > + if (has_broken_cntvoff() && hyp_timer_get_offset(vcpu_vtimer(vcpu))) > set |= CNTHCTL_EL1TVT | CNTHCTL_EL1TVCT; > > sysreg_clear_set(cnthctl_el2, clr, set); > -- > 2.55.0.654.g21b8a5bc05-goog >