Subject: Re: [PATCH 14/43] KVM: arm64: gic-v5: Request VPE doorbells when going non-resident

From: Sascha Bischoff <[email-masked]>
Date: Thu, 21 May 2026 14:06:01 +0000

On Thu, 2026-04-30 at 11:37 +0100, Marc Zyngier wrote:
> On Mon, 27 Apr 2026 17:10:49 +0100,
> Sascha Bischoff <[email-masked]> wrote:
> > 
> > When a VPE is made non-resident and is entering WFI, a doorbell
> > should
> > be requested for the VPE. This allows the VPE to be easily woken
> > once
> > an SPI/LPI interrupt is pending for it. This is tracked by the IRS,
> > which will signal the specific VPE doorbell for the VPE once such
> > an
> > interrupt arrives.
> > 
> > Requesting a doorbell involves calculating the DBPM - DoorBell
> > Priority Mask - which ensures that the DB is only signalled by the
> > hardware if the pending interrupt is of sufficient priority. This
> > avoids waking a VPE that can't process the incoming interrupt.
> > 
> > Doorbells are NOT requested if a VPE is not entering WFI as we
> > expect
> > to enter again imminently.
> > 
> > Signed-off-by: Sascha Bischoff <[email-masked]>
> > ---
> >  arch/arm64/kvm/vgic/vgic-v5.c | 28 ++++++++++++++++++++++++++++
> >  1 file changed, 28 insertions(+)
> > 
> > diff --git a/arch/arm64/kvm/vgic/vgic-v5.c
> > b/arch/arm64/kvm/vgic/vgic-v5.c
> > index 11a1a491b7e0a..2fc6fa4df034f 100644
> > --- a/arch/arm64/kvm/vgic/vgic-v5.c
> > +++ b/arch/arm64/kvm/vgic/vgic-v5.c
> > @@ -1077,6 +1077,9 @@ void vgic_v5_load(struct kvm_vcpu *vcpu)
> >  void vgic_v5_put(struct kvm_vcpu *vcpu)
> >  {
> >   struct vgic_v5_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v5;
> > + bool req_db = !!vcpu_get_flag(vcpu, IN_WFI);
> 
> Drop the spurious variable and move the check in the if () statement.
> This is way more readable than declaring a variable.

Done.

> 
> > + u32 priority_mask;
> > + int dbpm;
> 
> Move these in the inner block.

Done.

> 
> >  
> >   /*
> >   * Do nothing if we're not resident. This can happen in the WFI
> > path
> > @@ -1090,6 +1093,31 @@ void vgic_v5_put(struct kvm_vcpu *vcpu)
> >   kvm_call_hyp(__vgic_v5_save_apr, cpu_if);
> >  
> >   cpu_if->vgic_contextr = 0;
> > + if (req_db) {
> > + /*
> > + * Find the virtual running priority and use this to calculate
> > + * the doorbell priority mask. We combine the highest active
> > + * priority and the CPU's priority mask. The guest can't handle
> > + * interrupts with priorities less than or equal to the virtual
> > + * running priority, so there's literally no point in waking the
> > + * guest for these.
> > + *
> > + * The priority needs to be higher than the mask to signal, so
> > + * pick the next higher priority (subtract 1).
> > + */
> > + priority_mask = vgic_v5_get_effective_priority_mask(vcpu);
> > +
> > + /* Don't request a doorbell if the max priority is masked */
> 
> This comment reads badly. I'd suggest something like "Request a
> doorbell *unless* the priority is 0, indicating that no interrupt can
> wake the vcpu up".

Done.

> 
> > + if (priority_mask) {
> > + dbpm = priority_mask - 1;
> > + cpu_if->vgic_contextr = FIELD_PREP(ICH_CONTEXTR_EL2_DB, 1) |
> > + FIELD_PREP(ICH_CONTEXTR_EL2_DBPM, dbpm);
> > + }
> > +
> > + /* Make the doorbell affine to this CPU */
> > + WARN_ON(irq_set_affinity(vgic_v5_vpe_db(vcpu),
> > + cpumask_of(smp_processor_id())));
> 
> Repeatedly setting the affinity is likely to be costly. It may be
> worth comparing with the current affinity somehow.

I've changed this to check the affinity first, and then only change it
if the CPU has changed since it was last set.

> 
> > + }
> >  
> >   kvm_call_hyp(__vgic_v5_make_non_resident, cpu_if);
> >  
> 
> Thanks,
> 
>  M.
> 

Thanks,
Sascha