@samitouri / QOSamiQemu / commits / 5cebd7c354

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);