[bug report] KVM: arm64: vgic-its: Performance degradation on GICv3 LPI injection
Zhiqiang Ni
nizhiqiang1 at huawei.com
Wed Oct 23 23:08:13 PDT 2024
在 2024/10/24 13:06, Zhiqiang Ni 写道:
> Hi all,
>
> I found a performance degradation on GICv3 LPI injection after this
> commit ad362fe07fecf0aba839ff2cc59a3617bd42c33f(KVM: arm64: vgic-its:
> Avoid potential UAF in LPI translation cache).
>
> In my testcase, the vm's configuration is 60 VCPU 120G RAM with a
> 32-queue NIC and the kernel version is 5.10. The number of new TCP
> connections per second changed from 150,000 to 50,000 after this
> patch, with the %sys of cpu changed from 15% to 85%.
>
> From the ftrace, I found that the duration of vgic_put_irq() is
> 13.320 us, which may be the reason for the performance degradation.
>
> The call stack looks like below:
> kvm_arch_set_irq_inatomic()
> vgic_has_its();
> vgic_its_inject_cached_translation()
> vgic_its_check_cache()
> vgic_queue_irq_unlock()
> vgic_put_irq()
>
> So, I tried to modify the code like below and I found the performance
> degradation is gone. Is this a good idea?
>
I am sorry. This is not the correct patch.
> From 2bd98f8a2cc02a17423ced36e07f7bb3c7e044af Mon Sep 17 00:00:00 2001
> From: Zhiqiang Ni <nizhiqiang1 at huawei.com>
> Date: Thu, 24 Oct 2024 12:29:28 +0800
> Subject: [PATCH] KVM: arm64: vgic-its: Avoid vgic_put_irq in LPI translation
> cache
>
> ---
> arch/arm64/kvm/vgic/vgic-its.c | 32 ++++++++++----------------------
> 1 file changed, 10 insertions(+), 22 deletions(-)
>
> diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c
> index 93c0365cd..0efabe555 100644
> --- a/arch/arm64/kvm/vgic/vgic-its.c
> +++ b/arch/arm64/kvm/vgic/vgic-its.c
> @@ -579,24 +579,6 @@ static struct vgic_irq *__vgic_its_check_cache(struct vgic_dist *dist,
> return NULL;
> }
>
> -static struct vgic_irq *vgic_its_check_cache(struct kvm *kvm, phys_addr_t db,
> - u32 devid, u32 eventid)
> -{
> - struct vgic_dist *dist = &kvm->arch.vgic;
> - struct vgic_irq *irq;
> - unsigned long flags;
> -
> - raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
> -
> - irq = __vgic_its_check_cache(dist, db, devid, eventid);
> - if (irq)
> - vgic_get_irq_kref(irq);
> -
> - raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
> -
> - return irq;
> -}
> -
> static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
> u32 devid, u32 eventid,
> struct vgic_irq *irq)
> @@ -759,18 +741,24 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
> int vgic_its_inject_cached_translation(struct kvm *kvm, struct kvm_msi *msi)
> {
> struct vgic_irq *irq;
> - unsigned long flags;
> + unsigned long flags, flags2;
> phys_addr_t db;
> + struct vgic_dist *dist = &kvm->arch.vgic;
>
> db = (u64)msi->address_hi << 32 | msi->address_lo;
> - irq = vgic_its_check_cache(kvm, db, msi->devid, msi->data);
> - if (!irq)
> + raw_spin_lock_irqsave(&dist->lpi_list_lock, flags2);
> + irq = __vgic_its_check_cache(dist, db, msi->devid, msi->data);
> +
> + if (!irq) {
> + raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags2);
> return -EWOULDBLOCK;
> + }
>
> raw_spin_lock_irqsave(&irq->irq_lock, flags);
> irq->pending_latch = true;
> vgic_queue_irq_unlock(kvm, irq, flags);
> - vgic_put_irq(kvm, irq);
> +
> + raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags2);
>
> return 0;
> }
More information about the linux-arm-kernel
mailing list