// SPDX-License-Identifier: GPL-2.0-only1/*2* ARM64 Specific Low-Level ACPI Boot Support3*4* Copyright (C) 2013-2014, Linaro Ltd.5* Author: Al Stone <[email protected]>6* Author: Graeme Gregory <[email protected]>7* Author: Hanjun Guo <[email protected]>8* Author: Tomasz Nowicki <[email protected]>9* Author: Naresh Bhat <[email protected]>10*/1112#define pr_fmt(fmt) "ACPI: " fmt1314#include <linux/acpi.h>15#include <linux/arm-smccc.h>16#include <linux/cpumask.h>17#include <linux/efi.h>18#include <linux/efi-bgrt.h>19#include <linux/init.h>20#include <linux/irq.h>21#include <linux/irqdomain.h>22#include <linux/irq_work.h>23#include <linux/memblock.h>24#include <linux/of_fdt.h>25#include <linux/libfdt.h>26#include <linux/smp.h>27#include <linux/serial_core.h>28#include <linux/suspend.h>29#include <linux/pgtable.h>3031#include <acpi/ghes.h>32#include <acpi/processor.h>33#include <asm/cputype.h>34#include <asm/cpu_ops.h>35#include <asm/daifflags.h>36#include <asm/smp_plat.h>3738int acpi_noirq = 1; /* skip ACPI IRQ initialization */39int acpi_disabled = 1;40EXPORT_SYMBOL(acpi_disabled);4142int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */43EXPORT_SYMBOL(acpi_pci_disabled);4445static bool param_acpi_off __initdata;46static bool param_acpi_on __initdata;47static bool param_acpi_force __initdata;48static bool param_acpi_nospcr __initdata;4950static int __init parse_acpi(char *arg)51{52if (!arg)53return -EINVAL;5455/* "acpi=off" disables both ACPI table parsing and interpreter */56if (strcmp(arg, "off") == 0)57param_acpi_off = true;58else if (strcmp(arg, "on") == 0) /* prefer ACPI over DT */59param_acpi_on = true;60else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */61param_acpi_force = true;62else if (strcmp(arg, "nospcr") == 0) /* disable SPCR as default console */63param_acpi_nospcr = true;64else65return -EINVAL; /* Core will print when we return error */6667return 0;68}69early_param("acpi", parse_acpi);7071static bool __init dt_is_stub(void)72{73int node;7475fdt_for_each_subnode(node, initial_boot_params, 0) {76const char *name = fdt_get_name(initial_boot_params, node, NULL);77if (strcmp(name, "chosen") == 0)78continue;79if (strcmp(name, "hypervisor") == 0 &&80of_flat_dt_is_compatible(node, "xen,xen"))81continue;8283return false;84}8586return true;87}8889/*90* __acpi_map_table() will be called before page_init(), so early_ioremap()91* or early_memremap() should be called here to for ACPI table mapping.92*/93void __init __iomem *__acpi_map_table(unsigned long phys, unsigned long size)94{95if (!size)96return NULL;9798return early_memremap(phys, size);99}100101void __init __acpi_unmap_table(void __iomem *map, unsigned long size)102{103if (!map || !size)104return;105106early_memunmap(map, size);107}108109bool __init acpi_psci_present(void)110{111return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_COMPLIANT;112}113114/* Whether HVC must be used instead of SMC as the PSCI conduit */115bool acpi_psci_use_hvc(void)116{117return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_USE_HVC;118}119120/*121* acpi_fadt_sanity_check() - Check FADT presence and carry out sanity122* checks on it123*124* Return 0 on success, <0 on failure125*/126static int __init acpi_fadt_sanity_check(void)127{128struct acpi_table_header *table;129struct acpi_table_fadt *fadt;130acpi_status status;131int ret = 0;132133/*134* FADT is required on arm64; retrieve it to check its presence135* and carry out revision and ACPI HW reduced compliancy tests136*/137status = acpi_get_table(ACPI_SIG_FADT, 0, &table);138if (ACPI_FAILURE(status)) {139const char *msg = acpi_format_exception(status);140141pr_err("Failed to get FADT table, %s\n", msg);142return -ENODEV;143}144145fadt = (struct acpi_table_fadt *)table;146147/*148* Revision in table header is the FADT Major revision, and there149* is a minor revision of FADT which was introduced by ACPI 5.1,150* we only deal with ACPI 5.1 or newer revision to get GIC and SMP151* boot protocol configuration data.152*/153if (table->revision < 5 ||154(table->revision == 5 && fadt->minor_revision < 1)) {155pr_err(FW_BUG "Unsupported FADT revision %d.%d, should be 5.1+\n",156table->revision, fadt->minor_revision);157158if (!fadt->arm_boot_flags) {159ret = -EINVAL;160goto out;161}162pr_err("FADT has ARM boot flags set, assuming 5.1\n");163}164165if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) {166pr_err("FADT not ACPI hardware reduced compliant\n");167ret = -EINVAL;168}169170out:171/*172* acpi_get_table() creates FADT table mapping that173* should be released after parsing and before resuming boot174*/175acpi_put_table(table);176return ret;177}178179/*180* acpi_boot_table_init() called from setup_arch(), always.181* 1. find RSDP and get its address, and then find XSDT182* 2. extract all tables and checksums them all183* 3. check ACPI FADT revision184* 4. check ACPI FADT HW reduced flag185*186* We can parse ACPI boot-time tables such as MADT after187* this function is called.188*189* On return ACPI is enabled if either:190*191* - ACPI tables are initialized and sanity checks passed192* - acpi=force was passed in the command line and ACPI was not disabled193* explicitly through acpi=off command line parameter194*195* ACPI is disabled on function return otherwise196*/197void __init acpi_boot_table_init(void)198{199int ret;200201/*202* Enable ACPI instead of device tree unless203* - ACPI has been disabled explicitly (acpi=off), or204* - the device tree is not empty (it has more than just a /chosen node,205* and a /hypervisor node when running on Xen)206* and ACPI has not been [force] enabled (acpi=on|force)207*/208if (param_acpi_off ||209(!param_acpi_on && !param_acpi_force && !dt_is_stub()))210goto done;211212/*213* ACPI is disabled at this point. Enable it in order to parse214* the ACPI tables and carry out sanity checks215*/216enable_acpi();217218/*219* If ACPI tables are initialized and FADT sanity checks passed,220* leave ACPI enabled and carry on booting; otherwise disable ACPI221* on initialization error.222* If acpi=force was passed on the command line it forces ACPI223* to be enabled even if its initialization failed.224*/225if (acpi_table_init() || acpi_fadt_sanity_check()) {226pr_err("Failed to init ACPI tables\n");227if (!param_acpi_force)228disable_acpi();229}230231done:232if (acpi_disabled) {233if (earlycon_acpi_spcr_enable)234early_init_dt_scan_chosen_stdout();235} else {236#ifdef CONFIG_HIBERNATION237struct acpi_table_header *facs = NULL;238acpi_get_table(ACPI_SIG_FACS, 1, &facs);239if (facs) {240swsusp_hardware_signature =241((struct acpi_table_facs *)facs)->hardware_signature;242acpi_put_table(facs);243}244#endif245246/*247* For varying privacy and security reasons, sometimes need248* to completely silence the serial console output, and only249* enable it when needed.250* But there are many existing systems that depend on this251* behaviour, use acpi=nospcr to disable console in ACPI SPCR252* table as default serial console.253*/254ret = acpi_parse_spcr(earlycon_acpi_spcr_enable,255!param_acpi_nospcr);256if (!ret || param_acpi_nospcr || !IS_ENABLED(CONFIG_ACPI_SPCR_TABLE))257pr_info("Use ACPI SPCR as default console: No\n");258else259pr_info("Use ACPI SPCR as default console: Yes\n");260261if (IS_ENABLED(CONFIG_ACPI_BGRT))262acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);263}264}265266static pgprot_t __acpi_get_writethrough_mem_attribute(void)267{268/*269* Although UEFI specifies the use of Normal Write-through for270* EFI_MEMORY_WT, it is seldom used in practice and not implemented271* by most (all?) CPUs. Rather than allocate a MAIR just for this272* purpose, emit a warning and use Normal Non-cacheable instead.273*/274pr_warn_once("No MAIR allocation for EFI_MEMORY_WT; treating as Normal Non-cacheable\n");275return __pgprot(PROT_NORMAL_NC);276}277278pgprot_t __acpi_get_mem_attribute(phys_addr_t addr)279{280/*281* According to "Table 8 Map: EFI memory types to AArch64 memory282* types" of UEFI 2.5 section 2.3.6.1, each EFI memory type is283* mapped to a corresponding MAIR attribute encoding.284* The EFI memory attribute advises all possible capabilities285* of a memory region.286*/287288u64 attr;289290attr = efi_mem_attributes(addr);291if (attr & EFI_MEMORY_WB)292return PAGE_KERNEL;293if (attr & EFI_MEMORY_WC)294return __pgprot(PROT_NORMAL_NC);295if (attr & EFI_MEMORY_WT)296return __acpi_get_writethrough_mem_attribute();297return __pgprot(PROT_DEVICE_nGnRnE);298}299300void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)301{302efi_memory_desc_t *md, *region = NULL;303pgprot_t prot;304305if (WARN_ON_ONCE(!efi_enabled(EFI_MEMMAP)))306return NULL;307308for_each_efi_memory_desc(md) {309u64 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);310311if (phys < md->phys_addr || phys >= end)312continue;313314if (phys + size > end) {315pr_warn(FW_BUG "requested region covers multiple EFI memory regions\n");316return NULL;317}318region = md;319break;320}321322/*323* It is fine for AML to remap regions that are not represented in the324* EFI memory map at all, as it only describes normal memory, and MMIO325* regions that require a virtual mapping to make them accessible to326* the EFI runtime services.327*/328prot = __pgprot(PROT_DEVICE_nGnRnE);329if (region) {330switch (region->type) {331case EFI_LOADER_CODE:332case EFI_LOADER_DATA:333case EFI_BOOT_SERVICES_CODE:334case EFI_BOOT_SERVICES_DATA:335case EFI_CONVENTIONAL_MEMORY:336case EFI_PERSISTENT_MEMORY:337if (memblock_is_map_memory(phys) ||338!memblock_is_region_memory(phys, size)) {339pr_warn(FW_BUG "requested region covers kernel memory @ %pa\n", &phys);340return NULL;341}342/*343* Mapping kernel memory is permitted if the region in344* question is covered by a single memblock with the345* NOMAP attribute set: this enables the use of ACPI346* table overrides passed via initramfs, which are347* reserved in memory using arch_reserve_mem_area()348* below. As this particular use case only requires349* read access, fall through to the R/O mapping case.350*/351fallthrough;352353case EFI_RUNTIME_SERVICES_CODE:354/*355* This would be unusual, but not problematic per se,356* as long as we take care not to create a writable357* mapping for executable code.358*/359prot = PAGE_KERNEL_RO;360break;361362case EFI_ACPI_RECLAIM_MEMORY:363/*364* ACPI reclaim memory is used to pass firmware tables365* and other data that is intended for consumption by366* the OS only, which may decide it wants to reclaim367* that memory and use it for something else. We never368* do that, but we usually add it to the linear map369* anyway, in which case we should use the existing370* mapping.371*/372if (memblock_is_map_memory(phys))373return (void __iomem *)__phys_to_virt(phys);374fallthrough;375376default:377if (region->attribute & EFI_MEMORY_WB)378prot = PAGE_KERNEL;379else if (region->attribute & EFI_MEMORY_WC)380prot = __pgprot(PROT_NORMAL_NC);381else if (region->attribute & EFI_MEMORY_WT)382prot = __acpi_get_writethrough_mem_attribute();383}384}385return ioremap_prot(phys, size, prot);386}387388/*389* Claim Synchronous External Aborts as a firmware first notification.390*391* Used by KVM and the arch do_sea handler.392* @regs may be NULL when called from process context.393*/394int apei_claim_sea(struct pt_regs *regs)395{396int err = -ENOENT;397bool return_to_irqs_enabled;398unsigned long current_flags;399400if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES))401return err;402403current_flags = local_daif_save_flags();404405/* current_flags isn't useful here as daif doesn't tell us about pNMI */406return_to_irqs_enabled = !irqs_disabled_flags(arch_local_save_flags());407408if (regs)409return_to_irqs_enabled = interrupts_enabled(regs);410411/*412* SEA can interrupt SError, mask it and describe this as an NMI so413* that APEI defers the handling.414*/415local_daif_restore(DAIF_ERRCTX);416nmi_enter();417err = ghes_notify_sea();418nmi_exit();419420/*421* APEI NMI-like notifications are deferred to irq_work. Unless422* we interrupted irqs-masked code, we can do that now.423*/424if (!err) {425if (return_to_irqs_enabled) {426local_daif_restore(DAIF_PROCCTX_NOIRQ);427__irq_enter();428irq_work_run();429__irq_exit();430} else {431pr_warn_ratelimited("APEI work queued but not completed");432err = -EINPROGRESS;433}434}435436local_daif_restore(current_flags);437438return err;439}440441void arch_reserve_mem_area(acpi_physical_address addr, size_t size)442{443memblock_mark_nomap(addr, size);444}445446#ifdef CONFIG_ACPI_HOTPLUG_CPU447int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 apci_id,448int *pcpu)449{450/* If an error code is passed in this stub can't fix it */451if (*pcpu < 0) {452pr_warn_once("Unable to map CPU to valid ID\n");453return *pcpu;454}455456return 0;457}458EXPORT_SYMBOL(acpi_map_cpu);459460int acpi_unmap_cpu(int cpu)461{462return 0;463}464EXPORT_SYMBOL(acpi_unmap_cpu);465#endif /* CONFIG_ACPI_HOTPLUG_CPU */466467468