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