1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 29703d9d7SCatalin Marinas /* 39703d9d7SCatalin Marinas * Based on arch/arm/kernel/setup.c 49703d9d7SCatalin Marinas * 59703d9d7SCatalin Marinas * Copyright (C) 1995-2001 Russell King 69703d9d7SCatalin Marinas * Copyright (C) 2012 ARM Ltd. 79703d9d7SCatalin Marinas */ 89703d9d7SCatalin Marinas 937655163SAl Stone #include <linux/acpi.h> 109703d9d7SCatalin Marinas #include <linux/export.h> 119703d9d7SCatalin Marinas #include <linux/kernel.h> 129703d9d7SCatalin Marinas #include <linux/stddef.h> 139703d9d7SCatalin Marinas #include <linux/ioport.h> 149703d9d7SCatalin Marinas #include <linux/delay.h> 159703d9d7SCatalin Marinas #include <linux/initrd.h> 169703d9d7SCatalin Marinas #include <linux/console.h> 17a41dc0e8SCatalin Marinas #include <linux/cache.h> 189703d9d7SCatalin Marinas #include <linux/screen_info.h> 199703d9d7SCatalin Marinas #include <linux/init.h> 209703d9d7SCatalin Marinas #include <linux/kexec.h> 219703d9d7SCatalin Marinas #include <linux/root_dev.h> 229703d9d7SCatalin Marinas #include <linux/cpu.h> 239703d9d7SCatalin Marinas #include <linux/interrupt.h> 249703d9d7SCatalin Marinas #include <linux/smp.h> 259703d9d7SCatalin Marinas #include <linux/fs.h> 269703d9d7SCatalin Marinas #include <linux/proc_fs.h> 279703d9d7SCatalin Marinas #include <linux/memblock.h> 289703d9d7SCatalin Marinas #include <linux/of_fdt.h> 29f84d0275SMark Salter #include <linux/efi.h> 30bff60792SMark Rutland #include <linux/psci.h> 319164bb4aSIngo Molnar #include <linux/sched/task.h> 322077be67SLaura Abbott #include <linux/mm.h> 339703d9d7SCatalin Marinas 3437655163SAl Stone #include <asm/acpi.h> 35bf4b558eSMark Salter #include <asm/fixmap.h> 36df857416SMark Rutland #include <asm/cpu.h> 379703d9d7SCatalin Marinas #include <asm/cputype.h> 3841bd5b5dSJames Morse #include <asm/daifflags.h> 399703d9d7SCatalin Marinas #include <asm/elf.h> 40930da09fSAndre Przywara #include <asm/cpufeature.h> 41e8765b26SMark Rutland #include <asm/cpu_ops.h> 4239d114ddSAndrey Ryabinin #include <asm/kasan.h> 431a2db300SGanapatrao Kulkarni #include <asm/numa.h> 449703d9d7SCatalin Marinas #include <asm/sections.h> 459703d9d7SCatalin Marinas #include <asm/setup.h> 464c7aa002SJavi Merino #include <asm/smp_plat.h> 479703d9d7SCatalin Marinas #include <asm/cacheflush.h> 489703d9d7SCatalin Marinas #include <asm/tlbflush.h> 499703d9d7SCatalin Marinas #include <asm/traps.h> 50f84d0275SMark Salter #include <asm/efi.h> 515882bfefSStefano Stabellini #include <asm/xen/hypervisor.h> 529e8e865bSMark Rutland #include <asm/mmu_context.h> 539703d9d7SCatalin Marinas 54d91680e6SWill Deacon static int num_standard_resources; 55d91680e6SWill Deacon static struct resource *standard_resources; 56d91680e6SWill Deacon 579703d9d7SCatalin Marinas phys_addr_t __fdt_pointer __initdata; 589703d9d7SCatalin Marinas 599703d9d7SCatalin Marinas /* 609703d9d7SCatalin Marinas * Standard memory resources 619703d9d7SCatalin Marinas */ 629703d9d7SCatalin Marinas static struct resource mem_res[] = { 639703d9d7SCatalin Marinas { 649703d9d7SCatalin Marinas .name = "Kernel code", 659703d9d7SCatalin Marinas .start = 0, 669703d9d7SCatalin Marinas .end = 0, 6735d98e93SToshi Kani .flags = IORESOURCE_SYSTEM_RAM 689703d9d7SCatalin Marinas }, 699703d9d7SCatalin Marinas { 709703d9d7SCatalin Marinas .name = "Kernel data", 719703d9d7SCatalin Marinas .start = 0, 729703d9d7SCatalin Marinas .end = 0, 7335d98e93SToshi Kani .flags = IORESOURCE_SYSTEM_RAM 749703d9d7SCatalin Marinas } 759703d9d7SCatalin Marinas }; 769703d9d7SCatalin Marinas 779703d9d7SCatalin Marinas #define kernel_code mem_res[0] 789703d9d7SCatalin Marinas #define kernel_data mem_res[1] 799703d9d7SCatalin Marinas 80da9c177dSArd Biesheuvel /* 81da9c177dSArd Biesheuvel * The recorded values of x0 .. x3 upon kernel entry. 82da9c177dSArd Biesheuvel */ 83da9c177dSArd Biesheuvel u64 __cacheline_aligned boot_args[4]; 84da9c177dSArd Biesheuvel 8571586276SWill Deacon void __init smp_setup_processor_id(void) 8671586276SWill Deacon { 8780708677SMark Rutland u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; 8880708677SMark Rutland cpu_logical_map(0) = mpidr; 8980708677SMark Rutland 9071586276SWill Deacon /* 9171586276SWill Deacon * clear __my_cpu_offset on boot CPU to avoid hang caused by 9271586276SWill Deacon * using percpu variable early, for example, lockdep will 9371586276SWill Deacon * access percpu variable inside lock_release 9471586276SWill Deacon */ 9571586276SWill Deacon set_my_cpu_offset(0); 96ccaac162SMark Rutland pr_info("Booting Linux on physical CPU 0x%010lx [0x%08x]\n", 97ccaac162SMark Rutland (unsigned long)mpidr, read_cpuid_id()); 9871586276SWill Deacon } 9971586276SWill Deacon 1006e15d0e0SSudeep KarkadaNagesha bool arch_match_cpu_phys_id(int cpu, u64 phys_id) 1016e15d0e0SSudeep KarkadaNagesha { 1026e15d0e0SSudeep KarkadaNagesha return phys_id == cpu_logical_map(cpu); 1036e15d0e0SSudeep KarkadaNagesha } 1046e15d0e0SSudeep KarkadaNagesha 105976d7d3fSLorenzo Pieralisi struct mpidr_hash mpidr_hash; 106976d7d3fSLorenzo Pieralisi /** 107976d7d3fSLorenzo Pieralisi * smp_build_mpidr_hash - Pre-compute shifts required at each affinity 108976d7d3fSLorenzo Pieralisi * level in order to build a linear index from an 109976d7d3fSLorenzo Pieralisi * MPIDR value. Resulting algorithm is a collision 110976d7d3fSLorenzo Pieralisi * free hash carried out through shifting and ORing 111976d7d3fSLorenzo Pieralisi */ 112976d7d3fSLorenzo Pieralisi static void __init smp_build_mpidr_hash(void) 113976d7d3fSLorenzo Pieralisi { 114976d7d3fSLorenzo Pieralisi u32 i, affinity, fs[4], bits[4], ls; 115976d7d3fSLorenzo Pieralisi u64 mask = 0; 116976d7d3fSLorenzo Pieralisi /* 117976d7d3fSLorenzo Pieralisi * Pre-scan the list of MPIDRS and filter out bits that do 118976d7d3fSLorenzo Pieralisi * not contribute to affinity levels, ie they never toggle. 119976d7d3fSLorenzo Pieralisi */ 120976d7d3fSLorenzo Pieralisi for_each_possible_cpu(i) 121976d7d3fSLorenzo Pieralisi mask |= (cpu_logical_map(i) ^ cpu_logical_map(0)); 122976d7d3fSLorenzo Pieralisi pr_debug("mask of set bits %#llx\n", mask); 123976d7d3fSLorenzo Pieralisi /* 124976d7d3fSLorenzo Pieralisi * Find and stash the last and first bit set at all affinity levels to 125976d7d3fSLorenzo Pieralisi * check how many bits are required to represent them. 126976d7d3fSLorenzo Pieralisi */ 127976d7d3fSLorenzo Pieralisi for (i = 0; i < 4; i++) { 128976d7d3fSLorenzo Pieralisi affinity = MPIDR_AFFINITY_LEVEL(mask, i); 129976d7d3fSLorenzo Pieralisi /* 130976d7d3fSLorenzo Pieralisi * Find the MSB bit and LSB bits position 131976d7d3fSLorenzo Pieralisi * to determine how many bits are required 132976d7d3fSLorenzo Pieralisi * to express the affinity level. 133976d7d3fSLorenzo Pieralisi */ 134976d7d3fSLorenzo Pieralisi ls = fls(affinity); 135976d7d3fSLorenzo Pieralisi fs[i] = affinity ? ffs(affinity) - 1 : 0; 136976d7d3fSLorenzo Pieralisi bits[i] = ls - fs[i]; 137976d7d3fSLorenzo Pieralisi } 138976d7d3fSLorenzo Pieralisi /* 139976d7d3fSLorenzo Pieralisi * An index can be created from the MPIDR_EL1 by isolating the 140976d7d3fSLorenzo Pieralisi * significant bits at each affinity level and by shifting 141976d7d3fSLorenzo Pieralisi * them in order to compress the 32 bits values space to a 142976d7d3fSLorenzo Pieralisi * compressed set of values. This is equivalent to hashing 143976d7d3fSLorenzo Pieralisi * the MPIDR_EL1 through shifting and ORing. It is a collision free 144976d7d3fSLorenzo Pieralisi * hash though not minimal since some levels might contain a number 145976d7d3fSLorenzo Pieralisi * of CPUs that is not an exact power of 2 and their bit 146976d7d3fSLorenzo Pieralisi * representation might contain holes, eg MPIDR_EL1[7:0] = {0x2, 0x80}. 147976d7d3fSLorenzo Pieralisi */ 148976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[0] = MPIDR_LEVEL_SHIFT(0) + fs[0]; 149976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[1] = MPIDR_LEVEL_SHIFT(1) + fs[1] - bits[0]; 150976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[2] = MPIDR_LEVEL_SHIFT(2) + fs[2] - 151976d7d3fSLorenzo Pieralisi (bits[1] + bits[0]); 152976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[3] = MPIDR_LEVEL_SHIFT(3) + 153976d7d3fSLorenzo Pieralisi fs[3] - (bits[2] + bits[1] + bits[0]); 154976d7d3fSLorenzo Pieralisi mpidr_hash.mask = mask; 155976d7d3fSLorenzo Pieralisi mpidr_hash.bits = bits[3] + bits[2] + bits[1] + bits[0]; 156976d7d3fSLorenzo Pieralisi pr_debug("MPIDR hash: aff0[%u] aff1[%u] aff2[%u] aff3[%u] mask[%#llx] bits[%u]\n", 157976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[0], 158976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[1], 159976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[2], 160976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[3], 161976d7d3fSLorenzo Pieralisi mpidr_hash.mask, 162976d7d3fSLorenzo Pieralisi mpidr_hash.bits); 163976d7d3fSLorenzo Pieralisi /* 164976d7d3fSLorenzo Pieralisi * 4x is an arbitrary value used to warn on a hash table much bigger 165976d7d3fSLorenzo Pieralisi * than expected on most systems. 166976d7d3fSLorenzo Pieralisi */ 167976d7d3fSLorenzo Pieralisi if (mpidr_hash_size() > 4 * num_possible_cpus()) 168976d7d3fSLorenzo Pieralisi pr_warn("Large number of MPIDR hash buckets detected\n"); 169976d7d3fSLorenzo Pieralisi } 170137650aaSMark Rutland 1719703d9d7SCatalin Marinas static void __init setup_machine_fdt(phys_addr_t dt_phys) 1729703d9d7SCatalin Marinas { 173e112b032SHsin-Yi Wang int size; 174e112b032SHsin-Yi Wang void *dt_virt = fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL); 1752f9a0becSGeert Uytterhoeven const char *name; 17661bd93ceSArd Biesheuvel 177e112b032SHsin-Yi Wang if (dt_virt) 178e112b032SHsin-Yi Wang memblock_reserve(dt_phys, size); 179e112b032SHsin-Yi Wang 18061bd93ceSArd Biesheuvel if (!dt_virt || !early_init_dt_scan(dt_virt)) { 18161bd93ceSArd Biesheuvel pr_crit("\n" 18261bd93ceSArd Biesheuvel "Error: invalid device tree blob at physical address %pa (virtual address 0x%p)\n" 18361bd93ceSArd Biesheuvel "The dtb must be 8-byte aligned and must not exceed 2 MB in size\n" 18461bd93ceSArd Biesheuvel "\nPlease check your bootloader.", 18561bd93ceSArd Biesheuvel &dt_phys, dt_virt); 1869703d9d7SCatalin Marinas 1879703d9d7SCatalin Marinas while (true) 1889703d9d7SCatalin Marinas cpu_relax(); 1899703d9d7SCatalin Marinas } 1905e39977eSWill Deacon 191e112b032SHsin-Yi Wang /* Early fixups are done, map the FDT as read-only now */ 192e112b032SHsin-Yi Wang fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL_RO); 193e112b032SHsin-Yi Wang 1942f9a0becSGeert Uytterhoeven name = of_flat_dt_get_machine_name(); 195690e95ddSKefeng Wang if (!name) 196690e95ddSKefeng Wang return; 197690e95ddSKefeng Wang 1982f9a0becSGeert Uytterhoeven pr_info("Machine model: %s\n", name); 1992f9a0becSGeert Uytterhoeven dump_stack_set_arch_desc("%s (DT)", name); 2009703d9d7SCatalin Marinas } 2019703d9d7SCatalin Marinas 2029703d9d7SCatalin Marinas static void __init request_standard_resources(void) 2039703d9d7SCatalin Marinas { 2049703d9d7SCatalin Marinas struct memblock_region *region; 2059703d9d7SCatalin Marinas struct resource *res; 206d91680e6SWill Deacon unsigned long i = 0; 2078a7f97b9SMike Rapoport size_t res_size; 2089703d9d7SCatalin Marinas 2092077be67SLaura Abbott kernel_code.start = __pa_symbol(_text); 2102077be67SLaura Abbott kernel_code.end = __pa_symbol(__init_begin - 1); 2112077be67SLaura Abbott kernel_data.start = __pa_symbol(_sdata); 2122077be67SLaura Abbott kernel_data.end = __pa_symbol(_end - 1); 2139703d9d7SCatalin Marinas 214d91680e6SWill Deacon num_standard_resources = memblock.memory.cnt; 2158a7f97b9SMike Rapoport res_size = num_standard_resources * sizeof(*standard_resources); 2169e0a17dbSChen Zhou standard_resources = memblock_alloc(res_size, SMP_CACHE_BYTES); 2178a7f97b9SMike Rapoport if (!standard_resources) 2188a7f97b9SMike Rapoport panic("%s: Failed to allocate %zu bytes\n", __func__, res_size); 219d91680e6SWill Deacon 2209703d9d7SCatalin Marinas for_each_memblock(memory, region) { 221d91680e6SWill Deacon res = &standard_resources[i++]; 222e7cd1903SAKASHI Takahiro if (memblock_is_nomap(region)) { 223e7cd1903SAKASHI Takahiro res->name = "reserved"; 22479ba11d2SArd Biesheuvel res->flags = IORESOURCE_MEM; 225e7cd1903SAKASHI Takahiro } else { 2269703d9d7SCatalin Marinas res->name = "System RAM"; 227e7cd1903SAKASHI Takahiro res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; 228e7cd1903SAKASHI Takahiro } 2299703d9d7SCatalin Marinas res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); 2309703d9d7SCatalin Marinas res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; 2319703d9d7SCatalin Marinas 2329703d9d7SCatalin Marinas request_resource(&iomem_resource, res); 2339703d9d7SCatalin Marinas 2349703d9d7SCatalin Marinas if (kernel_code.start >= res->start && 2359703d9d7SCatalin Marinas kernel_code.end <= res->end) 2369703d9d7SCatalin Marinas request_resource(res, &kernel_code); 2379703d9d7SCatalin Marinas if (kernel_data.start >= res->start && 2389703d9d7SCatalin Marinas kernel_data.end <= res->end) 2399703d9d7SCatalin Marinas request_resource(res, &kernel_data); 240764b51eaSAKASHI Takahiro #ifdef CONFIG_KEXEC_CORE 241764b51eaSAKASHI Takahiro /* Userspace will find "Crash kernel" region in /proc/iomem. */ 242764b51eaSAKASHI Takahiro if (crashk_res.end && crashk_res.start >= res->start && 243764b51eaSAKASHI Takahiro crashk_res.end <= res->end) 244764b51eaSAKASHI Takahiro request_resource(res, &crashk_res); 245764b51eaSAKASHI Takahiro #endif 2469703d9d7SCatalin Marinas } 2479703d9d7SCatalin Marinas } 2489703d9d7SCatalin Marinas 24950d7ba36SJames Morse static int __init reserve_memblock_reserved_regions(void) 25050d7ba36SJames Morse { 251d91680e6SWill Deacon u64 i, j; 25250d7ba36SJames Morse 253d91680e6SWill Deacon for (i = 0; i < num_standard_resources; ++i) { 254d91680e6SWill Deacon struct resource *mem = &standard_resources[i]; 255d91680e6SWill Deacon phys_addr_t r_start, r_end, mem_size = resource_size(mem); 25650d7ba36SJames Morse 257d91680e6SWill Deacon if (!memblock_is_region_reserved(mem->start, mem_size)) 25850d7ba36SJames Morse continue; 259d91680e6SWill Deacon 260d91680e6SWill Deacon for_each_reserved_mem_region(j, &r_start, &r_end) { 261d91680e6SWill Deacon resource_size_t start, end; 262d91680e6SWill Deacon 263d91680e6SWill Deacon start = max(PFN_PHYS(PFN_DOWN(r_start)), mem->start); 264d91680e6SWill Deacon end = min(PFN_PHYS(PFN_UP(r_end)) - 1, mem->end); 265d91680e6SWill Deacon 266d91680e6SWill Deacon if (start > mem->end || end < mem->start) 267d91680e6SWill Deacon continue; 26850d7ba36SJames Morse 26950d7ba36SJames Morse reserve_region_with_split(mem, start, end, "reserved"); 27050d7ba36SJames Morse } 271d91680e6SWill Deacon } 27250d7ba36SJames Morse 27350d7ba36SJames Morse return 0; 27450d7ba36SJames Morse } 27550d7ba36SJames Morse arch_initcall(reserve_memblock_reserved_regions); 27650d7ba36SJames Morse 2774c7aa002SJavi Merino u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID }; 2784c7aa002SJavi Merino 2799703d9d7SCatalin Marinas void __init setup_arch(char **cmdline_p) 2809703d9d7SCatalin Marinas { 2819703d9d7SCatalin Marinas init_mm.start_code = (unsigned long) _text; 2829703d9d7SCatalin Marinas init_mm.end_code = (unsigned long) _etext; 2839703d9d7SCatalin Marinas init_mm.end_data = (unsigned long) _edata; 2849703d9d7SCatalin Marinas init_mm.brk = (unsigned long) _end; 2859703d9d7SCatalin Marinas 2869703d9d7SCatalin Marinas *cmdline_p = boot_command_line; 2879703d9d7SCatalin Marinas 28809e3c22aSMark Brown /* 28909e3c22aSMark Brown * If know now we are going to need KPTI then use non-global 29009e3c22aSMark Brown * mappings from the start, avoiding the cost of rewriting 29109e3c22aSMark Brown * everything later. 29209e3c22aSMark Brown */ 29309e3c22aSMark Brown arm64_use_ng_mappings = kaslr_requires_kpti(); 29409e3c22aSMark Brown 295af86e597SLaura Abbott early_fixmap_init(); 296bf4b558eSMark Salter early_ioremap_init(); 2970bf757c7SMark Salter 29861bd93ceSArd Biesheuvel setup_machine_fdt(__fdt_pointer); 29961bd93ceSArd Biesheuvel 300ba5c5e4aSKees Cook /* 301ba5c5e4aSKees Cook * Initialise the static keys early as they may be enabled by the 302ba5c5e4aSKees Cook * cpufeature code and early parameters. 303ba5c5e4aSKees Cook */ 304ba5c5e4aSKees Cook jump_label_init(); 3059703d9d7SCatalin Marinas parse_early_param(); 3069703d9d7SCatalin Marinas 3077a9c43beSJon Masters /* 30841bd5b5dSJames Morse * Unmask asynchronous aborts and fiq after bringing up possible 30941bd5b5dSJames Morse * earlycon. (Report possible System Errors once we can report this 31041bd5b5dSJames Morse * occurred). 3117a9c43beSJon Masters */ 31241bd5b5dSJames Morse local_daif_restore(DAIF_PROCCTX_NOIRQ); 3137a9c43beSJon Masters 31486ccce89SMark Rutland /* 31586ccce89SMark Rutland * TTBR0 is only used for the identity mapping at this stage. Make it 31686ccce89SMark Rutland * point to zero page to avoid speculatively fetching new entries. 31786ccce89SMark Rutland */ 31886ccce89SMark Rutland cpu_uninstall_idmap(); 31986ccce89SMark Rutland 3209b08aaa3SShannon Zhao xen_early_init(); 321f84d0275SMark Salter efi_init(); 322dd4bc607SArd Biesheuvel 323dd4bc607SArd Biesheuvel if (!efi_enabled(EFI_BOOT) && ((u64)_text % MIN_KIMG_ALIGN) != 0) 324dd4bc607SArd Biesheuvel pr_warn(FW_BUG "Kernel image misaligned at boot, please fix your bootloader!"); 325dd4bc607SArd Biesheuvel 3269703d9d7SCatalin Marinas arm64_memblock_init(); 3279703d9d7SCatalin Marinas 32838b04a74SJon Masters paging_init(); 32938b04a74SJon Masters 33038b04a74SJon Masters acpi_table_upgrade(); 33138b04a74SJon Masters 33237655163SAl Stone /* Parse the ACPI tables for possible boot-time configuration */ 33337655163SAl Stone acpi_boot_table_init(); 33437655163SAl Stone 3353194ac6eSDavid Daney if (acpi_disabled) 3363194ac6eSDavid Daney unflatten_device_tree(); 3373194ac6eSDavid Daney 3383194ac6eSDavid Daney bootmem_init(); 3393194ac6eSDavid Daney 34039d114ddSAndrey Ryabinin kasan_init(); 34139d114ddSAndrey Ryabinin 3429703d9d7SCatalin Marinas request_standard_resources(); 3439703d9d7SCatalin Marinas 3440e63ea48SArd Biesheuvel early_ioremap_reset(); 345f84d0275SMark Salter 3463194ac6eSDavid Daney if (acpi_disabled) 3477c59a3dfSGraeme Gregory psci_dt_init(); 3483194ac6eSDavid Daney else 349fccb9a81SHanjun Guo psci_acpi_init(); 3503194ac6eSDavid Daney 3516885fb12SGavin Shan init_bootcpu_ops(); 3520f078336SLorenzo Pieralisi smp_init_cpus(); 353976d7d3fSLorenzo Pieralisi smp_build_mpidr_hash(); 3549703d9d7SCatalin Marinas 3553f41b609SAndrey Konovalov /* Init percpu seeds for random tags after cpus are set up. */ 3563f41b609SAndrey Konovalov kasan_init_tags(); 3573f41b609SAndrey Konovalov 35839bc88e5SCatalin Marinas #ifdef CONFIG_ARM64_SW_TTBR0_PAN 35939bc88e5SCatalin Marinas /* 36039bc88e5SCatalin Marinas * Make sure init_thread_info.ttbr0 always generates translation 36139bc88e5SCatalin Marinas * faults in case uaccess_enable() is inadvertently called by the init 36239bc88e5SCatalin Marinas * thread. 36339bc88e5SCatalin Marinas */ 364cbb999ddSGeert Uytterhoeven init_task.thread_info.ttbr0 = __pa_symbol(empty_zero_page); 36539bc88e5SCatalin Marinas #endif 36639bc88e5SCatalin Marinas 367da9c177dSArd Biesheuvel if (boot_args[1] || boot_args[2] || boot_args[3]) { 368da9c177dSArd Biesheuvel pr_err("WARNING: x1-x3 nonzero in violation of boot protocol:\n" 369da9c177dSArd Biesheuvel "\tx1: %016llx\n\tx2: %016llx\n\tx3: %016llx\n" 370da9c177dSArd Biesheuvel "This indicates a broken bootloader or old kernel\n", 371da9c177dSArd Biesheuvel boot_args[1], boot_args[2], boot_args[3]); 372da9c177dSArd Biesheuvel } 3739703d9d7SCatalin Marinas } 3749703d9d7SCatalin Marinas 375d55c5f28SSudeep Holla static inline bool cpu_can_disable(unsigned int cpu) 376d55c5f28SSudeep Holla { 377d55c5f28SSudeep Holla #ifdef CONFIG_HOTPLUG_CPU 378de58ed5eSGavin Shan const struct cpu_operations *ops = get_cpu_ops(cpu); 379de58ed5eSGavin Shan 380de58ed5eSGavin Shan if (ops && ops->cpu_can_disable) 381de58ed5eSGavin Shan return ops->cpu_can_disable(cpu); 382d55c5f28SSudeep Holla #endif 383d55c5f28SSudeep Holla return false; 384d55c5f28SSudeep Holla } 385d55c5f28SSudeep Holla 3869703d9d7SCatalin Marinas static int __init topology_init(void) 3879703d9d7SCatalin Marinas { 3889703d9d7SCatalin Marinas int i; 3899703d9d7SCatalin Marinas 3901a2db300SGanapatrao Kulkarni for_each_online_node(i) 3911a2db300SGanapatrao Kulkarni register_one_node(i); 3921a2db300SGanapatrao Kulkarni 3939703d9d7SCatalin Marinas for_each_possible_cpu(i) { 394df857416SMark Rutland struct cpu *cpu = &per_cpu(cpu_data.cpu, i); 395d55c5f28SSudeep Holla cpu->hotpluggable = cpu_can_disable(i); 3969703d9d7SCatalin Marinas register_cpu(cpu, i); 3979703d9d7SCatalin Marinas } 3989703d9d7SCatalin Marinas 3999703d9d7SCatalin Marinas return 0; 4009703d9d7SCatalin Marinas } 4019703d9d7SCatalin Marinas subsys_initcall(topology_init); 402f80fb3a3SArd Biesheuvel 403638d5031SAnshuman Khandual static void dump_kernel_offset(void) 404f80fb3a3SArd Biesheuvel { 4057ede8665SAlexander Popov const unsigned long offset = kaslr_offset(); 406f80fb3a3SArd Biesheuvel 4077ede8665SAlexander Popov if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && offset > 0) { 4087ede8665SAlexander Popov pr_emerg("Kernel Offset: 0x%lx from 0x%lx\n", 4097ede8665SAlexander Popov offset, KIMAGE_VADDR); 41012f799c8SMiles Chen pr_emerg("PHYS_OFFSET: 0x%llx\n", PHYS_OFFSET); 411f80fb3a3SArd Biesheuvel } else { 412f80fb3a3SArd Biesheuvel pr_emerg("Kernel Offset: disabled\n"); 413f80fb3a3SArd Biesheuvel } 414638d5031SAnshuman Khandual } 415638d5031SAnshuman Khandual 416638d5031SAnshuman Khandual static int arm64_panic_block_dump(struct notifier_block *self, 417638d5031SAnshuman Khandual unsigned long v, void *p) 418638d5031SAnshuman Khandual { 419638d5031SAnshuman Khandual dump_kernel_offset(); 420638d5031SAnshuman Khandual dump_cpu_features(); 421638d5031SAnshuman Khandual dump_mem_limit(); 422f80fb3a3SArd Biesheuvel return 0; 423f80fb3a3SArd Biesheuvel } 424f80fb3a3SArd Biesheuvel 425638d5031SAnshuman Khandual static struct notifier_block arm64_panic_block = { 426638d5031SAnshuman Khandual .notifier_call = arm64_panic_block_dump 427f80fb3a3SArd Biesheuvel }; 428f80fb3a3SArd Biesheuvel 429638d5031SAnshuman Khandual static int __init register_arm64_panic_block(void) 430f80fb3a3SArd Biesheuvel { 431f80fb3a3SArd Biesheuvel atomic_notifier_chain_register(&panic_notifier_list, 432638d5031SAnshuman Khandual &arm64_panic_block); 433f80fb3a3SArd Biesheuvel return 0; 434f80fb3a3SArd Biesheuvel } 435638d5031SAnshuman Khandual device_initcall(register_arm64_panic_block); 436