summaryrefslogtreecommitdiff
path: root/sys/arch/amd64
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2020-05-14 13:07:12 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2020-05-14 13:07:12 +0000
commitb857c663aeebfdf6245335135509ac3cbc5a0586 (patch)
tree4506c4f982fc2d6160abe0012d23c46b749e5c66 /sys/arch/amd64
parent1ac42c8d743e72edb2e40a7837467f7bbba89d3a (diff)
Bring back the acpi(4) changes. This time around only use the ACPI _CRS
information on ACPI 5.0 and later. ok krw@, patrick@
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r--sys/arch/amd64/amd64/mainbus.c12
-rw-r--r--sys/arch/amd64/conf/RAMDISK3
-rw-r--r--sys/arch/amd64/conf/RAMDISK_CD3
-rw-r--r--sys/arch/amd64/pci/acpipci.c242
-rw-r--r--sys/arch/amd64/pci/pci_machdep.c60
5 files changed, 246 insertions, 74 deletions
diff --git a/sys/arch/amd64/amd64/mainbus.c b/sys/arch/amd64/amd64/mainbus.c
index 392712ab00d..ed8bd9c4368 100644
--- a/sys/arch/amd64/amd64/mainbus.c
+++ b/sys/arch/amd64/amd64/mainbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mainbus.c,v 1.49 2019/09/07 13:46:19 kettenis Exp $ */
+/* $OpenBSD: mainbus.c,v 1.50 2020/05/14 13:07:11 kettenis Exp $ */
/* $NetBSD: mainbus.c,v 1.1 2003/04/26 18:39:29 fvdl Exp $ */
/*
@@ -231,6 +231,13 @@ mainbus_attach(struct device *parent, struct device *self, void *aux)
#endif
#if NPCI > 0
+#if NACPI > 0
+ if (acpi_haspci) {
+ extern void acpipci_attach_busses(struct device *);
+
+ acpipci_attach_busses(self);
+ } else
+#endif
{
pci_init_extents();
@@ -245,9 +252,6 @@ mainbus_attach(struct device *parent, struct device *self, void *aux)
mba.mba_pba.pba_domain = pci_ndomains++;
mba.mba_pba.pba_bus = 0;
config_found(self, &mba.mba_pba, mainbus_print);
-#if NACPI > 0
- acpi_pciroots_attach(self, &mba.mba_pba, mainbus_print);
-#endif
}
#endif
diff --git a/sys/arch/amd64/conf/RAMDISK b/sys/arch/amd64/conf/RAMDISK
index b308202c675..d94340db5b1 100644
--- a/sys/arch/amd64/conf/RAMDISK
+++ b/sys/arch/amd64/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.77 2020/03/05 16:36:30 otto Exp $
+# $OpenBSD: RAMDISK,v 1.78 2020/05/14 13:07:11 kettenis Exp $
machine amd64
maxusers 4
@@ -30,6 +30,7 @@ acpi0 at bios?
#acpicpu* at acpi?
acpicmos* at acpi?
acpiec* at acpi?
+acpipci* at acpi?
acpiprt* at acpi?
acpimadt0 at acpi?
#acpitz* at acpi?
diff --git a/sys/arch/amd64/conf/RAMDISK_CD b/sys/arch/amd64/conf/RAMDISK_CD
index f106f6b87c0..91022751e7b 100644
--- a/sys/arch/amd64/conf/RAMDISK_CD
+++ b/sys/arch/amd64/conf/RAMDISK_CD
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK_CD,v 1.188 2020/02/15 08:49:11 stsp Exp $
+# $OpenBSD: RAMDISK_CD,v 1.189 2020/05/14 13:07:11 kettenis Exp $
machine amd64
maxusers 4
@@ -37,6 +37,7 @@ acpi0 at bios?
#acpicpu* at acpi?
acpicmos* at acpi?
acpiec* at acpi?
+acpipci* at acpi?
acpiprt* at acpi?
acpimadt0 at acpi?
#acpitz* at acpi?
diff --git a/sys/arch/amd64/pci/acpipci.c b/sys/arch/amd64/pci/acpipci.c
index 33833de6975..94351eb47e8 100644
--- a/sys/arch/amd64/pci/acpipci.c
+++ b/sys/arch/amd64/pci/acpipci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpipci.c,v 1.3 2019/09/07 13:46:19 kettenis Exp $ */
+/* $OpenBSD: acpipci.c,v 1.4 2020/05/14 13:07:11 kettenis Exp $ */
/*
* Copyright (c) 2018 Mark Kettenis
*
@@ -53,6 +53,19 @@ struct acpipci_softc {
struct device sc_dev;
struct acpi_softc *sc_acpi;
struct aml_node *sc_node;
+
+ bus_space_tag_t sc_iot;
+ bus_space_tag_t sc_memt;
+ bus_dma_tag_t sc_dmat;
+
+ struct extent *sc_busex;
+ struct extent *sc_memex;
+ struct extent *sc_ioex;
+ char sc_busex_name[32];
+ char sc_ioex_name[32];
+ char sc_memex_name[32];
+ int sc_bus;
+ uint32_t sc_seg;
};
int acpipci_match(struct device *, void *, void *);
@@ -72,6 +85,11 @@ const char *acpipci_hids[] = {
NULL
};
+void acpipci_attach_deferred(struct device *);
+int acpipci_print(void *, const char *);
+int acpipci_parse_resources(int, union acpi_resource *, void *);
+void acpipci_osc(struct acpipci_softc *);
+
int
acpipci_match(struct device *parent, void *match, void *aux)
{
@@ -86,15 +104,225 @@ acpipci_attach(struct device *parent, struct device *self, void *aux)
{
struct acpi_attach_args *aaa = aux;
struct acpipci_softc *sc = (struct acpipci_softc *)self;
- struct aml_value args[4];
struct aml_value res;
- static uint8_t uuid[16] = ACPI_PCI_UUID;
- uint32_t buf[3];
+ uint64_t bbn = 0;
+ uint64_t seg = 0;
+
+ acpi_haspci = 1;
+
+ sc->sc_iot = aaa->aaa_iot;
+ sc->sc_memt = aaa->aaa_memt;
+ sc->sc_dmat = aaa->aaa_dmat;
sc->sc_acpi = (struct acpi_softc *)parent;
sc->sc_node = aaa->aaa_node;
printf(" %s", sc->sc_node->name);
+ acpipci_osc(sc);
+
+ aml_evalinteger(sc->sc_acpi, sc->sc_node, "_BBN", 0, NULL, &bbn);
+ sc->sc_bus = bbn;
+
+ aml_evalinteger(sc->sc_acpi, sc->sc_node, "_SEG", 0, NULL, &seg);
+ sc->sc_seg = seg;
+
+ if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) {
+ printf(": can't find resources\n");
+
+ pci_init_extents();
+ sc->sc_busex = pcibus_ex;
+ sc->sc_ioex = pciio_ex;
+ sc->sc_memex = pcimem_ex;
+
+ return;
+ }
+
+ /* Create extents for our address spaces. */
+ snprintf(sc->sc_busex_name, sizeof(sc->sc_busex_name),
+ "%s pcibus", sc->sc_dev.dv_xname);
+ snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name),
+ "%s pciio", sc->sc_dev.dv_xname);
+ snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name),
+ "%s pcimem", sc->sc_dev.dv_xname);
+ sc->sc_busex = extent_create(sc->sc_busex_name, 0, 255,
+ M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
+ sc->sc_ioex = extent_create(sc->sc_ioex_name, 0, 0xffffffff,
+ M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
+ sc->sc_memex = extent_create(sc->sc_memex_name, 0, (u_long)-1,
+ M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
+
+ aml_parse_resource(&res, acpipci_parse_resources, sc);
+
+ if (sc->sc_acpi->sc_major < 5) {
+ extent_destroy(sc->sc_ioex);
+ extent_destroy(sc->sc_memex);
+
+ pci_init_extents();
+ sc->sc_ioex = pciio_ex;
+ sc->sc_memex = pcimem_ex;
+ }
+
+ printf("\n");
+
+#ifdef DIAGNOSTIC
+ extent_print(sc->sc_busex);
+ extent_print(sc->sc_ioex);
+ extent_print(sc->sc_memex);
+#endif
+}
+
+void
+acpipci_attach_bus(struct device *parent, struct acpipci_softc *sc)
+{
+ struct pcibus_attach_args pba;
+ pcitag_t tag;
+ pcireg_t id, class;
+
+ memset(&pba, 0, sizeof(pba));
+ pba.pba_busname = "pci";
+ pba.pba_iot = sc->sc_iot;
+ pba.pba_memt = sc->sc_memt;
+ pba.pba_dmat = sc->sc_dmat;
+ pba.pba_busex = sc->sc_busex;
+ pba.pba_ioex = sc->sc_ioex;
+ pba.pba_memex = sc->sc_memex;
+ pba.pba_pmemex = sc->sc_memex;
+ pba.pba_domain = pci_ndomains++;
+ pba.pba_bus = sc->sc_bus;
+
+ /* Enable MSI in ACPI 2.0 and above, unless we're told not to. */
+ if (sc->sc_acpi->sc_fadt->hdr.revision >= 2 &&
+ (sc->sc_acpi->sc_fadt->iapc_boot_arch & FADT_NO_MSI) == 0)
+ pba.pba_flags |= PCI_FLAGS_MSI_ENABLED;
+
+ /*
+ * Don't enable MSI on chipsets from low-end manifacturers
+ * like VIA and SiS. We do this by looking at the host
+ * bridge, which should be device 0 function 0.
+ */
+ tag = pci_make_tag(pba.pba_pc, sc->sc_bus, 0, 0);
+ id = pci_conf_read(pba.pba_pc, tag, PCI_ID_REG);
+ class = pci_conf_read(pba.pba_pc, tag, PCI_CLASS_REG);
+ if (PCI_CLASS(class) == PCI_CLASS_BRIDGE &&
+ PCI_SUBCLASS(class) != PCI_SUBCLASS_BRIDGE_HOST &&
+ PCI_VENDOR(id) != PCI_VENDOR_AMD &&
+ PCI_VENDOR(id) != PCI_VENDOR_NVIDIA &&
+ PCI_VENDOR(id) != PCI_VENDOR_INTEL)
+ pba.pba_flags &= ~PCI_FLAGS_MSI_ENABLED;
+
+ /*
+ * Don't enable MSI on a HyperTransport bus. In order to
+ * determine that a bus is a HyperTransport bus, we look at
+ * device 24 function 0, which is the HyperTransport
+ * host/primary interface integrated on most 64-bit AMD CPUs.
+ * If that device has a HyperTransport capability, this must
+ * be a HyperTransport bus and we disable MSI.
+ */
+ tag = pci_make_tag(pba.pba_pc, sc->sc_bus, 24, 0);
+ if (pci_get_capability(pba.pba_pc, tag, PCI_CAP_HT, NULL, NULL))
+ pba.pba_flags &= ~PCI_FLAGS_MSI_ENABLED;
+
+ config_found(parent, &pba, acpipci_print);
+}
+
+void
+acpipci_attach_busses(struct device *parent)
+{
+ int i;
+
+ for (i = 0; i < acpipci_cd.cd_ndevs; i++) {
+ if (acpipci_cd.cd_devs[i])
+ acpipci_attach_bus(parent, acpipci_cd.cd_devs[i]);
+ }
+}
+
+int
+acpipci_print(void *aux, const char *pnp)
+{
+ struct pcibus_attach_args *pba = aux;
+
+ if (pnp)
+ printf("%s at %s", pba->pba_busname, pnp);
+ printf(" bus %d", pba->pba_bus);
+ return (UNCONF);
+}
+
+int
+acpipci_parse_resources(int crsidx, union acpi_resource *crs, void *arg)
+{
+ struct acpipci_softc *sc = arg;
+ int type = AML_CRSTYPE(crs);
+ int restype, tflags = 0;
+ u_long min, len = 0, tra = 0;
+
+ switch (type) {
+ case LR_WORD:
+ restype = crs->lr_word.type;
+ tflags = crs->lr_word.tflags;
+ min = crs->lr_word._min;
+ len = crs->lr_word._len;
+ tra = crs->lr_word._tra;
+ break;
+ case LR_DWORD:
+ restype = crs->lr_dword.type;
+ tflags = crs->lr_dword.tflags;
+ min = crs->lr_dword._min;
+ len = crs->lr_dword._len;
+ tra = crs->lr_dword._tra;
+ break;
+ case LR_QWORD:
+ restype = crs->lr_qword.type;
+ tflags = crs->lr_qword.tflags;
+ min = crs->lr_qword._min;
+ len = crs->lr_qword._len;
+ tra = crs->lr_qword._tra;
+ break;
+ case LR_MEM32FIXED:
+ /*
+ * Coreboot on the PC Engines apu2 incorrectly uses a
+ * Memory32Fixed resource descriptor to describe mmio
+ * address space forwarded to the PCI bus.
+ */
+ restype = LR_TYPE_MEMORY;
+ min = crs->lr_m32fixed._bas;
+ len = crs->lr_m32fixed._len;
+ break;
+ }
+
+ if (len == 0)
+ return 0;
+
+ switch (restype) {
+ case LR_TYPE_MEMORY:
+ if (tflags & LR_MEMORY_TTP)
+ return 0;
+ extent_free(sc->sc_memex, min, len, EX_WAITOK | EX_CONFLICTOK);
+ break;
+ case LR_TYPE_IO:
+ if (tflags & LR_IO_TTP)
+ return 0;
+ extent_free(sc->sc_ioex, min, len, EX_WAITOK | EX_CONFLICTOK);
+ break;
+ case LR_TYPE_BUS:
+ extent_free(sc->sc_busex, min, len, EX_WAITOK);
+ /*
+ * Let _CRS minimum bus number override _BBN.
+ */
+ sc->sc_bus = min;
+ break;
+ }
+
+ return 0;
+}
+
+void
+acpipci_osc(struct acpipci_softc *sc)
+{
+ struct aml_value args[4];
+ struct aml_value res;
+ static uint8_t uuid[16] = ACPI_PCI_UUID;
+ uint32_t buf[3];
+
memset(args, 0, sizeof(args));
args[0].type = AML_OBJTYPE_BUFFER;
args[0].v_buffer = uuid;
@@ -112,10 +340,8 @@ acpipci_attach(struct device *parent, struct device *self, void *aux)
buf[1] = ACPI_PCI_PCIE_CONFIG | ACPI_PCI_MSI;
buf[2] = ACPI_PCI_PCIE_HOTPLUG;
- if (aml_evalname(sc->sc_acpi, sc->sc_node, "_OSC", 4, args, &res)) {
- printf(": _OSC failed\n");
+ if (aml_evalname(sc->sc_acpi, sc->sc_node, "_OSC", 4, args, &res))
return;
- }
if (res.type == AML_OBJTYPE_BUFFER) {
size_t len = res.length;
@@ -128,6 +354,4 @@ acpipci_attach(struct device *parent, struct device *self, void *aux)
len -= 4;
}
}
-
- printf("\n");
}
diff --git a/sys/arch/amd64/pci/pci_machdep.c b/sys/arch/amd64/pci/pci_machdep.c
index 70dab3ecbfb..d0fd8d43691 100644
--- a/sys/arch/amd64/pci/pci_machdep.c
+++ b/sys/arch/amd64/pci/pci_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.c,v 1.73 2019/09/07 13:46:19 kettenis Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.74 2020/05/14 13:07:11 kettenis Exp $ */
/* $NetBSD: pci_machdep.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */
/*-
@@ -163,64 +163,6 @@ void
pci_attach_hook(struct device *parent, struct device *self,
struct pcibus_attach_args *pba)
{
- pci_chipset_tag_t pc = pba->pba_pc;
- pcitag_t tag;
- pcireg_t id, class;
-
- if (pba->pba_bus != 0)
- return;
-
- /*
- * In order to decide whether the system supports MSI we look
- * at the host bridge, which should be device 0 function 0 on
- * bus 0. It is better to not enable MSI on systems that
- * support it than the other way around, so be conservative
- * here. So we don't enable MSI if we don't find a host
- * bridge there. We also deliberately don't enable MSI on
- * chipsets from low-end manifacturers like VIA and SiS.
- */
- tag = pci_make_tag(pc, 0, 0, 0);
- id = pci_conf_read(pc, tag, PCI_ID_REG);
- class = pci_conf_read(pc, tag, PCI_CLASS_REG);
-
- if (PCI_CLASS(class) != PCI_CLASS_BRIDGE ||
- PCI_SUBCLASS(class) != PCI_SUBCLASS_BRIDGE_HOST)
- return;
-
- switch (PCI_VENDOR(id)) {
- case PCI_VENDOR_INTEL:
- /*
- * In the wonderful world of virtualization you can
- * have the latest 64-bit AMD multicore CPU behind a
- * prehistoric Intel host bridge. Give them what they
- * deserve.
- */
- switch (PCI_PRODUCT(id)) {
- case PCI_PRODUCT_INTEL_82441FX: /* QEMU */
- case PCI_PRODUCT_INTEL_82443BX: /* VMWare */
- break;
- default:
- pba->pba_flags |= PCI_FLAGS_MSI_ENABLED;
- break;
- }
- break;
- case PCI_VENDOR_NVIDIA:
- case PCI_VENDOR_AMD:
- pba->pba_flags |= PCI_FLAGS_MSI_ENABLED;
- break;
- }
-
- /*
- * Don't enable MSI on a HyperTransport bus. In order to
- * determine that bus 0 is a HyperTransport bus, we look at
- * device 24 function 0, which is the HyperTransport
- * host/primary interface integrated on most 64-bit AMD CPUs.
- * If that device has a HyperTransport capability, bus 0 must
- * be a HyperTransport bus and we disable MSI.
- */
- tag = pci_make_tag(pc, 0, 24, 0);
- if (pci_get_capability(pc, tag, PCI_CAP_HT, NULL, NULL))
- pba->pba_flags &= ~PCI_FLAGS_MSI_ENABLED;
}
int