@samitouri / QOSamiQemu / commits / 61c139c4fa

accel/accel-irq: add AccelRouteChange abstraction

The accelerated irqchip routines use a record of changes to batch changes when programming routes. Currently this mechanism is coupled to the KVM accelerator, this change introduces an abstraction that replaces KVMRouteChange and keeps a pointer to an abstract AccelState instead of the concrete type, converting the state where necessary. This is done to further align the irqchip programming in the MSHV accelerator with the existing KVM code in QEMU. Subsequent commits will introduce AccelRouteChange to the MSHV accelerator code. Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com> Link: https://lore.kernel.org/r/20260417105618.3621-5-magnuskulke@linux.microsoft.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Magnus Kulke committed Apr 17, 2026 at 12:55 UTC 61c139c4fad707f777cf362a9c63f59ca3154263
11 files changed +41 -24
accel/accel-irq.c
+2 -2
@@ -16,7 +16,7 @@
16 #include "system/mshv.h"
17 #include "system/accel-irq.h"
18
19 -int accel_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev)
19 +int accel_irqchip_add_msi_route(AccelRouteChange *c, int vector, PCIDevice *dev)
20 {
21 #ifdef CONFIG_MSHV_IS_POSSIBLE
22 if (mshv_msi_via_irqfd_enabled()) {
@@ -42,7 +42,7 @@ int accel_irqchip_update_msi_route(int vector, MSIMessage msg, PCIDevice *dev)
42 return -ENOSYS;
43 }
44
45 -void accel_irqchip_commit_route_changes(KVMRouteChange *c)
45 +void accel_irqchip_commit_route_changes(AccelRouteChange *c)
46 {
47 #ifdef CONFIG_MSHV_IS_POSSIBLE
48 if (mshv_msi_via_irqfd_enabled()) {
accel/kvm/kvm-all.c
+3 -3
@@ -2359,11 +2359,11 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
2359 return kvm_vm_ioctl(s, KVM_SIGNAL_MSI, &msi);
2360 }
2361
2362 -int kvm_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev)
2362 +int kvm_irqchip_add_msi_route(AccelRouteChange *c, int vector, PCIDevice *dev)
2363 {
2364 struct kvm_irq_routing_entry kroute = {};
2365 int virq;
2366 - KVMState *s = c->s;
2366 + KVMState *s = KVM_STATE(c->accel);
2367 MSIMessage msg = {0, 0};
2368
2369 if (pci_available && dev) {
@@ -2506,7 +2506,7 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
2506 abort();
2507 }
2508
2509 -int kvm_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev)
2509 +int kvm_irqchip_add_msi_route(AccelRouteChange *c, int vector, PCIDevice *dev)
2510 {
2511 return -ENOSYS;
2512 }
accel/stubs/kvm-stub.c
+1 -1
@@ -44,7 +44,7 @@ int kvm_on_sigbus(int code, void *addr)
44 return 1;
45 }
46
47 -int kvm_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev)
47 +int kvm_irqchip_add_msi_route(AccelRouteChange *c, int vector, PCIDevice *dev)
48 {
49 return -ENOSYS;
50 }
hw/misc/ivshmem-pci.c
+1 -1
@@ -424,7 +424,7 @@ static void ivshmem_add_kvm_msi_virq(IVShmemState *s, int vector,
424 Error **errp)
425 {
426 PCIDevice *pdev = PCI_DEVICE(s);
427 - KVMRouteChange c;
427 + AccelRouteChange c;
428 int ret;
429
430 IVSHMEM_DPRINTF("ivshmem_add_kvm_msi_virq vector:%d\n", vector);
hw/vfio/pci.c
+1 -1
@@ -50,7 +50,7 @@
50 #include "vfio-helpers.h"
51
52 /* Protected by BQL */
53 -static KVMRouteChange vfio_route_change;
53 +static AccelRouteChange vfio_route_change;
54
55 static void vfio_disable_interrupts(VFIOPCIDevice *vdev);
56 static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled);
hw/virtio/virtio-pci.c
+1 -2
@@ -869,7 +869,7 @@ static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy,
869 int ret;
870
871 if (irqfd->users == 0) {
872 - KVMRouteChange c = kvm_irqchip_begin_route_changes(kvm_state);
872 + AccelRouteChange c = kvm_irqchip_begin_route_changes(kvm_state);
873 ret = accel_irqchip_add_msi_route(&c, vector, &proxy->pci_dev);
874 if (ret < 0) {
875 return ret;
@@ -2669,4 +2669,3 @@ static void virtio_pci_register_types(void)
2669 }
2670
2671 type_init(virtio_pci_register_types)
2672 -
include/accel/accel-route.h new
+17
@@ -0,0 +1,17 @@
1 +/*
2 + * Accelerator MSI route change tracking
3 + *
4 + * SPDX-License-Identifier: GPL-2.0-or-later
5 + */
6 +
7 +#ifndef ACCEL_ROUTE_H
8 +#define ACCEL_ROUTE_H
9 +
10 +#include "qemu/accel.h"
11 +
12 +typedef struct AccelRouteChange {
13 + AccelState *accel;
14 + int changes;
15 +} AccelRouteChange;
16 +
17 +#endif /* ACCEL_ROUTE_H */
include/system/accel-irq.h
+3 -2
@@ -25,9 +25,10 @@ static inline bool accel_irqchip_is_split(void)
25 return mshv_msi_via_irqfd_enabled() || kvm_irqchip_is_split();
26 }
27
28 -int accel_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev);
28 +int accel_irqchip_add_msi_route(AccelRouteChange *c, int vector,
29 + PCIDevice *dev);
30 int accel_irqchip_update_msi_route(int vector, MSIMessage msg, PCIDevice *dev);
30 -void accel_irqchip_commit_route_changes(KVMRouteChange *c);
31 +void accel_irqchip_commit_route_changes(AccelRouteChange *c);
32 void accel_irqchip_commit_routes(void);
33 void accel_irqchip_release_virq(int virq);
34 int accel_irqchip_add_irqfd_notifier_gsi(EventNotifier *n, EventNotifier *rn,
include/system/kvm.h
+10 -11
@@ -18,6 +18,7 @@
18
19 #include "exec/memattrs.h"
20 #include "qemu/accel.h"
21 +#include "accel/accel-route.h"
22 #include "qom/object.h"
23
24 #ifdef COMPILING_PER_TARGET
@@ -183,11 +184,6 @@ extern KVMState *kvm_state;
184 typedef struct Notifier Notifier;
185 typedef struct NotifierWithReturn NotifierWithReturn;
186
186 -typedef struct KVMRouteChange {
187 - KVMState *s;
188 - int changes;
189 -} KVMRouteChange;
190 -
187 /* external API */
188
189 unsigned int kvm_get_max_memslots(void);
@@ -466,7 +462,7 @@ void kvm_init_cpu_signals(CPUState *cpu);
462
463 /**
464 * kvm_irqchip_add_msi_route - Add MSI route for specific vector
469 - * @c: KVMRouteChange instance.
465 + * @c: AccelRouteChange instance.
466 * @vector: which vector to add. This can be either MSI/MSIX
467 * vector. The function will automatically detect whether
468 * MSI/MSIX is enabled, and fetch corresponding MSI
@@ -475,20 +471,23 @@ void kvm_init_cpu_signals(CPUState *cpu);
471 * as @NULL, an empty MSI message will be inited.
472 * @return: virq (>=0) when success, errno (<0) when failed.
473 */
478 -int kvm_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev);
474 +int kvm_irqchip_add_msi_route(AccelRouteChange *c, int vector, PCIDevice *dev);
475 int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg,
476 PCIDevice *dev);
477 void kvm_irqchip_commit_routes(KVMState *s);
478
483 -static inline KVMRouteChange kvm_irqchip_begin_route_changes(KVMState *s)
479 +static inline AccelRouteChange kvm_irqchip_begin_route_changes(KVMState *s)
480 {
485 - return (KVMRouteChange) { .s = s, .changes = 0 };
481 + return (AccelRouteChange) {
482 + .accel = ACCEL(s),
483 + .changes = 0,
484 + };
485 }
486
488 -static inline void kvm_irqchip_commit_route_changes(KVMRouteChange *c)
487 +static inline void kvm_irqchip_commit_route_changes(AccelRouteChange *c)
488 {
489 if (c->changes) {
491 - kvm_irqchip_commit_routes(c->s);
490 + kvm_irqchip_commit_routes(KVM_STATE(c->accel));
491 c->changes = 0;
492 }
493 }
include/system/mshv.h
+1
@@ -21,6 +21,7 @@
21 #include "qapi/qapi-types-common.h"
22 #include "system/memory.h"
23 #include "accel/accel-ops.h"
24 +#include "accel/accel-route.h"
25
26 #ifdef COMPILING_PER_TARGET
27 #ifdef CONFIG_MSHV
target/i386/kvm/kvm.c
+1 -1
@@ -6678,7 +6678,7 @@ void kvm_arch_init_irq_routing(KVMState *s)
6678 kvm_gsi_routing_allowed = true;
6679
6680 if (kvm_irqchip_is_split()) {
6681 - KVMRouteChange c = kvm_irqchip_begin_route_changes(s);
6681 + AccelRouteChange c = kvm_irqchip_begin_route_changes(s);
6682 int i;
6683
6684 /* If the ioapic is in QEMU and the lapics are in KVM, reserve