diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile --- a/usr.sbin/bhyve/Makefile +++ b/usr.sbin/bhyve/Makefile @@ -44,6 +44,7 @@ pci_hda.c \ pci_hostbridge.c \ pci_irq.c \ + pci_irq_machdep.c \ pci_nvme.c \ pci_uart.c \ pci_virtio_9p.c \ diff --git a/usr.sbin/bhyve/aarch64/pci_irq.c b/usr.sbin/bhyve/aarch64/pci_irq_machdep.c rename from usr.sbin/bhyve/aarch64/pci_irq.c rename to usr.sbin/bhyve/aarch64/pci_irq_machdep.c --- a/usr.sbin/bhyve/aarch64/pci_irq.c +++ b/usr.sbin/bhyve/aarch64/pci_irq_machdep.c @@ -54,13 +54,13 @@ } void -pci_irq_route(struct pci_devinst *pi, struct pci_irq *irq) +pci_irq_route(struct vmctx *ctx __unused, struct pci_irq *irq, int slot, + int lintr_pin) { /* * Assign swizzled IRQ for this INTx if one is not yet assigned. Must * match fdt_add_pcie(). */ if (irq->gic_irq == 0) - irq->gic_irq = - gic_irqs[(pi->pi_slot + pi->pi_lintr.pin - 1) % 4]; + irq->gic_irq = gic_irqs[(slot + lintr_pin - 1) % 4]; } diff --git a/usr.sbin/bhyve/amd64/ioapic.h b/usr.sbin/bhyve/amd64/ioapic.h --- a/usr.sbin/bhyve/amd64/ioapic.h +++ b/usr.sbin/bhyve/amd64/ioapic.h @@ -36,6 +36,6 @@ * Allocate a PCI IRQ from the I/O APIC. */ void ioapic_init(struct vmctx *ctx); -int ioapic_pci_alloc_irq(struct pci_devinst *pi); +int ioapic_pci_alloc_irq(int slot, int lintr_pin); #endif diff --git a/usr.sbin/bhyve/amd64/ioapic.c b/usr.sbin/bhyve/amd64/ioapic.c --- a/usr.sbin/bhyve/amd64/ioapic.c +++ b/usr.sbin/bhyve/amd64/ioapic.c @@ -38,6 +38,8 @@ #include "pci_emul.h" #include "pci_lpc.h" +#define IOAPIC_PCI_INT_BASE 16 + /* * Assign PCI INTx interrupts to I/O APIC pins in a round-robin * fashion. Note that we have no idea what the HPET is using, but the @@ -59,15 +61,15 @@ } /* Ignore the first 16 pins. */ - if (pci_pins <= 16) { + if (pci_pins <= IOAPIC_PCI_INT_BASE) { pci_pins = 0; return; } - pci_pins -= 16; + pci_pins -= IOAPIC_PCI_INT_BASE; } int -ioapic_pci_alloc_irq(struct pci_devinst *pi) +ioapic_pci_alloc_irq(int slot, int pin) { static int last_pin; @@ -75,7 +77,7 @@ return (-1); if (bootrom_boot()) { /* For external bootrom use fixed mapping. */ - return (16 + (4 + pi->pi_slot + pi->pi_lintr.pin) % 8); + return (IOAPIC_PCI_INT_BASE + (4 + slot + pin) % 8); } - return (16 + (last_pin++ % pci_pins)); + return (IOAPIC_PCI_INT_BASE + (last_pin++ % pci_pins)); } diff --git a/usr.sbin/bhyve/amd64/pci_irq.c b/usr.sbin/bhyve/amd64/pci_irq_machdep.c rename from usr.sbin/bhyve/amd64/pci_irq.c rename to usr.sbin/bhyve/amd64/pci_irq_machdep.c --- a/usr.sbin/bhyve/amd64/pci_irq.c +++ b/usr.sbin/bhyve/amd64/pci_irq_machdep.c @@ -199,16 +199,15 @@ } static int -pirq_alloc_pin(struct pci_devinst *pi) +pirq_alloc_pin(struct vmctx *ctx, int slot, int lintr_pin) { - struct vmctx *ctx = pi->pi_vmctx; int best_count, best_irq, best_pin, irq, pin; pirq_cold = 0; if (bootrom_boot()) { /* For external bootrom use fixed mapping. */ - best_pin = (4 + pi->pi_slot + pi->pi_lintr.pin) % 8; + best_pin = (4 + slot + lintr_pin) % 8; } else { /* Find the least-used PIRQ pin. */ best_pin = 0; @@ -251,14 +250,14 @@ } void -pci_irq_route(struct pci_devinst *pi, struct pci_irq *irq) +pci_irq_route(struct vmctx *ctx, struct pci_irq *irq, int slot, int lintr_pin) { /* * Attempt to allocate an I/O APIC pin for this intpin if one * is not yet assigned. */ if (irq->ioapic_irq == 0) - irq->ioapic_irq = ioapic_pci_alloc_irq(pi); + irq->ioapic_irq = ioapic_pci_alloc_irq(slot, lintr_pin); assert(irq->ioapic_irq > 0); /* @@ -266,7 +265,7 @@ * not yet assigned. */ if (irq->pirq_pin == 0) - irq->pirq_pin = pirq_alloc_pin(pi); + irq->pirq_pin = pirq_alloc_pin(ctx, slot, lintr_pin); assert(irq->pirq_pin > 0); } diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -2063,7 +2063,7 @@ assert(bi != NULL); ii = &bi->slotinfo[pi->pi_slot].si_intpins[pi->pi_lintr.pin - 1]; irq = &ii->ii_irq; - pci_irq_route(pi, irq); + pci_irq_route_dev(pi, irq); pi->pi_lintr.irq = *irq; pci_set_cfgdata8(pi, PCIR_INTLINE, pci_irq_intline(irq)); } @@ -2140,6 +2140,7 @@ struct businfo *bi; struct slotinfo *si; struct intxinfo *ii; + struct pci_irq *irq; int slot, pin; if ((bi = pci_businfo[bus]) == NULL) @@ -2149,8 +2150,10 @@ si = &bi->slotinfo[slot]; for (pin = 0; pin < 4; pin++) { ii = &si->si_intpins[pin]; - if (ii->ii_count != 0) - cb(bus, slot, pin + 1, &ii->ii_irq, arg); + if (ii->ii_count == 0) + continue; + irq = &ii->ii_irq; + cb(bus, slot, pin + 1, irq, arg); } } } diff --git a/usr.sbin/bhyve/pci_irq.h b/usr.sbin/bhyve/pci_irq.h --- a/usr.sbin/bhyve/pci_irq.h +++ b/usr.sbin/bhyve/pci_irq.h @@ -31,6 +31,7 @@ #define __PCI_IRQ_H__ struct pci_devinst; +struct vmctx; #if defined(__amd64__) #include "amd64/pci_irq_machdep.h" @@ -44,6 +45,7 @@ void pci_irq_assert(struct pci_devinst *pi); void pci_irq_deassert(struct pci_devinst *pi); -void pci_irq_route(struct pci_devinst *pi, struct pci_irq *irq); +void pci_irq_route(struct vmctx *ctx, struct pci_irq *irq, int slot, int lintr_pin); +void pci_irq_route_dev(struct pci_devinst *pi, struct pci_irq *irq); #endif diff --git a/usr.sbin/bhyve/pci_irq.c b/usr.sbin/bhyve/pci_irq.c new file mode 100644 --- /dev/null +++ b/usr.sbin/bhyve/pci_irq.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Bojan Novković + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +#include "pci_irq.h" +#include "pci_emul.h" + +void +pci_irq_route_dev(struct pci_devinst *pi, struct pci_irq *irq) +{ + pci_irq_route(pi->pi_vmctx, irq, pi->pi_slot, pi->pi_lintr.pin); +} + diff --git a/usr.sbin/bhyve/riscv/pci_irq.c b/usr.sbin/bhyve/riscv/pci_irq_machdep.c rename from usr.sbin/bhyve/riscv/pci_irq.c rename to usr.sbin/bhyve/riscv/pci_irq_machdep.c --- a/usr.sbin/bhyve/riscv/pci_irq.c +++ b/usr.sbin/bhyve/riscv/pci_irq_machdep.c @@ -54,13 +54,13 @@ } void -pci_irq_route(struct pci_devinst *pi, struct pci_irq *irq) +pci_irq_route(struct vmctx *ctx __unused, struct pci_irq *irq, int slot, + int lintr_pin) { /* * Assign swizzled IRQ for this INTx if one is not yet assigned. Must * match fdt_add_pcie(). */ if (irq->aplic_irq == 0) - irq->aplic_irq = - aplic_irqs[(pi->pi_slot + pi->pi_lintr.pin - 1) % 4]; + irq->aplic_irq = aplic_irqs[(slot + lintr_pin - 1) % 4]; }