So the 24-core arm64 machine I have now contains two PCI host bridges. And since this isn't a PeeCee those are exposed as two separate PCI "segments". This means I need to add support for muliple segments to the ACPI code. The diff does this by adding a segment argument to the pci_mcfg_init() function and introducing a new pci_lookup_segment() function. For amd64 and i386 I continue to assume that there is only a segment zero. On those platforms ACPI should never use additional segments unless we explicitly tell it that we support it (which we don't do). A lookup of a non-zero segment will trigger a KASSERT. For arm64 I still only support segment zero, but a lookup of other segments will not trigger a panic. Instead I return a "dummy" PCI chipset tag that returns 0xfffffff for all config space reads and ignores all config space writes.
I will implement true multi-segment support for arm64 in a follow-up diff. ok? Index: arch/amd64/amd64/acpi_machdep.c =================================================================== RCS file: /cvs/src/sys/arch/amd64/amd64/acpi_machdep.c,v retrieving revision 1.84 diff -u -p -r1.84 acpi_machdep.c --- arch/amd64/amd64/acpi_machdep.c 4 Jul 2018 20:46:21 -0000 1.84 +++ arch/amd64/amd64/acpi_machdep.c 16 Aug 2018 21:02:48 -0000 @@ -97,7 +97,6 @@ acpi_attach(struct device *parent, struc sc->sc_iot = ba->ba_iot; sc->sc_memt = ba->ba_memt; sc->sc_dmat = &pci_bus_dma_tag; - sc->sc_pc = NULL; /* Legacy 0xcf8/0xcfc access mechanism */ acpi_attach_common(sc, ba->ba_acpipbase); } Index: arch/amd64/include/pci_machdep.h =================================================================== RCS file: /cvs/src/sys/arch/amd64/include/pci_machdep.h,v retrieving revision 1.26 diff -u -p -r1.26 pci_machdep.h --- arch/amd64/include/pci_machdep.h 4 Jul 2018 20:46:22 -0000 1.26 +++ arch/amd64/include/pci_machdep.h 16 Aug 2018 21:02:48 -0000 @@ -95,7 +95,8 @@ void pci_dev_postattach(struct device pcireg_t pci_min_powerstate(pci_chipset_tag_t, pcitag_t); void pci_set_powerstate_md(pci_chipset_tag_t, pcitag_t, int, int); -pci_chipset_tag_t pci_mcfg_init(bus_space_tag_t, bus_addr_t, int, int); +void pci_mcfg_init(bus_space_tag_t, bus_addr_t, int, int, int); +pci_chipset_tag_t pci_lookup_segment(int); /* * ALL OF THE FOLLOWING ARE MACHINE-DEPENDENT, AND SHOULD NOT BE USED Index: arch/amd64/pci/pci_machdep.c =================================================================== RCS file: /cvs/src/sys/arch/amd64/pci/pci_machdep.c,v retrieving revision 1.68 diff -u -p -r1.68 pci_machdep.c --- arch/amd64/pci/pci_machdep.c 4 Jul 2018 20:46:22 -0000 1.68 +++ arch/amd64/pci/pci_machdep.c 16 Aug 2018 21:02:48 -0000 @@ -140,14 +140,22 @@ struct bus_dma_tag pci_bus_dma_tag = { _bus_dmamem_mmap, }; -pci_chipset_tag_t -pci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int min_bus, int max_bus) +void +pci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int segment, + int min_bus, int max_bus) { - pci_mcfgt = iot; - pci_mcfg_addr = addr; - pci_mcfg_min_bus = min_bus; - pci_mcfg_max_bus = max_bus; + if (segment == 0) { + pci_mcfgt = iot; + pci_mcfg_addr = addr; + pci_mcfg_min_bus = min_bus; + pci_mcfg_max_bus = max_bus; + } +} +pci_chipset_tag_t +pci_lookup_segment(int segment) +{ + KASSERT(segment == 0); return NULL; } Index: arch/arm64/dev/acpipci.c =================================================================== RCS file: /cvs/src/sys/arch/arm64/dev/acpipci.c,v retrieving revision 1.6 diff -u -p -r1.6 acpipci.c --- arch/arm64/dev/acpipci.c 11 Aug 2018 22:47:27 -0000 1.6 +++ arch/arm64/dev/acpipci.c 16 Aug 2018 21:02:48 -0000 @@ -567,11 +567,15 @@ pci_mcfg_conf_write(void *v, pcitag_t ta bus_space_write_4(pci_mcfgt, pci_mcfgh, tag | reg, data); } -pci_chipset_tag_t -pci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int min_bus, int max_bus) +void +pci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int segment, + int min_bus, int max_bus) { pci_chipset_tag_t pc = &pci_mcfg_chipset; + if (segment != 0) + return; + pci_mcfgt = iot; pci_mcfg_addr = addr; pci_mcfg_min_bus = min_bus; @@ -588,8 +592,35 @@ pci_mcfg_init(bus_space_tag_t iot, bus_a pc->pc_conf_size = acpipci_conf_size; pc->pc_conf_read = pci_mcfg_conf_read; pc->pc_conf_write = pci_mcfg_conf_write; +} + +pcireg_t +pci_dummy_conf_read(void *v, pcitag_t tag, int reg) +{ + return 0xffffffff; +} + +void +pci_dummy_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) +{ +} + +struct arm64_pci_chipset pci_dummy_chipset = { + .pc_bus_maxdevs = acpipci_bus_maxdevs, + .pc_make_tag = acpipci_make_tag, + .pc_decompose_tag = acpipci_decompose_tag, + .pc_conf_size = acpipci_conf_size, + .pc_conf_read = pci_dummy_conf_read, + .pc_conf_write = pci_dummy_conf_write, +}; + +pci_chipset_tag_t +pci_lookup_segment(int segment) +{ + if (segment == 0) + return &pci_mcfg_chipset; - return pc; + return &pci_dummy_chipset; } /* Index: arch/i386/i386/acpi_machdep.c =================================================================== RCS file: /cvs/src/sys/arch/i386/i386/acpi_machdep.c,v retrieving revision 1.68 diff -u -p -r1.68 acpi_machdep.c --- arch/i386/i386/acpi_machdep.c 4 Jul 2018 20:46:22 -0000 1.68 +++ arch/i386/i386/acpi_machdep.c 16 Aug 2018 21:02:48 -0000 @@ -107,7 +107,6 @@ acpi_attach(struct device *parent, struc sc->sc_iot = ba->ba_iot; sc->sc_memt = ba->ba_memt; sc->sc_dmat = &pci_bus_dma_tag; - sc->sc_pc = NULL; /* Legacy 0xcf8/0xcfc access mechanism */ acpi_attach_common(sc, ba->ba_acpipbase); } Index: arch/i386/pci/pci_machdep.c =================================================================== RCS file: /cvs/src/sys/arch/i386/pci/pci_machdep.c,v retrieving revision 1.83 diff -u -p -r1.83 pci_machdep.c --- arch/i386/pci/pci_machdep.c 4 Jul 2018 20:46:22 -0000 1.83 +++ arch/i386/pci/pci_machdep.c 16 Aug 2018 21:02:48 -0000 @@ -191,14 +191,22 @@ struct bus_dma_tag pci_bus_dma_tag = { _bus_dmamem_mmap, }; -pci_chipset_tag_t -pci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int min_bus, int max_bus) +void +pci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int segment, + int min_bus, int max_bus) { - pci_mcfgt = iot; - pci_mcfg_addr = addr; - pci_mcfg_min_bus = min_bus; - pci_mcfg_max_bus = max_bus; + if (segment == 0) { + pci_mcfgt = iot; + pci_mcfg_addr = addr; + pci_mcfg_min_bus = min_bus; + pci_mcfg_max_bus = max_bus; + } +} +pci_chipset_tag_t +pci_lookup_segment(int segment) +{ + KASSERT(segment == 0); return NULL; } Index: arch/i386/pci/pci_machdep.h =================================================================== RCS file: /cvs/src/sys/arch/i386/pci/pci_machdep.h,v retrieving revision 1.29 diff -u -p -r1.29 pci_machdep.h --- arch/i386/pci/pci_machdep.h 4 Jul 2018 20:46:22 -0000 1.29 +++ arch/i386/pci/pci_machdep.h 16 Aug 2018 21:02:48 -0000 @@ -111,7 +111,8 @@ void pci_dev_postattach(struct device pcireg_t pci_min_powerstate(pci_chipset_tag_t, pcitag_t); void pci_set_powerstate_md(pci_chipset_tag_t, pcitag_t, int, int); -pci_chipset_tag_t pci_mcfg_init(bus_space_tag_t, bus_addr_t, int, int); +void pci_mcfg_init(bus_space_tag_t, bus_addr_t, int, int, int); +pci_chipset_tag_t pci_lookup_segment(int); /* * Section 6.2.4, `Miscellaneous Functions' of the PIC Specification, Index: dev/acpi/acpi.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpi.c,v retrieving revision 1.356 diff -u -p -r1.356 acpi.c --- dev/acpi/acpi.c 3 Aug 2018 22:18:13 -0000 1.356 +++ dev/acpi/acpi.c 16 Aug 2018 21:02:49 -0000 @@ -328,13 +328,6 @@ acpi_gasio(struct acpi_softc *sc, int io break; case GAS_PCI_CFG_SPACE: - /* format of address: - * bits 00..15 = register - * bits 16..31 = function - * bits 32..47 = device - * bits 48..63 = bus - */ - /* * The ACPI standard says that a function number of * FFFF can be used to refer to all functions on a @@ -349,7 +342,7 @@ acpi_gasio(struct acpi_softc *sc, int io return (0); } - pc = sc->sc_pc; + pc = pci_lookup_segment(ACPI_PCI_SEG(address)); tag = pci_make_tag(pc, ACPI_PCI_BUS(address), ACPI_PCI_DEV(address), ACPI_PCI_FN(address)); @@ -564,7 +557,7 @@ acpi_getpci(struct aml_node *node, void struct acpi_pci *pci, *ppci; struct aml_value res; struct acpi_softc *sc = arg; - pci_chipset_tag_t pc = sc->sc_pc; + pci_chipset_tag_t pc; pcitag_t tag; uint64_t val; uint32_t reg; @@ -610,6 +603,7 @@ acpi_getpci(struct aml_node *node, void return 0; pci = malloc(sizeof(*pci), M_DEVBUF, M_WAITOK|M_ZERO); + pci->seg = ppci->seg; pci->bus = ppci->sub; pci->dev = ACPI_ADR_PCIDEV(val); pci->fun = ACPI_ADR_PCIFUN(val); @@ -643,6 +637,7 @@ acpi_getpci(struct aml_node *node, void free(pci, M_DEVBUF, sizeof(*pci)); return (1); } + pc = pci_lookup_segment(pci->seg); tag = pci_make_tag(pc, pci->bus, pci->dev, pci->fun); reg = pci_conf_read(pc, tag, PCI_ID_REG); if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID) { @@ -815,7 +810,7 @@ int acpi_pci_notify(struct aml_node *node, int ntype, void *arg) { struct acpi_pci *pdev = arg; - pci_chipset_tag_t pc = acpi_softc->sc_pc; + pci_chipset_tag_t pc; pcitag_t tag; pcireg_t reg; int offset; @@ -824,6 +819,7 @@ acpi_pci_notify(struct aml_node *node, i if (ntype != 2) return (0); + pc = pci_lookup_segment(pdev->seg); tag = pci_make_tag(pc, pdev->bus, pdev->dev, pdev->fun); if (pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, 0)) { /* Clear the PME Status bit if it is set. */ Index: dev/acpi/acpimcfg.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpimcfg.c,v retrieving revision 1.3 diff -u -p -r1.3 acpimcfg.c --- dev/acpi/acpimcfg.c 4 Jul 2018 20:46:22 -0000 1.3 +++ dev/acpi/acpimcfg.c 16 Aug 2018 21:02:49 -0000 @@ -59,7 +59,6 @@ acpimcfg_match(struct device *parent, vo void acpimcfg_attach(struct device *parent, struct device *self, void *aux) { - struct acpi_softc *sc = (struct acpi_softc *)parent; struct acpi_attach_args *aaa = aux; struct acpi_mcfg *mcfg = (struct acpi_mcfg *)aaa->aaa_table; @@ -73,6 +72,6 @@ acpimcfg_attach(struct device *parent, s if (mcfg->min_bus_number == mcfg->max_bus_number) return; - sc->sc_pc = pci_mcfg_init(aaa->aaa_memt, mcfg->base_address, - mcfg->min_bus_number, mcfg->max_bus_number); + pci_mcfg_init(aaa->aaa_memt, mcfg->base_address, + mcfg->segment, mcfg->min_bus_number, mcfg->max_bus_number); } Index: dev/acpi/acpireg.h =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpireg.h,v retrieving revision 1.42 diff -u -p -r1.42 acpireg.h --- dev/acpi/acpireg.h 1 Jul 2018 10:26:17 -0000 1.42 +++ dev/acpi/acpireg.h 16 Aug 2018 21:02:49 -0000 @@ -671,11 +671,12 @@ struct acpi_ivrs { */ #define ACPI_ADR_PCIDEV(addr) (uint16_t)(addr >> 16) #define ACPI_ADR_PCIFUN(addr) (uint16_t)(addr & 0xFFFF) -#define ACPI_PCI_BUS(addr) (uint16_t)((addr) >> 48) -#define ACPI_PCI_DEV(addr) (uint16_t)((addr) >> 32) + +#define ACPI_PCI_SEG(addr) (uint16_t)((addr) >> 48) +#define ACPI_PCI_BUS(addr) (uint8_t)((addr) >> 40) +#define ACPI_PCI_DEV(addr) (uint8_t)((addr) >> 32) #define ACPI_PCI_FN(addr) (uint16_t)((addr) >> 16) #define ACPI_PCI_REG(addr) (uint16_t)(addr) -#define ACPI_PCI_ADDR(b,d,f,r) ((uint64_t)(b)<<48LL | (uint64_t)(d)<<32LL | (f)<<16LL | (r)) /* * PM1 Status Registers Fixed Hardware Feature Status Bits Index: dev/acpi/acpivar.h =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpivar.h,v retrieving revision 1.97 diff -u -p -r1.97 acpivar.h --- dev/acpi/acpivar.h 3 Aug 2018 22:18:13 -0000 1.97 +++ dev/acpi/acpivar.h 16 Aug 2018 21:02:49 -0000 @@ -209,8 +209,6 @@ struct acpi_softc { bus_space_tag_t sc_memt; bus_dma_tag_t sc_dmat; - pci_chipset_tag_t sc_pc; /* XXX assume single segment */ - /* * First-level ACPI tables */ Index: dev/acpi/dsdt.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/dsdt.c,v retrieving revision 1.242 diff -u -p -r1.242 dsdt.c --- dev/acpi/dsdt.c 29 Jun 2018 17:39:18 -0000 1.242 +++ dev/acpi/dsdt.c 16 Aug 2018 21:02:49 -0000 @@ -2303,14 +2303,21 @@ aml_rdpciaddr(struct aml_node *pcidev, u { int64_t res; + addr->bus = 0; + addr->seg = 0; if (aml_evalinteger(acpi_softc, pcidev, "_ADR", 0, NULL, &res) == 0) { addr->fun = res & 0xFFFF; addr->dev = res >> 16; } while (pcidev != NULL) { - /* HID device (PCI or PCIE root): eval _BBN */ + /* HID device (PCI or PCIE root): eval _SEG and _BBN */ if (__aml_search(pcidev, "_HID", 0)) { - if (aml_evalinteger(acpi_softc, pcidev, "_BBN", 0, NULL, &res) == 0) { + if (aml_evalinteger(acpi_softc, pcidev, "_SEG", + 0, NULL, &res) == 0) { + addr->seg = res; + } + if (aml_evalinteger(acpi_softc, pcidev, "_BBN", + 0, NULL, &res) == 0) { addr->bus = res; break; } Index: dev/acpi/dsdt.h =================================================================== RCS file: /cvs/src/sys/dev/acpi/dsdt.h,v retrieving revision 1.76 diff -u -p -r1.76 dsdt.h --- dev/acpi/dsdt.h 5 Jul 2018 19:25:38 -0000 1.76 +++ dev/acpi/dsdt.h 16 Aug 2018 21:02:49 -0000 @@ -339,8 +339,9 @@ union amlpci_t { struct { uint16_t reg; uint16_t fun; - uint16_t dev; - uint16_t bus; + uint8_t dev; + uint8_t bus; + uint16_t seg; }; }; int aml_rdpciaddr(struct aml_node *pcidev,