git: 0efad4aceb53 - main - bhyve: Support legacy PCI interrupts on arm64
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 10 Apr 2024 15:19:24 UTC
The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=0efad4aceb533ef32905de586ab0112b1c563996 commit 0efad4aceb533ef32905de586ab0112b1c563996 Author: Jessica Clarke <jrtc27@jrtc27.com> AuthorDate: 2024-02-17 01:44:51 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2024-04-10 15:17:56 +0000 bhyve: Support legacy PCI interrupts on arm64 This allows us to remove various #ifdef hacks and enable building more PCI devices. Note that a hole is left in the interrupt mapping for the RTC rather than having the two core devices straddle the PCIe interrupts. QEMU's virt machine also takes this approach. Reviewed by: jhb MFC after: 2 weeks Obtained from: CheriBSD --- usr.sbin/bhyve/Makefile | 6 +++ usr.sbin/bhyve/aarch64/bhyverun_machdep.c | 10 ++++- usr.sbin/bhyve/aarch64/fdt.c | 39 +++++++++++------- usr.sbin/bhyve/aarch64/fdt.h | 2 +- usr.sbin/bhyve/aarch64/pci_irq.c | 66 +++++++++++++++++++++++++++++++ usr.sbin/bhyve/aarch64/pci_irq_machdep.h | 49 +++++++++++++++++++++++ usr.sbin/bhyve/amd64/Makefile.inc | 6 --- usr.sbin/bhyve/amd64/mptbl.c | 6 +-- usr.sbin/bhyve/amd64/pci_irq.c | 35 ++++++++++++---- usr.sbin/bhyve/amd64/pci_irq_machdep.h | 60 ++++++++++++++++++++++++++++ usr.sbin/bhyve/pci_emul.c | 64 ++++++++---------------------- usr.sbin/bhyve/pci_emul.h | 13 +++--- usr.sbin/bhyve/{amd64 => }/pci_irq.h | 16 ++++---- usr.sbin/bhyve/virtio.c | 7 ---- usr.sbin/bhyve/virtio.h | 2 - 15 files changed, 276 insertions(+), 105 deletions(-) diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile index 124476ef7d2f..d5d7dfc26ab9 100644 --- a/usr.sbin/bhyve/Makefile +++ b/usr.sbin/bhyve/Makefile @@ -37,9 +37,14 @@ SRCS= \ net_backend_slirp.c \ net_backends.c \ net_utils.c \ + pci_ahci.c \ + pci_e82545.c \ pci_emul.c \ + pci_hda.c \ pci_hostbridge.c \ + pci_irq.c \ pci_nvme.c \ + pci_uart.c \ pci_virtio_9p.c \ pci_virtio_block.c \ pci_virtio_console.c \ @@ -47,6 +52,7 @@ SRCS= \ pci_virtio_net.c \ pci_virtio_rnd.c \ pci_virtio_scsi.c \ + pci_xhci.c \ qemu_fwcfg.c \ qemu_loader.c \ smbiostbl.c \ diff --git a/usr.sbin/bhyve/aarch64/bhyverun_machdep.c b/usr.sbin/bhyve/aarch64/bhyverun_machdep.c index 22b8b85e6b9b..2aa7d2d9b4fd 100644 --- a/usr.sbin/bhyve/aarch64/bhyverun_machdep.c +++ b/usr.sbin/bhyve/aarch64/bhyverun_machdep.c @@ -47,6 +47,7 @@ #include "fdt.h" #include "mem.h" #include "pci_emul.h" +#include "pci_irq.h" #include "uart_emul.h" /* Start of mem + 1M */ @@ -63,7 +64,10 @@ #define GIC_REDIST_BASE 0x2f100000 #define GIC_REDIST_SIZE(ncpu) ((ncpu) * 2 * PAGE_SIZE_64K) -#define PCIE_INTR 33 +#define PCIE_INTA 34 +#define PCIE_INTB 35 +#define PCIE_INTC 36 +#define PCIE_INTD 37 void bhyve_init_config(void) @@ -295,6 +299,7 @@ bhyve_init_platform(struct vmctx *ctx, struct vcpu *bsp) const char *bootrom; uint64_t elr; int error; + int pcie_intrs[4] = {PCIE_INTA, PCIE_INTB, PCIE_INTC, PCIE_INTD}; bootrom = get_config_value("bootrom"); if (bootrom == NULL) { @@ -324,7 +329,8 @@ bhyve_init_platform(struct vmctx *ctx, struct vcpu *bsp) if (init_mmio_uart(ctx)) fdt_add_uart(UART_MMIO_BASE, UART_MMIO_SIZE, UART_INTR); fdt_add_timer(); - fdt_add_pcie(PCIE_INTR); + pci_irq_init(pcie_intrs); + fdt_add_pcie(pcie_intrs); return (0); } diff --git a/usr.sbin/bhyve/aarch64/fdt.c b/usr.sbin/bhyve/aarch64/fdt.c index 4b99e7009296..65876f0f90e8 100644 --- a/usr.sbin/bhyve/aarch64/fdt.c +++ b/usr.sbin/bhyve/aarch64/fdt.c @@ -271,12 +271,12 @@ fdt_add_timer(void) } void -fdt_add_pcie(int intr) +fdt_add_pcie(int intrs[static 4]) { void *fdt, *prop; + int slot, pin, intr, i; assert(gic_phandle != 0); - assert(intr >= GIC_FIRST_SPI); fdt = fdtroot; @@ -320,24 +320,35 @@ fdt_add_pcie(int intr) fdt_property_u32(fdt, "#interrupt-cells", 1); fdt_property_u32(fdt, "interrupt-parent", gic_phandle); + + /* + * Describe standard swizzled interrupts routing (pins rotated by one + * for each consecutive slot). Must match pci_irq_route(). + */ fdt_property_placeholder(fdt, "interrupt-map-mask", 4 * sizeof(uint32_t), &prop); - SET_PROP_U32(prop, 0, 0); + SET_PROP_U32(prop, 0, 3 << 11); SET_PROP_U32(prop, 1, 0); SET_PROP_U32(prop, 2, 0); SET_PROP_U32(prop, 3, 7); fdt_property_placeholder(fdt, "interrupt-map", - 10 * sizeof(uint32_t), &prop); - SET_PROP_U32(prop, 0, 0); - SET_PROP_U32(prop, 1, 0); - SET_PROP_U32(prop, 2, 0); - SET_PROP_U32(prop, 3, 1); - SET_PROP_U32(prop, 4, gic_phandle); - SET_PROP_U32(prop, 5, 0); - SET_PROP_U32(prop, 6, 0); - SET_PROP_U32(prop, 7, GIC_SPI); - SET_PROP_U32(prop, 8, intr - GIC_FIRST_SPI); - SET_PROP_U32(prop, 9, IRQ_TYPE_LEVEL_HIGH); + 160 * sizeof(uint32_t), &prop); + for (i = 0; i < 16; ++i) { + pin = i % 4; + slot = i / 4; + intr = intrs[(pin + slot) % 4]; + assert(intr >= GIC_FIRST_SPI); + SET_PROP_U32(prop, 10 * i + 0, slot << 11); + SET_PROP_U32(prop, 10 * i + 1, 0); + SET_PROP_U32(prop, 10 * i + 2, 0); + SET_PROP_U32(prop, 10 * i + 3, pin + 1); + SET_PROP_U32(prop, 10 * i + 4, gic_phandle); + SET_PROP_U32(prop, 10 * i + 5, 0); + SET_PROP_U32(prop, 10 * i + 6, 0); + SET_PROP_U32(prop, 10 * i + 7, GIC_SPI); + SET_PROP_U32(prop, 10 * i + 8, intr - GIC_FIRST_SPI); + SET_PROP_U32(prop, 10 * i + 9, IRQ_TYPE_LEVEL_HIGH); + } fdt_end_node(fdt); } diff --git a/usr.sbin/bhyve/aarch64/fdt.h b/usr.sbin/bhyve/aarch64/fdt.h index a559d2289187..6534266173d0 100644 --- a/usr.sbin/bhyve/aarch64/fdt.h +++ b/usr.sbin/bhyve/aarch64/fdt.h @@ -40,7 +40,7 @@ int fdt_init(struct vmctx *ctx, int ncpu, vm_paddr_t addrp, void fdt_add_gic(uint64_t dist_base, uint64_t dist_size, uint64_t redist_base, uint64_t redist_size); void fdt_add_timer(void); -void fdt_add_pcie(int intr); +void fdt_add_pcie(int intrs[static 4]); void fdt_add_uart(uint64_t uart_base, uint64_t uart_size, int intr); void fdt_finalize(void); diff --git a/usr.sbin/bhyve/aarch64/pci_irq.c b/usr.sbin/bhyve/aarch64/pci_irq.c new file mode 100644 index 000000000000..f2c4602fe2e9 --- /dev/null +++ b/usr.sbin/bhyve/aarch64/pci_irq.c @@ -0,0 +1,66 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Jessica Clarke <jrtc27@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <vmmapi.h> + +#include "pci_emul.h" +#include "pci_irq.h" + +static int gic_irqs[4]; + +void +pci_irq_init(int intrs[static 4]) +{ + int i; + + for (i = 0; i < 4; ++i) + gic_irqs[i] = intrs[i]; +} + +void +pci_irq_assert(struct pci_devinst *pi) +{ + vm_assert_irq(pi->pi_vmctx, pi->pi_lintr.irq.gic_irq); +} + +void +pci_irq_deassert(struct pci_devinst *pi) +{ + vm_deassert_irq(pi->pi_vmctx, pi->pi_lintr.irq.gic_irq); +} + +void +pci_irq_route(struct pci_devinst *pi, struct pci_irq *irq) +{ + /* + * 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]; +} diff --git a/usr.sbin/bhyve/aarch64/pci_irq_machdep.h b/usr.sbin/bhyve/aarch64/pci_irq_machdep.h new file mode 100644 index 000000000000..c10af3aa53b2 --- /dev/null +++ b/usr.sbin/bhyve/aarch64/pci_irq_machdep.h @@ -0,0 +1,49 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Jessica Clarke <jrtc27@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __PCI_IRQ_MD_H__ +#define __PCI_IRQ_MD_H__ + +struct pci_irq { + int gic_irq; +}; + +void pci_irq_init(int intrs[static 4]); + +static inline void +pci_irq_init_irq(struct pci_irq *irq) +{ + irq->gic_irq = 0; +} + +static inline uint8_t +pci_irq_intline(struct pci_irq *irq __unused) +{ + return (255); +} + +#endif diff --git a/usr.sbin/bhyve/amd64/Makefile.inc b/usr.sbin/bhyve/amd64/Makefile.inc index d281e3cf1581..53320a70178b 100644 --- a/usr.sbin/bhyve/amd64/Makefile.inc +++ b/usr.sbin/bhyve/amd64/Makefile.inc @@ -8,16 +8,10 @@ SRCS+= \ ioapic.c \ kernemu_dev.c \ mptbl.c \ - pci_ahci.c \ - pci_e82545.c \ pci_fbuf.c \ pci_gvt-d.c \ - pci_hda.c \ - pci_irq.c \ pci_lpc.c \ pci_passthru.c \ - pci_uart.c \ - pci_xhci.c \ pctestdev.c \ pm.c \ post.c \ diff --git a/usr.sbin/bhyve/amd64/mptbl.c b/usr.sbin/bhyve/amd64/mptbl.c index 4be412524b60..328cc77980ac 100644 --- a/usr.sbin/bhyve/amd64/mptbl.c +++ b/usr.sbin/bhyve/amd64/mptbl.c @@ -208,8 +208,8 @@ mpt_count_ioint_entries(void) } static void -mpt_generate_pci_int(int bus, int slot, int pin, int pirq_pin __unused, - int ioapic_irq, void *arg) +mpt_generate_pci_int(int bus, int slot, int pin, struct pci_irq *irq, + void *arg) { int_entry_ptr *mpiep, mpie; @@ -226,7 +226,7 @@ mpt_generate_pci_int(int bus, int slot, int pin, int pirq_pin __unused, mpie->src_bus_id = bus; mpie->src_bus_irq = slot << 2 | (pin - 1); mpie->dst_apic_id = mpie[-1].dst_apic_id; - mpie->dst_apic_int = ioapic_irq; + mpie->dst_apic_int = irq->ioapic_irq; *mpiep = mpie + 1; } diff --git a/usr.sbin/bhyve/amd64/pci_irq.c b/usr.sbin/bhyve/amd64/pci_irq.c index 24593befee49..7e1aee7fbb1d 100644 --- a/usr.sbin/bhyve/amd64/pci_irq.c +++ b/usr.sbin/bhyve/amd64/pci_irq.c @@ -39,6 +39,7 @@ #include "acpi.h" #include "inout.h" +#include "ioapic.h" #include "pci_emul.h" #include "pci_irq.h" #include "pci_lpc.h" @@ -156,7 +157,7 @@ pci_irq_assert(struct pci_devinst *pi) struct pirq *pirq; int pin; - pin = pi->pi_lintr.pirq_pin; + pin = pi->pi_lintr.irq.pirq_pin; if (pin > 0) { assert(pin <= NPIRQS); pirq = &pirqs[pin - 1]; @@ -164,13 +165,13 @@ pci_irq_assert(struct pci_devinst *pi) pirq->active_count++; if (pirq->active_count == 1 && pirq_valid_irq(pirq->reg)) { vm_isa_assert_irq(pi->pi_vmctx, pirq->reg & PIRQ_IRQ, - pi->pi_lintr.ioapic_irq); + pi->pi_lintr.irq.ioapic_irq); pthread_mutex_unlock(&pirq->lock); return; } pthread_mutex_unlock(&pirq->lock); } - vm_ioapic_assert_irq(pi->pi_vmctx, pi->pi_lintr.ioapic_irq); + vm_ioapic_assert_irq(pi->pi_vmctx, pi->pi_lintr.irq.ioapic_irq); } void @@ -179,7 +180,7 @@ pci_irq_deassert(struct pci_devinst *pi) struct pirq *pirq; int pin; - pin = pi->pi_lintr.pirq_pin; + pin = pi->pi_lintr.irq.pirq_pin; if (pin > 0) { assert(pin <= NPIRQS); pirq = &pirqs[pin - 1]; @@ -187,16 +188,16 @@ pci_irq_deassert(struct pci_devinst *pi) pirq->active_count--; if (pirq->active_count == 0 && pirq_valid_irq(pirq->reg)) { vm_isa_deassert_irq(pi->pi_vmctx, pirq->reg & PIRQ_IRQ, - pi->pi_lintr.ioapic_irq); + pi->pi_lintr.irq.ioapic_irq); pthread_mutex_unlock(&pirq->lock); return; } pthread_mutex_unlock(&pirq->lock); } - vm_ioapic_deassert_irq(pi->pi_vmctx, pi->pi_lintr.ioapic_irq); + vm_ioapic_deassert_irq(pi->pi_vmctx, pi->pi_lintr.irq.ioapic_irq); } -int +static int pirq_alloc_pin(struct pci_devinst *pi) { struct vmctx *ctx = pi->pi_vmctx; @@ -248,6 +249,26 @@ pirq_irq(int pin) return (pirqs[pin - 1].reg & PIRQ_IRQ); } +void +pci_irq_route(struct pci_devinst *pi, struct pci_irq *irq) +{ + /* + * 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); + assert(irq->ioapic_irq > 0); + + /* + * Attempt to allocate a PIRQ pin for this intpin if one is + * not yet assigned. + */ + if (irq->pirq_pin == 0) + irq->pirq_pin = pirq_alloc_pin(pi); + assert(irq->pirq_pin > 0); +} + /* XXX: Generate $PIR table. */ static void diff --git a/usr.sbin/bhyve/amd64/pci_irq_machdep.h b/usr.sbin/bhyve/amd64/pci_irq_machdep.h new file mode 100644 index 000000000000..c4be29babe34 --- /dev/null +++ b/usr.sbin/bhyve/amd64/pci_irq_machdep.h @@ -0,0 +1,60 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2014 Hudson River Trading LLC + * Written by: John H. Baldwin <jhb@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __PCI_IRQ_MD_H__ +#define __PCI_IRQ_MD_H__ + +struct vmctx; + +struct pci_irq { + int pirq_pin; + int ioapic_irq; +}; + +void pci_irq_init(struct vmctx *ctx); +void pci_irq_reserve(int irq); +void pci_irq_use(int irq); +int pirq_irq(int pin); +uint8_t pirq_read(int pin); +void pirq_write(struct vmctx *ctx, int pin, uint8_t val); + +static inline void +pci_irq_init_irq(struct pci_irq *irq) +{ + irq->pirq_pin = 0; + irq->ioapic_irq = 0; +} + +static inline uint8_t +pci_irq_intline(struct pci_irq *irq) +{ + return (pirq_irq(irq->pirq_pin)); +} + +#endif diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index f2c9c4c9b6e7..0b0be09c4de7 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -52,12 +52,10 @@ #include "debug.h" #ifdef __amd64__ #include "amd64/inout.h" -#include "amd64/ioapic.h" #endif #include "mem.h" #include "pci_emul.h" #ifdef __amd64__ -#include "amd64/pci_irq.h" #include "amd64/pci_lpc.h" #include "pci_passthru.h" #endif @@ -81,9 +79,8 @@ struct funcinfo { }; struct intxinfo { - int ii_count; - int ii_pirq_pin; - int ii_ioapic_irq; + int ii_count; + struct pci_irq ii_irq; }; struct slotinfo { @@ -157,10 +154,8 @@ SYSRES_MEM(PCI_EMUL_ECFG_BASE, PCI_EMUL_ECFG_SIZE); #define PCI_EMUL_MEMLIMIT32 PCI_EMUL_ECFG_BASE #define PCI_EMUL_MEMSIZE64 (32*GB) -#ifdef __amd64__ static void pci_lintr_route(struct pci_devinst *pi); static void pci_lintr_update(struct pci_devinst *pi); -#endif static struct pci_devemu *pci_emul_finddev(const char *name); static void pci_cfgrw(int in, int bus, int slot, int func, int coff, @@ -1133,13 +1128,10 @@ pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int bus, int slot, pdi->pi_bus = bus; pdi->pi_slot = slot; pdi->pi_func = func; -#ifdef __amd64__ pthread_mutex_init(&pdi->pi_lintr.lock, NULL); pdi->pi_lintr.pin = 0; pdi->pi_lintr.state = IDLE; - pdi->pi_lintr.pirq_pin = 0; - pdi->pi_lintr.ioapic_irq = 0; -#endif + pci_irq_init_irq(&pdi->pi_lintr.irq); pdi->pi_d = pde; snprintf(pdi->pi_name, PI_NAMESZ, "%s@pci.%d.%d.%d", pde->pe_emu, bus, slot, func); @@ -1277,9 +1269,7 @@ msixcap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, pi->pi_msix.enabled = val & PCIM_MSIXCTRL_MSIX_ENABLE; pi->pi_msix.function_mask = val & PCIM_MSIXCTRL_FUNCTION_MASK; -#ifdef __amd64__ pci_lintr_update(pi); -#endif } CFGWRITE(pi, offset, val, bytes); @@ -1321,9 +1311,7 @@ msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, } else { pi->pi_msi.maxmsgnum = 0; } -#ifdef __amd64__ pci_lintr_update(pi); -#endif } static void @@ -1617,7 +1605,6 @@ init_pci(struct vmctx *ctx) bi->memlimit64 = pci_emul_membase64; } -#ifdef __amd64__ /* * PCI backends are initialized before routing INTx interrupts * so that LPC devices are able to reserve ISA IRQs before @@ -1637,6 +1624,7 @@ init_pci(struct vmctx *ctx) } } } +#ifdef __amd64__ lpc_pirq_routed(); #endif @@ -1696,8 +1684,8 @@ init_pci(struct vmctx *ctx) #ifdef __amd64__ static void -pci_apic_prt_entry(int bus __unused, int slot, int pin, int pirq_pin __unused, - int ioapic_irq, void *arg __unused) +pci_apic_prt_entry(int bus __unused, int slot, int pin, struct pci_irq *irq, + void *arg __unused) { dsdt_line(" Package ()"); @@ -1705,17 +1693,17 @@ pci_apic_prt_entry(int bus __unused, int slot, int pin, int pirq_pin __unused, dsdt_line(" 0x%X,", slot << 16 | 0xffff); dsdt_line(" 0x%02X,", pin - 1); dsdt_line(" Zero,"); - dsdt_line(" 0x%X", ioapic_irq); + dsdt_line(" 0x%X", irq->ioapic_irq); dsdt_line(" },"); } static void -pci_pirq_prt_entry(int bus __unused, int slot, int pin, int pirq_pin, - int ioapic_irq __unused, void *arg __unused) +pci_pirq_prt_entry(int bus __unused, int slot, int pin, struct pci_irq *irq, + void *arg __unused) { char *name; - name = lpc_pirq_name(pirq_pin); + name = lpc_pirq_name(irq->pirq_pin); if (name == NULL) return; dsdt_line(" Package ()"); @@ -1968,7 +1956,6 @@ pci_generate_msi(struct pci_devinst *pi, int index) } } -#ifdef __amd64__ static bool pci_lintr_permitted(struct pci_devinst *pi) { @@ -2013,6 +2000,7 @@ pci_lintr_route(struct pci_devinst *pi) { struct businfo *bi; struct intxinfo *ii; + struct pci_irq *irq; if (pi->pi_lintr.pin == 0) return; @@ -2020,26 +2008,10 @@ pci_lintr_route(struct pci_devinst *pi) bi = pci_businfo[pi->pi_bus]; assert(bi != NULL); ii = &bi->slotinfo[pi->pi_slot].si_intpins[pi->pi_lintr.pin - 1]; - - /* - * Attempt to allocate an I/O APIC pin for this intpin if one - * is not yet assigned. - */ - if (ii->ii_ioapic_irq == 0) - ii->ii_ioapic_irq = ioapic_pci_alloc_irq(pi); - assert(ii->ii_ioapic_irq > 0); - - /* - * Attempt to allocate a PIRQ pin for this intpin if one is - * not yet assigned. - */ - if (ii->ii_pirq_pin == 0) - ii->ii_pirq_pin = pirq_alloc_pin(pi); - assert(ii->ii_pirq_pin > 0); - - pi->pi_lintr.ioapic_irq = ii->ii_ioapic_irq; - pi->pi_lintr.pirq_pin = ii->ii_pirq_pin; - pci_set_cfgdata8(pi, PCIR_INTLINE, pirq_irq(ii->ii_pirq_pin)); + irq = &ii->ii_irq; + pci_irq_route(pi, irq); + pi->pi_lintr.irq = *irq; + pci_set_cfgdata8(pi, PCIR_INTLINE, pci_irq_intline(irq)); } void @@ -2124,12 +2096,10 @@ pci_walk_lintr(int bus, pci_lintr_cb cb, void *arg) for (pin = 0; pin < 4; pin++) { ii = &si->si_intpins[pin]; if (ii->ii_count != 0) - cb(bus, slot, pin + 1, ii->ii_pirq_pin, - ii->ii_ioapic_irq, arg); + cb(bus, slot, pin + 1, &ii->ii_irq, arg); } } } -#endif /* __amd64__ */ /* * Return 1 if the emulated device in 'slot' is a multi-function device. @@ -2234,13 +2204,11 @@ pci_emul_cmd_changed(struct pci_devinst *pi, uint16_t old) } } -#ifdef __amd64__ /* * If INTx has been unmasked and is pending, assert the * interrupt. */ pci_lintr_update(pi); -#endif } static void diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h index c367169113f8..063b4b84e044 100644 --- a/usr.sbin/bhyve/pci_emul.h +++ b/usr.sbin/bhyve/pci_emul.h @@ -40,6 +40,8 @@ #include <assert.h> +#include "pci_irq.h" + #define PCI_BARMAX PCIR_MAX_BAR_0 /* BAR registers in a Type 0 header */ #define PCI_BARMAX_WITH_ROM (PCI_BARMAX + 1) #define PCI_ROM_IDX (PCI_BARMAX + 1) @@ -124,7 +126,6 @@ struct pci_devinst { int pi_prevcap; int pi_capend; -#ifdef __amd64__ struct { int8_t pin; enum { @@ -132,11 +133,9 @@ struct pci_devinst { ASSERTED, PENDING, } state; - int pirq_pin; - int ioapic_irq; + struct pci_irq irq; pthread_mutex_t lock; } pi_lintr; -#endif struct { int enabled; @@ -221,15 +220,13 @@ struct pciecap { } __packed; static_assert(sizeof(struct pciecap) == 60, "compile-time assertion failed"); -#ifdef __amd64__ -typedef void (*pci_lintr_cb)(int b, int s, int pin, int pirq_pin, - int ioapic_irq, void *arg); +typedef void (*pci_lintr_cb)(int b, int s, int pin, struct pci_irq *irq, + void *arg); void pci_lintr_assert(struct pci_devinst *pi); void pci_lintr_deassert(struct pci_devinst *pi); void pci_lintr_request(struct pci_devinst *pi); int pci_count_lintr(int bus); void pci_walk_lintr(int bus, pci_lintr_cb cb, void *arg); -#endif int init_pci(struct vmctx *ctx); void pci_callback(void); diff --git a/usr.sbin/bhyve/amd64/pci_irq.h b/usr.sbin/bhyve/pci_irq.h similarity index 86% rename from usr.sbin/bhyve/amd64/pci_irq.h rename to usr.sbin/bhyve/pci_irq.h index 50ea2eec00a9..8b556ddc91a2 100644 --- a/usr.sbin/bhyve/amd64/pci_irq.h +++ b/usr.sbin/bhyve/pci_irq.h @@ -32,14 +32,16 @@ struct pci_devinst; +#if defined(__amd64__) +#include "amd64/pci_irq_machdep.h" +#elif defined(__aarch64__) +#include "aarch64/pci_irq_machdep.h" +#else +#error Unsupported platform +#endif + void pci_irq_assert(struct pci_devinst *pi); void pci_irq_deassert(struct pci_devinst *pi); -void pci_irq_init(struct vmctx *ctx); -void pci_irq_reserve(int irq); -void pci_irq_use(int irq); -int pirq_alloc_pin(struct pci_devinst *pi); -int pirq_irq(int pin); -uint8_t pirq_read(int pin); -void pirq_write(struct vmctx *ctx, int pin, uint8_t val); +void pci_irq_route(struct pci_devinst *pi, struct pci_irq *irq); #endif diff --git a/usr.sbin/bhyve/virtio.c b/usr.sbin/bhyve/virtio.c index eb09714d4f20..26df39ceb5b3 100644 --- a/usr.sbin/bhyve/virtio.c +++ b/usr.sbin/bhyve/virtio.c @@ -114,10 +114,8 @@ vi_reset_dev(struct virtio_softc *vs) vs->vs_negotiated_caps = 0; vs->vs_curq = 0; /* vs->vs_status = 0; -- redundant */ -#ifdef __amd64__ if (vs->vs_isr) pci_lintr_deassert(vs->vs_pi); -#endif vs->vs_isr = 0; vs->vs_msix_cfg_idx = VIRTIO_MSI_NO_VECTOR; } @@ -164,11 +162,8 @@ vi_intr_init(struct virtio_softc *vs, int barnum, int use_msix) /* Only 1 MSI vector for bhyve */ pci_emul_add_msicap(vs->vs_pi, 1); - /* XXX-MJ missing an implementation for arm64 */ -#ifdef __amd64__ /* Legacy interrupts are mandatory for virtio devices */ pci_lintr_request(vs->vs_pi); -#endif return (0); } @@ -656,10 +651,8 @@ bad: case VIRTIO_PCI_ISR: value = vs->vs_isr; vs->vs_isr = 0; /* a read clears this flag */ -#ifdef __amd64__ if (value) pci_lintr_deassert(pi); -#endif break; case VIRTIO_MSI_CONFIG_VECTOR: value = vs->vs_msix_cfg_idx; diff --git a/usr.sbin/bhyve/virtio.h b/usr.sbin/bhyve/virtio.h index 4c6c8004b2d1..2b72b862ab21 100644 --- a/usr.sbin/bhyve/virtio.h +++ b/usr.sbin/bhyve/virtio.h @@ -358,9 +358,7 @@ vi_interrupt(struct virtio_softc *vs, uint8_t isr, uint16_t msix_idx) VS_LOCK(vs); vs->vs_isr |= isr; pci_generate_msi(vs->vs_pi, 0); -#ifdef __amd64__ pci_lintr_assert(vs->vs_pi); -#endif VS_UNLOCK(vs); } }