mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 21:05:08 +00:00
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:
parent
54416d2d78
commit
0efad4aceb
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
66
usr.sbin/bhyve/aarch64/pci_irq.c
Normal file
66
usr.sbin/bhyve/aarch64/pci_irq.c
Normal 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];
|
||||
}
|
49
usr.sbin/bhyve/aarch64/pci_irq_machdep.h
Normal file
49
usr.sbin/bhyve/aarch64/pci_irq_machdep.h
Normal 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
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
60
usr.sbin/bhyve/amd64/pci_irq_machdep.h
Normal file
60
usr.sbin/bhyve/amd64/pci_irq_machdep.h
Normal 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
|
|
@ -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
|
||||
|
@ -82,8 +80,7 @@ struct funcinfo {
|
|||
|
||||
struct intxinfo {
|
||||
int ii_count;
|
||||
int ii_pirq_pin;
|
||||
int ii_ioapic_irq;
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue