From 3f9fa059d728aa84a279591b28ace3f492381d74 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 23 Sep 2009 15:42:35 +0000 Subject: Extract the code to find and map the MADT ACPI table during early kernel startup and genericize it so it can be reused to map other tables as well: - Add a routine to walk a list of ACPI subtables such as those used in the APIC and SRAT tables in the MI acpi(4) driver. - Move the routines for mapping and unmapping an ACPI table as well as mapping the RSDT or XSDT and searching for a table with a given signature out into acpica_machdep.c for both amd64 and i386. --- sys/i386/acpica/madt.c | 232 +++---------------------------------------------- 1 file changed, 10 insertions(+), 222 deletions(-) (limited to 'sys/i386/acpica/madt.c') diff --git a/sys/i386/acpica/madt.c b/sys/i386/acpica/madt.c index f9756ec..114fbc7 100644 --- a/sys/i386/acpica/madt.c +++ b/sys/i386/acpica/madt.c @@ -36,27 +36,19 @@ __FBSDID("$FreeBSD$"); #include #include #include - #include -#include #include #include -#include #include #include -#include -#include #include -#include #include #include #include -typedef void madt_entry_handler(ACPI_SUBTABLE_HEADER *entry, void *arg); - /* These two arrays are indexed by APIC IDs. */ struct ioapic_info { void *io_apic; @@ -79,8 +71,6 @@ static enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source); static enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source); static int madt_find_cpu(u_int acpi_id, u_int *apic_id); static int madt_find_interrupt(int intr, void **apic, u_int *pin); -static void *madt_map(vm_paddr_t pa, int offset, vm_offset_t length); -static void *madt_map_table(vm_paddr_t pa, int offset, const char *sig); static void madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg); static void madt_parse_interrupt_override( ACPI_MADT_INTERRUPT_OVERRIDE *intr); @@ -92,13 +82,10 @@ static int madt_probe(void); static int madt_probe_cpus(void); static void madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg __unused); -static int madt_probe_table(vm_paddr_t address); static void madt_register(void *dummy); static int madt_setup_local(void); static int madt_setup_io(void); -static void madt_unmap(void *data, vm_offset_t length); -static void madt_unmap_table(void *table); -static void madt_walk_table(madt_entry_handler *handler, void *arg); +static void madt_walk_table(acpi_subtable_handler *handler, void *arg); static struct apic_enumerator madt_enumerator = { "MADT", @@ -108,87 +95,6 @@ static struct apic_enumerator madt_enumerator = { madt_setup_io }; -/* - * 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: 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) -{ - vm_offset_t va, off; - void *data; - - off = pa & PAGE_MASK; - length = roundup(length + off, PAGE_SIZE); - pa = pa & PG_FRAME; - va = (vm_offset_t)pmap_kenter_temporary(pa, offset) + - (offset * PAGE_SIZE); - data = (void *)(va + off); - length -= PAGE_SIZE; - while (length > 0) { - va += PAGE_SIZE; - pa += PAGE_SIZE; - length -= PAGE_SIZE; - pmap_kenter(va, pa); - invlpg(va); - } - return (data); -} - -static void -madt_unmap(void *data, vm_offset_t length) -{ - vm_offset_t va, off; - - va = (vm_offset_t)data; - off = va & PAGE_MASK; - length = roundup(length + off, PAGE_SIZE); - va &= ~PAGE_MASK; - while (length > 0) { - pmap_kremove(va); - invlpg(va); - va += PAGE_SIZE; - length -= PAGE_SIZE; - } -} - -static void * -madt_map_table(vm_paddr_t pa, int offset, const char *sig) -{ - ACPI_TABLE_HEADER *header; - vm_offset_t length; - void *table; - - header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER)); - if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 0) { - madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); - return (NULL); - } - length = header->Length; - madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); - table = madt_map(pa, offset, length); - if (ACPI_FAILURE(AcpiTbChecksum(table, length))) { - if (bootverbose) - printf("MADT: Failed checksum for table %s\n", sig); - madt_unmap(table, length); - return (NULL); - } - return (table); -} - -static void -madt_unmap_table(void *table) -{ - ACPI_TABLE_HEADER *header; - - header = (ACPI_TABLE_HEADER *)table; - madt_unmap(table, header->Length); -} /* * Look for an ACPI Multiple APIC Description Table ("APIC") @@ -196,137 +102,25 @@ madt_unmap_table(void *table) static int madt_probe(void) { - ACPI_PHYSICAL_ADDRESS rsdp_ptr; - ACPI_TABLE_RSDP *rsdp; - ACPI_TABLE_RSDT *rsdt; - ACPI_TABLE_XSDT *xsdt; - int i, count; - - if (resource_disabled("acpi", 0)) - return (ENXIO); - - /* - * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn - * calls pmap_mapbios() to find the RSDP, we assume that we can use - * pmap_mapbios() to map the RSDP. - */ - if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0) - return (ENXIO); - rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP)); - if (rsdp == NULL) { - if (bootverbose) - printf("MADT: Failed to map RSDP\n"); - return (ENXIO); - } - - /* - * For ACPI >= 2.0, use the XSDT if it is available. - * Otherwise, use the RSDT. We map the XSDT or RSDT at page 1 - * in the crashdump area. Page 0 is used to map in the - * headers of candidate ACPI tables. - */ - if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) { - /* - * AcpiOsGetRootPointer only verifies the checksum for - * the version 1.0 portion of the RSDP. Version 2.0 has - * an additional checksum that we verify first. - */ - if (AcpiTbChecksum((UINT8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) { - if (bootverbose) - printf("MADT: RSDP failed extended checksum\n"); - return (ENXIO); - } - xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 2, - ACPI_SIG_XSDT); - if (xsdt == NULL) { - if (bootverbose) - printf("MADT: Failed to map XSDT\n"); - return (ENXIO); - } - count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / - sizeof(UINT64); - for (i = 0; i < count; i++) - if (madt_probe_table(xsdt->TableOffsetEntry[i])) - break; - madt_unmap_table(xsdt); - } else { - rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 2, - ACPI_SIG_RSDT); - if (rsdt == NULL) { - if (bootverbose) - printf("MADT: Failed to map RSDT\n"); - return (ENXIO); - } - count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / - sizeof(UINT32); - for (i = 0; i < count; i++) - if (madt_probe_table(rsdt->TableOffsetEntry[i])) - break; - madt_unmap_table(rsdt); - } - pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP)); - if (madt_physaddr == 0) { - if (bootverbose) - printf("MADT: No MADT table found\n"); - return (ENXIO); - } - if (bootverbose) - printf("MADT: Found table at 0x%jx\n", - (uintmax_t)madt_physaddr); - /* - * Verify that we can map the full table and that its checksum is - * correct, etc. - */ - madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT); - if (madt == NULL) + madt_physaddr = acpi_find_table(ACPI_SIG_MADT); + if (madt_physaddr == 0) return (ENXIO); - madt_unmap_table(madt); - madt = NULL; - return (0); } /* - * See if a given ACPI table is the MADT. - */ -static int -madt_probe_table(vm_paddr_t address) -{ - ACPI_TABLE_HEADER *table; - - table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER)); - if (table == NULL) { - if (bootverbose) - printf("MADT: Failed to map table at 0x%jx\n", - (uintmax_t)address); - return (0); - } - if (bootverbose) - printf("Table '%.4s' at 0x%jx\n", table->Signature, - (uintmax_t)address); - - if (strncmp(table->Signature, ACPI_SIG_MADT, ACPI_NAME_SIZE) != 0) { - madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); - return (0); - } - madt_physaddr = address; - madt_length = table->Length; - madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); - return (1); -} - -/* * Run through the MP table enumerating CPUs. */ static int madt_probe_cpus(void) { - madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT); + madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT); + madt_length = madt->Header.Length; KASSERT(madt != NULL, ("Unable to re-map MADT")); madt_walk_table(madt_probe_cpus_handler, NULL); - madt_unmap_table(madt); + acpi_unmap_table(madt); madt = NULL; return (0); } @@ -416,17 +210,11 @@ SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_SECOND, madt_register, NULL); * Call the handler routine for each entry in the MADT table. */ static void -madt_walk_table(madt_entry_handler *handler, void *arg) +madt_walk_table(acpi_subtable_handler *handler, void *arg) { - ACPI_SUBTABLE_HEADER *entry; - u_char *p, *end; - - end = (u_char *)(madt) + madt->Header.Length; - for (p = (u_char *)(madt + 1); p < end; ) { - entry = (ACPI_SUBTABLE_HEADER *)p; - handler(entry, arg); - p += entry->Length; - } + + acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, + handler, arg); } static void -- cgit v1.1