From nobody Sun Feb 8 09:23:01 2026 Received: from baidu.com (mx24.baidu.com [111.206.215.185]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E50FF2AD2F; Tue, 7 Oct 2025 12:48:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=111.206.215.185 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759841331; cv=none; b=V1jb7e6kXhirIlGasa6isON410eAZxR7MFMJeNP5KiAXNqSENuYCYmYIyQReATdJ0pLZtNKbyGbbBwp7otXmbRaIzD5b5ti0VVhfnBQhowLCl53L7cPbcNZTRZ+Za1ThexVKRtypkzMGB5Riw7iEBOgX5pPjP9o3RFBTK+riqto= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759841331; c=relaxed/simple; bh=/+lawd4CjpTfUD3/n0BGr4AZmlHdIk7S/ZqLXTelGDg=; h=From:To:CC:Subject:Date:Message-ID:MIME-Version:Content-Type; b=I/QwgKg3451nqu54racj5wr9H9v0oZS0YK2GzmQ2FA654z6NUCatZytP/k+LeEY6U0teOiFGp8zfb2NIQR+1kWkepHREpwQwd8aq16bVESqLEBr2bbPEJokQVwtcWF4r5uYnAfQ8cQvV1hyVjZKo3OuI2Fqp2l88ydSr20VEMHc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=baidu.com; spf=pass smtp.mailfrom=baidu.com; arc=none smtp.client-ip=111.206.215.185 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=baidu.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baidu.com From: lirongqing To: , , , CC: Li RongQing Subject: [PATCH] KVM: use call_rcu instead of synchronize_srcu_expedited() for MMIO unregistration Date: Tue, 7 Oct 2025 20:48:29 +0800 Message-ID: <20251007124829.2051-1-lirongqing@baidu.com> X-Mailer: git-send-email 2.17.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: bjkjy-exc13.internal.baidu.com (172.31.51.13) To bjkjy-exc3.internal.baidu.com (172.31.50.47) X-FEAS-Client-IP: 172.31.50.47 X-FE-Policy-ID: 52:10:53:SYSTEM Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Li RongQing During VM reboot/shutdown, device MMIO unregistration maybe occurs frequently. The current use of synchronize_srcu_expedited() introduces measurable latency in these operations. Replace with call_rcu to defer cleanup asynchronously, speed up VM reboot/shutdown. Add a 'dev' field to struct kvm_io_bus to hold the device being unregistered for the RCU callback. Adjust related code to ensure proper list management before unregistration. Signed-off-by: Li RongQing --- include/linux/kvm_host.h | 1 + virt/kvm/coalesced_mmio.c | 2 +- virt/kvm/eventfd.c | 2 +- virt/kvm/kvm_main.c | 13 ++++++++----- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 19b8c4b..38498d9 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -208,6 +208,7 @@ struct kvm_io_bus { int dev_count; int ioeventfd_count; struct rcu_head rcu; + struct kvm_io_device *dev; struct kvm_io_range range[]; }; =20 diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c index 375d628..0db6af2 100644 --- a/virt/kvm/coalesced_mmio.c +++ b/virt/kvm/coalesced_mmio.c @@ -82,7 +82,6 @@ static void coalesced_mmio_destructor(struct kvm_io_devic= e *this) { struct kvm_coalesced_mmio_dev *dev =3D to_mmio(this); =20 - list_del(&dev->list); =20 kfree(dev); } @@ -169,6 +168,7 @@ int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *= kvm, list_for_each_entry_safe(dev, tmp, &kvm->coalesced_zones, list) { if (zone->pio =3D=3D dev->zone.pio && coalesced_mmio_in_range(dev, zone->addr, zone->size)) { + list_del(&dev->list); r =3D kvm_io_bus_unregister_dev(kvm, zone->pio ? KVM_PIO_BUS : KVM_MMIO_BUS, &dev->dev); /* diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index 6b1133a..8a2f0e0 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c @@ -750,7 +750,6 @@ static void ioeventfd_release(struct _ioeventfd *p) { eventfd_ctx_put(p->eventfd); - list_del(&p->list); kfree(p); } =20 @@ -949,6 +948,7 @@ kvm_deassign_ioeventfd_idx(struct kvm *kvm, enum kvm_bu= s bus_idx, if (!p->wildcard && p->datamatch !=3D args->datamatch) continue; =20 + list_del(&p->list); kvm_io_bus_unregister_dev(kvm, bus_idx, &p->dev); bus =3D kvm_get_bus(kvm, bus_idx); if (bus) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index f2e77eb..3ddad34 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -5955,10 +5955,12 @@ int kvm_io_bus_read(struct kvm_vcpu *vcpu, enum kvm= _bus bus_idx, gpa_t addr, } EXPORT_SYMBOL_GPL(kvm_io_bus_read); =20 -static void __free_bus(struct rcu_head *rcu) +static void __free_bus_dev(struct rcu_head *rcu) { struct kvm_io_bus *bus =3D container_of(rcu, struct kvm_io_bus, rcu); =20 + if (bus->dev) + kvm_iodevice_destructor(bus->dev); kfree(bus); } =20 @@ -6000,7 +6002,8 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm= _bus bus_idx, gpa_t addr, memcpy(new_bus->range + i + 1, bus->range + i, (bus->dev_count - i) * sizeof(struct kvm_io_range)); rcu_assign_pointer(kvm->buses[bus_idx], new_bus); - call_srcu(&kvm->srcu, &bus->rcu, __free_bus); + bus->dev =3D NULL; + call_srcu(&kvm->srcu, &bus->rcu, __free_bus_dev); =20 return 0; } @@ -6036,20 +6039,20 @@ int kvm_io_bus_unregister_dev(struct kvm *kvm, enum= kvm_bus bus_idx, } =20 rcu_assign_pointer(kvm->buses[bus_idx], new_bus); - synchronize_srcu_expedited(&kvm->srcu); =20 /* * If NULL bus is installed, destroy the old bus, including all the * attached devices. Otherwise, destroy the caller's device only. */ if (!new_bus) { + synchronize_srcu_expedited(&kvm->srcu); pr_err("kvm: failed to shrink bus, removing it completely\n"); kvm_io_bus_destroy(bus); return -ENOMEM; } =20 - kvm_iodevice_destructor(dev); - kfree(bus); + bus->dev =3D dev; + call_srcu(&kvm->srcu, &bus->rcu, __free_bus_dev); return 0; } =20 --=20 2.9.4