Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
37655163 AS |
2 | /* |
3 | * ARM64 Specific Low-Level ACPI Boot Support | |
4 | * | |
5 | * Copyright (C) 2013-2014, Linaro Ltd. | |
6 | * Author: Al Stone <al.stone@linaro.org> | |
7 | * Author: Graeme Gregory <graeme.gregory@linaro.org> | |
8 | * Author: Hanjun Guo <hanjun.guo@linaro.org> | |
9 | * Author: Tomasz Nowicki <tomasz.nowicki@linaro.org> | |
10 | * Author: Naresh Bhat <naresh.bhat@linaro.org> | |
37655163 AS |
11 | */ |
12 | ||
13 | #define pr_fmt(fmt) "ACPI: " fmt | |
14 | ||
15 | #include <linux/acpi.h> | |
1d280ce0 | 16 | #include <linux/arm-smccc.h> |
37655163 | 17 | #include <linux/cpumask.h> |
09ffcb0d | 18 | #include <linux/efi.h> |
6e7300cf | 19 | #include <linux/efi-bgrt.h> |
37655163 AS |
20 | #include <linux/init.h> |
21 | #include <linux/irq.h> | |
22 | #include <linux/irqdomain.h> | |
8fcc4ae6 | 23 | #include <linux/irq_work.h> |
37655163 | 24 | #include <linux/memblock.h> |
b10d79f7 | 25 | #include <linux/of_fdt.h> |
b6363fe7 | 26 | #include <linux/libfdt.h> |
37655163 | 27 | #include <linux/smp.h> |
888125a7 | 28 | #include <linux/serial_core.h> |
fbaad243 | 29 | #include <linux/suspend.h> |
65fddcfc | 30 | #include <linux/pgtable.h> |
37655163 | 31 | |
d44f1b8d | 32 | #include <acpi/ghes.h> |
9d087389 | 33 | #include <acpi/processor.h> |
fccb9a81 HG |
34 | #include <asm/cputype.h> |
35 | #include <asm/cpu_ops.h> | |
d44f1b8d | 36 | #include <asm/daifflags.h> |
fccb9a81 HG |
37 | #include <asm/smp_plat.h> |
38 | ||
b10d79f7 AS |
39 | int acpi_noirq = 1; /* skip ACPI IRQ initialization */ |
40 | int acpi_disabled = 1; | |
37655163 AS |
41 | EXPORT_SYMBOL(acpi_disabled); |
42 | ||
b10d79f7 | 43 | int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ |
37655163 AS |
44 | EXPORT_SYMBOL(acpi_pci_disabled); |
45 | ||
b10d79f7 | 46 | static bool param_acpi_off __initdata; |
6a1f5471 | 47 | static bool param_acpi_on __initdata; |
fb094eb1 | 48 | static bool param_acpi_force __initdata; |
f5a4af3c | 49 | static bool param_acpi_nospcr __initdata; |
b10d79f7 AS |
50 | |
51 | static int __init parse_acpi(char *arg) | |
52 | { | |
53 | if (!arg) | |
54 | return -EINVAL; | |
55 | ||
56 | /* "acpi=off" disables both ACPI table parsing and interpreter */ | |
57 | if (strcmp(arg, "off") == 0) | |
58 | param_acpi_off = true; | |
6a1f5471 AB |
59 | else if (strcmp(arg, "on") == 0) /* prefer ACPI over DT */ |
60 | param_acpi_on = true; | |
b10d79f7 AS |
61 | else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */ |
62 | param_acpi_force = true; | |
f5a4af3c LW |
63 | else if (strcmp(arg, "nospcr") == 0) /* disable SPCR as default console */ |
64 | param_acpi_nospcr = true; | |
b10d79f7 AS |
65 | else |
66 | return -EINVAL; /* Core will print when we return error */ | |
67 | ||
68 | return 0; | |
69 | } | |
70 | early_param("acpi", parse_acpi); | |
71 | ||
b6363fe7 | 72 | static bool __init dt_is_stub(void) |
b10d79f7 | 73 | { |
b6363fe7 | 74 | int node; |
2366c7fd | 75 | |
b6363fe7 RH |
76 | fdt_for_each_subnode(node, initial_boot_params, 0) { |
77 | const char *name = fdt_get_name(initial_boot_params, node, NULL); | |
78 | if (strcmp(name, "chosen") == 0) | |
79 | continue; | |
80 | if (strcmp(name, "hypervisor") == 0 && | |
81 | of_flat_dt_is_compatible(node, "xen,xen")) | |
82 | continue; | |
9981293f | 83 | |
b6363fe7 RH |
84 | return false; |
85 | } | |
9981293f | 86 | |
b6363fe7 | 87 | return true; |
b10d79f7 AS |
88 | } |
89 | ||
37655163 AS |
90 | /* |
91 | * __acpi_map_table() will be called before page_init(), so early_ioremap() | |
92 | * or early_memremap() should be called here to for ACPI table mapping. | |
93 | */ | |
6c9a58e8 | 94 | void __init __iomem *__acpi_map_table(unsigned long phys, unsigned long size) |
37655163 AS |
95 | { |
96 | if (!size) | |
97 | return NULL; | |
98 | ||
99 | return early_memremap(phys, size); | |
100 | } | |
101 | ||
6c9a58e8 | 102 | void __init __acpi_unmap_table(void __iomem *map, unsigned long size) |
37655163 AS |
103 | { |
104 | if (!map || !size) | |
105 | return; | |
106 | ||
107 | early_memunmap(map, size); | |
108 | } | |
109 | ||
c5a13305 MR |
110 | bool __init acpi_psci_present(void) |
111 | { | |
112 | return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_COMPLIANT; | |
113 | } | |
114 | ||
115 | /* Whether HVC must be used instead of SMC as the PSCI conduit */ | |
fa31ab77 | 116 | bool acpi_psci_use_hvc(void) |
c5a13305 MR |
117 | { |
118 | return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_USE_HVC; | |
119 | } | |
120 | ||
54971e43 LP |
121 | /* |
122 | * acpi_fadt_sanity_check() - Check FADT presence and carry out sanity | |
123 | * checks on it | |
124 | * | |
125 | * Return 0 on success, <0 on failure | |
126 | */ | |
127 | static int __init acpi_fadt_sanity_check(void) | |
37655163 | 128 | { |
54971e43 LP |
129 | struct acpi_table_header *table; |
130 | struct acpi_table_fadt *fadt; | |
131 | acpi_status status; | |
54971e43 LP |
132 | int ret = 0; |
133 | ||
134 | /* | |
135 | * FADT is required on arm64; retrieve it to check its presence | |
136 | * and carry out revision and ACPI HW reduced compliancy tests | |
137 | */ | |
6b11d1d6 | 138 | status = acpi_get_table(ACPI_SIG_FADT, 0, &table); |
54971e43 LP |
139 | if (ACPI_FAILURE(status)) { |
140 | const char *msg = acpi_format_exception(status); | |
141 | ||
142 | pr_err("Failed to get FADT table, %s\n", msg); | |
143 | return -ENODEV; | |
144 | } | |
145 | ||
146 | fadt = (struct acpi_table_fadt *)table; | |
37655163 AS |
147 | |
148 | /* | |
149 | * Revision in table header is the FADT Major revision, and there | |
150 | * is a minor revision of FADT which was introduced by ACPI 5.1, | |
151 | * we only deal with ACPI 5.1 or newer revision to get GIC and SMP | |
54971e43 | 152 | * boot protocol configuration data. |
37655163 | 153 | */ |
54971e43 LP |
154 | if (table->revision < 5 || |
155 | (table->revision == 5 && fadt->minor_revision < 1)) { | |
2af22f3e | 156 | pr_err(FW_BUG "Unsupported FADT revision %d.%d, should be 5.1+\n", |
54971e43 | 157 | table->revision, fadt->minor_revision); |
2af22f3e AB |
158 | |
159 | if (!fadt->arm_boot_flags) { | |
160 | ret = -EINVAL; | |
161 | goto out; | |
162 | } | |
163 | pr_err("FADT has ARM boot flags set, assuming 5.1\n"); | |
fccb9a81 | 164 | } |
37655163 | 165 | |
54971e43 LP |
166 | if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) { |
167 | pr_err("FADT not ACPI hardware reduced compliant\n"); | |
168 | ret = -EINVAL; | |
169 | } | |
37655163 | 170 | |
54971e43 LP |
171 | out: |
172 | /* | |
6b11d1d6 | 173 | * acpi_get_table() creates FADT table mapping that |
54971e43 LP |
174 | * should be released after parsing and before resuming boot |
175 | */ | |
6b11d1d6 | 176 | acpi_put_table(table); |
54971e43 | 177 | return ret; |
37655163 AS |
178 | } |
179 | ||
180 | /* | |
181 | * acpi_boot_table_init() called from setup_arch(), always. | |
182 | * 1. find RSDP and get its address, and then find XSDT | |
183 | * 2. extract all tables and checksums them all | |
184 | * 3. check ACPI FADT revision | |
54971e43 | 185 | * 4. check ACPI FADT HW reduced flag |
37655163 AS |
186 | * |
187 | * We can parse ACPI boot-time tables such as MADT after | |
188 | * this function is called. | |
54971e43 | 189 | * |
fb094eb1 LP |
190 | * On return ACPI is enabled if either: |
191 | * | |
192 | * - ACPI tables are initialized and sanity checks passed | |
193 | * - acpi=force was passed in the command line and ACPI was not disabled | |
194 | * explicitly through acpi=off command line parameter | |
195 | * | |
196 | * ACPI is disabled on function return otherwise | |
37655163 AS |
197 | */ |
198 | void __init acpi_boot_table_init(void) | |
199 | { | |
b10d79f7 AS |
200 | /* |
201 | * Enable ACPI instead of device tree unless | |
202 | * - ACPI has been disabled explicitly (acpi=off), or | |
2366c7fd SZ |
203 | * - the device tree is not empty (it has more than just a /chosen node, |
204 | * and a /hypervisor node when running on Xen) | |
6a1f5471 | 205 | * and ACPI has not been [force] enabled (acpi=on|force) |
b10d79f7 AS |
206 | */ |
207 | if (param_acpi_off || | |
b6363fe7 | 208 | (!param_acpi_on && !param_acpi_force && !dt_is_stub())) |
888125a7 | 209 | goto done; |
37655163 | 210 | |
54971e43 LP |
211 | /* |
212 | * ACPI is disabled at this point. Enable it in order to parse | |
213 | * the ACPI tables and carry out sanity checks | |
214 | */ | |
b10d79f7 AS |
215 | enable_acpi(); |
216 | ||
54971e43 LP |
217 | /* |
218 | * If ACPI tables are initialized and FADT sanity checks passed, | |
219 | * leave ACPI enabled and carry on booting; otherwise disable ACPI | |
220 | * on initialization error. | |
fb094eb1 LP |
221 | * If acpi=force was passed on the command line it forces ACPI |
222 | * to be enabled even if its initialization failed. | |
54971e43 LP |
223 | */ |
224 | if (acpi_table_init() || acpi_fadt_sanity_check()) { | |
225 | pr_err("Failed to init ACPI tables\n"); | |
fb094eb1 LP |
226 | if (!param_acpi_force) |
227 | disable_acpi(); | |
37655163 | 228 | } |
888125a7 AM |
229 | |
230 | done: | |
231 | if (acpi_disabled) { | |
0231d000 | 232 | if (earlycon_acpi_spcr_enable) |
888125a7 AM |
233 | early_init_dt_scan_chosen_stdout(); |
234 | } else { | |
fbaad243 DW |
235 | #ifdef CONFIG_HIBERNATION |
236 | struct acpi_table_header *facs = NULL; | |
237 | acpi_get_table(ACPI_SIG_FACS, 1, &facs); | |
238 | if (facs) { | |
239 | swsusp_hardware_signature = | |
240 | ((struct acpi_table_facs *)facs)->hardware_signature; | |
241 | acpi_put_table(facs); | |
242 | } | |
243 | #endif | |
f5a4af3c LW |
244 | |
245 | /* | |
246 | * For varying privacy and security reasons, sometimes need | |
247 | * to completely silence the serial console output, and only | |
248 | * enable it when needed. | |
249 | * But there are many existing systems that depend on this | |
250 | * behaviour, use acpi=nospcr to disable console in ACPI SPCR | |
251 | * table as default serial console. | |
252 | */ | |
253 | acpi_parse_spcr(earlycon_acpi_spcr_enable, | |
254 | !param_acpi_nospcr); | |
255 | pr_info("Use ACPI SPCR as default console: %s\n", | |
256 | param_acpi_nospcr ? "No" : "Yes"); | |
257 | ||
6e7300cf BS |
258 | if (IS_ENABLED(CONFIG_ACPI_BGRT)) |
259 | acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); | |
888125a7 | 260 | } |
37655163 | 261 | } |
d60fc389 | 262 | |
ee67c110 WD |
263 | static pgprot_t __acpi_get_writethrough_mem_attribute(void) |
264 | { | |
265 | /* | |
266 | * Although UEFI specifies the use of Normal Write-through for | |
267 | * EFI_MEMORY_WT, it is seldom used in practice and not implemented | |
268 | * by most (all?) CPUs. Rather than allocate a MAIR just for this | |
269 | * purpose, emit a warning and use Normal Non-cacheable instead. | |
270 | */ | |
271 | pr_warn_once("No MAIR allocation for EFI_MEMORY_WT; treating as Normal Non-cacheable\n"); | |
272 | return __pgprot(PROT_NORMAL_NC); | |
273 | } | |
274 | ||
09ffcb0d | 275 | pgprot_t __acpi_get_mem_attribute(phys_addr_t addr) |
89e44b51 JZZ |
276 | { |
277 | /* | |
278 | * According to "Table 8 Map: EFI memory types to AArch64 memory | |
279 | * types" of UEFI 2.5 section 2.3.6.1, each EFI memory type is | |
280 | * mapped to a corresponding MAIR attribute encoding. | |
281 | * The EFI memory attribute advises all possible capabilities | |
ee67c110 | 282 | * of a memory region. |
89e44b51 JZZ |
283 | */ |
284 | ||
285 | u64 attr; | |
286 | ||
287 | attr = efi_mem_attributes(addr); | |
288 | if (attr & EFI_MEMORY_WB) | |
289 | return PAGE_KERNEL; | |
89e44b51 JZZ |
290 | if (attr & EFI_MEMORY_WC) |
291 | return __pgprot(PROT_NORMAL_NC); | |
ee67c110 WD |
292 | if (attr & EFI_MEMORY_WT) |
293 | return __acpi_get_writethrough_mem_attribute(); | |
89e44b51 JZZ |
294 | return __pgprot(PROT_DEVICE_nGnRnE); |
295 | } | |
d44f1b8d | 296 | |
12064c17 | 297 | void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) |
1583052d AB |
298 | { |
299 | efi_memory_desc_t *md, *region = NULL; | |
300 | pgprot_t prot; | |
301 | ||
302 | if (WARN_ON_ONCE(!efi_enabled(EFI_MEMMAP))) | |
303 | return NULL; | |
304 | ||
305 | for_each_efi_memory_desc(md) { | |
306 | u64 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); | |
307 | ||
308 | if (phys < md->phys_addr || phys >= end) | |
309 | continue; | |
310 | ||
311 | if (phys + size > end) { | |
312 | pr_warn(FW_BUG "requested region covers multiple EFI memory regions\n"); | |
313 | return NULL; | |
314 | } | |
315 | region = md; | |
316 | break; | |
317 | } | |
318 | ||
319 | /* | |
320 | * It is fine for AML to remap regions that are not represented in the | |
321 | * EFI memory map at all, as it only describes normal memory, and MMIO | |
322 | * regions that require a virtual mapping to make them accessible to | |
12064c17 | 323 | * the EFI runtime services. |
1583052d | 324 | */ |
12064c17 | 325 | prot = __pgprot(PROT_DEVICE_nGnRnE); |
1583052d AB |
326 | if (region) { |
327 | switch (region->type) { | |
328 | case EFI_LOADER_CODE: | |
329 | case EFI_LOADER_DATA: | |
330 | case EFI_BOOT_SERVICES_CODE: | |
331 | case EFI_BOOT_SERVICES_DATA: | |
332 | case EFI_CONVENTIONAL_MEMORY: | |
333 | case EFI_PERSISTENT_MEMORY: | |
a509a66a AB |
334 | if (memblock_is_map_memory(phys) || |
335 | !memblock_is_region_memory(phys, size)) { | |
336 | pr_warn(FW_BUG "requested region covers kernel memory @ %pa\n", &phys); | |
337 | return NULL; | |
338 | } | |
339 | /* | |
340 | * Mapping kernel memory is permitted if the region in | |
341 | * question is covered by a single memblock with the | |
342 | * NOMAP attribute set: this enables the use of ACPI | |
343 | * table overrides passed via initramfs, which are | |
344 | * reserved in memory using arch_reserve_mem_area() | |
345 | * below. As this particular use case only requires | |
346 | * read access, fall through to the R/O mapping case. | |
347 | */ | |
348 | fallthrough; | |
325f5585 AB |
349 | |
350 | case EFI_RUNTIME_SERVICES_CODE: | |
351 | /* | |
352 | * This would be unusual, but not problematic per se, | |
353 | * as long as we take care not to create a writable | |
354 | * mapping for executable code. | |
355 | */ | |
356 | prot = PAGE_KERNEL_RO; | |
357 | break; | |
1583052d AB |
358 | |
359 | case EFI_ACPI_RECLAIM_MEMORY: | |
360 | /* | |
361 | * ACPI reclaim memory is used to pass firmware tables | |
362 | * and other data that is intended for consumption by | |
363 | * the OS only, which may decide it wants to reclaim | |
364 | * that memory and use it for something else. We never | |
365 | * do that, but we usually add it to the linear map | |
366 | * anyway, in which case we should use the existing | |
367 | * mapping. | |
368 | */ | |
369 | if (memblock_is_map_memory(phys)) | |
370 | return (void __iomem *)__phys_to_virt(phys); | |
df561f66 | 371 | fallthrough; |
1583052d AB |
372 | |
373 | default: | |
374 | if (region->attribute & EFI_MEMORY_WB) | |
375 | prot = PAGE_KERNEL; | |
1583052d AB |
376 | else if (region->attribute & EFI_MEMORY_WC) |
377 | prot = __pgprot(PROT_NORMAL_NC); | |
ee67c110 WD |
378 | else if (region->attribute & EFI_MEMORY_WT) |
379 | prot = __acpi_get_writethrough_mem_attribute(); | |
1583052d AB |
380 | } |
381 | } | |
86758b50 | 382 | return ioremap_prot(phys, size, prot); |
1583052d AB |
383 | } |
384 | ||
d44f1b8d JM |
385 | /* |
386 | * Claim Synchronous External Aborts as a firmware first notification. | |
387 | * | |
388 | * Used by KVM and the arch do_sea handler. | |
389 | * @regs may be NULL when called from process context. | |
390 | */ | |
391 | int apei_claim_sea(struct pt_regs *regs) | |
392 | { | |
393 | int err = -ENOENT; | |
8fcc4ae6 | 394 | bool return_to_irqs_enabled; |
d44f1b8d JM |
395 | unsigned long current_flags; |
396 | ||
397 | if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES)) | |
398 | return err; | |
399 | ||
e533dbe9 | 400 | current_flags = local_daif_save_flags(); |
d44f1b8d | 401 | |
8fcc4ae6 JM |
402 | /* current_flags isn't useful here as daif doesn't tell us about pNMI */ |
403 | return_to_irqs_enabled = !irqs_disabled_flags(arch_local_save_flags()); | |
404 | ||
405 | if (regs) | |
406 | return_to_irqs_enabled = interrupts_enabled(regs); | |
407 | ||
d44f1b8d JM |
408 | /* |
409 | * SEA can interrupt SError, mask it and describe this as an NMI so | |
410 | * that APEI defers the handling. | |
411 | */ | |
412 | local_daif_restore(DAIF_ERRCTX); | |
413 | nmi_enter(); | |
414 | err = ghes_notify_sea(); | |
415 | nmi_exit(); | |
8fcc4ae6 JM |
416 | |
417 | /* | |
418 | * APEI NMI-like notifications are deferred to irq_work. Unless | |
419 | * we interrupted irqs-masked code, we can do that now. | |
420 | */ | |
421 | if (!err) { | |
422 | if (return_to_irqs_enabled) { | |
423 | local_daif_restore(DAIF_PROCCTX_NOIRQ); | |
424 | __irq_enter(); | |
425 | irq_work_run(); | |
426 | __irq_exit(); | |
427 | } else { | |
428 | pr_warn_ratelimited("APEI work queued but not completed"); | |
429 | err = -EINPROGRESS; | |
430 | } | |
431 | } | |
432 | ||
d44f1b8d JM |
433 | local_daif_restore(current_flags); |
434 | ||
435 | return err; | |
436 | } | |
a509a66a AB |
437 | |
438 | void arch_reserve_mem_area(acpi_physical_address addr, size_t size) | |
439 | { | |
440 | memblock_mark_nomap(addr, size); | |
441 | } | |
1d280ce0 | 442 | |
9d087389 JC |
443 | #ifdef CONFIG_ACPI_HOTPLUG_CPU |
444 | int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 apci_id, | |
445 | int *pcpu) | |
446 | { | |
447 | /* If an error code is passed in this stub can't fix it */ | |
448 | if (*pcpu < 0) { | |
449 | pr_warn_once("Unable to map CPU to valid ID\n"); | |
450 | return *pcpu; | |
451 | } | |
452 | ||
453 | return 0; | |
454 | } | |
455 | EXPORT_SYMBOL(acpi_map_cpu); | |
456 | ||
457 | int acpi_unmap_cpu(int cpu) | |
458 | { | |
459 | return 0; | |
460 | } | |
461 | EXPORT_SYMBOL(acpi_unmap_cpu); | |
462 | #endif /* CONFIG_ACPI_HOTPLUG_CPU */ |