.. | .. |
---|
| 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 | +} |
---|