The diff below should fix one of the issues uncovered by the
acpipci(4) changes that I just backed out.

On some systems, ACPI specifies overlapping regions of address space
that gets forwarded to the PCI bus.  Since we use extent_free(9) to
make those regions of address space available, that code needs to be
able to handle overlaps.

Since the acpipci(4) has been backed out, I attach the diff (with
debug print code) below.  Alexander, it would be great if you can test
this on that SuperMicro box.


Index: sys/kern/subr_extent.c
===================================================================
RCS file: /cvs/src/sys/kern/subr_extent.c,v
retrieving revision 1.61
diff -u -p -r1.61 subr_extent.c
--- sys/kern/subr_extent.c      28 Aug 2019 22:22:43 -0000      1.61
+++ sys/kern/subr_extent.c      7 Sep 2019 13:55:01 -0000
@@ -962,6 +962,7 @@ int
 extent_free(struct extent *ex, u_long start, u_long size, int flags)
 {
        struct extent_region *rp, *nrp = NULL;
+       struct extent_region *tmp;
        u_long end = start + (size - 1);
        int exflags;
        int error = 0;
@@ -1019,8 +1020,12 @@ extent_free(struct extent *ex, u_long st
         *
         * Cases 2, 3, and 4 require that the EXF_NOCOALESCE flag
         * is not set.
+        *
+        * If the EX_CONFLICTOK flag is set, partially overlapping
+        * regions are allowed.  This is handled in cases 1a, 2a and
+        * 3a below.
         */
-       LIST_FOREACH(rp, &ex->ex_regions, er_link) {
+       LIST_FOREACH_SAFE(rp, &ex->ex_regions, er_link, tmp) {
                /*
                 * Save ourselves some comparisons; does the current
                 * region end before chunk to be freed begins?  If so,
@@ -1080,12 +1085,28 @@ extent_free(struct extent *ex, u_long st
                        nrp = NULL;
                        goto done;
                }
+
+               if ((flags & EX_CONFLICTOK) == 0)
+                       continue;
+
+               /* Case 1a. */
+               if ((start <= rp->er_start && end >= rp->er_end)) {
+                       LIST_REMOVE(rp, er_link);
+                       extent_free_region_descriptor(ex, rp);
+                       continue;
+               }
+
+               /* Case 2a. */
+               if ((start <= rp->er_start) && (end >= rp->er_start))
+                       rp->er_start = (end + 1);
+
+               /* Case 3a. */
+               if ((start <= rp->er_end) && (end >= rp->er_end))
+                       rp->er_end = (start - 1);
        }
 
-       if (flags & EX_CONFLICTOK) {
-               error = EINVAL;
+       if (flags & EX_CONFLICTOK)
                goto done;
-       }
 
        /* Region not found, or request otherwise invalid. */
 #if defined(DIAGNOSTIC) || defined(DDB)
Index: regress/sys/kern/extent/extest.awk
===================================================================
RCS file: /cvs/src/regress/sys/kern/extent/extest.awk,v
retrieving revision 1.2
diff -u -p -r1.2 extest.awk
--- regress/sys/kern/extent/extest.awk  10 Apr 2009 20:57:04 -0000      1.2
+++ regress/sys/kern/extent/extest.awk  7 Sep 2019 13:55:01 -0000
@@ -67,7 +67,12 @@ $1 == "alloc_subregion" {
 }
 
 $1 == "free" {
-       printf("error = extent_free(ex, %s, %s, 0);\n", $2, $3)
+       if ($4 == "") {
+               flags = "0";
+       } else {
+               flags = $4;
+       }
+       printf("error = extent_free(ex, %s, %s, %s);\n", $2, $3, flags)
        printf("if (error)\n\tprintf(\"error: %%s\\n\", strerror(error));\n")
 }
 
Index: regress/sys/kern/extent/extest.exp
===================================================================
RCS file: /cvs/src/regress/sys/kern/extent/extest.exp,v
retrieving revision 1.4
diff -u -p -r1.4 extest.exp
--- regress/sys/kern/extent/extest.exp  13 Oct 2009 20:53:40 -0000      1.4
+++ regress/sys/kern/extent/extest.exp  7 Sep 2019 13:55:01 -0000
@@ -92,3 +92,13 @@ extent `test16' (0x0 - 0xffffffff), flag
 output for test17
 extent `test17' (0x0 - 0xffffffffffffffff), flags = 0x0
      0x0 - 0xffffffffffffffff
+output for test18
+extent `test18' (0x0 - 0xffff), flags = 0x0
+     0x0 - 0xcff
+     0xf000 - 0xffff
+output for test19
+extent `test19' (0x0 - 0xffff), flags = 0x0
+     0x0 - 0xcff
+output for test20
+extent `test20' (0x0 - 0xffff), flags = 0x0
+     0xf000 - 0xffff
Index: regress/sys/kern/extent/tests
===================================================================
RCS file: /cvs/src/regress/sys/kern/extent/tests,v
retrieving revision 1.5
diff -u -p -r1.5 tests
--- regress/sys/kern/extent/tests       13 Oct 2009 20:53:40 -0000      1.5
+++ regress/sys/kern/extent/tests       7 Sep 2019 13:55:01 -0000
@@ -136,3 +136,19 @@ print
 extent test17 0x00000000 -1L EX_FILLED
 alloc_region 0 0x4000 EX_CONFLICTOK
 print
+
+# Check freeing overkapping regions from a filled extent
+extent test18 0x0000 0xffff EX_FILLED
+free 0x164e 0x2
+free 0x0d00 0xe300 EX_CONFLICTOK
+print
+
+extent test19 0x0000 0xffff EX_FILLED
+free 0x164e 0x2
+free 0x0d00 0xf300 EX_CONFLICTOK
+print
+
+extent test20 0x0000 0xffff EX_FILLED
+free 0x164e 0x2
+free 0x0000 0xf000 EX_CONFLICTOK
+print






Index: dev/acpi/acpi.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpi.c,v
retrieving revision 1.374
diff -u -p -r1.374 acpi.c
--- dev/acpi/acpi.c     7 Sep 2019 13:46:20 -0000       1.374
+++ dev/acpi/acpi.c     7 Sep 2019 14:04:45 -0000
@@ -71,6 +71,7 @@ int   acpi_debug = 16;
 
 int    acpi_poll_enabled;
 int    acpi_hasprocfvs;
+int    acpi_haspci;
 
 #define ACPIEN_RETRIES 15
 
Index: dev/acpi/acpivar.h
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpivar.h,v
retrieving revision 1.105
diff -u -p -r1.105 acpivar.h
--- dev/acpi/acpivar.h  7 Sep 2019 13:46:20 -0000       1.105
+++ dev/acpi/acpivar.h  7 Sep 2019 14:04:45 -0000
@@ -43,6 +43,7 @@ extern int acpi_debug;
 #endif
 
 extern int acpi_hasprocfvs;
+extern int acpi_haspci;
 
 struct klist;
 struct acpiec_softc;
Index: arch/amd64/amd64/mainbus.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/mainbus.c,v
retrieving revision 1.49
diff -u -p -r1.49 mainbus.c
--- arch/amd64/amd64/mainbus.c  7 Sep 2019 13:46:19 -0000       1.49
+++ arch/amd64/amd64/mainbus.c  7 Sep 2019 14:04:45 -0000
@@ -231,6 +231,9 @@ mainbus_attach(struct device *parent, st
 #endif
 
 #if NPCI > 0
+#if NACPI > 0
+       if (!acpi_haspci)
+#endif
        {
                pci_init_extents();
 
@@ -244,6 +247,7 @@ mainbus_attach(struct device *parent, st
                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);
Index: arch/amd64/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v
retrieving revision 1.478
diff -u -p -r1.478 GENERIC
--- arch/amd64/conf/GENERIC     7 Sep 2019 13:46:19 -0000       1.478
+++ arch/amd64/conf/GENERIC     7 Sep 2019 14:04:45 -0000
@@ -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?
Index: arch/amd64/conf/RAMDISK
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/RAMDISK,v
retrieving revision 1.74
diff -u -p -r1.74 RAMDISK
--- arch/amd64/conf/RAMDISK     7 Sep 2019 13:46:19 -0000       1.74
+++ arch/amd64/conf/RAMDISK     7 Sep 2019 14:04:46 -0000
@@ -29,6 +29,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?
Index: arch/amd64/conf/RAMDISK_CD
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/RAMDISK_CD,v
retrieving revision 1.184
diff -u -p -r1.184 RAMDISK_CD
--- arch/amd64/conf/RAMDISK_CD  7 Sep 2019 13:46:19 -0000       1.184
+++ arch/amd64/conf/RAMDISK_CD  7 Sep 2019 14:04:46 -0000
@@ -37,6 +37,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?
Index: arch/amd64/conf/files.amd64
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/files.amd64,v
retrieving revision 1.104
diff -u -p -r1.104 files.amd64
--- arch/amd64/conf/files.amd64 7 Sep 2019 13:46:19 -0000       1.104
+++ arch/amd64/conf/files.amd64 7 Sep 2019 14:04:46 -0000
@@ -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
 
Index: arch/amd64/pci/acpipci.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/pci/acpipci.c,v
retrieving revision 1.3
diff -u -p -r1.3 acpipci.c
--- arch/amd64/pci/acpipci.c    7 Sep 2019 13:46:19 -0000       1.3
+++ arch/amd64/pci/acpipci.c    7 Sep 2019 14:04:46 -0000
@@ -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,167 @@ acpipci_attach(struct device *parent, st
 {
        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");
+
+       extent_print(sc->sc_busex);
+       extent_print(sc->sc_ioex);
+       extent_print(sc->sc_memex);
+
+       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 +282,8 @@ acpipci_attach(struct device *parent, st
        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 +296,4 @@ acpipci_attach(struct device *parent, st
                        len -= 4;
                }
        }
-
-       printf("\n");
 }
Index: arch/amd64/pci/pci_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/pci/pci_machdep.c,v
retrieving revision 1.73
diff -u -p -r1.73 pci_machdep.c
--- arch/amd64/pci/pci_machdep.c        7 Sep 2019 13:46:19 -0000       1.73
+++ arch/amd64/pci/pci_machdep.c        7 Sep 2019 14:04:46 -0000
@@ -189,24 +189,11 @@ pci_attach_hook(struct device *parent, s
 
        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;
        }
 

Reply via email to