diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2019-08-28 22:39:10 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2019-08-28 22:39:10 +0000 |
commit | 6562579e3488568ffa9de6a24f313876ca35baf3 (patch) | |
tree | 53ced8d60fe2cca37196552ea5cca8019d2dfdd4 /sys/arch/amd64 | |
parent | 29db85a4b86d3236476bdebab5771104d1ef0baa (diff) |
Use ACPI information to attach PCI busses like we do on arm64. There are a
few additional quirks though, and attaching the PCI busses is delayed to
replicate the existing code more closely. That may be changed in the
future. Also tweak how we handle MSI support and respect to ACPI flag
that says we shouldn't attempt to use MSIs.
Some fallout is expected.
ok patrick@
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r-- | sys/arch/amd64/amd64/mainbus.c | 6 | ||||
-rw-r--r-- | sys/arch/amd64/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/amd64/conf/RAMDISK | 4 | ||||
-rw-r--r-- | sys/arch/amd64/conf/RAMDISK_CD | 4 | ||||
-rw-r--r-- | sys/arch/amd64/conf/files.amd64 | 4 | ||||
-rw-r--r-- | sys/arch/amd64/pci/acpipci.c | 180 | ||||
-rw-r--r-- | sys/arch/amd64/pci/pci_machdep.c | 21 |
7 files changed, 190 insertions, 32 deletions
diff --git a/sys/arch/amd64/amd64/mainbus.c b/sys/arch/amd64/amd64/mainbus.c index 6d2080ee2b1..af1ba119e3a 100644 --- a/sys/arch/amd64/amd64/mainbus.c +++ b/sys/arch/amd64/amd64/mainbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mainbus.c,v 1.47 2019/05/17 19:07:15 guenther Exp $ */ +/* $OpenBSD: mainbus.c,v 1.48 2019/08/28 22:39:09 kettenis Exp $ */ /* $NetBSD: mainbus.c,v 1.1 2003/04/26 18:39:29 fvdl Exp $ */ /* @@ -231,6 +231,9 @@ mainbus_attach(struct device *parent, struct device *self, void *aux) #endif #if NPCI > 0 +#if NACPI > 0 + if (!acpi_haspci) +#endif { pci_init_extents(); @@ -244,6 +247,7 @@ mainbus_attach(struct device *parent, struct device *self, void *aux) mba.mba_pba.pba_busex = pcibus_ex; mba.mba_pba.pba_domain = pci_ndomains++; mba.mba_pba.pba_bus = 0; + mba.mba_pba.pba_flags = PCI_FLAGS_MSI_ENABLED; config_found(self, &mba.mba_pba, mainbus_print); #if NACPI > 0 acpi_pciroots_attach(self, &mba.mba_pba, mainbus_print); diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC index 563c9f855de..068a2bb2ec5 100644 --- a/sys/arch/amd64/conf/GENERIC +++ b/sys/arch/amd64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.476 2019/08/14 00:08:46 jsg Exp $ +# $OpenBSD: GENERIC,v 1.477 2019/08/28 22:39:09 kettenis Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -48,6 +48,7 @@ acpicmos* at acpi? acpidock* at acpi? acpiec* at acpi? acpipci* at acpi? +pci* at acpipci? acpiprt* at acpi? acpisbs* at acpi? acpitz* at acpi? diff --git a/sys/arch/amd64/conf/RAMDISK b/sys/arch/amd64/conf/RAMDISK index bbc452fe4cc..5eec537843b 100644 --- a/sys/arch/amd64/conf/RAMDISK +++ b/sys/arch/amd64/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.71 2018/03/27 21:11:16 kettenis Exp $ +# $OpenBSD: RAMDISK,v 1.72 2019/08/28 22:39:09 kettenis Exp $ machine amd64 maxusers 4 @@ -31,6 +31,8 @@ acpi0 at bios? #acpicpu* at acpi? acpicmos* at acpi? acpiec* at acpi? +acpipci* at acpi? +pci* at acpipci? 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 96b15483567..2583a8f0e9f 100644 --- a/sys/arch/amd64/conf/RAMDISK_CD +++ b/sys/arch/amd64/conf/RAMDISK_CD @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK_CD,v 1.181 2019/06/24 21:33:27 kettenis Exp $ +# $OpenBSD: RAMDISK_CD,v 1.182 2019/08/28 22:39:09 kettenis Exp $ machine amd64 maxusers 4 @@ -39,6 +39,8 @@ acpi0 at bios? #acpicpu* at acpi? acpicmos* at acpi? acpiec* at acpi? +acpipci* at acpi? +pci* at acpipci? acpiprt* at acpi? acpimadt0 at acpi? #acpitz* at acpi? diff --git a/sys/arch/amd64/conf/files.amd64 b/sys/arch/amd64/conf/files.amd64 index 15e7d6bf137..b1c7f5d52b8 100644 --- a/sys/arch/amd64/conf/files.amd64 +++ b/sys/arch/amd64/conf/files.amd64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.amd64,v 1.102 2019/05/17 19:07:16 guenther Exp $ +# $OpenBSD: files.amd64,v 1.103 2019/08/28 22:39:09 kettenis Exp $ maxpartitions 16 maxusers 2 16 128 @@ -237,7 +237,7 @@ attach acpi at bios file arch/amd64/amd64/acpi_machdep.c acpi file arch/amd64/amd64/acpi_wakecode.S acpi & !small_kernel -device acpipci +device acpipci: pcibus attach acpipci at acpi file arch/amd64/pci/acpipci.c acpipci diff --git a/sys/arch/amd64/pci/acpipci.c b/sys/arch/amd64/pci/acpipci.c index 4bc996b2c13..0161b28df81 100644 --- a/sys/arch/amd64/pci/acpipci.c +++ b/sys/arch/amd64/pci/acpipci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpipci.c,v 1.1 2018/10/26 20:26:19 kettenis Exp $ */ +/* $OpenBSD: acpipci.c,v 1.2 2019/08/28 22:39:09 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,163 @@ 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; sc->sc_acpi = (struct acpi_softc *)parent; sc->sc_node = aaa->aaa_node; printf(" %s", sc->sc_node->name); + if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) { + printf(": can't find resources\n"); + return; + } + + 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; + + /* 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); + + acpipci_osc(sc); + + printf("\n"); + + acpi_haspci = 1; + + sc->sc_iot = aaa->aaa_iot; + sc->sc_memt = aaa->aaa_memt; + sc->sc_dmat = aaa->aaa_dmat; + + config_defer(self, acpipci_attach_deferred); +} + +void +acpipci_attach_deferred(struct device *self) +{ + struct acpipci_softc *sc = (struct acpipci_softc *)self; + struct pcibus_attach_args pba; + + 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; + + config_found(self, &pba, acpipci_print); +} + +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); + 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 +278,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 +292,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 27e78c7cfa4..d207ab54c65 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.71 2019/06/25 16:46:32 kettenis Exp $ */ +/* $OpenBSD: pci_machdep.c,v 1.72 2019/08/28 22:39:09 kettenis Exp $ */ /* $NetBSD: pci_machdep.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */ /*- @@ -189,24 +189,11 @@ pci_attach_hook(struct device *parent, struct device *self, 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; + default: + pba->pba_flags &= ~PCI_FLAGS_MSI_ENABLED; break; } |