xref: /openbmc/linux/arch/arm64/kernel/setup.c (revision 0f078336)
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 
1089703d9d7SCatalin Marinas void __init early_print(const char *str, ...)
1099703d9d7SCatalin Marinas {
1109703d9d7SCatalin Marinas 	char buf[256];
1119703d9d7SCatalin Marinas 	va_list ap;
1129703d9d7SCatalin Marinas 
1139703d9d7SCatalin Marinas 	va_start(ap, str);
1149703d9d7SCatalin Marinas 	vsnprintf(buf, sizeof(buf), str, ap);
1159703d9d7SCatalin Marinas 	va_end(ap);
1169703d9d7SCatalin Marinas 
1179703d9d7SCatalin Marinas 	printk("%s", buf);
1189703d9d7SCatalin Marinas }
1199703d9d7SCatalin Marinas 
120da9c177dSArd Biesheuvel /*
121da9c177dSArd Biesheuvel  * The recorded values of x0 .. x3 upon kernel entry.
122da9c177dSArd Biesheuvel  */
123da9c177dSArd Biesheuvel u64 __cacheline_aligned boot_args[4];
124da9c177dSArd Biesheuvel 
12571586276SWill Deacon void __init smp_setup_processor_id(void)
12671586276SWill Deacon {
12780708677SMark Rutland 	u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
12880708677SMark Rutland 	cpu_logical_map(0) = mpidr;
12980708677SMark Rutland 
13071586276SWill Deacon 	/*
13171586276SWill Deacon 	 * clear __my_cpu_offset on boot CPU to avoid hang caused by
13271586276SWill Deacon 	 * using percpu variable early, for example, lockdep will
13371586276SWill Deacon 	 * access percpu variable inside lock_release
13471586276SWill Deacon 	 */
13571586276SWill Deacon 	set_my_cpu_offset(0);
13680708677SMark Rutland 	pr_info("Booting Linux on physical CPU 0x%lx\n", (unsigned long)mpidr);
13771586276SWill Deacon }
13871586276SWill Deacon 
1396e15d0e0SSudeep KarkadaNagesha bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
1406e15d0e0SSudeep KarkadaNagesha {
1416e15d0e0SSudeep KarkadaNagesha 	return phys_id == cpu_logical_map(cpu);
1426e15d0e0SSudeep KarkadaNagesha }
1436e15d0e0SSudeep KarkadaNagesha 
144976d7d3fSLorenzo Pieralisi struct mpidr_hash mpidr_hash;
145976d7d3fSLorenzo Pieralisi #ifdef CONFIG_SMP
146976d7d3fSLorenzo Pieralisi /**
147976d7d3fSLorenzo Pieralisi  * smp_build_mpidr_hash - Pre-compute shifts required at each affinity
148976d7d3fSLorenzo Pieralisi  *			  level in order to build a linear index from an
149976d7d3fSLorenzo Pieralisi  *			  MPIDR value. Resulting algorithm is a collision
150976d7d3fSLorenzo Pieralisi  *			  free hash carried out through shifting and ORing
151976d7d3fSLorenzo Pieralisi  */
152976d7d3fSLorenzo Pieralisi static void __init smp_build_mpidr_hash(void)
153976d7d3fSLorenzo Pieralisi {
154976d7d3fSLorenzo Pieralisi 	u32 i, affinity, fs[4], bits[4], ls;
155976d7d3fSLorenzo Pieralisi 	u64 mask = 0;
156976d7d3fSLorenzo Pieralisi 	/*
157976d7d3fSLorenzo Pieralisi 	 * Pre-scan the list of MPIDRS and filter out bits that do
158976d7d3fSLorenzo Pieralisi 	 * not contribute to affinity levels, ie they never toggle.
159976d7d3fSLorenzo Pieralisi 	 */
160976d7d3fSLorenzo Pieralisi 	for_each_possible_cpu(i)
161976d7d3fSLorenzo Pieralisi 		mask |= (cpu_logical_map(i) ^ cpu_logical_map(0));
162976d7d3fSLorenzo Pieralisi 	pr_debug("mask of set bits %#llx\n", mask);
163976d7d3fSLorenzo Pieralisi 	/*
164976d7d3fSLorenzo Pieralisi 	 * Find and stash the last and first bit set at all affinity levels to
165976d7d3fSLorenzo Pieralisi 	 * check how many bits are required to represent them.
166976d7d3fSLorenzo Pieralisi 	 */
167976d7d3fSLorenzo Pieralisi 	for (i = 0; i < 4; i++) {
168976d7d3fSLorenzo Pieralisi 		affinity = MPIDR_AFFINITY_LEVEL(mask, i);
169976d7d3fSLorenzo Pieralisi 		/*
170976d7d3fSLorenzo Pieralisi 		 * Find the MSB bit and LSB bits position
171976d7d3fSLorenzo Pieralisi 		 * to determine how many bits are required
172976d7d3fSLorenzo Pieralisi 		 * to express the affinity level.
173976d7d3fSLorenzo Pieralisi 		 */
174976d7d3fSLorenzo Pieralisi 		ls = fls(affinity);
175976d7d3fSLorenzo Pieralisi 		fs[i] = affinity ? ffs(affinity) - 1 : 0;
176976d7d3fSLorenzo Pieralisi 		bits[i] = ls - fs[i];
177976d7d3fSLorenzo Pieralisi 	}
178976d7d3fSLorenzo Pieralisi 	/*
179976d7d3fSLorenzo Pieralisi 	 * An index can be created from the MPIDR_EL1 by isolating the
180976d7d3fSLorenzo Pieralisi 	 * significant bits at each affinity level and by shifting
181976d7d3fSLorenzo Pieralisi 	 * them in order to compress the 32 bits values space to a
182976d7d3fSLorenzo Pieralisi 	 * compressed set of values. This is equivalent to hashing
183976d7d3fSLorenzo Pieralisi 	 * the MPIDR_EL1 through shifting and ORing. It is a collision free
184976d7d3fSLorenzo Pieralisi 	 * hash though not minimal since some levels might contain a number
185976d7d3fSLorenzo Pieralisi 	 * of CPUs that is not an exact power of 2 and their bit
186976d7d3fSLorenzo Pieralisi 	 * representation might contain holes, eg MPIDR_EL1[7:0] = {0x2, 0x80}.
187976d7d3fSLorenzo Pieralisi 	 */
188976d7d3fSLorenzo Pieralisi 	mpidr_hash.shift_aff[0] = MPIDR_LEVEL_SHIFT(0) + fs[0];
189976d7d3fSLorenzo Pieralisi 	mpidr_hash.shift_aff[1] = MPIDR_LEVEL_SHIFT(1) + fs[1] - bits[0];
190976d7d3fSLorenzo Pieralisi 	mpidr_hash.shift_aff[2] = MPIDR_LEVEL_SHIFT(2) + fs[2] -
191976d7d3fSLorenzo Pieralisi 						(bits[1] + bits[0]);
192976d7d3fSLorenzo Pieralisi 	mpidr_hash.shift_aff[3] = MPIDR_LEVEL_SHIFT(3) +
193976d7d3fSLorenzo Pieralisi 				  fs[3] - (bits[2] + bits[1] + bits[0]);
194976d7d3fSLorenzo Pieralisi 	mpidr_hash.mask = mask;
195976d7d3fSLorenzo Pieralisi 	mpidr_hash.bits = bits[3] + bits[2] + bits[1] + bits[0];
196976d7d3fSLorenzo Pieralisi 	pr_debug("MPIDR hash: aff0[%u] aff1[%u] aff2[%u] aff3[%u] mask[%#llx] bits[%u]\n",
197976d7d3fSLorenzo Pieralisi 		mpidr_hash.shift_aff[0],
198976d7d3fSLorenzo Pieralisi 		mpidr_hash.shift_aff[1],
199976d7d3fSLorenzo Pieralisi 		mpidr_hash.shift_aff[2],
200976d7d3fSLorenzo Pieralisi 		mpidr_hash.shift_aff[3],
201976d7d3fSLorenzo Pieralisi 		mpidr_hash.mask,
202976d7d3fSLorenzo Pieralisi 		mpidr_hash.bits);
203976d7d3fSLorenzo Pieralisi 	/*
204976d7d3fSLorenzo Pieralisi 	 * 4x is an arbitrary value used to warn on a hash table much bigger
205976d7d3fSLorenzo Pieralisi 	 * than expected on most systems.
206976d7d3fSLorenzo Pieralisi 	 */
207976d7d3fSLorenzo Pieralisi 	if (mpidr_hash_size() > 4 * num_possible_cpus())
208976d7d3fSLorenzo Pieralisi 		pr_warn("Large number of MPIDR hash buckets detected\n");
209976d7d3fSLorenzo Pieralisi 	__flush_dcache_area(&mpidr_hash, sizeof(struct mpidr_hash));
210976d7d3fSLorenzo Pieralisi }
211976d7d3fSLorenzo Pieralisi #endif
212976d7d3fSLorenzo Pieralisi 
213667f3fd3SMark Rutland static void __init hyp_mode_check(void)
214667f3fd3SMark Rutland {
215667f3fd3SMark Rutland 	if (is_hyp_mode_available())
216667f3fd3SMark Rutland 		pr_info("CPU: All CPU(s) started at EL2\n");
217667f3fd3SMark Rutland 	else if (is_hyp_mode_mismatched())
218667f3fd3SMark Rutland 		WARN_TAINT(1, TAINT_CPU_OUT_OF_SPEC,
219667f3fd3SMark Rutland 			   "CPU: CPUs started in inconsistent modes");
220667f3fd3SMark Rutland 	else
221667f3fd3SMark Rutland 		pr_info("CPU: All CPU(s) started at EL1\n");
222667f3fd3SMark Rutland }
223667f3fd3SMark Rutland 
224137650aaSMark Rutland void __init do_post_cpus_up_work(void)
225137650aaSMark Rutland {
226667f3fd3SMark Rutland 	hyp_mode_check();
227137650aaSMark Rutland 	apply_alternatives_all();
228137650aaSMark Rutland }
229137650aaSMark Rutland 
230137650aaSMark Rutland #ifdef CONFIG_UP_LATE_INIT
231137650aaSMark Rutland void __init up_late_init(void)
232137650aaSMark Rutland {
233137650aaSMark Rutland 	do_post_cpus_up_work();
234137650aaSMark Rutland }
235137650aaSMark Rutland #endif /* CONFIG_UP_LATE_INIT */
236137650aaSMark Rutland 
2379703d9d7SCatalin Marinas static void __init setup_processor(void)
2389703d9d7SCatalin Marinas {
2394bff28ccSSteve Capper 	u64 features, block;
240a41dc0e8SCatalin Marinas 	u32 cwg;
241a41dc0e8SCatalin Marinas 	int cls;
2429703d9d7SCatalin Marinas 
243a591ede4SMarc Zyngier 	printk("CPU: AArch64 Processor [%08x] revision %d\n",
244a591ede4SMarc Zyngier 	       read_cpuid_id(), read_cpuid_id() & 15);
2459703d9d7SCatalin Marinas 
24694ed1f2cSWill Deacon 	sprintf(init_utsname()->machine, ELF_PLATFORM);
2479703d9d7SCatalin Marinas 	elf_hwcap = 0;
2484bff28ccSSteve Capper 
249df857416SMark Rutland 	cpuinfo_store_boot_cpu();
250df857416SMark Rutland 
2514bff28ccSSteve Capper 	/*
252a41dc0e8SCatalin Marinas 	 * Check for sane CTR_EL0.CWG value.
253a41dc0e8SCatalin Marinas 	 */
254a41dc0e8SCatalin Marinas 	cwg = cache_type_cwg();
255a41dc0e8SCatalin Marinas 	cls = cache_line_size();
256a41dc0e8SCatalin Marinas 	if (!cwg)
257a41dc0e8SCatalin Marinas 		pr_warn("No Cache Writeback Granule information, assuming cache line size %d\n",
258a41dc0e8SCatalin Marinas 			cls);
259a41dc0e8SCatalin Marinas 	if (L1_CACHE_BYTES < cls)
260a41dc0e8SCatalin Marinas 		pr_warn("L1_CACHE_BYTES smaller than the Cache Writeback Granule (%d < %d)\n",
261a41dc0e8SCatalin Marinas 			L1_CACHE_BYTES, cls);
262a41dc0e8SCatalin Marinas 
263a41dc0e8SCatalin Marinas 	/*
2644bff28ccSSteve Capper 	 * ID_AA64ISAR0_EL1 contains 4-bit wide signed feature blocks.
2654bff28ccSSteve Capper 	 * The blocks we test below represent incremental functionality
2664bff28ccSSteve Capper 	 * for non-negative values. Negative values are reserved.
2674bff28ccSSteve Capper 	 */
2684bff28ccSSteve Capper 	features = read_cpuid(ID_AA64ISAR0_EL1);
2694bff28ccSSteve Capper 	block = (features >> 4) & 0xf;
2704bff28ccSSteve Capper 	if (!(block & 0x8)) {
2714bff28ccSSteve Capper 		switch (block) {
2724bff28ccSSteve Capper 		default:
2734bff28ccSSteve Capper 		case 2:
2744bff28ccSSteve Capper 			elf_hwcap |= HWCAP_PMULL;
2754bff28ccSSteve Capper 		case 1:
2764bff28ccSSteve Capper 			elf_hwcap |= HWCAP_AES;
2774bff28ccSSteve Capper 		case 0:
2784bff28ccSSteve Capper 			break;
2794bff28ccSSteve Capper 		}
2804bff28ccSSteve Capper 	}
2814bff28ccSSteve Capper 
2824bff28ccSSteve Capper 	block = (features >> 8) & 0xf;
2834bff28ccSSteve Capper 	if (block && !(block & 0x8))
2844bff28ccSSteve Capper 		elf_hwcap |= HWCAP_SHA1;
2854bff28ccSSteve Capper 
2864bff28ccSSteve Capper 	block = (features >> 12) & 0xf;
2874bff28ccSSteve Capper 	if (block && !(block & 0x8))
2884bff28ccSSteve Capper 		elf_hwcap |= HWCAP_SHA2;
2894bff28ccSSteve Capper 
2904bff28ccSSteve Capper 	block = (features >> 16) & 0xf;
2914bff28ccSSteve Capper 	if (block && !(block & 0x8))
2924bff28ccSSteve Capper 		elf_hwcap |= HWCAP_CRC32;
2934cf761cdSArd Biesheuvel 
2944cf761cdSArd Biesheuvel #ifdef CONFIG_COMPAT
2954cf761cdSArd Biesheuvel 	/*
2964cf761cdSArd Biesheuvel 	 * ID_ISAR5_EL1 carries similar information as above, but pertaining to
2974cf761cdSArd Biesheuvel 	 * the Aarch32 32-bit execution state.
2984cf761cdSArd Biesheuvel 	 */
2994cf761cdSArd Biesheuvel 	features = read_cpuid(ID_ISAR5_EL1);
3004cf761cdSArd Biesheuvel 	block = (features >> 4) & 0xf;
3014cf761cdSArd Biesheuvel 	if (!(block & 0x8)) {
3024cf761cdSArd Biesheuvel 		switch (block) {
3034cf761cdSArd Biesheuvel 		default:
3044cf761cdSArd Biesheuvel 		case 2:
3054cf761cdSArd Biesheuvel 			compat_elf_hwcap2 |= COMPAT_HWCAP2_PMULL;
3064cf761cdSArd Biesheuvel 		case 1:
3074cf761cdSArd Biesheuvel 			compat_elf_hwcap2 |= COMPAT_HWCAP2_AES;
3084cf761cdSArd Biesheuvel 		case 0:
3094cf761cdSArd Biesheuvel 			break;
3104cf761cdSArd Biesheuvel 		}
3114cf761cdSArd Biesheuvel 	}
3124cf761cdSArd Biesheuvel 
3134cf761cdSArd Biesheuvel 	block = (features >> 8) & 0xf;
3144cf761cdSArd Biesheuvel 	if (block && !(block & 0x8))
3154cf761cdSArd Biesheuvel 		compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA1;
3164cf761cdSArd Biesheuvel 
3174cf761cdSArd Biesheuvel 	block = (features >> 12) & 0xf;
3184cf761cdSArd Biesheuvel 	if (block && !(block & 0x8))
3194cf761cdSArd Biesheuvel 		compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA2;
3204cf761cdSArd Biesheuvel 
3214cf761cdSArd Biesheuvel 	block = (features >> 16) & 0xf;
3224cf761cdSArd Biesheuvel 	if (block && !(block & 0x8))
3234cf761cdSArd Biesheuvel 		compat_elf_hwcap2 |= COMPAT_HWCAP2_CRC32;
3244cf761cdSArd Biesheuvel #endif
3259703d9d7SCatalin Marinas }
3269703d9d7SCatalin Marinas 
3279703d9d7SCatalin Marinas static void __init setup_machine_fdt(phys_addr_t dt_phys)
3289703d9d7SCatalin Marinas {
329d5189cc5SRob Herring 	if (!dt_phys || !early_init_dt_scan(phys_to_virt(dt_phys))) {
3309703d9d7SCatalin Marinas 		early_print("\n"
3319703d9d7SCatalin Marinas 			"Error: invalid device tree blob at physical address 0x%p (virtual address 0x%p)\n"
332d5189cc5SRob Herring 			"The dtb must be 8-byte aligned and passed in the first 512MB of memory\n"
3339703d9d7SCatalin Marinas 			"\nPlease check your bootloader.\n",
334d5189cc5SRob Herring 			dt_phys, phys_to_virt(dt_phys));
3359703d9d7SCatalin Marinas 
3369703d9d7SCatalin Marinas 		while (true)
3379703d9d7SCatalin Marinas 			cpu_relax();
3389703d9d7SCatalin Marinas 	}
3395e39977eSWill Deacon 
34044b82b77SMark Rutland 	dump_stack_set_arch_desc("%s (DT)", of_flat_dt_get_machine_name());
3419703d9d7SCatalin Marinas }
3429703d9d7SCatalin Marinas 
3439703d9d7SCatalin Marinas static void __init request_standard_resources(void)
3449703d9d7SCatalin Marinas {
3459703d9d7SCatalin Marinas 	struct memblock_region *region;
3469703d9d7SCatalin Marinas 	struct resource *res;
3479703d9d7SCatalin Marinas 
3489703d9d7SCatalin Marinas 	kernel_code.start   = virt_to_phys(_text);
3499703d9d7SCatalin Marinas 	kernel_code.end     = virt_to_phys(_etext - 1);
3509703d9d7SCatalin Marinas 	kernel_data.start   = virt_to_phys(_sdata);
3519703d9d7SCatalin Marinas 	kernel_data.end     = virt_to_phys(_end - 1);
3529703d9d7SCatalin Marinas 
3539703d9d7SCatalin Marinas 	for_each_memblock(memory, region) {
3549703d9d7SCatalin Marinas 		res = alloc_bootmem_low(sizeof(*res));
3559703d9d7SCatalin Marinas 		res->name  = "System RAM";
3569703d9d7SCatalin Marinas 		res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
3579703d9d7SCatalin Marinas 		res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
3589703d9d7SCatalin Marinas 		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
3599703d9d7SCatalin Marinas 
3609703d9d7SCatalin Marinas 		request_resource(&iomem_resource, res);
3619703d9d7SCatalin Marinas 
3629703d9d7SCatalin Marinas 		if (kernel_code.start >= res->start &&
3639703d9d7SCatalin Marinas 		    kernel_code.end <= res->end)
3649703d9d7SCatalin Marinas 			request_resource(res, &kernel_code);
3659703d9d7SCatalin Marinas 		if (kernel_data.start >= res->start &&
3669703d9d7SCatalin Marinas 		    kernel_data.end <= res->end)
3679703d9d7SCatalin Marinas 			request_resource(res, &kernel_data);
3689703d9d7SCatalin Marinas 	}
3699703d9d7SCatalin Marinas }
3709703d9d7SCatalin Marinas 
3714c7aa002SJavi Merino u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
3724c7aa002SJavi Merino 
3739703d9d7SCatalin Marinas void __init setup_arch(char **cmdline_p)
3749703d9d7SCatalin Marinas {
3759703d9d7SCatalin Marinas 	setup_processor();
3769703d9d7SCatalin Marinas 
3779703d9d7SCatalin Marinas 	setup_machine_fdt(__fdt_pointer);
3789703d9d7SCatalin Marinas 
3799703d9d7SCatalin Marinas 	init_mm.start_code = (unsigned long) _text;
3809703d9d7SCatalin Marinas 	init_mm.end_code   = (unsigned long) _etext;
3819703d9d7SCatalin Marinas 	init_mm.end_data   = (unsigned long) _edata;
3829703d9d7SCatalin Marinas 	init_mm.brk	   = (unsigned long) _end;
3839703d9d7SCatalin Marinas 
3849703d9d7SCatalin Marinas 	*cmdline_p = boot_command_line;
3859703d9d7SCatalin Marinas 
386af86e597SLaura Abbott 	early_fixmap_init();
387bf4b558eSMark Salter 	early_ioremap_init();
3880bf757c7SMark Salter 
3899703d9d7SCatalin Marinas 	parse_early_param();
3909703d9d7SCatalin Marinas 
3917a9c43beSJon Masters 	/*
3927a9c43beSJon Masters 	 *  Unmask asynchronous aborts after bringing up possible earlycon.
3937a9c43beSJon Masters 	 * (Report possible System Errors once we can report this occurred)
3947a9c43beSJon Masters 	 */
3957a9c43beSJon Masters 	local_async_enable();
3967a9c43beSJon Masters 
397f84d0275SMark Salter 	efi_init();
3989703d9d7SCatalin Marinas 	arm64_memblock_init();
3999703d9d7SCatalin Marinas 
40037655163SAl Stone 	/* Parse the ACPI tables for possible boot-time configuration */
40137655163SAl Stone 	acpi_boot_table_init();
40237655163SAl Stone 
4039703d9d7SCatalin Marinas 	paging_init();
4049703d9d7SCatalin Marinas 	request_standard_resources();
4059703d9d7SCatalin Marinas 
4060e63ea48SArd Biesheuvel 	early_ioremap_reset();
407f84d0275SMark Salter 
408fb094eb1SLorenzo Pieralisi 	if (acpi_disabled) {
4099703d9d7SCatalin Marinas 		unflatten_device_tree();
4107c59a3dfSGraeme Gregory 		psci_dt_init();
411fccb9a81SHanjun Guo 	} else {
412fccb9a81SHanjun Guo 		psci_acpi_init();
413fccb9a81SHanjun Guo 	}
414fccb9a81SHanjun Guo 
4150f078336SLorenzo Pieralisi 	cpu_read_bootcpu_ops();
416fccb9a81SHanjun Guo #ifdef CONFIG_SMP
4170f078336SLorenzo Pieralisi 	smp_init_cpus();
418976d7d3fSLorenzo Pieralisi 	smp_build_mpidr_hash();
4199703d9d7SCatalin Marinas #endif
4209703d9d7SCatalin Marinas 
4219703d9d7SCatalin Marinas #ifdef CONFIG_VT
4229703d9d7SCatalin Marinas #if defined(CONFIG_VGA_CONSOLE)
4239703d9d7SCatalin Marinas 	conswitchp = &vga_con;
4249703d9d7SCatalin Marinas #elif defined(CONFIG_DUMMY_CONSOLE)
4259703d9d7SCatalin Marinas 	conswitchp = &dummy_con;
4269703d9d7SCatalin Marinas #endif
4279703d9d7SCatalin Marinas #endif
428da9c177dSArd Biesheuvel 	if (boot_args[1] || boot_args[2] || boot_args[3]) {
429da9c177dSArd Biesheuvel 		pr_err("WARNING: x1-x3 nonzero in violation of boot protocol:\n"
430da9c177dSArd Biesheuvel 			"\tx1: %016llx\n\tx2: %016llx\n\tx3: %016llx\n"
431da9c177dSArd Biesheuvel 			"This indicates a broken bootloader or old kernel\n",
432da9c177dSArd Biesheuvel 			boot_args[1], boot_args[2], boot_args[3]);
433da9c177dSArd Biesheuvel 	}
4349703d9d7SCatalin Marinas }
4359703d9d7SCatalin Marinas 
436c560ecfeSCatalin Marinas static int __init arm64_device_init(void)
437de79a64dSCatalin Marinas {
43878d51e0bSRobin Murphy 	of_iommu_init();
439c560ecfeSCatalin Marinas 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
440de79a64dSCatalin Marinas 	return 0;
441de79a64dSCatalin Marinas }
4426ecba8ebSCatalin Marinas arch_initcall_sync(arm64_device_init);
443de79a64dSCatalin Marinas 
4449703d9d7SCatalin Marinas static int __init topology_init(void)
4459703d9d7SCatalin Marinas {
4469703d9d7SCatalin Marinas 	int i;
4479703d9d7SCatalin Marinas 
4489703d9d7SCatalin Marinas 	for_each_possible_cpu(i) {
449df857416SMark Rutland 		struct cpu *cpu = &per_cpu(cpu_data.cpu, i);
4509703d9d7SCatalin Marinas 		cpu->hotpluggable = 1;
4519703d9d7SCatalin Marinas 		register_cpu(cpu, i);
4529703d9d7SCatalin Marinas 	}
4539703d9d7SCatalin Marinas 
4549703d9d7SCatalin Marinas 	return 0;
4559703d9d7SCatalin Marinas }
4569703d9d7SCatalin Marinas subsys_initcall(topology_init);
4579703d9d7SCatalin Marinas 
4589703d9d7SCatalin Marinas static const char *hwcap_str[] = {
4599703d9d7SCatalin Marinas 	"fp",
4609703d9d7SCatalin Marinas 	"asimd",
46146efe547SSudeep KarkadaNagesha 	"evtstrm",
4624bff28ccSSteve Capper 	"aes",
4634bff28ccSSteve Capper 	"pmull",
4644bff28ccSSteve Capper 	"sha1",
4654bff28ccSSteve Capper 	"sha2",
4664bff28ccSSteve Capper 	"crc32",
4679703d9d7SCatalin Marinas 	NULL
4689703d9d7SCatalin Marinas };
4699703d9d7SCatalin Marinas 
47044b82b77SMark Rutland #ifdef CONFIG_COMPAT
47144b82b77SMark Rutland static const char *compat_hwcap_str[] = {
47244b82b77SMark Rutland 	"swp",
47344b82b77SMark Rutland 	"half",
47444b82b77SMark Rutland 	"thumb",
47544b82b77SMark Rutland 	"26bit",
47644b82b77SMark Rutland 	"fastmult",
47744b82b77SMark Rutland 	"fpa",
47844b82b77SMark Rutland 	"vfp",
47944b82b77SMark Rutland 	"edsp",
48044b82b77SMark Rutland 	"java",
48144b82b77SMark Rutland 	"iwmmxt",
48244b82b77SMark Rutland 	"crunch",
48344b82b77SMark Rutland 	"thumbee",
48444b82b77SMark Rutland 	"neon",
48544b82b77SMark Rutland 	"vfpv3",
48644b82b77SMark Rutland 	"vfpv3d16",
48744b82b77SMark Rutland 	"tls",
48844b82b77SMark Rutland 	"vfpv4",
48944b82b77SMark Rutland 	"idiva",
49044b82b77SMark Rutland 	"idivt",
49144b82b77SMark Rutland 	"vfpd32",
49244b82b77SMark Rutland 	"lpae",
49344b82b77SMark Rutland 	"evtstrm"
49444b82b77SMark Rutland };
49544b82b77SMark Rutland 
49644b82b77SMark Rutland static const char *compat_hwcap2_str[] = {
49744b82b77SMark Rutland 	"aes",
49844b82b77SMark Rutland 	"pmull",
49944b82b77SMark Rutland 	"sha1",
50044b82b77SMark Rutland 	"sha2",
50144b82b77SMark Rutland 	"crc32",
50244b82b77SMark Rutland 	NULL
50344b82b77SMark Rutland };
50444b82b77SMark Rutland #endif /* CONFIG_COMPAT */
50544b82b77SMark Rutland 
5069703d9d7SCatalin Marinas static int c_show(struct seq_file *m, void *v)
5079703d9d7SCatalin Marinas {
50844b82b77SMark Rutland 	int i, j;
5099703d9d7SCatalin Marinas 
5109703d9d7SCatalin Marinas 	for_each_online_cpu(i) {
51144b82b77SMark Rutland 		struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
51244b82b77SMark Rutland 		u32 midr = cpuinfo->reg_midr;
51344b82b77SMark Rutland 
5149703d9d7SCatalin Marinas 		/*
5159703d9d7SCatalin Marinas 		 * glibc reads /proc/cpuinfo to determine the number of
5169703d9d7SCatalin Marinas 		 * online processors, looking for lines beginning with
5179703d9d7SCatalin Marinas 		 * "processor".  Give glibc what it expects.
5189703d9d7SCatalin Marinas 		 */
5199703d9d7SCatalin Marinas #ifdef CONFIG_SMP
5209703d9d7SCatalin Marinas 		seq_printf(m, "processor\t: %d\n", i);
5219703d9d7SCatalin Marinas #endif
5229703d9d7SCatalin Marinas 
52344b82b77SMark Rutland 		/*
52444b82b77SMark Rutland 		 * Dump out the common processor features in a single line.
52544b82b77SMark Rutland 		 * Userspace should read the hwcaps with getauxval(AT_HWCAP)
52644b82b77SMark Rutland 		 * rather than attempting to parse this, but there's a body of
52744b82b77SMark Rutland 		 * software which does already (at least for 32-bit).
52844b82b77SMark Rutland 		 */
5295e39977eSWill Deacon 		seq_puts(m, "Features\t:");
53044b82b77SMark Rutland 		if (personality(current->personality) == PER_LINUX32) {
53144b82b77SMark Rutland #ifdef CONFIG_COMPAT
53244b82b77SMark Rutland 			for (j = 0; compat_hwcap_str[j]; j++)
53344b82b77SMark Rutland 				if (compat_elf_hwcap & (1 << j))
53444b82b77SMark Rutland 					seq_printf(m, " %s", compat_hwcap_str[j]);
5355e39977eSWill Deacon 
53644b82b77SMark Rutland 			for (j = 0; compat_hwcap2_str[j]; j++)
53744b82b77SMark Rutland 				if (compat_elf_hwcap2 & (1 << j))
53844b82b77SMark Rutland 					seq_printf(m, " %s", compat_hwcap2_str[j]);
53944b82b77SMark Rutland #endif /* CONFIG_COMPAT */
54044b82b77SMark Rutland 		} else {
54144b82b77SMark Rutland 			for (j = 0; hwcap_str[j]; j++)
54244b82b77SMark Rutland 				if (elf_hwcap & (1 << j))
54344b82b77SMark Rutland 					seq_printf(m, " %s", hwcap_str[j]);
54444b82b77SMark Rutland 		}
5455e39977eSWill Deacon 		seq_puts(m, "\n");
5465e39977eSWill Deacon 
54744b82b77SMark Rutland 		seq_printf(m, "CPU implementer\t: 0x%02x\n",
54844b82b77SMark Rutland 			   MIDR_IMPLEMENTOR(midr));
54944b82b77SMark Rutland 		seq_printf(m, "CPU architecture: 8\n");
55044b82b77SMark Rutland 		seq_printf(m, "CPU variant\t: 0x%x\n", MIDR_VARIANT(midr));
55144b82b77SMark Rutland 		seq_printf(m, "CPU part\t: 0x%03x\n", MIDR_PARTNUM(midr));
55244b82b77SMark Rutland 		seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr));
55344b82b77SMark Rutland 	}
5545e39977eSWill Deacon 
5559703d9d7SCatalin Marinas 	return 0;
5569703d9d7SCatalin Marinas }
5579703d9d7SCatalin Marinas 
5589703d9d7SCatalin Marinas static void *c_start(struct seq_file *m, loff_t *pos)
5599703d9d7SCatalin Marinas {
5609703d9d7SCatalin Marinas 	return *pos < 1 ? (void *)1 : NULL;
5619703d9d7SCatalin Marinas }
5629703d9d7SCatalin Marinas 
5639703d9d7SCatalin Marinas static void *c_next(struct seq_file *m, void *v, loff_t *pos)
5649703d9d7SCatalin Marinas {
5659703d9d7SCatalin Marinas 	++*pos;
5669703d9d7SCatalin Marinas 	return NULL;
5679703d9d7SCatalin Marinas }
5689703d9d7SCatalin Marinas 
5699703d9d7SCatalin Marinas static void c_stop(struct seq_file *m, void *v)
5709703d9d7SCatalin Marinas {
5719703d9d7SCatalin Marinas }
5729703d9d7SCatalin Marinas 
5739703d9d7SCatalin Marinas const struct seq_operations cpuinfo_op = {
5749703d9d7SCatalin Marinas 	.start	= c_start,
5759703d9d7SCatalin Marinas 	.next	= c_next,
5769703d9d7SCatalin Marinas 	.stop	= c_stop,
5779703d9d7SCatalin Marinas 	.show	= c_show
5789703d9d7SCatalin Marinas };
579