Re: [PATCH v2 3/3] KVM: arm64: Fix hvhe and broken CNTVOFF_EL2
Mostafa Saleh <[email protected]> Sat, 8 Aug 2026 15:31:04 +0100
| Newsgroups | dev.linux.lists.kvmarm,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAFgf54pb+5UnYYkbMKe280-ODvbQ=Vhtj8Qk7btR6ZNDwrmzrQ@mail.gmail.com> |
On Sat, Aug 8, 2026 at 9:58 AM Mostafa Saleh <[email protected]> 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: > > [ 0.000000] Internal error: Oops - Undefined instruction: 0000000000000000 [#1] SMP > [ 0.000000] Modules linked in: > [ 0.000000] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 7.2.0-rc3-g05f75bd71e0e-dirty #29 PREEMPT > [ 0.000000] Hardware name: linux,dummy-virt (DT) > [ 0.000000] pstate: 000003c5 (nzcv DAIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) > [ 0.000000] pc : arch_timer_shutdown_virt+0x4/0x1c > [ 0.000000] lr : arch_timer_starting_cpu+0x1c4/0x2d4 > [ 0.000000] sp : ffffa6bd9a193c00 > [ 0.000000] x29: ffffa6bd9a193c20 x28: ffffa6bd9a1bcf88 x27: 0000000000000000 > [ 0.000000] x26: ffff00001be70dd8 x25: ffffa6bd99d85000 x24: ffffa6bd99d85ee4 > [ 0.000000] x23: ffffa6bd99d85000 x22: ffffa6bd9a1499c0 x21: ffffa6bd9a1ab900 > [ 0.000000] x20: 00ffffffffffffff x19: ffff00001be8b600 x18: 000000000000028c > [ 0.000000] x17: 00000000510f0010 x16: 00000000510f0010 x15: 00000000500f0000 > [ 0.000000] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000018 > [ 0.000000] x11: ffffa6bd9a8ac000 x10: 0000000000f0000f x9 : ffffffffffffffff > [ 0.000000] x8 : ffffa6bd98822e18 x7 : 0070752d65746174 x6 : 00111ff76e007261 > [ 0.000000] x5 : ffffa6bd9ad68078 x4 : 0000000000000000 x3 : ffffa6bd98822a0c > [ 0.000000] x2 : 0000000000000073 x1 : 0000000000000001 x0 : ffff00001be8b600 > [ 0.000000] Call trace: > [ 0.000000] arch_timer_shutdown_virt+0x4/0x1c (P) > [ 0.000000] cpuhp_invoke_callback+0x11c/0x280 > [ 0.000000] cpuhp_issue_call+0x1e8/0x224 > [ 0.000000] __cpuhp_setup_state_cpuslocked+0x1d8/0x2b8 > [ 0.000000] __cpuhp_setup_state+0x50/0x74 > [ 0.000000] arch_timer_register+0xc0/0x148 > [ 0.000000] arch_timer_of_init+0x148/0x170 > [ 0.000000] timer_probe+0x74/0x124 > [ 0.000000] time_init+0x18/0x58 > [ 0.000000] start_kernel+0x1c0/0x3ac > [ 0.000000] __primary_switched+0x88/0x90 > [ 0.000000] Code: c80b7d2a 35ffffab 17ffffeb d503245f (d53be328) > > 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() > > Fixes: 0bc9a9e85fcf ("KVM: arm64: Work around x1e's CNTVOFF_EL2 bogosity") > Signed-off-by: Marc Zyngier <[email protected]> For some reason, when I used b4 to pull the first version, it added Marc's `Signed-off-by` which was not intended. Probably it got confused by the patch in the reply. Thanks, Mostafa > Reviewed-by: Yuan Yao <[email protected]> > Reviewed-by: Fuad Tabba <[email protected]> > Tested-by: Fuad Tabba <[email protected]> > Signed-off-by: Mostafa Saleh <[email protected]> > --- > arch/arm64/kvm/hyp/nvhe/timer-sr.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/arch/arm64/kvm/hyp/nvhe/timer-sr.c b/arch/arm64/kvm/hyp/nvhe/timer-sr.c > index 51b4f5010b66..993065716913 100644 > --- a/arch/arm64/kvm/hyp/nvhe/timer-sr.c > +++ b/arch/arm64/kvm/hyp/nvhe/timer-sr.c > @@ -61,9 +61,9 @@ void __timer_enable_traps(struct kvm_vcpu *vcpu) > > /* > * Trap the virtual counter/timer if we have a broken cntvoff > - * implementation. > + * implementation and non zero offset as in timer_set_traps() > */ > - if (has_broken_cntvoff()) > + if (has_broken_cntvoff() && timer_get_offset(vcpu_vtimer(vcpu))) > set |= CNTHCTL_EL1TVT | CNTHCTL_EL1TVCT; > > sysreg_clear_set(cnthctl_el2, clr, set); > -- > 2.55.0.654.g21b8a5bc05-goog >