On Thu, Dec 18, 2014 at 11:14:54PM +0100, Frederic Nowak wrote:
> Hi!
> 
> The diff for extracting memory ranges from ACPI was obviously not tested
> with ACPI disabled...so we definitely have to check if the values in
> pcimem_range make some sense. The diff below now uses the old values in
> case ACPI is disabled or does not return valid values.
> 
> I hope this is somewhat interesting for someone else as well :)
> Please let me know if this is just noise or if there is anything else I
> am missing.

This looks like the right direction, except I think we only really want to use
the ACPI range information to add new ranges to the existing one that covers
the 36-bit address space, rather than relying on it for everything.  No point
relying on the ACPI stuff being correct if we don't need to.

I hacked this around a bit today and ended up with the diff below.  This only
deals with ranges outside the 36-bit space, so it makes no difference on most
machines, and on the r630 that needs it, it adds two ranges,
0x0000030000000000 to 0x0000033FFFFFFFFF and 0x0000034000000000 to
0x0000037FFFFFFFFF.


Index: arch/amd64/pci/pci_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/pci/pci_machdep.c,v
retrieving revision 1.60
diff -u -p -r1.60 pci_machdep.c
--- arch/amd64/pci/pci_machdep.c        16 Dec 2014 23:13:20 -0000      1.60
+++ arch/amd64/pci/pci_machdep.c        19 Dec 2014 12:54:44 -0000
@@ -90,12 +90,17 @@
 #include <dev/pci/ppbreg.h>
 
 #include "ioapic.h"
+#include "acpi.h"
 
 #if NIOAPIC > 0
 #include <machine/i82093var.h>
 #include <machine/mpbiosvar.h>
 #endif
 
+#if NACPI > 0
+#include <dev/acpi/acpivar.h>
+#endif
+
 /*
  * Memory Mapped Configuration space access.
  *
@@ -622,17 +627,13 @@ pci_init_extents(void)
                 * here.  As long as vendors continue to support
                 * 32-bit operating systems, we should never see BARs
                 * outside that region.
-                *
-                * 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.
                 */
                pcimem_ex = extent_create("pcimem", 0, 0xffffffffffffffffUL,
                    M_DEVBUF, NULL, 0, EX_NOWAIT);
                if (pcimem_ex == NULL)
                        return;
-               extent_alloc_region(pcimem_ex, 0x40000000000UL,
-                   0xfffffc0000000000UL, EX_NOWAIT);
+               extent_alloc_region(pcimem_ex, 0x1000000000UL,
+                   0xfffffff000000000UL, EX_NOWAIT);
 
                for (bmp = bios_memmap; bmp->type != BIOS_MAP_END; bmp++) {
                        /*
@@ -657,6 +658,14 @@ pci_init_extents(void)
                /* Take out the video buffer area and BIOS areas. */
                extent_alloc_region(pcimem_ex, IOM_BEGIN, IOM_SIZE,
                    EX_CONFLICTOK | EX_NOWAIT);
+
+#if NACPI > 0
+               /*
+                * Free up any regions outside the 36-bit address space
+                * specified via ACPI.
+                */
+               acpi_pciroots_extents(pcimem_ex, 0x1000000000UL);
+#endif
        }
 
        if (pcibus_ex == NULL) {
@@ -665,7 +674,6 @@ pci_init_extents(void)
        }
 }
 
-#include "acpi.h"
 #if NACPI > 0
 void acpi_pci_match(struct device *, struct pci_attach_args *);
 pcireg_t acpi_pci_min_powerstate(pci_chipset_tag_t, pcitag_t);
