• Marc Zyngier's avatar
    KVM: arm/arm64: vgic: Don't populate multiple LRs with the same vintid · 16ca6a60
    Marc Zyngier authored
    The vgic code is trying to be clever when injecting GICv2 SGIs,
    and will happily populate LRs with the same interrupt number if
    they come from multiple vcpus (after all, they are distinct
    interrupt sources).
    
    Unfortunately, this is against the letter of the architecture,
    and the GICv2 architecture spec says "Each valid interrupt stored
    in the List registers must have a unique VirtualID for that
    virtual CPU interface.". GICv3 has similar (although slightly
    ambiguous) restrictions.
    
    This results in guests locking up when using GICv2-on-GICv3, for
    example. The obvious fix is to stop trying so hard, and inject
    a single vcpu per SGI per guest entry. After all, pending SGIs
    with multiple source vcpus are pretty rare, and are mostly seen
    in scenario where the physical CPUs are severely overcomitted.
    
    But as we now only inject a single instance of a multi-source SGI per
    vcpu entry, we may delay those interrupts for longer than strictly
    necessary, and run the risk of injecting lower priority interrupts
    in the meantime.
    
    In order to address this, we adopt a three stage strategy:
    - If we encounter a multi-source SGI in the AP list while computing
      its depth, we force the list to be sorted
    - When populating the LRs, we prevent the injection of any interrupt
      of lower priority than that of the first multi-source SGI we've
      injected.
    - Finally, the injection of a multi-source SGI triggers the request
      of a maintenance interrupt when there will be no pending interrupt
      in the LRs (HCR_NPIE).
    
    At the point where the last pending interrupt in the LRs switches
    from Pending to Active, the maintenance interrupt will be delivered,
    allowing us to add the remaining SGIs using the same process.
    
    Cc: stable@vger.kernel.org
    Fixes: 0919e84c ("KVM: arm/arm64: vgic-new: Add IRQ sync/flush framework")
    Acked-by: default avatarChristoffer Dall <cdall@kernel.org>
    Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
    16ca6a60
vgic.c 23.9 KB