It seems more and more server machines ship in a "64-bit" configuration where the BIOS assigns addresses above the 4GB mark to 64-bit BARs. We have a hack in arch/amd64/pci_machdep.c:pci_init_extents() to deal with some of these configurations:
/* * ... * * Dell 13G servers have important devices outside the * 36-bit address space. Until we can extract the address * ranges from ACPI, expand the allowed range to suit. */ I ran into a SuperMicro machine that puts stuff even higher. And ratherthan extending the range again, I think it is time to bite the bullet and trust ACPI. The diff below is a first stab. Needs a bit more polish, but before I spend more time on it, I'd like to get some test results. I'd like to see the diff tested on a wide variety of machines. Please send me old and new dmesg and acpidump output. Warning! A kernel with this diff might panic early on in the boot process, so don't play with it unless you have a way to boot your previous kernel. Index: acpi.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpi.c,v retrieving revision 1.297 diff -u -p -r1.297 acpi.c --- acpi.c 23 Nov 2015 00:10:53 -0000 1.297 +++ acpi.c 30 Dec 2015 13:03:38 -0000 @@ -561,6 +561,48 @@ acpi_matchhids(struct acpi_attach_args * return (0); } +int +acpi_fill_memex(union acpi_resource *crs, void *arg) +{ + int type = AML_CRSTYPE(crs); + struct extent *ex = arg; + uint64_t min, max, len; + uint16_t flags; + + switch (type) { + case LR_DWORD: + type = crs->lr_dword.type; + flags = crs->lr_dword.flags; + len = crs->lr_dword._len; + min = crs->lr_dword._min; + max = crs->lr_dword._max; + break; + case LR_QWORD: + type = crs->lr_qword.type; + flags = crs->lr_qword.flags; + len = crs->lr_qword._len; + min = crs->lr_qword._min; + max = crs->lr_qword._max; + break; + default: + return 0; + } + + if (type != 0) + return 0; + if (len == 0) + return 0; + if ((flags & 0xc) != 0xc) + return 0; + if (min >= max) + return 0; + if (len != max - min + 1) + return 0; + + extent_free(ex, min, len, EX_NOWAIT); + return 0; +} + /* Map ACPI device node to PCI */ int acpi_getpci(struct aml_node *node, void *arg) @@ -573,10 +615,17 @@ acpi_getpci(struct aml_node *node, void pcitag_t tag; uint64_t val; uint32_t reg; + int64_t sta = 0; if (!node->value || node->value->type != AML_OBJTYPE_DEVICE) return 0; - if (!aml_evalhid(node, &res)) { + + /* Evaluate _STA to decide PCI Root node fate and walk fate */ + if (aml_evalinteger(sc, node, "_STA", 0, NULL, &sta)) + sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000; + + if ((sta & (STA_PRESENT|STA_ENABLED)) == (STA_PRESENT|STA_ENABLED) && + !aml_evalhid(node, &res)) { /* Check if this is a PCI Root node */ if (_acpi_matchhids(res.v_string, pcihid)) { aml_freevalue(&res); @@ -603,6 +652,18 @@ acpi_getpci(struct aml_node *node, void dnprintf(10, "found PCI root: %s %d\n", aml_nodename(node), pci->bus); TAILQ_INSERT_TAIL(&acpi_pcirootdevs, pci, next); + + pci->memex = extent_create("pcimem", 0, -1, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED); + KASSERT(pci->memex != NULL); + + if (aml_evalname(sc, node, "_CRS", 0, NULL, &res) == 0) { + aml_parse_resource(&res, acpi_fill_memex, pci->memex); + aml_freevalue(&res); + printf("bus %d\n", pci->bus); + extent_print(pci->memex); + if (pci->bus == 0) + pcimem_ex = pci->memex; + } } aml_freevalue(&res); return 0; @@ -833,6 +894,7 @@ acpi_pciroots_attach(struct device *dev, 1, EX_NOWAIT) != 0) continue; pba->pba_bus = pdev->bus; + pba->pba_memex = pdev->memex; config_found(dev, pba, pr); } } Index: amltypes.h =================================================================== RCS file: /cvs/src/sys/dev/acpi/amltypes.h,v retrieving revision 1.40 diff -u -p -r1.40 amltypes.h --- amltypes.h 7 Sep 2012 19:19:59 -0000 1.40 +++ amltypes.h 30 Dec 2015 13:03:38 -0000 @@ -362,6 +362,8 @@ struct acpi_pci { int _s3w; int _s4d; int _s4w; + + struct extent *memex; }; struct aml_node {