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

Vishnu Pajjuri
2026-03-30T11:52:01Z

Hi Fuad Tabba,
I'm trying to run nested VMs on Ampere platforms after this patch
series(v6.19+) but nested VMs are not booting and triggering soft
lockups on L0 and L0 hang. But just before this patch I could able to
successfully boot the Nested VMs.

I bisected the failure to a single commit which is this patch which is
causing the issue.

I would like to understand from you that did you observed anything like
that?

Were you able to boot Nested VMs successfully after v6.19+?

LOG:
[ 164.647367] Call trace:
[ 164.647368] smp_call_function_many_cond+0x334/0x7a0 (P)
[ 164.647372] smp_call_function_many+0x20/0x40
[ 164.647374] kvm_make_all_cpus_request+0xec/0x1b8
[ 164.647377] vgic_queue_irq_unlock+0x1c8/0x2c8
[ 164.647380] kvm_vgic_inject_irq+0x194/0x1e0
[ 164.647381] kvm_vm_ioctl_irq_line+0x170/0x400
[ 164.647386] kvm_vm_ioctl+0x7b8/0xc88
[ 164.647389] __arm64_sys_ioctl+0xb4/0x118
[ 164.647393] invoke_syscall+0x6c/0x100
[ 164.647397] el0_svc_common.constprop.0+0x48/0xf0
[ 164.647398] do_el0_svc+0x24/0x38
[ 164.647400] el0_svc+0x3c/0x170
[ 164.647403] el0t_64_sync_handler+0xa0/0xe8
[ 164.647405] el0t_64_sync+0x1b0/0x1b8

Regards,
-Vishnu.

On 20-11-2025 22:55, Marc Zyngier wrote:
> Pretty much like the rest of the LR handling, deactivation of an
> L2 interrupt gets reflected in the L1 LRs, and therefore must be
> propagated into the L1 shadow state if the interrupt is HW-bound.
>
> Instead of directly handling the active state (which looks a bit
> off as it ignores locking and L1->L0 HW propagation), use the new
> deactivation primitive to perform the deactivation and deal with
> the required maintenance.
>
> Tested-by: Fuad Tabba <tabba@google.com>
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
> arch/arm64/kvm/vgic/vgic-v3-nested.c | 19 +++++++++----------
> 1 file changed, 9 insertions(+), 10 deletions(-)
>
> diff --git a/arch/arm64/kvm/vgic/vgic-v3-nested.c b/arch/arm64/kvm/vgic/vgic-v3-nested.c
> index 40f7a37e0685c..15e7033a7937e 100644
> --- a/arch/arm64/kvm/vgic/vgic-v3-nested.c
> +++ b/arch/arm64/kvm/vgic/vgic-v3-nested.c
> @@ -280,7 +280,6 @@ void vgic_v3_sync_nested(struct kvm_vcpu *vcpu)
>
> for_each_set_bit(i, &shadow_if->lr_map, kvm_vgic_global_state.nr_lr) {
> u64 val, host_lr, lr;
> - struct vgic_irq *irq;
>
> host_lr = __gic_v3_get_lr(lr_map_idx_to_shadow_idx(shadow_if, i));
>
> @@ -290,7 +289,14 @@ void vgic_v3_sync_nested(struct kvm_vcpu *vcpu)
> val |= host_lr & ICH_LR_STATE;
> __vcpu_assign_sys_reg(vcpu, ICH_LRN(i), val);
>
> - if (!(lr & ICH_LR_HW) || !(lr & ICH_LR_STATE))
> + /*
> + * Deactivation of a HW interrupt: the LR must have the HW
> + * bit set, have been in a non-invalid state before the run,
> + * and now be in an invalid state. If any of that doesn't
> + * hold, we're done with this LR.
> + */
> + if (!((lr & ICH_LR_HW) && (lr & ICH_LR_STATE) &&
> + !(host_lr & ICH_LR_STATE)))
> continue;
>
> /*
> @@ -298,14 +304,7 @@ void vgic_v3_sync_nested(struct kvm_vcpu *vcpu)
> * need to emulate the HW effect between the guest hypervisor
> * and the nested guest.
> */
> - irq = vgic_get_vcpu_irq(vcpu, FIELD_GET(ICH_LR_PHYS_ID_MASK, lr));
> - if (WARN_ON(!irq)) /* Shouldn't happen as we check on load */
> - continue;
> -
> - if (!(host_lr & ICH_LR_STATE))
> - irq->active = false;
> -
> - vgic_put_irq(vcpu->kvm, irq);
> + vgic_v3_deactivate(vcpu, FIELD_GET(ICH_LR_PHYS_ID_MASK, lr));
> }
>
> /* We need these to be synchronised to generate the MI */