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;
}