Index: dev/acpi/acpivar.h
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpivar.h,v
retrieving revision 1.79
diff -u -p -r1.79 acpivar.h
--- dev/acpi/acpivar.h  8 Dec 2014 07:12:37 -0000       1.79
+++ dev/acpi/acpivar.h  19 Dec 2014 12:54:44 -0000
@@ -47,6 +47,7 @@ extern u_int8_t acpi_lapic_flags[LAPIC_M
 struct klist;
 struct acpiec_softc;
 struct acpipwrres_softc;
+struct extent;
 
 struct acpivideo_softc {
        struct device sc_dev;
@@ -357,6 +358,7 @@ int acpi_acquire_glk(uint32_t *);
 int    acpi_release_glk(uint32_t *);
 
 void   acpi_pciroots_attach(struct device *, void *, cfprint_t);
+void   acpi_pciroots_extents(struct extent *, u_int64_t);
 
 #endif
 
Index: dev/acpi/amltypes.h
===================================================================
RCS file: /cvs/src/sys/dev/acpi/amltypes.h,v
retrieving revision 1.40
diff -u -p -r1.40 amltypes.h
--- dev/acpi/amltypes.h 7 Sep 2012 19:19:59 -0000       1.40
+++ dev/acpi/amltypes.h 19 Dec 2014 12:54:44 -0000
@@ -346,6 +346,12 @@ struct aml_value {
 #define aml_pkglen(v)          ((v)->length)
 #define aml_pkgval(v,i)                (&(v)->v_package[(i)])
 
+struct acpi_pci_range {
+       SLIST_ENTRY(acpi_pci_range)     next;
+       uint64_t                        base;
+       uint64_t                        len;
+};
+
 struct acpi_pci {
        TAILQ_ENTRY(acpi_pci)           next;
 
@@ -362,6 +368,8 @@ struct acpi_pci {
        int                             _s3w;
        int                             _s4d;
        int                             _s4w;
+
+       SLIST_HEAD(, acpi_pci_range)    ranges;
 };
 
 struct aml_node {
Index: dev/acpi/acpi.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpi.c,v
retrieving revision 1.277
diff -u -p -r1.277 acpi.c
--- dev/acpi/acpi.c     9 Dec 2014 06:58:29 -0000       1.277
+++ dev/acpi/acpi.c     19 Dec 2014 12:54:44 -0000
@@ -384,20 +384,41 @@ TAILQ_HEAD(, acpi_pci) acpi_pcirootdevs 
     TAILQ_HEAD_INITIALIZER(acpi_pcirootdevs);
 
 int acpi_getpci(struct aml_node *node, void *arg);
-int acpi_getminbus(union acpi_resource *crs, void *arg);
+int acpi_parse_pci(union acpi_resource *crs, void *arg);
 
 int
-acpi_getminbus(union acpi_resource *crs, void *arg)
+acpi_parse_pci(union acpi_resource *crs, void *arg)
 {
-       int *bbn = arg;
+       struct acpi_pci *pci = arg;
+       struct acpi_pci_range *pcir;
        int typ = AML_CRSTYPE(crs);
 
-       /* Check for embedded bus number */
-       if (typ == LR_WORD && crs->lr_word.type == 2) {
-               /* If _MIN > _MAX, the resource is considered to be invalid. */
-               if (crs->lr_word._min > crs->lr_word._max)
-                       return -1;
-               *bbn = crs->lr_word._min;
+       switch (typ) {  
+       case LR_WORD:
+               /* Check for embedded bus number */
+               if (crs->lr_word.type == 2) {
+                       /*
+                        * If _MIN > _MAX, the resource is considered to be
+                        * invalid.
+                        */
+                       if (crs->lr_word._min > crs->lr_word._max)
+                               return -1;
+                       pci->bus = crs->lr_word._min;
+               }
+               break;
+
+       case LR_QWORD:
+               /*
+                * We only care about ranges outside the 32-bit address space,
+                * so only LR_QWORD is interesting here.
+                */
+               if (crs->lr_qword.type == 0) {
+                       pcir = malloc(sizeof(*pcir), M_DEVBUF, M_WAITOK|M_ZERO);
+                       pcir->base = crs->lr_qword._min;
+                       pcir->len = crs->lr_qword._max - crs->lr_qword._min;
+                       SLIST_INSERT_HEAD(&pci->ranges, pcir, next);
+               }
+               break;
        }
        return 0;
 }
@@ -455,8 +476,7 @@ acpi_getpci(struct aml_node *node, void 
                        if (!aml_evalinteger(sc, node, "_SEG", 0, NULL, &val))
                                pci->seg = val;
                        if (!aml_evalname(sc, node, "_CRS", 0, NULL, &res)) {
-                               aml_parse_resource(&res, acpi_getminbus,
-                                   &pci->bus);
+                               aml_parse_resource(&res, acpi_parse_pci, pci);
                                dnprintf(10, "%s post-crs: %d\n", 
aml_nodename(node), 
                                    pci->bus);
                        }
@@ -686,6 +706,21 @@ acpi_pci_notify(struct aml_node *node, i
        }
 
        return (0);
+}
+
+void
+acpi_pciroots_extents(struct extent *memex, u_int64_t minaddr)
+{
+       struct acpi_pci                 *pdev;
+       struct acpi_pci_range           *range;
+
+       TAILQ_FOREACH(pdev, &acpi_pcirootdevs, next) {
+               SLIST_FOREACH(range, &pdev->ranges, next) {
+                       if (range->base > minaddr) {
+                               extent_free(memex, range->base, range->len, 0);
+                       }
+               }
+       }
 }
 
 void

Reply via email to