Re: [PATCH v4 35/49] KVM: arm64: GICv3: nv: Plug L1 LR sync into deactivation primitive

Marc Zyngier
2026-04-26T09:14:14Z

On Wed, 22 Apr 2026 15:57:44 +0100,
Vishnu Pajjuri <vishnu@os.amperecomputing.com> wrote:
>
> Hi Marc,
>
> On 22-04-2026 12:25, Marc Zyngier wrote:
> >
> > Have you made progress on this? I can't reproduce it at all despite my
> > best effort. I'm perfectly happy to help, but you need to give me
> > *something* to go on.
>
>
> Thanks for your support!!
>
> The issue is triggered as soon as the timer interrupt (IRQ 27) is
> deactivated. Preventing the deactivation of IRQ 27 during nested VGIC
> state transitions prevents the failure from reproducing.

Which level of deactivation? From L2 to L1? Or L1 to L0? The former
should just be a an update to the irq structure, while the latter is
effectively a write to ICC_DIR_EL1, and *that* is a new behaviour
introduced by this patch.

I wonder if your implementation is such that ICC_DIR_EL1 is trapped by
ICH_HCR_EL2.TDIR, which is allowed by the architecture, but that none
of the two implementations I have actually enforce (the trap only
applies to ICV_DIR_EL1). Can you try the hack below which disables the
traps much earlier, and let me know if that helps?

Even if that's the case, this should result in an EL2->EL2 exception,
and that should be caught as an unhandled exception in entry-common.c,
so something else is afoot.

Thanks,

M.

diff --git a/arch/arm64/kvm/vgic/vgic-v3-nested.c b/arch/arm64/kvm/vgic/vgic-v3-nested.c
index 5c69fa615823c..ee415c1038b4e 100644
--- a/arch/arm64/kvm/vgic/vgic-v3-nested.c
+++ b/arch/arm64/kvm/vgic/vgic-v3-nested.c
@@ -280,6 +280,14 @@ void vgic_v3_sync_nested(struct kvm_vcpu *vcpu)
struct shadow_if *shadow_if = get_shadow_if();
int i;

+ /* We need these to be synchronised to generate the MI */
+ __vcpu_assign_sys_reg(vcpu, ICH_VMCR_EL2, read_sysreg_s(SYS_ICH_VMCR_EL2));
+ __vcpu_rmw_sys_reg(vcpu, ICH_HCR_EL2, &=, ~ICH_HCR_EL2_EOIcount);
+ __vcpu_rmw_sys_reg(vcpu, ICH_HCR_EL2, |=, read_sysreg_s(SYS_ICH_HCR_EL2) & ICH_HCR_EL2_EOIcount);
+
+ write_sysreg_s(0, SYS_ICH_HCR_EL2);
+ isb();
+
for_each_set_bit(i, &shadow_if->lr_map, kvm_vgic_global_state.nr_lr) {
u64 val, host_lr, lr;

@@ -309,14 +317,6 @@ void vgic_v3_sync_nested(struct kvm_vcpu *vcpu)
vgic_v3_deactivate(vcpu, FIELD_GET(ICH_LR_PHYS_ID_MASK, lr));
}

- /* We need these to be synchronised to generate the MI */
- __vcpu_assign_sys_reg(vcpu, ICH_VMCR_EL2, read_sysreg_s(SYS_ICH_VMCR_EL2));
- __vcpu_rmw_sys_reg(vcpu, ICH_HCR_EL2, &=, ~ICH_HCR_EL2_EOIcount);
- __vcpu_rmw_sys_reg(vcpu, ICH_HCR_EL2, |=, read_sysreg_s(SYS_ICH_HCR_EL2) & ICH_HCR_EL2_EOIcount);
-
- write_sysreg_s(0, SYS_ICH_HCR_EL2);
- isb();
-
vgic_v3_nested_update_mi(vcpu);
}

--
Without deviation from the norm, progress is not possible.