| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * boot.c - Architecture-Specific Low-Level ACPI Boot Support |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> |
|---|
| 5 | 6 | * Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com> |
|---|
| 6 | | - * |
|---|
| 7 | | - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 10 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 11 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 12 | | - * (at your option) any later version. |
|---|
| 13 | | - * |
|---|
| 14 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 15 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 16 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 17 | | - * GNU General Public License for more details. |
|---|
| 18 | | - * |
|---|
| 19 | | - * You should have received a copy of the GNU General Public License |
|---|
| 20 | | - * along with this program; if not, write to the Free Software |
|---|
| 21 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 22 | | - * |
|---|
| 23 | | - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 24 | 7 | */ |
|---|
| 25 | 8 | |
|---|
| 26 | 9 | #include <linux/init.h> |
|---|
| .. | .. |
|---|
| 32 | 15 | #include <linux/dmi.h> |
|---|
| 33 | 16 | #include <linux/irq.h> |
|---|
| 34 | 17 | #include <linux/slab.h> |
|---|
| 35 | | -#include <linux/bootmem.h> |
|---|
| 18 | +#include <linux/memblock.h> |
|---|
| 36 | 19 | #include <linux/ioport.h> |
|---|
| 37 | 20 | #include <linux/pci.h> |
|---|
| 38 | 21 | #include <linux/efi-bgrt.h> |
|---|
| 39 | 22 | #include <linux/serial_core.h> |
|---|
| 23 | +#include <linux/pgtable.h> |
|---|
| 40 | 24 | |
|---|
| 41 | 25 | #include <asm/e820/api.h> |
|---|
| 42 | 26 | #include <asm/irqdomain.h> |
|---|
| 43 | 27 | #include <asm/pci_x86.h> |
|---|
| 44 | | -#include <asm/pgtable.h> |
|---|
| 45 | 28 | #include <asm/io_apic.h> |
|---|
| 46 | 29 | #include <asm/apic.h> |
|---|
| 47 | 30 | #include <asm/io.h> |
|---|
| 48 | 31 | #include <asm/mpspec.h> |
|---|
| 49 | 32 | #include <asm/smp.h> |
|---|
| 50 | 33 | #include <asm/i8259.h> |
|---|
| 34 | +#include <asm/setup.h> |
|---|
| 51 | 35 | |
|---|
| 52 | 36 | #include "sleep.h" /* To include x86_acpi_suspend_lowlevel */ |
|---|
| 53 | 37 | static int __initdata acpi_force = 0; |
|---|
| .. | .. |
|---|
| 61 | 45 | #define PREFIX "ACPI: " |
|---|
| 62 | 46 | |
|---|
| 63 | 47 | int acpi_noirq; /* skip ACPI IRQ initialization */ |
|---|
| 48 | +static int acpi_nobgrt; /* skip ACPI BGRT */ |
|---|
| 64 | 49 | int acpi_pci_disabled; /* skip ACPI PCI scan and IRQ initialization */ |
|---|
| 65 | 50 | EXPORT_SYMBOL(acpi_pci_disabled); |
|---|
| 66 | 51 | |
|---|
| .. | .. |
|---|
| 196 | 181 | } |
|---|
| 197 | 182 | |
|---|
| 198 | 183 | static int __init |
|---|
| 199 | | -acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end) |
|---|
| 184 | +acpi_parse_x2apic(union acpi_subtable_headers *header, const unsigned long end) |
|---|
| 200 | 185 | { |
|---|
| 201 | 186 | struct acpi_madt_local_x2apic *processor = NULL; |
|---|
| 202 | 187 | #ifdef CONFIG_X86_X2APIC |
|---|
| .. | .. |
|---|
| 209 | 194 | if (BAD_MADT_ENTRY(processor, end)) |
|---|
| 210 | 195 | return -EINVAL; |
|---|
| 211 | 196 | |
|---|
| 212 | | - acpi_table_print_madt_entry(header); |
|---|
| 197 | + acpi_table_print_madt_entry(&header->common); |
|---|
| 213 | 198 | |
|---|
| 214 | 199 | #ifdef CONFIG_X86_X2APIC |
|---|
| 215 | 200 | apic_id = processor->local_apic_id; |
|---|
| .. | .. |
|---|
| 241 | 226 | } |
|---|
| 242 | 227 | |
|---|
| 243 | 228 | static int __init |
|---|
| 244 | | -acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end) |
|---|
| 229 | +acpi_parse_lapic(union acpi_subtable_headers * header, const unsigned long end) |
|---|
| 245 | 230 | { |
|---|
| 246 | 231 | struct acpi_madt_local_apic *processor = NULL; |
|---|
| 247 | 232 | |
|---|
| .. | .. |
|---|
| 250 | 235 | if (BAD_MADT_ENTRY(processor, end)) |
|---|
| 251 | 236 | return -EINVAL; |
|---|
| 252 | 237 | |
|---|
| 253 | | - acpi_table_print_madt_entry(header); |
|---|
| 238 | + acpi_table_print_madt_entry(&header->common); |
|---|
| 254 | 239 | |
|---|
| 255 | 240 | /* Ignore invalid ID */ |
|---|
| 256 | 241 | if (processor->id == 0xff) |
|---|
| .. | .. |
|---|
| 271 | 256 | } |
|---|
| 272 | 257 | |
|---|
| 273 | 258 | static int __init |
|---|
| 274 | | -acpi_parse_sapic(struct acpi_subtable_header *header, const unsigned long end) |
|---|
| 259 | +acpi_parse_sapic(union acpi_subtable_headers *header, const unsigned long end) |
|---|
| 275 | 260 | { |
|---|
| 276 | 261 | struct acpi_madt_local_sapic *processor = NULL; |
|---|
| 277 | 262 | |
|---|
| .. | .. |
|---|
| 280 | 265 | if (BAD_MADT_ENTRY(processor, end)) |
|---|
| 281 | 266 | return -EINVAL; |
|---|
| 282 | 267 | |
|---|
| 283 | | - acpi_table_print_madt_entry(header); |
|---|
| 268 | + acpi_table_print_madt_entry(&header->common); |
|---|
| 284 | 269 | |
|---|
| 285 | 270 | acpi_register_lapic((processor->id << 8) | processor->eid,/* APIC ID */ |
|---|
| 286 | 271 | processor->processor_id, /* ACPI ID */ |
|---|
| .. | .. |
|---|
| 290 | 275 | } |
|---|
| 291 | 276 | |
|---|
| 292 | 277 | static int __init |
|---|
| 293 | | -acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header, |
|---|
| 278 | +acpi_parse_lapic_addr_ovr(union acpi_subtable_headers * header, |
|---|
| 294 | 279 | const unsigned long end) |
|---|
| 295 | 280 | { |
|---|
| 296 | 281 | struct acpi_madt_local_apic_override *lapic_addr_ovr = NULL; |
|---|
| .. | .. |
|---|
| 300 | 285 | if (BAD_MADT_ENTRY(lapic_addr_ovr, end)) |
|---|
| 301 | 286 | return -EINVAL; |
|---|
| 302 | 287 | |
|---|
| 303 | | - acpi_table_print_madt_entry(header); |
|---|
| 288 | + acpi_table_print_madt_entry(&header->common); |
|---|
| 304 | 289 | |
|---|
| 305 | 290 | acpi_lapic_addr = lapic_addr_ovr->address; |
|---|
| 306 | 291 | |
|---|
| .. | .. |
|---|
| 308 | 293 | } |
|---|
| 309 | 294 | |
|---|
| 310 | 295 | static int __init |
|---|
| 311 | | -acpi_parse_x2apic_nmi(struct acpi_subtable_header *header, |
|---|
| 296 | +acpi_parse_x2apic_nmi(union acpi_subtable_headers *header, |
|---|
| 312 | 297 | const unsigned long end) |
|---|
| 313 | 298 | { |
|---|
| 314 | 299 | struct acpi_madt_local_x2apic_nmi *x2apic_nmi = NULL; |
|---|
| .. | .. |
|---|
| 318 | 303 | if (BAD_MADT_ENTRY(x2apic_nmi, end)) |
|---|
| 319 | 304 | return -EINVAL; |
|---|
| 320 | 305 | |
|---|
| 321 | | - acpi_table_print_madt_entry(header); |
|---|
| 306 | + acpi_table_print_madt_entry(&header->common); |
|---|
| 322 | 307 | |
|---|
| 323 | 308 | if (x2apic_nmi->lint != 1) |
|---|
| 324 | 309 | printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n"); |
|---|
| .. | .. |
|---|
| 327 | 312 | } |
|---|
| 328 | 313 | |
|---|
| 329 | 314 | static int __init |
|---|
| 330 | | -acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end) |
|---|
| 315 | +acpi_parse_lapic_nmi(union acpi_subtable_headers * header, const unsigned long end) |
|---|
| 331 | 316 | { |
|---|
| 332 | 317 | struct acpi_madt_local_apic_nmi *lapic_nmi = NULL; |
|---|
| 333 | 318 | |
|---|
| .. | .. |
|---|
| 336 | 321 | if (BAD_MADT_ENTRY(lapic_nmi, end)) |
|---|
| 337 | 322 | return -EINVAL; |
|---|
| 338 | 323 | |
|---|
| 339 | | - acpi_table_print_madt_entry(header); |
|---|
| 324 | + acpi_table_print_madt_entry(&header->common); |
|---|
| 340 | 325 | |
|---|
| 341 | 326 | if (lapic_nmi->lint != 1) |
|---|
| 342 | 327 | printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n"); |
|---|
| .. | .. |
|---|
| 448 | 433 | } |
|---|
| 449 | 434 | |
|---|
| 450 | 435 | static int __init |
|---|
| 451 | | -acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end) |
|---|
| 436 | +acpi_parse_ioapic(union acpi_subtable_headers * header, const unsigned long end) |
|---|
| 452 | 437 | { |
|---|
| 453 | 438 | struct acpi_madt_io_apic *ioapic = NULL; |
|---|
| 454 | 439 | struct ioapic_domain_cfg cfg = { |
|---|
| .. | .. |
|---|
| 461 | 446 | if (BAD_MADT_ENTRY(ioapic, end)) |
|---|
| 462 | 447 | return -EINVAL; |
|---|
| 463 | 448 | |
|---|
| 464 | | - acpi_table_print_madt_entry(header); |
|---|
| 449 | + acpi_table_print_madt_entry(&header->common); |
|---|
| 465 | 450 | |
|---|
| 466 | 451 | /* Statically assign IRQ numbers for IOAPICs hosting legacy IRQs */ |
|---|
| 467 | 452 | if (ioapic->global_irq_base < nr_legacy_irqs()) |
|---|
| .. | .. |
|---|
| 507 | 492 | } |
|---|
| 508 | 493 | |
|---|
| 509 | 494 | static int __init |
|---|
| 510 | | -acpi_parse_int_src_ovr(struct acpi_subtable_header * header, |
|---|
| 495 | +acpi_parse_int_src_ovr(union acpi_subtable_headers * header, |
|---|
| 511 | 496 | const unsigned long end) |
|---|
| 512 | 497 | { |
|---|
| 513 | 498 | struct acpi_madt_interrupt_override *intsrc = NULL; |
|---|
| .. | .. |
|---|
| 517 | 502 | if (BAD_MADT_ENTRY(intsrc, end)) |
|---|
| 518 | 503 | return -EINVAL; |
|---|
| 519 | 504 | |
|---|
| 520 | | - acpi_table_print_madt_entry(header); |
|---|
| 505 | + acpi_table_print_madt_entry(&header->common); |
|---|
| 521 | 506 | |
|---|
| 522 | 507 | if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) { |
|---|
| 523 | 508 | acpi_sci_ioapic_setup(intsrc->source_irq, |
|---|
| .. | .. |
|---|
| 549 | 534 | } |
|---|
| 550 | 535 | |
|---|
| 551 | 536 | static int __init |
|---|
| 552 | | -acpi_parse_nmi_src(struct acpi_subtable_header * header, const unsigned long end) |
|---|
| 537 | +acpi_parse_nmi_src(union acpi_subtable_headers * header, const unsigned long end) |
|---|
| 553 | 538 | { |
|---|
| 554 | 539 | struct acpi_madt_nmi_source *nmi_src = NULL; |
|---|
| 555 | 540 | |
|---|
| .. | .. |
|---|
| 558 | 543 | if (BAD_MADT_ENTRY(nmi_src, end)) |
|---|
| 559 | 544 | return -EINVAL; |
|---|
| 560 | 545 | |
|---|
| 561 | | - acpi_table_print_madt_entry(header); |
|---|
| 546 | + acpi_table_print_madt_entry(&header->common); |
|---|
| 562 | 547 | |
|---|
| 563 | 548 | /* TBD: Support nimsrc entries? */ |
|---|
| 564 | 549 | |
|---|
| .. | .. |
|---|
| 847 | 832 | /** |
|---|
| 848 | 833 | * acpi_ioapic_registered - Check whether IOAPIC assoicatied with @gsi_base |
|---|
| 849 | 834 | * has been registered |
|---|
| 850 | | - * @handle: ACPI handle of the IOAPIC deivce |
|---|
| 835 | + * @handle: ACPI handle of the IOAPIC device |
|---|
| 851 | 836 | * @gsi_base: GSI base associated with the IOAPIC |
|---|
| 852 | 837 | * |
|---|
| 853 | 838 | * Assume caller holds some type of lock to serialize acpi_ioapic_registered() |
|---|
| .. | .. |
|---|
| 932 | 917 | * the resource tree during the lateinit timeframe. |
|---|
| 933 | 918 | */ |
|---|
| 934 | 919 | #define HPET_RESOURCE_NAME_SIZE 9 |
|---|
| 935 | | - hpet_res = alloc_bootmem(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE); |
|---|
| 920 | + hpet_res = memblock_alloc(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE, |
|---|
| 921 | + SMP_CACHE_BYTES); |
|---|
| 922 | + if (!hpet_res) |
|---|
| 923 | + panic("%s: Failed to allocate %zu bytes\n", __func__, |
|---|
| 924 | + sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE); |
|---|
| 936 | 925 | |
|---|
| 937 | 926 | hpet_res->name = (void *)&hpet_res[1]; |
|---|
| 938 | 927 | hpet_res->flags = IORESOURCE_MEM; |
|---|
| .. | .. |
|---|
| 1351 | 1340 | return 0; |
|---|
| 1352 | 1341 | } |
|---|
| 1353 | 1342 | |
|---|
| 1343 | +static int __init disable_acpi_xsdt(const struct dmi_system_id *d) |
|---|
| 1344 | +{ |
|---|
| 1345 | + if (!acpi_force) { |
|---|
| 1346 | + pr_notice("%s detected: force use of acpi=rsdt\n", d->ident); |
|---|
| 1347 | + acpi_gbl_do_not_use_xsdt = TRUE; |
|---|
| 1348 | + } else { |
|---|
| 1349 | + pr_notice("Warning: DMI blacklist says broken, but acpi XSDT forced\n"); |
|---|
| 1350 | + } |
|---|
| 1351 | + return 0; |
|---|
| 1352 | +} |
|---|
| 1353 | + |
|---|
| 1354 | 1354 | static int __init dmi_disable_acpi(const struct dmi_system_id *d) |
|---|
| 1355 | 1355 | { |
|---|
| 1356 | 1356 | if (!acpi_force) { |
|---|
| .. | .. |
|---|
| 1473 | 1473 | .matches = { |
|---|
| 1474 | 1474 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
|---|
| 1475 | 1475 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), |
|---|
| 1476 | + }, |
|---|
| 1477 | + }, |
|---|
| 1478 | + /* |
|---|
| 1479 | + * Boxes that need ACPI XSDT use disabled due to corrupted tables |
|---|
| 1480 | + */ |
|---|
| 1481 | + { |
|---|
| 1482 | + .callback = disable_acpi_xsdt, |
|---|
| 1483 | + .ident = "Advantech DAC-BJ01", |
|---|
| 1484 | + .matches = { |
|---|
| 1485 | + DMI_MATCH(DMI_SYS_VENDOR, "NEC"), |
|---|
| 1486 | + DMI_MATCH(DMI_PRODUCT_NAME, "Bearlake CRB Board"), |
|---|
| 1487 | + DMI_MATCH(DMI_BIOS_VERSION, "V1.12"), |
|---|
| 1488 | + DMI_MATCH(DMI_BIOS_DATE, "02/01/2011"), |
|---|
| 1476 | 1489 | }, |
|---|
| 1477 | 1490 | }, |
|---|
| 1478 | 1491 | {} |
|---|
| .. | .. |
|---|
| 1630 | 1643 | acpi_process_madt(); |
|---|
| 1631 | 1644 | |
|---|
| 1632 | 1645 | acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet); |
|---|
| 1633 | | - if (IS_ENABLED(CONFIG_ACPI_BGRT)) |
|---|
| 1646 | + if (IS_ENABLED(CONFIG_ACPI_BGRT) && !acpi_nobgrt) |
|---|
| 1634 | 1647 | acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); |
|---|
| 1635 | 1648 | |
|---|
| 1636 | 1649 | if (!acpi_noirq) |
|---|
| .. | .. |
|---|
| 1681 | 1694 | return 0; |
|---|
| 1682 | 1695 | } |
|---|
| 1683 | 1696 | early_param("acpi", parse_acpi); |
|---|
| 1697 | + |
|---|
| 1698 | +static int __init parse_acpi_bgrt(char *arg) |
|---|
| 1699 | +{ |
|---|
| 1700 | + acpi_nobgrt = true; |
|---|
| 1701 | + return 0; |
|---|
| 1702 | +} |
|---|
| 1703 | +early_param("bgrt_disable", parse_acpi_bgrt); |
|---|
| 1684 | 1704 | |
|---|
| 1685 | 1705 | /* FIXME: Using pci= for an ACPI parameter is a travesty. */ |
|---|
| 1686 | 1706 | static int __init parse_pci(char *arg) |
|---|
| .. | .. |
|---|
| 1770 | 1790 | e820__range_add(addr, size, E820_TYPE_ACPI); |
|---|
| 1771 | 1791 | e820__update_table_print(); |
|---|
| 1772 | 1792 | } |
|---|
| 1793 | + |
|---|
| 1794 | +void x86_default_set_root_pointer(u64 addr) |
|---|
| 1795 | +{ |
|---|
| 1796 | + boot_params.acpi_rsdp_addr = addr; |
|---|
| 1797 | +} |
|---|
| 1798 | + |
|---|
| 1799 | +u64 x86_default_get_root_pointer(void) |
|---|
| 1800 | +{ |
|---|
| 1801 | + return boot_params.acpi_rsdp_addr; |
|---|
| 1802 | +} |
|---|