Here is a new version of the diff to make sure we respect the access size of pci config space reads and writes in acpi code that was backed out. This version adds some code to make sure those reads and writes are properly aligned. This should prevent the panic that some people saw with the previous diff. Apparently some AML writers think it makes perfect sense to have a region that is only 16-bit aligned but demand 32-bit access to it.
Giovanni, can you try this on that "bigio" machine? Index: acpi.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpi.c,v retrieving revision 1.291 diff -u -p -r1.291 acpi.c --- acpi.c 4 Aug 2015 15:21:59 -0000 1.291 +++ acpi.c 18 Aug 2015 21:11:05 -0000 @@ -218,6 +218,50 @@ struct acpi_softc *acpi_softc; #define acpi_bus_space_map _bus_space_map #define acpi_bus_space_unmap _bus_space_unmap +uint8_t +acpi_pci_conf_read_1(pci_chipset_tag_t pc, pcitag_t tag, int reg) +{ + uint32_t val = pci_conf_read(pc, tag, reg & ~0x3); + return (val >> ((reg & 0x3) << 3)); +} + +uint16_t +acpi_pci_conf_read_2(pci_chipset_tag_t pc, pcitag_t tag, int reg) +{ + uint32_t val = pci_conf_read(pc, tag, reg & ~0x2); + return (val >> ((reg & 0x2) << 3)); +} + +uint32_t +acpi_pci_conf_read_4(pci_chipset_tag_t pc, pcitag_t tag, int reg) +{ + return pci_conf_read(pc, tag, reg); +} + +void +acpi_pci_conf_write_1(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint8_t val) +{ + uint32_t tmp = pci_conf_read(pc, tag, reg & ~0x3); + tmp &= ~(0xff << ((reg & 0x3) << 3)); + tmp |= (val << ((reg & 0x3) << 3)); + pci_conf_write(pc, tag, reg & ~0x3, tmp); +} + +void +acpi_pci_conf_write_2(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint16_t val) +{ + uint32_t tmp = pci_conf_read(pc, tag, reg & ~0x2); + tmp &= ~(0xffff << ((reg & 0x2) << 3)); + tmp |= (val << ((reg & 0x2) << 3)); + pci_conf_write(pc, tag, reg & ~0x2, tmp); +} + +void +acpi_pci_conf_write_4(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint32_t val) +{ + pci_conf_write(pc, tag, reg, val); +} + int acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address, int access_size, int len, void *buffer) @@ -227,7 +271,7 @@ acpi_gasio(struct acpi_softc *sc, int io bus_space_handle_t ioh; pci_chipset_tag_t pc; pcitag_t tag; - int reg, idx, ival, sval; + int reg, idx; dnprintf(50, "gasio: %.2x 0x%.8llx %s\n", iospace, address, (iodir == ACPI_IOWRITE) ? "write" : "read"); @@ -326,19 +370,47 @@ acpi_gasio(struct acpi_softc *sc, int io ACPI_PCI_BUS(address), ACPI_PCI_DEV(address), ACPI_PCI_FN(address)); - /* XXX: This is ugly. read-modify-write does a byte at a time */ reg = ACPI_PCI_REG(address); - for (idx = reg; idx < reg+len; idx++) { - ival = pci_conf_read(pc, tag, idx & ~0x3); + for (idx = 0; idx < len; idx += access_size) { if (iodir == ACPI_IOREAD) { - *pb = ival >> (8 * (idx & 0x3)); + switch (access_size) { + case 1: + *(uint8_t *)(pb + idx) = + acpi_pci_conf_read_1(pc, tag, reg + idx); + break; + case 2: + *(uint16_t *)(pb + idx) = + acpi_pci_conf_read_2(pc, tag, reg + idx); + break; + case 4: + *(uint32_t *)(pb + idx) = + acpi_pci_conf_read_4(pc, tag, reg + idx); + break; + default: + printf("%s: rdcfg: invalid size %d\n", + DEVNAME(sc), access_size); + return (-1); + } } else { - sval = *pb; - ival &= ~(0xFF << (8* (idx & 0x3))); - ival |= sval << (8* (idx & 0x3)); - pci_conf_write(pc, tag, idx & ~0x3, ival); + switch (access_size) { + case 1: + acpi_pci_conf_write_1(pc, tag, reg + idx, + *(uint8_t *)(pb + idx)); + break; + case 2: + acpi_pci_conf_write_2(pc, tag, reg + idx, + *(uint16_t *)(pb + idx)); + break; + case 4: + acpi_pci_conf_write_4(pc, tag, reg + idx, + *(uint32_t *)(pb + idx)); + break; + default: + printf("%s: wrcfg: invalid size %d\n", + DEVNAME(sc), access_size); + return (-1); + } } - pb++; } break; Index: dsdt.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/dsdt.c,v retrieving revision 1.217 diff -u -p -r1.217 dsdt.c --- dsdt.c 4 May 2015 10:42:06 -0000 1.217 +++ dsdt.c 18 Aug 2015 21:11:05 -0000 @@ -2260,7 +2260,8 @@ aml_rwgas(struct aml_value *rgn, int bpo break; } - pi.addr = rgn->v_opregion.iobase + ((bpos >> 3) & ~(sz - 1)); + pi.addr = (rgn->v_opregion.iobase + (bpos >> 3)) & ~(sz - 1); + bpos += ((rgn->v_opregion.iobase & (sz - 1)) << 3); bpos &= ((sz << 3) - 1); if (rgn->v_opregion.iospace == GAS_PCI_CFG_SPACE) {