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,