Date: Thu, 20 Aug 2020 00:52:54 +0000 (UTC) From: Mark Johnston <markj@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r364411 - in head/sys: amd64/acpica i386/acpica Message-ID: <202008200052.07K0qsrO000721@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: markj Date: Thu Aug 20 00:52:53 2020 New Revision: 364411 URL: https://svnweb.freebsd.org/changeset/base/364411 Log: Use pmap_mapbios() to map ACPI tables on amd64 and i386. The ACPI table-mapping code used pmap_kenter_temporary() to create mappings, which in turn uses the fixed-size crashdump map. Moreover, the code was not verifying that the table fits in this map, so when mapping large tables we could clobber adjacent mappings. This use of pmap_kenter_temporary() appears to predate support in pmap_mapbios() for creating early mappings, but that restriction no longer applies. PR: 248746 Reviewed by: kib, mav Tested by: gallatin, Curtis Villamizar <curtis@ipv6.occnc.com> MFC after: 3 days Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D26125 Modified: head/sys/amd64/acpica/acpi_machdep.c head/sys/i386/acpica/acpi_machdep.c Modified: head/sys/amd64/acpica/acpi_machdep.c ============================================================================== --- head/sys/amd64/acpica/acpi_machdep.c Thu Aug 20 00:38:32 2020 (r364410) +++ head/sys/amd64/acpica/acpi_machdep.c Thu Aug 20 00:52:53 2020 (r364411) @@ -91,91 +91,29 @@ acpi_machdep_quirks(int *quirks) } /* - * Support for mapping ACPI tables during early boot. Currently this - * uses the crashdump map to map each table. However, the crashdump - * map is created in pmap_bootstrap() right after the direct map, so - * we should be able to just use pmap_mapbios() here instead. - * - * This makes 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. This has to use 2 pages for the table headers in case a - * header spans a page boundary. - * - * XXX: We don't ensure the table fits in the available address space - * in the crashdump map. + * Map a table. First map the header to determine the table length and then map + * the entire table. */ - -/* - * Map some memory using the crashdump map. 'offset' is an offset in - * pages into the crashdump map to use for the start of the mapping. - */ static void * -table_map(vm_paddr_t pa, int offset, vm_offset_t length) +map_table(vm_paddr_t pa, const char *sig) { - vm_offset_t va, off; - void *data; - - off = pa & PAGE_MASK; - length = round_page(length + off); - 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); -} - -/* Unmap memory previously mapped with table_map(). */ -static void -table_unmap(void *data, vm_offset_t length) -{ - vm_offset_t va, off; - - va = (vm_offset_t)data; - off = va & PAGE_MASK; - length = round_page(length + off); - va &= ~PAGE_MASK; - while (length > 0) { - pmap_kremove(va); - invlpg(va); - va += PAGE_SIZE; - length -= PAGE_SIZE; - } -} - -/* - * Map a table at a given offset into the crashdump map. It first - * maps the header to determine the table length and then maps the - * entire table. - */ -static void * -map_table(vm_paddr_t pa, int offset, const char *sig) -{ ACPI_TABLE_HEADER *header; vm_offset_t length; void *table; - header = table_map(pa, offset, sizeof(ACPI_TABLE_HEADER)); + header = pmap_mapbios(pa, sizeof(ACPI_TABLE_HEADER)); if (strncmp(header->Signature, sig, ACPI_NAMESEG_SIZE) != 0) { - table_unmap(header, sizeof(ACPI_TABLE_HEADER)); + pmap_unmapbios((vm_offset_t)header, sizeof(ACPI_TABLE_HEADER)); return (NULL); } length = header->Length; - table_unmap(header, sizeof(ACPI_TABLE_HEADER)); - table = table_map(pa, offset, length); + pmap_unmapbios((vm_offset_t)header, sizeof(ACPI_TABLE_HEADER)); + table = pmap_mapbios(pa, length); if (ACPI_FAILURE(AcpiTbChecksum(table, length))) { if (bootverbose) printf("ACPI: Failed checksum for table %s\n", sig); #if (ACPI_CHECKSUM_ABORT) - table_unmap(table, length); + pmap_unmapbios((vm_offset_t)table, length); return (NULL); #endif } @@ -190,21 +128,12 @@ static int probe_table(vm_paddr_t address, const char *sig) { ACPI_TABLE_HEADER *table; + int ret; - table = table_map(address, 0, sizeof(ACPI_TABLE_HEADER)); - if (table == NULL) { - if (bootverbose) - printf("ACPI: Failed to map table at 0x%jx\n", - (uintmax_t)address); - return (0); - } - - if (strncmp(table->Signature, sig, ACPI_NAMESEG_SIZE) != 0) { - table_unmap(table, sizeof(ACPI_TABLE_HEADER)); - return (0); - } - table_unmap(table, sizeof(ACPI_TABLE_HEADER)); - return (1); + table = pmap_mapbios(address, sizeof(ACPI_TABLE_HEADER)); + ret = strncmp(table->Signature, sig, ACPI_NAMESEG_SIZE) == 0; + pmap_unmapbios((vm_offset_t)table, sizeof(ACPI_TABLE_HEADER)); + return (ret); } /* @@ -215,7 +144,7 @@ void * acpi_map_table(vm_paddr_t pa, const char *sig) { - return (map_table(pa, 0, sig)); + return (map_table(pa, sig)); } /* Unmap a table previously mapped via acpi_map_table(). */ @@ -225,7 +154,7 @@ acpi_unmap_table(void *table) ACPI_TABLE_HEADER *header; header = (ACPI_TABLE_HEADER *)table; - table_unmap(table, header->Length); + pmap_unmapbios((vm_offset_t)table, header->Length); } /* @@ -262,9 +191,7 @@ acpi_find_table(const char *sig) /* * For ACPI >= 2.0, use the XSDT if it is available. - * Otherwise, use the RSDT. We map the XSDT or RSDT at page 2 - * in the crashdump area. Pages 0 and 1 are used to map in the - * headers of candidate ACPI tables. + * Otherwise, use the RSDT. */ addr = 0; if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) { @@ -278,7 +205,7 @@ acpi_find_table(const char *sig) printf("ACPI: RSDP failed extended checksum\n"); return (0); } - xsdt = map_table(rsdp->XsdtPhysicalAddress, 2, ACPI_SIG_XSDT); + xsdt = map_table(rsdp->XsdtPhysicalAddress, ACPI_SIG_XSDT); if (xsdt == NULL) { if (bootverbose) printf("ACPI: Failed to map XSDT\n"); @@ -293,7 +220,7 @@ acpi_find_table(const char *sig) } acpi_unmap_table(xsdt); } else { - rsdt = map_table(rsdp->RsdtPhysicalAddress, 2, ACPI_SIG_RSDT); + rsdt = map_table(rsdp->RsdtPhysicalAddress, ACPI_SIG_RSDT); if (rsdt == NULL) { if (bootverbose) printf("ACPI: Failed to map RSDT\n"); @@ -316,7 +243,7 @@ acpi_find_table(const char *sig) * Verify that we can map the full table and that its checksum is * correct, etc. */ - table = map_table(addr, 0, sig); + table = map_table(addr, sig); if (table == NULL) return (0); acpi_unmap_table(table); Modified: head/sys/i386/acpica/acpi_machdep.c ============================================================================== --- head/sys/i386/acpica/acpi_machdep.c Thu Aug 20 00:38:32 2020 (r364410) +++ head/sys/i386/acpica/acpi_machdep.c Thu Aug 20 00:52:53 2020 (r364411) @@ -109,89 +109,29 @@ acpi_machdep_quirks(int *quirks) } /* - * Support for mapping ACPI tables during early boot. This abuses the - * crashdump map because the kernel cannot allocate KVA in - * pmap_mapbios() when this is used. This makes 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. This has to use - * 2 pages for the table headers in case a header spans a page - * boundary. - * - * XXX: We don't ensure the table fits in the available address space - * in the crashdump map. + * Map a table. First map the header to determine the table length and then map + * the entire table. */ - -/* - * Map some memory using the crashdump map. 'offset' is an offset in - * pages into the crashdump map to use for the start of the mapping. - */ static void * -table_map(vm_paddr_t pa, int offset, vm_offset_t length) +map_table(vm_paddr_t pa, const char *sig) { - vm_offset_t va, off; - void *data; - - off = pa & PAGE_MASK; - length = round_page(length + off); - pa = pmap_pg_frame(pa); - 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); -} - -/* Unmap memory previously mapped with table_map(). */ -static void -table_unmap(void *data, vm_offset_t length) -{ - vm_offset_t va, off; - - va = (vm_offset_t)data; - off = va & PAGE_MASK; - length = round_page(length + off); - va &= ~PAGE_MASK; - while (length > 0) { - pmap_kremove(va); - invlpg(va); - va += PAGE_SIZE; - length -= PAGE_SIZE; - } -} - -/* - * Map a table at a given offset into the crashdump map. It first - * maps the header to determine the table length and then maps the - * entire table. - */ -static void * -map_table(vm_paddr_t pa, int offset, const char *sig) -{ ACPI_TABLE_HEADER *header; vm_offset_t length; void *table; - header = table_map(pa, offset, sizeof(ACPI_TABLE_HEADER)); + header = pmap_mapbios(pa, sizeof(ACPI_TABLE_HEADER)); if (strncmp(header->Signature, sig, ACPI_NAMESEG_SIZE) != 0) { - table_unmap(header, sizeof(ACPI_TABLE_HEADER)); + pmap_unmapbios((vm_offset_t)header, sizeof(ACPI_TABLE_HEADER)); return (NULL); } length = header->Length; - table_unmap(header, sizeof(ACPI_TABLE_HEADER)); - table = table_map(pa, offset, length); + pmap_unmapbios((vm_offset_t)header, sizeof(ACPI_TABLE_HEADER)); + table = pmap_mapbios(pa, length); if (ACPI_FAILURE(AcpiTbChecksum(table, length))) { if (bootverbose) printf("ACPI: Failed checksum for table %s\n", sig); #if (ACPI_CHECKSUM_ABORT) - table_unmap(table, length); + pmap_unmapbios((vm_offset_t)table, length); return (NULL); #endif } @@ -206,21 +146,12 @@ static int probe_table(vm_paddr_t address, const char *sig) { ACPI_TABLE_HEADER *table; + int ret; - table = table_map(address, 0, sizeof(ACPI_TABLE_HEADER)); - if (table == NULL) { - if (bootverbose) - printf("ACPI: Failed to map table at 0x%jx\n", - (uintmax_t)address); - return (0); - } - - if (strncmp(table->Signature, sig, ACPI_NAMESEG_SIZE) != 0) { - table_unmap(table, sizeof(ACPI_TABLE_HEADER)); - return (0); - } - table_unmap(table, sizeof(ACPI_TABLE_HEADER)); - return (1); + table = pmap_mapbios(address, sizeof(ACPI_TABLE_HEADER)); + ret = strncmp(table->Signature, sig, ACPI_NAMESEG_SIZE) == 0; + pmap_unmapbios((vm_offset_t)table, sizeof(ACPI_TABLE_HEADER)); + return (ret); } /* @@ -231,7 +162,7 @@ void * acpi_map_table(vm_paddr_t pa, const char *sig) { - return (map_table(pa, 0, sig)); + return (map_table(pa, sig)); } /* Unmap a table previously mapped via acpi_map_table(). */ @@ -241,7 +172,7 @@ acpi_unmap_table(void *table) ACPI_TABLE_HEADER *header; header = (ACPI_TABLE_HEADER *)table; - table_unmap(table, header->Length); + pmap_unmapbios((vm_offset_t)table, header->Length); } /* @@ -278,9 +209,7 @@ acpi_find_table(const char *sig) /* * For ACPI >= 2.0, use the XSDT if it is available. - * Otherwise, use the RSDT. We map the XSDT or RSDT at page 2 - * in the crashdump area. Pages 0 and 1 are used to map in the - * headers of candidate ACPI tables. + * Otherwise, use the RSDT. */ addr = 0; if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) { @@ -294,7 +223,7 @@ acpi_find_table(const char *sig) printf("ACPI: RSDP failed extended checksum\n"); return (0); } - xsdt = map_table(rsdp->XsdtPhysicalAddress, 2, ACPI_SIG_XSDT); + xsdt = map_table(rsdp->XsdtPhysicalAddress, ACPI_SIG_XSDT); if (xsdt == NULL) { if (bootverbose) printf("ACPI: Failed to map XSDT\n"); @@ -309,7 +238,7 @@ acpi_find_table(const char *sig) } acpi_unmap_table(xsdt); } else { - rsdt = map_table(rsdp->RsdtPhysicalAddress, 2, ACPI_SIG_RSDT); + rsdt = map_table(rsdp->RsdtPhysicalAddress, ACPI_SIG_RSDT); if (rsdt == NULL) { if (bootverbose) printf("ACPI: Failed to map RSDT\n"); @@ -332,7 +261,7 @@ acpi_find_table(const char *sig) * Verify that we can map the full table and that its checksum is * correct, etc. */ - table = map_table(addr, 0, sig); + table = map_table(addr, sig); if (table == NULL) return (0); acpi_unmap_table(table);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202008200052.07K0qsrO000721>