accel/mshv: update s->irq_routes in add_msi_route
The irq_routes field of the state is populated with native mshv irq route entries. The allocation logic is modelled after the KVM implementation: we will always allocate a minumum of 64 entries and use a bitmask to find/set/clear GSIs. The old implementation of add_msi_routes will be removed in a subsequent commit. Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com> Link: https://lore.kernel.org/r/20260417105618.3621-9-magnuskulke@linux.microsoft.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Magnus Kulke committed
Apr 17, 2026 at 12:55 UTC
5cebd7c354798fafaac7db50fc77899771a1472c
4 files changed
+84
-10
accel/accel-irq.c
+1
-1
@@ -21,7 +21,7 @@ int accel_irqchip_add_msi_route(AccelRouteChange *c, int vector, PCIDevice *dev)
21
{
22
#ifdef CONFIG_MSHV_IS_POSSIBLE
23
if (mshv_msi_via_irqfd_enabled()) {
24
- return mshv_irqchip_add_msi_route(vector, dev);
24
+ return mshv_irqchip_add_msi_route(c, vector, dev);
25
}
26
#endif
27
if (kvm_enabled()) {
accel/mshv/irq.c
+80
-7
@@ -278,18 +278,91 @@ static int irqchip_update_irqfd_notifier_gsi(const EventNotifier *event,
278
return register_irqfd(vm_fd, fd, virq);
279
}
280
281
+static int irqchip_allocate_gsi(MshvState *s, int *gsi)
282
+{
283
+ int next_gsi;
284
+
285
+ /* Return the lowest unused GSI in the bitmap */
286
+ next_gsi = find_first_zero_bit(s->used_gsi_bitmap, s->gsi_count);
287
+ if (next_gsi >= s->gsi_count) {
288
+ return -ENOSPC;
289
+ }
290
+
291
+ *gsi = next_gsi;
292
+
293
+ return 0;
294
+}
295
+
296
+static void irqchip_release_gsi(MshvState *s, int gsi)
297
+{
298
+ clear_bit(gsi, s->used_gsi_bitmap);
299
+}
300
+
301
+static void add_routing_entry(MshvState *s, struct mshv_user_irq_entry *entry)
302
+{
303
+ struct mshv_user_irq_entry *new;
304
+ int n, size;
305
+
306
+ if (s->irq_routes->nr == s->nr_allocated_irq_routes) {
307
+ n = s->nr_allocated_irq_routes * 2;
308
+ if (n < MSHV_MIN_ALLOCATED_MSI_ROUTES) {
309
+ n = MSHV_MIN_ALLOCATED_MSI_ROUTES;
310
+ }
311
+ size = sizeof(struct mshv_user_irq_table);
312
+ size += n * sizeof(*new);
313
+ s->irq_routes = g_realloc(s->irq_routes, size);
314
+ s->nr_allocated_irq_routes = n;
315
+ }
316
+
317
+ n = s->irq_routes->nr;
318
+ s->irq_routes->nr++;
319
+ new = &s->irq_routes->entries[n];
320
+
321
+ *new = *entry;
322
+
323
+ set_bit(entry->gsi, s->used_gsi_bitmap);
324
282
-int mshv_irqchip_add_msi_route(int vector, PCIDevice *dev)
325
+ trace_mshv_add_msi_routing(entry->address_lo | entry->address_hi,
326
+ entry->data);
327
+}
328
+
329
+int mshv_irqchip_add_msi_route(AccelRouteChange *c, int vector, PCIDevice *dev)
330
{
284
- MSIMessage msg = { 0, 0 };
285
- int virq = 0;
331
+ struct mshv_user_irq_entry entry = { 0 };
332
+ MSIMessage msg = { 0 };
333
+ uint32_t data, high_addr, low_addr;
334
+ int gsi, ret;
335
+ MshvState *s = MSHV_STATE(c->accel);
336
+
337
+ if (!pci_available || !dev) {
338
+ return 0;
339
+ }
340
287
- if (pci_available && dev) {
288
- msg = pci_get_msi_message(dev, vector);
289
- virq = add_msi_routing(msg.address, le32_to_cpu(msg.data));
341
+ msg = pci_get_msi_message(dev, vector);
342
+
343
+ ret = irqchip_allocate_gsi(mshv_state, &gsi);
344
+ if (ret < 0) {
345
+ error_report("Could not allocate GSI for MSI route");
346
+ return -1;
347
+ }
348
+ high_addr = msg.address >> 32;
349
+ low_addr = msg.address & 0xFFFFFFFF;
350
+ data = le32_to_cpu(msg.data);
351
+
352
+ entry.gsi = gsi;
353
+ entry.address_hi = high_addr;
354
+ entry.address_lo = low_addr;
355
+ entry.data = data;
356
+
357
+ if (s->irq_routes->nr < s->gsi_count) {
358
+ add_routing_entry(s, &entry);
359
+ c->changes++;
360
+ } else {
361
+ irqchip_release_gsi(s, gsi);
362
+ return -ENOSPC;
363
}
364
292
- return virq;
365
+ return gsi;
366
}
367
368
void mshv_irqchip_release_virq(int virq)
accel/stubs/mshv-stub.c
+1
-1
@@ -14,7 +14,7 @@
14
15
bool mshv_allowed;
16
17
-int mshv_irqchip_add_msi_route(int vector, PCIDevice *dev)
17
+int mshv_irqchip_add_msi_route(AccelRouteChange *c, int vector, PCIDevice *dev)
18
{
19
return -ENOSYS;
20
}
include/system/mshv.h
+2
-1
@@ -33,6 +33,7 @@
33
#endif
34
35
#define MSHV_MAX_MSI_ROUTES 4096
36
+#define MSHV_MIN_ALLOCATED_MSI_ROUTES 64
37
38
#define MSHV_PAGE_SHIFT 12
39
@@ -59,7 +60,7 @@ int mshv_request_interrupt(MshvState *mshv_state, uint32_t interrupt_type, uint3
60
uint32_t vp_index, bool logical_destination_mode,
61
bool level_triggered);
62
62
-int mshv_irqchip_add_msi_route(int vector, PCIDevice *dev);
63
+int mshv_irqchip_add_msi_route(AccelRouteChange *c, int vector, PCIDevice *dev);
64
int mshv_irqchip_update_msi_route(int virq, MSIMessage msg, PCIDevice *dev);
65
void mshv_irqchip_commit_routes(void);
66
void mshv_irqchip_release_virq(int virq);