aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJessica Clarke <jrtc27@jrtc27.com>2024-02-17 01:44:51 +0000
committerMark Johnston <markj@FreeBSD.org>2024-04-10 15:17:56 +0000
commit0efad4aceb533ef32905de586ab0112b1c563996 (patch)
treec20c55d1c03fed91339f934f6bf58159b94b5763
parent54416d2d786ae364b918c9c5af2d8f1d1bb0a1c1 (diff)
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
-rw-r--r--usr.sbin/bhyve/Makefile6
-rw-r--r--usr.sbin/bhyve/aarch64/bhyverun_machdep.c10
-rw-r--r--usr.sbin/bhyve/aarch64/fdt.c39
-rw-r--r--usr.sbin/bhyve/aarch64/fdt.h2
-rw-r--r--usr.sbin/bhyve/aarch64/pci_irq.c66
-rw-r--r--usr.sbin/bhyve/aarch64/pci_irq_machdep.h49
-rw-r--r--usr.sbin/bhyve/amd64/Makefile.inc6
-rw-r--r--usr.sbin/bhyve/amd64/mptbl.c6
-rw-r--r--usr.sbin/bhyve/amd64/pci_irq.c35
-rw-r--r--usr.sbin/bhyve/amd64/pci_irq_machdep.h60
-rw-r--r--usr.sbin/bhyve/pci_emul.c64
-rw-r--r--usr.sbin/bhyve/pci_emul.h13
-rw-r--r--usr.sbin/bhyve/pci_irq.h (renamed from usr.sbin/bhyve/amd64/pci_irq.h)16
-rw-r--r--usr.sbin/bhyve/virtio.c7
-rw-r--r--usr.sbin/bhyve/virtio.h2
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
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);
}
}