Page MenuHomeFreeBSD

D12205.id32585.diff
No OneTemporary

D12205.id32585.diff

Index: sys/x86/include/apicreg.h
===================================================================
--- sys/x86/include/apicreg.h
+++ sys/x86/include/apicreg.h
@@ -469,6 +469,8 @@
#define IOAPIC_WINDOW 0x10
#define IOAPIC_EOIR 0x40
+#define IOAPIC_WND_SIZE 0x50
+
/* indexes into IO APIC */
#define IOAPIC_ID 0x00
#define IOAPIC_VER 0x01
Index: sys/x86/include/apicvar.h
===================================================================
--- sys/x86/include/apicvar.h
+++ sys/x86/include/apicvar.h
@@ -478,6 +478,8 @@
void lapic_handle_intr(int vector, struct trapframe *frame);
void lapic_handle_timer(struct trapframe *frame);
+int ioapic_get_rid(u_int apic_id, uint16_t *ridp);
+
extern int x2apic_mode;
extern int lapic_eoi_suppression;
Index: sys/x86/iommu/intel_drv.c
===================================================================
--- sys/x86/iommu/intel_drv.c
+++ sys/x86/iommu/intel_drv.c
@@ -71,6 +71,9 @@
#ifdef DEV_APIC
#include "pcib_if.h"
+#include <machine/intr_machdep.h>
+#include <x86/apicreg.h>
+#include <x86/apicvar.h>
#endif
#define DMAR_FAULT_IRQ_RID 0
@@ -788,7 +791,7 @@
ACPI_DMAR_DEVICE_SCOPE *devscope;
ACPI_DMAR_PCI_PATH *path;
char *ptr, *ptrend;
- int i;
+ int error, i;
for (i = 0; i < dmar_devcnt; i++) {
dmar_dev = dmar_devs[i];
@@ -809,6 +812,19 @@
continue;
if (devscope->EnumerationId != id)
continue;
+#ifdef DEV_APIC
+ if (entry_type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
+ error = ioapic_get_rid(id, rid);
+ /*
+ * If our IOAPIC has PCI bindings then
+ * use the PCI device rid.
+ */
+ if (error == 0)
+ return (unit);
+ }
+#else
+ &error;
+#endif
if (devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE)
== 2) {
if (rid != NULL) {
@@ -818,12 +834,11 @@
path->Device, path->Function);
}
return (unit);
- } else {
- /* XXXKIB */
- printf(
- "dmar_find_nonpci: id %d type %d path length != 2\n",
- id, entry_type);
}
+ printf(
+ "dmar_find_nonpci: id %d type %d path length != 2\n",
+ id, entry_type);
+ break;
}
}
return (NULL);
Index: sys/x86/x86/io_apic.c
===================================================================
--- sys/x86/x86/io_apic.c
+++ sys/x86/x86/io_apic.c
@@ -38,6 +38,7 @@
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcireg.h>
@@ -99,6 +100,9 @@
volatile ioapic_t *io_addr; /* XXX: should use bus_space */
vm_paddr_t io_paddr;
STAILQ_ENTRY(ioapic) io_next;
+ device_t pci_dev; /* matched pci device, if found */
+ struct resource *pci_wnd; /* BAR 0, should be same or alias to
+ io_paddr */
struct ioapic_intsrc io_pins[0];
};
@@ -622,6 +626,8 @@
io = malloc(sizeof(struct ioapic) +
numintr * sizeof(struct ioapic_intsrc), M_IOAPIC, M_WAITOK);
io->io_pic = ioapic_template;
+ io->pci_dev = NULL;
+ io->pci_wnd = NULL;
mtx_lock_spin(&icu_lock);
io->io_id = next_id++;
io->io_apic_id = ioapic_read(apic, IOAPIC_ID) >> APIC_ID_SHIFT;
@@ -954,7 +960,72 @@
static int
ioapic_pci_attach(device_t dev)
{
+ struct resource *res;
+ volatile ioapic_t *apic;
+ struct ioapic *io;
+ int rid;
+ u_int apic_id;
+ /*
+ * Try to match the enumerated ioapic. Match BAR start
+ * against io_paddr. Due to a fear that PCI window is not the
+ * same as the MADT reported io window, but an alias, read the
+ * APIC ID from the mapped BAR and match against it.
+ */
+ rid = PCIR_BAR(0);
+ res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (res == NULL) {
+ if (bootverbose)
+ device_printf(dev, "cannot activate BAR0\n");
+ return (ENXIO);
+ }
+ apic = (volatile ioapic_t *)rman_get_virtual(res);
+ if (rman_get_size(res) < IOAPIC_WND_SIZE) {
+ if (bootverbose)
+ device_printf(dev,
+ "BAR0 too small (%jd) for IOAPIC window\n",
+ (uintmax_t)rman_get_size(res));
+ goto fail;
+ }
+ mtx_lock_spin(&icu_lock);
+ apic_id = ioapic_read(apic, IOAPIC_ID) >> APIC_ID_SHIFT;
+ /* First match by io window address */
+ STAILQ_FOREACH(io, &ioapic_list, io_next) {
+ if (io->io_paddr == (vm_paddr_t)rman_get_start(res))
+ goto found;
+ }
+ /* Then by apic id */
+ STAILQ_FOREACH(io, &ioapic_list, io_next) {
+ if (io->io_id == apic_id)
+ goto found;
+ }
+ mtx_unlock_spin(&icu_lock);
+ if (bootverbose)
+ device_printf(dev,
+ "cannot match pci bar apic id %d against MADT\n",
+ apic_id);
+fail:
+ bus_release_resource(dev, SYS_RES_MEMORY, rid, res);
+ return (ENXIO);
+found:
+ KASSERT(io->pci_dev == NULL,
+ ("ioapic %d pci_dev not NULL", io->io_id));
+ KASSERT(io->pci_wnd == NULL,
+ ("ioapic %d pci_wnd not NULL", io->io_id));
+
+ io->pci_dev = dev;
+ io->pci_wnd = res;
+ if (bootverbose && (io->io_paddr != (vm_paddr_t)rman_get_start(res) ||
+ io->io_id != apic_id)) {
+ device_printf(dev, "pci%d:%d:%d:%d pci BAR0@%jx id %d "
+ "MADT id %d paddr@%jx\n",
+ pci_get_domain(dev), pci_get_bus(dev),
+ pci_get_slot(dev), pci_get_function(dev),
+ (uintmax_t)rman_get_start(res), apic_id,
+ io->io_id, (uintmax_t)io->io_paddr);
+ }
+ mtx_unlock_spin(&icu_lock);
return (0);
}
@@ -971,6 +1042,28 @@
static devclass_t ioapic_devclass;
DRIVER_MODULE(ioapic, pci, ioapic_pci_driver, ioapic_devclass, 0, 0);
+int
+ioapic_get_rid(u_int apic_id, uint16_t *ridp)
+{
+ struct ioapic *io;
+ uintptr_t rid;
+ int error;
+
+ mtx_lock_spin(&icu_lock);
+ STAILQ_FOREACH(io, &ioapic_list, io_next) {
+ if (io->io_id == apic_id)
+ break;
+ }
+ mtx_unlock_spin(&icu_lock);
+ if (io == NULL || io->pci_dev == NULL)
+ return (EINVAL);
+ error = pci_get_id(io->pci_dev, PCI_ID_RID, &rid);
+ if (error != 0)
+ return (error);
+ *ridp = rid;
+ return (0);
+}
+
/*
* A new-bus driver to consume the memory resources associated with
* the APICs in the system. On some systems ACPI or PnPBIOS system
@@ -1008,7 +1101,7 @@
if (error)
panic("apic_add_resource: resource %d failed set with %d", rid,
error);
- bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0);
+ bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_SHAREABLE);
}
static int

File Metadata

Mime Type
text/plain
Expires
Fri, Feb 27, 6:02 PM (1 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29038008
Default Alt Text
D12205.id32585.diff (6 KB)

Event Timeline