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 {

Reply via email to