From 7157eae462b94ce5305a9d2611be2ecb6b8f917d Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 31 Jan 2008 16:51:43 +0000 Subject: [PATCH] For no good reason I had assumed that ACPI table headers would be page aligned (or at least not cross a page boundary). However, it turns out that on at least one machine one table header does cross a page boundary. This caused problems with the MADT early probe as it uses the crash dump map to load ACPI tables by loading the RSDT/XSDT into pages 1 ... N and loading the header of each ACPI table header into page 0 looking for the MADT. However, if a table header crossed a page boundary, then page 1 would get trashed resulting in a panic. Fix this by reserving the first 2 pages for ACPI table headers (headers are less than a page in size, so 2 pages will be sufficient) and use pages 2 .. N for the RSDT and XSDT. Note: amd64 should probably be simplified to just use pmap_mapbios() for all these tables which will use the direct map and not need the crash dump hack. MFC after: 5 days Tested on: i386 Reported by: Pete French petefrench of ticketswitch.com --- sys/amd64/acpica/madt.c | 12 +++++++----- sys/i386/acpica/madt.c | 12 +++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/sys/amd64/acpica/madt.c b/sys/amd64/acpica/madt.c index fcd40c8ad70b..3ed1ea703db0 100644 --- a/sys/amd64/acpica/madt.c +++ b/sys/amd64/acpica/madt.c @@ -109,9 +109,11 @@ static struct apic_enumerator madt_enumerator = { /* * Code to abuse the crashdump map to map in the tables for the early * probe. We cheat and make the following assumptions about how we - * use this KVA: page 0 is used to map in the first page of each table - * found via the RSDT or XSDT and pages 1 to n are used to map in the - * RSDT or XSDT. The offset is in pages; the length is in bytes. + * use this KVA: pages 0 and 1 are used to map in the header of each + * table found via the RSDT or XSDT and pages 2 to n are used to map + * in the RSDT or XSDT. We have to use 2 pages for the table headers + * in case a header spans a page boundary. The offset is in pages; + * the length is in bytes. */ static void * madt_map(vm_paddr_t pa, int offset, vm_offset_t length) @@ -232,7 +234,7 @@ madt_probe(void) printf("MADT: RSDP failed extended checksum\n"); return (ENXIO); } - xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, + xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 2, ACPI_SIG_XSDT); if (xsdt == NULL) { if (bootverbose) @@ -246,7 +248,7 @@ madt_probe(void) break; madt_unmap_table(xsdt); } else { - rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, + rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 2, ACPI_SIG_RSDT); if (rsdt == NULL) { if (bootverbose) diff --git a/sys/i386/acpica/madt.c b/sys/i386/acpica/madt.c index b0eadcabdfee..f00a3db962a3 100644 --- a/sys/i386/acpica/madt.c +++ b/sys/i386/acpica/madt.c @@ -109,9 +109,11 @@ static struct apic_enumerator madt_enumerator = { /* * Code to abuse the crashdump map to map in the tables for the early * probe. We cheat and make the following assumptions about how we - * use this KVA: page 0 is used to map in the first page of each table - * found via the RSDT or XSDT and pages 1 to n are used to map in the - * RSDT or XSDT. The offset is in pages; the length is in bytes. + * use this KVA: pages 0 and 1 are used to map in the header of each + * table found via the RSDT or XSDT and pages 2 to n are used to map + * in the RSDT or XSDT. We have to use 2 pages for the table headers + * in case a header spans a page boundary. The offset is in pages; + * the length is in bytes. */ static void * madt_map(vm_paddr_t pa, int offset, vm_offset_t length) @@ -232,7 +234,7 @@ madt_probe(void) printf("MADT: RSDP failed extended checksum\n"); return (ENXIO); } - xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, + xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 2, ACPI_SIG_XSDT); if (xsdt == NULL) { if (bootverbose) @@ -246,7 +248,7 @@ madt_probe(void) break; madt_unmap_table(xsdt); } else { - rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, + rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 2, ACPI_SIG_RSDT); if (rsdt == NULL) { if (bootverbose)