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
This commit is contained in:
Jessica Clarke 2024-02-17 01:44:51 +00:00 committed by Mark Johnston
parent 54416d2d78
commit 0efad4aceb
15 changed files with 276 additions and 105 deletions

View file

@ -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 \

View file

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

View file

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

View file

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

View file

@ -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];
}

View file

@ -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

View file

@ -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 \

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

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

View file

@ -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

View file

@ -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 @@ vi_pci_read(struct pci_devinst *pi, int baridx, uint64_t offset, int size)
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;

View file

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