19703d9d7SCatalin Marinas /* 29703d9d7SCatalin Marinas * Based on arch/arm/kernel/setup.c 39703d9d7SCatalin Marinas * 49703d9d7SCatalin Marinas * Copyright (C) 1995-2001 Russell King 59703d9d7SCatalin Marinas * Copyright (C) 2012 ARM Ltd. 69703d9d7SCatalin Marinas * 79703d9d7SCatalin Marinas * This program is free software; you can redistribute it and/or modify 89703d9d7SCatalin Marinas * it under the terms of the GNU General Public License version 2 as 99703d9d7SCatalin Marinas * published by the Free Software Foundation. 109703d9d7SCatalin Marinas * 119703d9d7SCatalin Marinas * This program is distributed in the hope that it will be useful, 129703d9d7SCatalin Marinas * but WITHOUT ANY WARRANTY; without even the implied warranty of 139703d9d7SCatalin Marinas * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 149703d9d7SCatalin Marinas * GNU General Public License for more details. 159703d9d7SCatalin Marinas * 169703d9d7SCatalin Marinas * You should have received a copy of the GNU General Public License 179703d9d7SCatalin Marinas * along with this program. If not, see <http://www.gnu.org/licenses/>. 189703d9d7SCatalin Marinas */ 199703d9d7SCatalin Marinas 2037655163SAl Stone #include <linux/acpi.h> 219703d9d7SCatalin Marinas #include <linux/export.h> 229703d9d7SCatalin Marinas #include <linux/kernel.h> 239703d9d7SCatalin Marinas #include <linux/stddef.h> 249703d9d7SCatalin Marinas #include <linux/ioport.h> 259703d9d7SCatalin Marinas #include <linux/delay.h> 269703d9d7SCatalin Marinas #include <linux/utsname.h> 279703d9d7SCatalin Marinas #include <linux/initrd.h> 289703d9d7SCatalin Marinas #include <linux/console.h> 29a41dc0e8SCatalin Marinas #include <linux/cache.h> 309703d9d7SCatalin Marinas #include <linux/bootmem.h> 319703d9d7SCatalin Marinas #include <linux/seq_file.h> 329703d9d7SCatalin Marinas #include <linux/screen_info.h> 339703d9d7SCatalin Marinas #include <linux/init.h> 349703d9d7SCatalin Marinas #include <linux/kexec.h> 359703d9d7SCatalin Marinas #include <linux/crash_dump.h> 369703d9d7SCatalin Marinas #include <linux/root_dev.h> 37de79a64dSCatalin Marinas #include <linux/clk-provider.h> 389703d9d7SCatalin Marinas #include <linux/cpu.h> 399703d9d7SCatalin Marinas #include <linux/interrupt.h> 409703d9d7SCatalin Marinas #include <linux/smp.h> 419703d9d7SCatalin Marinas #include <linux/fs.h> 429703d9d7SCatalin Marinas #include <linux/proc_fs.h> 439703d9d7SCatalin Marinas #include <linux/memblock.h> 4478d51e0bSRobin Murphy #include <linux/of_iommu.h> 459703d9d7SCatalin Marinas #include <linux/of_fdt.h> 46d6bafb9bSCatalin Marinas #include <linux/of_platform.h> 47f84d0275SMark Salter #include <linux/efi.h> 4844b82b77SMark Rutland #include <linux/personality.h> 499703d9d7SCatalin Marinas 5037655163SAl Stone #include <asm/acpi.h> 51bf4b558eSMark Salter #include <asm/fixmap.h> 52df857416SMark Rutland #include <asm/cpu.h> 539703d9d7SCatalin Marinas #include <asm/cputype.h> 549703d9d7SCatalin Marinas #include <asm/elf.h> 55930da09fSAndre Przywara #include <asm/cpufeature.h> 56e8765b26SMark Rutland #include <asm/cpu_ops.h> 579703d9d7SCatalin Marinas #include <asm/sections.h> 589703d9d7SCatalin Marinas #include <asm/setup.h> 594c7aa002SJavi Merino #include <asm/smp_plat.h> 609703d9d7SCatalin Marinas #include <asm/cacheflush.h> 619703d9d7SCatalin Marinas #include <asm/tlbflush.h> 629703d9d7SCatalin Marinas #include <asm/traps.h> 639703d9d7SCatalin Marinas #include <asm/memblock.h> 64e790f1deSWill Deacon #include <asm/psci.h> 65f84d0275SMark Salter #include <asm/efi.h> 66667f3fd3SMark Rutland #include <asm/virt.h> 679703d9d7SCatalin Marinas 6825804e6aSSteve Capper unsigned long elf_hwcap __read_mostly; 699703d9d7SCatalin Marinas EXPORT_SYMBOL_GPL(elf_hwcap); 709703d9d7SCatalin Marinas 7146efe547SSudeep KarkadaNagesha #ifdef CONFIG_COMPAT 7246efe547SSudeep KarkadaNagesha #define COMPAT_ELF_HWCAP_DEFAULT \ 7346efe547SSudeep KarkadaNagesha (COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\ 7446efe547SSudeep KarkadaNagesha COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\ 7546efe547SSudeep KarkadaNagesha COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\ 7646efe547SSudeep KarkadaNagesha COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\ 777d57511dSCatalin Marinas COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV|\ 787d57511dSCatalin Marinas COMPAT_HWCAP_LPAE) 7946efe547SSudeep KarkadaNagesha unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT; 8028964d32SArd Biesheuvel unsigned int compat_elf_hwcap2 __read_mostly; 8146efe547SSudeep KarkadaNagesha #endif 8246efe547SSudeep KarkadaNagesha 8306f9eb88SFabio Estevam DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); 84930da09fSAndre Przywara 859703d9d7SCatalin Marinas phys_addr_t __fdt_pointer __initdata; 869703d9d7SCatalin Marinas 879703d9d7SCatalin Marinas /* 889703d9d7SCatalin Marinas * Standard memory resources 899703d9d7SCatalin Marinas */ 909703d9d7SCatalin Marinas static struct resource mem_res[] = { 919703d9d7SCatalin Marinas { 929703d9d7SCatalin Marinas .name = "Kernel code", 939703d9d7SCatalin Marinas .start = 0, 949703d9d7SCatalin Marinas .end = 0, 959703d9d7SCatalin Marinas .flags = IORESOURCE_MEM 969703d9d7SCatalin Marinas }, 979703d9d7SCatalin Marinas { 989703d9d7SCatalin Marinas .name = "Kernel data", 999703d9d7SCatalin Marinas .start = 0, 1009703d9d7SCatalin Marinas .end = 0, 1019703d9d7SCatalin Marinas .flags = IORESOURCE_MEM 1029703d9d7SCatalin Marinas } 1039703d9d7SCatalin Marinas }; 1049703d9d7SCatalin Marinas 1059703d9d7SCatalin Marinas #define kernel_code mem_res[0] 1069703d9d7SCatalin Marinas #define kernel_data mem_res[1] 1079703d9d7SCatalin Marinas 108da9c177dSArd Biesheuvel /* 109da9c177dSArd Biesheuvel * The recorded values of x0 .. x3 upon kernel entry. 110da9c177dSArd Biesheuvel */ 111da9c177dSArd Biesheuvel u64 __cacheline_aligned boot_args[4]; 112da9c177dSArd Biesheuvel 11371586276SWill Deacon void __init smp_setup_processor_id(void) 11471586276SWill Deacon { 11580708677SMark Rutland u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; 11680708677SMark Rutland cpu_logical_map(0) = mpidr; 11780708677SMark Rutland 11871586276SWill Deacon /* 11971586276SWill Deacon * clear __my_cpu_offset on boot CPU to avoid hang caused by 12071586276SWill Deacon * using percpu variable early, for example, lockdep will 12171586276SWill Deacon * access percpu variable inside lock_release 12271586276SWill Deacon */ 12371586276SWill Deacon set_my_cpu_offset(0); 12480708677SMark Rutland pr_info("Booting Linux on physical CPU 0x%lx\n", (unsigned long)mpidr); 12571586276SWill Deacon } 12671586276SWill Deacon 1276e15d0e0SSudeep KarkadaNagesha bool arch_match_cpu_phys_id(int cpu, u64 phys_id) 1286e15d0e0SSudeep KarkadaNagesha { 1296e15d0e0SSudeep KarkadaNagesha return phys_id == cpu_logical_map(cpu); 1306e15d0e0SSudeep KarkadaNagesha } 1316e15d0e0SSudeep KarkadaNagesha 132976d7d3fSLorenzo Pieralisi struct mpidr_hash mpidr_hash; 133976d7d3fSLorenzo Pieralisi #ifdef CONFIG_SMP 134976d7d3fSLorenzo Pieralisi /** 135976d7d3fSLorenzo Pieralisi * smp_build_mpidr_hash - Pre-compute shifts required at each affinity 136976d7d3fSLorenzo Pieralisi * level in order to build a linear index from an 137976d7d3fSLorenzo Pieralisi * MPIDR value. Resulting algorithm is a collision 138976d7d3fSLorenzo Pieralisi * free hash carried out through shifting and ORing 139976d7d3fSLorenzo Pieralisi */ 140976d7d3fSLorenzo Pieralisi static void __init smp_build_mpidr_hash(void) 141976d7d3fSLorenzo Pieralisi { 142976d7d3fSLorenzo Pieralisi u32 i, affinity, fs[4], bits[4], ls; 143976d7d3fSLorenzo Pieralisi u64 mask = 0; 144976d7d3fSLorenzo Pieralisi /* 145976d7d3fSLorenzo Pieralisi * Pre-scan the list of MPIDRS and filter out bits that do 146976d7d3fSLorenzo Pieralisi * not contribute to affinity levels, ie they never toggle. 147976d7d3fSLorenzo Pieralisi */ 148976d7d3fSLorenzo Pieralisi for_each_possible_cpu(i) 149976d7d3fSLorenzo Pieralisi mask |= (cpu_logical_map(i) ^ cpu_logical_map(0)); 150976d7d3fSLorenzo Pieralisi pr_debug("mask of set bits %#llx\n", mask); 151976d7d3fSLorenzo Pieralisi /* 152976d7d3fSLorenzo Pieralisi * Find and stash the last and first bit set at all affinity levels to 153976d7d3fSLorenzo Pieralisi * check how many bits are required to represent them. 154976d7d3fSLorenzo Pieralisi */ 155976d7d3fSLorenzo Pieralisi for (i = 0; i < 4; i++) { 156976d7d3fSLorenzo Pieralisi affinity = MPIDR_AFFINITY_LEVEL(mask, i); 157976d7d3fSLorenzo Pieralisi /* 158976d7d3fSLorenzo Pieralisi * Find the MSB bit and LSB bits position 159976d7d3fSLorenzo Pieralisi * to determine how many bits are required 160976d7d3fSLorenzo Pieralisi * to express the affinity level. 161976d7d3fSLorenzo Pieralisi */ 162976d7d3fSLorenzo Pieralisi ls = fls(affinity); 163976d7d3fSLorenzo Pieralisi fs[i] = affinity ? ffs(affinity) - 1 : 0; 164976d7d3fSLorenzo Pieralisi bits[i] = ls - fs[i]; 165976d7d3fSLorenzo Pieralisi } 166976d7d3fSLorenzo Pieralisi /* 167976d7d3fSLorenzo Pieralisi * An index can be created from the MPIDR_EL1 by isolating the 168976d7d3fSLorenzo Pieralisi * significant bits at each affinity level and by shifting 169976d7d3fSLorenzo Pieralisi * them in order to compress the 32 bits values space to a 170976d7d3fSLorenzo Pieralisi * compressed set of values. This is equivalent to hashing 171976d7d3fSLorenzo Pieralisi * the MPIDR_EL1 through shifting and ORing. It is a collision free 172976d7d3fSLorenzo Pieralisi * hash though not minimal since some levels might contain a number 173976d7d3fSLorenzo Pieralisi * of CPUs that is not an exact power of 2 and their bit 174976d7d3fSLorenzo Pieralisi * representation might contain holes, eg MPIDR_EL1[7:0] = {0x2, 0x80}. 175976d7d3fSLorenzo Pieralisi */ 176976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[0] = MPIDR_LEVEL_SHIFT(0) + fs[0]; 177976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[1] = MPIDR_LEVEL_SHIFT(1) + fs[1] - bits[0]; 178976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[2] = MPIDR_LEVEL_SHIFT(2) + fs[2] - 179976d7d3fSLorenzo Pieralisi (bits[1] + bits[0]); 180976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[3] = MPIDR_LEVEL_SHIFT(3) + 181976d7d3fSLorenzo Pieralisi fs[3] - (bits[2] + bits[1] + bits[0]); 182976d7d3fSLorenzo Pieralisi mpidr_hash.mask = mask; 183976d7d3fSLorenzo Pieralisi mpidr_hash.bits = bits[3] + bits[2] + bits[1] + bits[0]; 184976d7d3fSLorenzo Pieralisi pr_debug("MPIDR hash: aff0[%u] aff1[%u] aff2[%u] aff3[%u] mask[%#llx] bits[%u]\n", 185976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[0], 186976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[1], 187976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[2], 188976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[3], 189976d7d3fSLorenzo Pieralisi mpidr_hash.mask, 190976d7d3fSLorenzo Pieralisi mpidr_hash.bits); 191976d7d3fSLorenzo Pieralisi /* 192976d7d3fSLorenzo Pieralisi * 4x is an arbitrary value used to warn on a hash table much bigger 193976d7d3fSLorenzo Pieralisi * than expected on most systems. 194976d7d3fSLorenzo Pieralisi */ 195976d7d3fSLorenzo Pieralisi if (mpidr_hash_size() > 4 * num_possible_cpus()) 196976d7d3fSLorenzo Pieralisi pr_warn("Large number of MPIDR hash buckets detected\n"); 197976d7d3fSLorenzo Pieralisi __flush_dcache_area(&mpidr_hash, sizeof(struct mpidr_hash)); 198976d7d3fSLorenzo Pieralisi } 199976d7d3fSLorenzo Pieralisi #endif 200976d7d3fSLorenzo Pieralisi 201667f3fd3SMark Rutland static void __init hyp_mode_check(void) 202667f3fd3SMark Rutland { 203667f3fd3SMark Rutland if (is_hyp_mode_available()) 204667f3fd3SMark Rutland pr_info("CPU: All CPU(s) started at EL2\n"); 205667f3fd3SMark Rutland else if (is_hyp_mode_mismatched()) 206667f3fd3SMark Rutland WARN_TAINT(1, TAINT_CPU_OUT_OF_SPEC, 207667f3fd3SMark Rutland "CPU: CPUs started in inconsistent modes"); 208667f3fd3SMark Rutland else 209667f3fd3SMark Rutland pr_info("CPU: All CPU(s) started at EL1\n"); 210667f3fd3SMark Rutland } 211667f3fd3SMark Rutland 212137650aaSMark Rutland void __init do_post_cpus_up_work(void) 213137650aaSMark Rutland { 214667f3fd3SMark Rutland hyp_mode_check(); 215137650aaSMark Rutland apply_alternatives_all(); 216137650aaSMark Rutland } 217137650aaSMark Rutland 218137650aaSMark Rutland #ifdef CONFIG_UP_LATE_INIT 219137650aaSMark Rutland void __init up_late_init(void) 220137650aaSMark Rutland { 221137650aaSMark Rutland do_post_cpus_up_work(); 222137650aaSMark Rutland } 223137650aaSMark Rutland #endif /* CONFIG_UP_LATE_INIT */ 224137650aaSMark Rutland 2259703d9d7SCatalin Marinas static void __init setup_processor(void) 2269703d9d7SCatalin Marinas { 2274bff28ccSSteve Capper u64 features, block; 228a41dc0e8SCatalin Marinas u32 cwg; 229a41dc0e8SCatalin Marinas int cls; 2309703d9d7SCatalin Marinas 231a591ede4SMarc Zyngier printk("CPU: AArch64 Processor [%08x] revision %d\n", 232a591ede4SMarc Zyngier read_cpuid_id(), read_cpuid_id() & 15); 2339703d9d7SCatalin Marinas 23494ed1f2cSWill Deacon sprintf(init_utsname()->machine, ELF_PLATFORM); 2359703d9d7SCatalin Marinas elf_hwcap = 0; 2364bff28ccSSteve Capper 237df857416SMark Rutland cpuinfo_store_boot_cpu(); 238df857416SMark Rutland 2394bff28ccSSteve Capper /* 240a41dc0e8SCatalin Marinas * Check for sane CTR_EL0.CWG value. 241a41dc0e8SCatalin Marinas */ 242a41dc0e8SCatalin Marinas cwg = cache_type_cwg(); 243a41dc0e8SCatalin Marinas cls = cache_line_size(); 244a41dc0e8SCatalin Marinas if (!cwg) 245a41dc0e8SCatalin Marinas pr_warn("No Cache Writeback Granule information, assuming cache line size %d\n", 246a41dc0e8SCatalin Marinas cls); 247a41dc0e8SCatalin Marinas if (L1_CACHE_BYTES < cls) 248a41dc0e8SCatalin Marinas pr_warn("L1_CACHE_BYTES smaller than the Cache Writeback Granule (%d < %d)\n", 249a41dc0e8SCatalin Marinas L1_CACHE_BYTES, cls); 250a41dc0e8SCatalin Marinas 251a41dc0e8SCatalin Marinas /* 2524bff28ccSSteve Capper * ID_AA64ISAR0_EL1 contains 4-bit wide signed feature blocks. 2534bff28ccSSteve Capper * The blocks we test below represent incremental functionality 2544bff28ccSSteve Capper * for non-negative values. Negative values are reserved. 2554bff28ccSSteve Capper */ 2564bff28ccSSteve Capper features = read_cpuid(ID_AA64ISAR0_EL1); 2574bff28ccSSteve Capper block = (features >> 4) & 0xf; 2584bff28ccSSteve Capper if (!(block & 0x8)) { 2594bff28ccSSteve Capper switch (block) { 2604bff28ccSSteve Capper default: 2614bff28ccSSteve Capper case 2: 2624bff28ccSSteve Capper elf_hwcap |= HWCAP_PMULL; 2634bff28ccSSteve Capper case 1: 2644bff28ccSSteve Capper elf_hwcap |= HWCAP_AES; 2654bff28ccSSteve Capper case 0: 2664bff28ccSSteve Capper break; 2674bff28ccSSteve Capper } 2684bff28ccSSteve Capper } 2694bff28ccSSteve Capper 2704bff28ccSSteve Capper block = (features >> 8) & 0xf; 2714bff28ccSSteve Capper if (block && !(block & 0x8)) 2724bff28ccSSteve Capper elf_hwcap |= HWCAP_SHA1; 2734bff28ccSSteve Capper 2744bff28ccSSteve Capper block = (features >> 12) & 0xf; 2754bff28ccSSteve Capper if (block && !(block & 0x8)) 2764bff28ccSSteve Capper elf_hwcap |= HWCAP_SHA2; 2774bff28ccSSteve Capper 2784bff28ccSSteve Capper block = (features >> 16) & 0xf; 2794bff28ccSSteve Capper if (block && !(block & 0x8)) 2804bff28ccSSteve Capper elf_hwcap |= HWCAP_CRC32; 2814cf761cdSArd Biesheuvel 2824cf761cdSArd Biesheuvel #ifdef CONFIG_COMPAT 2834cf761cdSArd Biesheuvel /* 2844cf761cdSArd Biesheuvel * ID_ISAR5_EL1 carries similar information as above, but pertaining to 2854cf761cdSArd Biesheuvel * the Aarch32 32-bit execution state. 2864cf761cdSArd Biesheuvel */ 2874cf761cdSArd Biesheuvel features = read_cpuid(ID_ISAR5_EL1); 2884cf761cdSArd Biesheuvel block = (features >> 4) & 0xf; 2894cf761cdSArd Biesheuvel if (!(block & 0x8)) { 2904cf761cdSArd Biesheuvel switch (block) { 2914cf761cdSArd Biesheuvel default: 2924cf761cdSArd Biesheuvel case 2: 2934cf761cdSArd Biesheuvel compat_elf_hwcap2 |= COMPAT_HWCAP2_PMULL; 2944cf761cdSArd Biesheuvel case 1: 2954cf761cdSArd Biesheuvel compat_elf_hwcap2 |= COMPAT_HWCAP2_AES; 2964cf761cdSArd Biesheuvel case 0: 2974cf761cdSArd Biesheuvel break; 2984cf761cdSArd Biesheuvel } 2994cf761cdSArd Biesheuvel } 3004cf761cdSArd Biesheuvel 3014cf761cdSArd Biesheuvel block = (features >> 8) & 0xf; 3024cf761cdSArd Biesheuvel if (block && !(block & 0x8)) 3034cf761cdSArd Biesheuvel compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA1; 3044cf761cdSArd Biesheuvel 3054cf761cdSArd Biesheuvel block = (features >> 12) & 0xf; 3064cf761cdSArd Biesheuvel if (block && !(block & 0x8)) 3074cf761cdSArd Biesheuvel compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA2; 3084cf761cdSArd Biesheuvel 3094cf761cdSArd Biesheuvel block = (features >> 16) & 0xf; 3104cf761cdSArd Biesheuvel if (block && !(block & 0x8)) 3114cf761cdSArd Biesheuvel compat_elf_hwcap2 |= COMPAT_HWCAP2_CRC32; 3124cf761cdSArd Biesheuvel #endif 3139703d9d7SCatalin Marinas } 3149703d9d7SCatalin Marinas 3159703d9d7SCatalin Marinas static void __init setup_machine_fdt(phys_addr_t dt_phys) 3169703d9d7SCatalin Marinas { 317*61bd93ceSArd Biesheuvel void *dt_virt = fixmap_remap_fdt(dt_phys); 318*61bd93ceSArd Biesheuvel 319*61bd93ceSArd Biesheuvel if (!dt_virt || !early_init_dt_scan(dt_virt)) { 320*61bd93ceSArd Biesheuvel pr_crit("\n" 321*61bd93ceSArd Biesheuvel "Error: invalid device tree blob at physical address %pa (virtual address 0x%p)\n" 322*61bd93ceSArd Biesheuvel "The dtb must be 8-byte aligned and must not exceed 2 MB in size\n" 323*61bd93ceSArd Biesheuvel "\nPlease check your bootloader.", 324*61bd93ceSArd Biesheuvel &dt_phys, dt_virt); 3259703d9d7SCatalin Marinas 3269703d9d7SCatalin Marinas while (true) 3279703d9d7SCatalin Marinas cpu_relax(); 3289703d9d7SCatalin Marinas } 3295e39977eSWill Deacon 33044b82b77SMark Rutland dump_stack_set_arch_desc("%s (DT)", of_flat_dt_get_machine_name()); 3319703d9d7SCatalin Marinas } 3329703d9d7SCatalin Marinas 3339703d9d7SCatalin Marinas static void __init request_standard_resources(void) 3349703d9d7SCatalin Marinas { 3359703d9d7SCatalin Marinas struct memblock_region *region; 3369703d9d7SCatalin Marinas struct resource *res; 3379703d9d7SCatalin Marinas 3389703d9d7SCatalin Marinas kernel_code.start = virt_to_phys(_text); 3399703d9d7SCatalin Marinas kernel_code.end = virt_to_phys(_etext - 1); 3409703d9d7SCatalin Marinas kernel_data.start = virt_to_phys(_sdata); 3419703d9d7SCatalin Marinas kernel_data.end = virt_to_phys(_end - 1); 3429703d9d7SCatalin Marinas 3439703d9d7SCatalin Marinas for_each_memblock(memory, region) { 3449703d9d7SCatalin Marinas res = alloc_bootmem_low(sizeof(*res)); 3459703d9d7SCatalin Marinas res->name = "System RAM"; 3469703d9d7SCatalin Marinas res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); 3479703d9d7SCatalin Marinas res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; 3489703d9d7SCatalin Marinas res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; 3499703d9d7SCatalin Marinas 3509703d9d7SCatalin Marinas request_resource(&iomem_resource, res); 3519703d9d7SCatalin Marinas 3529703d9d7SCatalin Marinas if (kernel_code.start >= res->start && 3539703d9d7SCatalin Marinas kernel_code.end <= res->end) 3549703d9d7SCatalin Marinas request_resource(res, &kernel_code); 3559703d9d7SCatalin Marinas if (kernel_data.start >= res->start && 3569703d9d7SCatalin Marinas kernel_data.end <= res->end) 3579703d9d7SCatalin Marinas request_resource(res, &kernel_data); 3589703d9d7SCatalin Marinas } 3599703d9d7SCatalin Marinas } 3609703d9d7SCatalin Marinas 3614c7aa002SJavi Merino u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID }; 3624c7aa002SJavi Merino 3639703d9d7SCatalin Marinas void __init setup_arch(char **cmdline_p) 3649703d9d7SCatalin Marinas { 3659703d9d7SCatalin Marinas setup_processor(); 3669703d9d7SCatalin Marinas 3679703d9d7SCatalin Marinas init_mm.start_code = (unsigned long) _text; 3689703d9d7SCatalin Marinas init_mm.end_code = (unsigned long) _etext; 3699703d9d7SCatalin Marinas init_mm.end_data = (unsigned long) _edata; 3709703d9d7SCatalin Marinas init_mm.brk = (unsigned long) _end; 3719703d9d7SCatalin Marinas 3729703d9d7SCatalin Marinas *cmdline_p = boot_command_line; 3739703d9d7SCatalin Marinas 374af86e597SLaura Abbott early_fixmap_init(); 375bf4b558eSMark Salter early_ioremap_init(); 3760bf757c7SMark Salter 377*61bd93ceSArd Biesheuvel setup_machine_fdt(__fdt_pointer); 378*61bd93ceSArd Biesheuvel 3799703d9d7SCatalin Marinas parse_early_param(); 3809703d9d7SCatalin Marinas 3817a9c43beSJon Masters /* 3827a9c43beSJon Masters * Unmask asynchronous aborts after bringing up possible earlycon. 3837a9c43beSJon Masters * (Report possible System Errors once we can report this occurred) 3847a9c43beSJon Masters */ 3857a9c43beSJon Masters local_async_enable(); 3867a9c43beSJon Masters 387f84d0275SMark Salter efi_init(); 3889703d9d7SCatalin Marinas arm64_memblock_init(); 3899703d9d7SCatalin Marinas 39037655163SAl Stone /* Parse the ACPI tables for possible boot-time configuration */ 39137655163SAl Stone acpi_boot_table_init(); 39237655163SAl Stone 3939703d9d7SCatalin Marinas paging_init(); 3949703d9d7SCatalin Marinas request_standard_resources(); 3959703d9d7SCatalin Marinas 3960e63ea48SArd Biesheuvel early_ioremap_reset(); 397f84d0275SMark Salter 398fb094eb1SLorenzo Pieralisi if (acpi_disabled) { 3999703d9d7SCatalin Marinas unflatten_device_tree(); 4007c59a3dfSGraeme Gregory psci_dt_init(); 401fccb9a81SHanjun Guo } else { 402fccb9a81SHanjun Guo psci_acpi_init(); 403fccb9a81SHanjun Guo } 404fccb9a81SHanjun Guo 4050f078336SLorenzo Pieralisi cpu_read_bootcpu_ops(); 406fccb9a81SHanjun Guo #ifdef CONFIG_SMP 4070f078336SLorenzo Pieralisi smp_init_cpus(); 408976d7d3fSLorenzo Pieralisi smp_build_mpidr_hash(); 4099703d9d7SCatalin Marinas #endif 4109703d9d7SCatalin Marinas 4119703d9d7SCatalin Marinas #ifdef CONFIG_VT 4129703d9d7SCatalin Marinas #if defined(CONFIG_VGA_CONSOLE) 4139703d9d7SCatalin Marinas conswitchp = &vga_con; 4149703d9d7SCatalin Marinas #elif defined(CONFIG_DUMMY_CONSOLE) 4159703d9d7SCatalin Marinas conswitchp = &dummy_con; 4169703d9d7SCatalin Marinas #endif 4179703d9d7SCatalin Marinas #endif 418da9c177dSArd Biesheuvel if (boot_args[1] || boot_args[2] || boot_args[3]) { 419da9c177dSArd Biesheuvel pr_err("WARNING: x1-x3 nonzero in violation of boot protocol:\n" 420da9c177dSArd Biesheuvel "\tx1: %016llx\n\tx2: %016llx\n\tx3: %016llx\n" 421da9c177dSArd Biesheuvel "This indicates a broken bootloader or old kernel\n", 422da9c177dSArd Biesheuvel boot_args[1], boot_args[2], boot_args[3]); 423da9c177dSArd Biesheuvel } 4249703d9d7SCatalin Marinas } 4259703d9d7SCatalin Marinas 426c560ecfeSCatalin Marinas static int __init arm64_device_init(void) 427de79a64dSCatalin Marinas { 42878d51e0bSRobin Murphy of_iommu_init(); 429c560ecfeSCatalin Marinas of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); 430de79a64dSCatalin Marinas return 0; 431de79a64dSCatalin Marinas } 4326ecba8ebSCatalin Marinas arch_initcall_sync(arm64_device_init); 433de79a64dSCatalin Marinas 4349703d9d7SCatalin Marinas static int __init topology_init(void) 4359703d9d7SCatalin Marinas { 4369703d9d7SCatalin Marinas int i; 4379703d9d7SCatalin Marinas 4389703d9d7SCatalin Marinas for_each_possible_cpu(i) { 439df857416SMark Rutland struct cpu *cpu = &per_cpu(cpu_data.cpu, i); 4409703d9d7SCatalin Marinas cpu->hotpluggable = 1; 4419703d9d7SCatalin Marinas register_cpu(cpu, i); 4429703d9d7SCatalin Marinas } 4439703d9d7SCatalin Marinas 4449703d9d7SCatalin Marinas return 0; 4459703d9d7SCatalin Marinas } 4469703d9d7SCatalin Marinas subsys_initcall(topology_init); 4479703d9d7SCatalin Marinas 4489703d9d7SCatalin Marinas static const char *hwcap_str[] = { 4499703d9d7SCatalin Marinas "fp", 4509703d9d7SCatalin Marinas "asimd", 45146efe547SSudeep KarkadaNagesha "evtstrm", 4524bff28ccSSteve Capper "aes", 4534bff28ccSSteve Capper "pmull", 4544bff28ccSSteve Capper "sha1", 4554bff28ccSSteve Capper "sha2", 4564bff28ccSSteve Capper "crc32", 4579703d9d7SCatalin Marinas NULL 4589703d9d7SCatalin Marinas }; 4599703d9d7SCatalin Marinas 46044b82b77SMark Rutland #ifdef CONFIG_COMPAT 46144b82b77SMark Rutland static const char *compat_hwcap_str[] = { 46244b82b77SMark Rutland "swp", 46344b82b77SMark Rutland "half", 46444b82b77SMark Rutland "thumb", 46544b82b77SMark Rutland "26bit", 46644b82b77SMark Rutland "fastmult", 46744b82b77SMark Rutland "fpa", 46844b82b77SMark Rutland "vfp", 46944b82b77SMark Rutland "edsp", 47044b82b77SMark Rutland "java", 47144b82b77SMark Rutland "iwmmxt", 47244b82b77SMark Rutland "crunch", 47344b82b77SMark Rutland "thumbee", 47444b82b77SMark Rutland "neon", 47544b82b77SMark Rutland "vfpv3", 47644b82b77SMark Rutland "vfpv3d16", 47744b82b77SMark Rutland "tls", 47844b82b77SMark Rutland "vfpv4", 47944b82b77SMark Rutland "idiva", 48044b82b77SMark Rutland "idivt", 48144b82b77SMark Rutland "vfpd32", 48244b82b77SMark Rutland "lpae", 48344b82b77SMark Rutland "evtstrm" 48444b82b77SMark Rutland }; 48544b82b77SMark Rutland 48644b82b77SMark Rutland static const char *compat_hwcap2_str[] = { 48744b82b77SMark Rutland "aes", 48844b82b77SMark Rutland "pmull", 48944b82b77SMark Rutland "sha1", 49044b82b77SMark Rutland "sha2", 49144b82b77SMark Rutland "crc32", 49244b82b77SMark Rutland NULL 49344b82b77SMark Rutland }; 49444b82b77SMark Rutland #endif /* CONFIG_COMPAT */ 49544b82b77SMark Rutland 4969703d9d7SCatalin Marinas static int c_show(struct seq_file *m, void *v) 4979703d9d7SCatalin Marinas { 49844b82b77SMark Rutland int i, j; 4999703d9d7SCatalin Marinas 5009703d9d7SCatalin Marinas for_each_online_cpu(i) { 50144b82b77SMark Rutland struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i); 50244b82b77SMark Rutland u32 midr = cpuinfo->reg_midr; 50344b82b77SMark Rutland 5049703d9d7SCatalin Marinas /* 5059703d9d7SCatalin Marinas * glibc reads /proc/cpuinfo to determine the number of 5069703d9d7SCatalin Marinas * online processors, looking for lines beginning with 5079703d9d7SCatalin Marinas * "processor". Give glibc what it expects. 5089703d9d7SCatalin Marinas */ 5099703d9d7SCatalin Marinas #ifdef CONFIG_SMP 5109703d9d7SCatalin Marinas seq_printf(m, "processor\t: %d\n", i); 5119703d9d7SCatalin Marinas #endif 5129703d9d7SCatalin Marinas 51344b82b77SMark Rutland /* 51444b82b77SMark Rutland * Dump out the common processor features in a single line. 51544b82b77SMark Rutland * Userspace should read the hwcaps with getauxval(AT_HWCAP) 51644b82b77SMark Rutland * rather than attempting to parse this, but there's a body of 51744b82b77SMark Rutland * software which does already (at least for 32-bit). 51844b82b77SMark Rutland */ 5195e39977eSWill Deacon seq_puts(m, "Features\t:"); 52044b82b77SMark Rutland if (personality(current->personality) == PER_LINUX32) { 52144b82b77SMark Rutland #ifdef CONFIG_COMPAT 52244b82b77SMark Rutland for (j = 0; compat_hwcap_str[j]; j++) 52344b82b77SMark Rutland if (compat_elf_hwcap & (1 << j)) 52444b82b77SMark Rutland seq_printf(m, " %s", compat_hwcap_str[j]); 5255e39977eSWill Deacon 52644b82b77SMark Rutland for (j = 0; compat_hwcap2_str[j]; j++) 52744b82b77SMark Rutland if (compat_elf_hwcap2 & (1 << j)) 52844b82b77SMark Rutland seq_printf(m, " %s", compat_hwcap2_str[j]); 52944b82b77SMark Rutland #endif /* CONFIG_COMPAT */ 53044b82b77SMark Rutland } else { 53144b82b77SMark Rutland for (j = 0; hwcap_str[j]; j++) 53244b82b77SMark Rutland if (elf_hwcap & (1 << j)) 53344b82b77SMark Rutland seq_printf(m, " %s", hwcap_str[j]); 53444b82b77SMark Rutland } 5355e39977eSWill Deacon seq_puts(m, "\n"); 5365e39977eSWill Deacon 53744b82b77SMark Rutland seq_printf(m, "CPU implementer\t: 0x%02x\n", 53844b82b77SMark Rutland MIDR_IMPLEMENTOR(midr)); 53944b82b77SMark Rutland seq_printf(m, "CPU architecture: 8\n"); 54044b82b77SMark Rutland seq_printf(m, "CPU variant\t: 0x%x\n", MIDR_VARIANT(midr)); 54144b82b77SMark Rutland seq_printf(m, "CPU part\t: 0x%03x\n", MIDR_PARTNUM(midr)); 54244b82b77SMark Rutland seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr)); 54344b82b77SMark Rutland } 5445e39977eSWill Deacon 5459703d9d7SCatalin Marinas return 0; 5469703d9d7SCatalin Marinas } 5479703d9d7SCatalin Marinas 5489703d9d7SCatalin Marinas static void *c_start(struct seq_file *m, loff_t *pos) 5499703d9d7SCatalin Marinas { 5509703d9d7SCatalin Marinas return *pos < 1 ? (void *)1 : NULL; 5519703d9d7SCatalin Marinas } 5529703d9d7SCatalin Marinas 5539703d9d7SCatalin Marinas static void *c_next(struct seq_file *m, void *v, loff_t *pos) 5549703d9d7SCatalin Marinas { 5559703d9d7SCatalin Marinas ++*pos; 5569703d9d7SCatalin Marinas return NULL; 5579703d9d7SCatalin Marinas } 5589703d9d7SCatalin Marinas 5599703d9d7SCatalin Marinas static void c_stop(struct seq_file *m, void *v) 5609703d9d7SCatalin Marinas { 5619703d9d7SCatalin Marinas } 5629703d9d7SCatalin Marinas 5639703d9d7SCatalin Marinas const struct seq_operations cpuinfo_op = { 5649703d9d7SCatalin Marinas .start = c_start, 5659703d9d7SCatalin Marinas .next = c_next, 5669703d9d7SCatalin Marinas .stop = c_stop, 5679703d9d7SCatalin Marinas .show = c_show 5689703d9d7SCatalin Marinas }; 569