xref: /openbmc/linux/arch/riscv/kernel/setup.c (revision 8ebc80a25f9d9bf7a8e368b266d5b740c485c362)
1588cb88cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
276d2a049SPalmer Dabbelt /*
376d2a049SPalmer Dabbelt  * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
476d2a049SPalmer Dabbelt  *  Chen Liqin <liqin.chen@sunplusct.com>
576d2a049SPalmer Dabbelt  *  Lennox Wu <lennox.wu@sunplusct.com>
676d2a049SPalmer Dabbelt  * Copyright (C) 2012 Regents of the University of California
700ab027aSNick Kossifidis  * Copyright (C) 2020 FORTH-ICS/CARV
800ab027aSNick Kossifidis  *  Nick Kossifidis <mick@ics.forth.gr>
976d2a049SPalmer Dabbelt  */
1076d2a049SPalmer Dabbelt 
11724f4c0dSSunil V L #include <linux/acpi.h>
12a0418108SRob Herring #include <linux/cpu.h>
1376d2a049SPalmer Dabbelt #include <linux/init.h>
1476d2a049SPalmer Dabbelt #include <linux/mm.h>
1576d2a049SPalmer Dabbelt #include <linux/memblock.h>
1676d2a049SPalmer Dabbelt #include <linux/sched.h>
1776d2a049SPalmer Dabbelt #include <linux/console.h>
1876d2a049SPalmer Dabbelt #include <linux/screen_info.h>
1976d2a049SPalmer Dabbelt #include <linux/of_fdt.h>
2076d2a049SPalmer Dabbelt #include <linux/sched/task.h>
21f1e58583SAtish Patra #include <linux/smp.h>
22b91540d5SAtish Patra #include <linux/efi.h>
23e53d2818SNick Kossifidis #include <linux/crash_dump.h>
2454a519e6SAlexandre Ghiti #include <linux/panic_notifier.h>
2576d2a049SPalmer Dabbelt 
26f9956119SSunil V L #include <asm/acpi.h>
27ffb0b0afSHeiko Stuebner #include <asm/alternative.h>
281631ba12SHeiko Stuebner #include <asm/cacheflush.h>
291b0a08a4SAndrew Jones #include <asm/cpufeature.h>
30f1e58583SAtish Patra #include <asm/cpu_ops.h>
316262f661SAtish Patra #include <asm/early_ioremap.h>
3244c92257SVitaly Wool #include <asm/pgtable.h>
3376d2a049SPalmer Dabbelt #include <asm/setup.h>
3419a00869SAtish Patra #include <asm/set_memory.h>
3576d2a049SPalmer Dabbelt #include <asm/sections.h>
36b9dcd9e4SAtish Patra #include <asm/sbi.h>
3776d2a049SPalmer Dabbelt #include <asm/tlbflush.h>
3876d2a049SPalmer Dabbelt #include <asm/thread_info.h>
398ad8b727SNick Hu #include <asm/kasan.h>
40b91540d5SAtish Patra #include <asm/efi.h>
4176d2a049SPalmer Dabbelt 
42ffaee272SPaul Walmsley #include "head.h"
43ffaee272SPaul Walmsley 
44d9a5d5c4SArnd Bergmann #if defined(CONFIG_EFI)
45d9a5d5c4SArnd Bergmann struct screen_info screen_info __section(".data");
4676d2a049SPalmer Dabbelt #endif
4776d2a049SPalmer Dabbelt 
48aff77833SZong Li /*
49aff77833SZong Li  * The lucky hart to first increment this variable will boot the other cores.
50aff77833SZong Li  * This is used before the kernel initializes the BSS so it can't be in the
51aff77833SZong Li  * BSS.
52aff77833SZong Li  */
5344c92257SVitaly Wool atomic_t hart_lottery __section(".sdata")
5444c92257SVitaly Wool #ifdef CONFIG_XIP_KERNEL
5544c92257SVitaly Wool = ATOMIC_INIT(0xC001BEEF)
5644c92257SVitaly Wool #endif
5744c92257SVitaly Wool ;
58f99fb607SAtish Patra unsigned long boot_cpu_hartid;
59f1e58583SAtish Patra static DEFINE_PER_CPU(struct cpu, cpu_devices);
6076d2a049SPalmer Dabbelt 
6100ab027aSNick Kossifidis /*
6200ab027aSNick Kossifidis  * Place kernel memory regions on the resource tree so that
6300ab027aSNick Kossifidis  * kexec-tools can retrieve them from /proc/iomem. While there
6400ab027aSNick Kossifidis  * also add "System RAM" regions for compatibility with other
6500ab027aSNick Kossifidis  * archs, and the rest of the known regions for completeness.
6600ab027aSNick Kossifidis  */
67ffe0e526SNick Kossifidis static struct resource kimage_res = { .name = "Kernel image", };
6800ab027aSNick Kossifidis static struct resource code_res = { .name = "Kernel code", };
6900ab027aSNick Kossifidis static struct resource data_res = { .name = "Kernel data", };
7000ab027aSNick Kossifidis static struct resource rodata_res = { .name = "Kernel rodata", };
7100ab027aSNick Kossifidis static struct resource bss_res = { .name = "Kernel bss", };
7256409750SNick Kossifidis #ifdef CONFIG_CRASH_DUMP
7356409750SNick Kossifidis static struct resource elfcorehdr_res = { .name = "ELF Core hdr", };
7456409750SNick Kossifidis #endif
7500ab027aSNick Kossifidis 
add_resource(struct resource * parent,struct resource * res)7600ab027aSNick Kossifidis static int __init add_resource(struct resource *parent,
7700ab027aSNick Kossifidis 				struct resource *res)
7800ab027aSNick Kossifidis {
7900ab027aSNick Kossifidis 	int ret = 0;
8000ab027aSNick Kossifidis 
8100ab027aSNick Kossifidis 	ret = insert_resource(parent, res);
8200ab027aSNick Kossifidis 	if (ret < 0) {
8300ab027aSNick Kossifidis 		pr_err("Failed to add a %s resource at %llx\n",
8400ab027aSNick Kossifidis 			res->name, (unsigned long long) res->start);
8500ab027aSNick Kossifidis 		return ret;
8600ab027aSNick Kossifidis 	}
8700ab027aSNick Kossifidis 
8800ab027aSNick Kossifidis 	return 1;
8900ab027aSNick Kossifidis }
9000ab027aSNick Kossifidis 
add_kernel_resources(void)91ffe0e526SNick Kossifidis static int __init add_kernel_resources(void)
9200ab027aSNick Kossifidis {
9300ab027aSNick Kossifidis 	int ret = 0;
9400ab027aSNick Kossifidis 
9500ab027aSNick Kossifidis 	/*
9600ab027aSNick Kossifidis 	 * The memory region of the kernel image is continuous and
97ffe0e526SNick Kossifidis 	 * was reserved on setup_bootmem, register it here as a
98ffe0e526SNick Kossifidis 	 * resource, with the various segments of the image as
99ffe0e526SNick Kossifidis 	 * child nodes.
10000ab027aSNick Kossifidis 	 */
10100ab027aSNick Kossifidis 
10200ab027aSNick Kossifidis 	code_res.start = __pa_symbol(_text);
10300ab027aSNick Kossifidis 	code_res.end = __pa_symbol(_etext) - 1;
10400ab027aSNick Kossifidis 	code_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
10500ab027aSNick Kossifidis 
10600ab027aSNick Kossifidis 	rodata_res.start = __pa_symbol(__start_rodata);
10700ab027aSNick Kossifidis 	rodata_res.end = __pa_symbol(__end_rodata) - 1;
10800ab027aSNick Kossifidis 	rodata_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
10900ab027aSNick Kossifidis 
11000ab027aSNick Kossifidis 	data_res.start = __pa_symbol(_data);
11100ab027aSNick Kossifidis 	data_res.end = __pa_symbol(_edata) - 1;
11200ab027aSNick Kossifidis 	data_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
11300ab027aSNick Kossifidis 
11400ab027aSNick Kossifidis 	bss_res.start = __pa_symbol(__bss_start);
11500ab027aSNick Kossifidis 	bss_res.end = __pa_symbol(__bss_stop) - 1;
11600ab027aSNick Kossifidis 	bss_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
11700ab027aSNick Kossifidis 
118ffe0e526SNick Kossifidis 	kimage_res.start = code_res.start;
119ffe0e526SNick Kossifidis 	kimage_res.end = bss_res.end;
120ffe0e526SNick Kossifidis 	kimage_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
121ffe0e526SNick Kossifidis 
122ffe0e526SNick Kossifidis 	ret = add_resource(&iomem_resource, &kimage_res);
123ffe0e526SNick Kossifidis 	if (ret < 0)
124ffe0e526SNick Kossifidis 		return ret;
125ffe0e526SNick Kossifidis 
126ffe0e526SNick Kossifidis 	ret = add_resource(&kimage_res, &code_res);
127ffe0e526SNick Kossifidis 	if (ret < 0)
128ffe0e526SNick Kossifidis 		return ret;
129ffe0e526SNick Kossifidis 
130ffe0e526SNick Kossifidis 	ret = add_resource(&kimage_res, &rodata_res);
131ffe0e526SNick Kossifidis 	if (ret < 0)
132ffe0e526SNick Kossifidis 		return ret;
133ffe0e526SNick Kossifidis 
134ffe0e526SNick Kossifidis 	ret = add_resource(&kimage_res, &data_res);
135ffe0e526SNick Kossifidis 	if (ret < 0)
136ffe0e526SNick Kossifidis 		return ret;
137ffe0e526SNick Kossifidis 
138ffe0e526SNick Kossifidis 	ret = add_resource(&kimage_res, &bss_res);
139ffe0e526SNick Kossifidis 
140ffe0e526SNick Kossifidis 	return ret;
141ffe0e526SNick Kossifidis }
142ffe0e526SNick Kossifidis 
init_resources(void)143ffe0e526SNick Kossifidis static void __init init_resources(void)
144ffe0e526SNick Kossifidis {
145ffe0e526SNick Kossifidis 	struct memblock_region *region = NULL;
146ffe0e526SNick Kossifidis 	struct resource *res = NULL;
147ffe0e526SNick Kossifidis 	struct resource *mem_res = NULL;
148ffe0e526SNick Kossifidis 	size_t mem_res_sz = 0;
149ffe0e526SNick Kossifidis 	int num_resources = 0, res_idx = 0;
150ffe0e526SNick Kossifidis 	int ret = 0;
151ffe0e526SNick Kossifidis 
152ffe0e526SNick Kossifidis 	/* + 1 as memblock_alloc() might increase memblock.reserved.cnt */
153ffe0e526SNick Kossifidis 	num_resources = memblock.memory.cnt + memblock.reserved.cnt + 1;
154ffe0e526SNick Kossifidis 	res_idx = num_resources - 1;
155ffe0e526SNick Kossifidis 
156ffe0e526SNick Kossifidis 	mem_res_sz = num_resources * sizeof(*mem_res);
157797f0375SAtish Patra 	mem_res = memblock_alloc(mem_res_sz, SMP_CACHE_BYTES);
158797f0375SAtish Patra 	if (!mem_res)
159797f0375SAtish Patra 		panic("%s: Failed to allocate %zu bytes\n", __func__, mem_res_sz);
160ffe0e526SNick Kossifidis 
16100ab027aSNick Kossifidis 	/*
16200ab027aSNick Kossifidis 	 * Start by adding the reserved regions, if they overlap
16300ab027aSNick Kossifidis 	 * with /memory regions, insert_resource later on will take
16400ab027aSNick Kossifidis 	 * care of it.
16500ab027aSNick Kossifidis 	 */
166ffe0e526SNick Kossifidis 	ret = add_kernel_resources();
167ffe0e526SNick Kossifidis 	if (ret < 0)
168ffe0e526SNick Kossifidis 		goto error;
169ffe0e526SNick Kossifidis 
170bbc8486eSMingzheng Xing #ifdef CONFIG_KEXEC_CORE
171bbc8486eSMingzheng Xing 	if (crashk_res.start != crashk_res.end) {
172bbc8486eSMingzheng Xing 		ret = add_resource(&iomem_resource, &crashk_res);
173bbc8486eSMingzheng Xing 		if (ret < 0)
174bbc8486eSMingzheng Xing 			goto error;
175bbc8486eSMingzheng Xing 	}
176bbc8486eSMingzheng Xing 	if (crashk_low_res.start != crashk_low_res.end) {
177bbc8486eSMingzheng Xing 		ret = add_resource(&iomem_resource, &crashk_low_res);
178bbc8486eSMingzheng Xing 		if (ret < 0)
179bbc8486eSMingzheng Xing 			goto error;
180bbc8486eSMingzheng Xing 	}
181bbc8486eSMingzheng Xing #endif
182bbc8486eSMingzheng Xing 
18356409750SNick Kossifidis #ifdef CONFIG_CRASH_DUMP
18456409750SNick Kossifidis 	if (elfcorehdr_size > 0) {
18556409750SNick Kossifidis 		elfcorehdr_res.start = elfcorehdr_addr;
18656409750SNick Kossifidis 		elfcorehdr_res.end = elfcorehdr_addr + elfcorehdr_size - 1;
18756409750SNick Kossifidis 		elfcorehdr_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
18856409750SNick Kossifidis 		add_resource(&iomem_resource, &elfcorehdr_res);
18956409750SNick Kossifidis 	}
19056409750SNick Kossifidis #endif
19156409750SNick Kossifidis 
19200ab027aSNick Kossifidis 	for_each_reserved_mem_region(region) {
193ffe0e526SNick Kossifidis 		res = &mem_res[res_idx--];
19400ab027aSNick Kossifidis 
19500ab027aSNick Kossifidis 		res->name = "Reserved";
196e61bf5c0SXianting Tian 		res->flags = IORESOURCE_MEM | IORESOURCE_EXCLUSIVE;
19700ab027aSNick Kossifidis 		res->start = __pfn_to_phys(memblock_region_reserved_base_pfn(region));
19800ab027aSNick Kossifidis 		res->end = __pfn_to_phys(memblock_region_reserved_end_pfn(region)) - 1;
19900ab027aSNick Kossifidis 
20000ab027aSNick Kossifidis 		/*
20100ab027aSNick Kossifidis 		 * Ignore any other reserved regions within
20200ab027aSNick Kossifidis 		 * system memory.
20300ab027aSNick Kossifidis 		 */
204797f0375SAtish Patra 		if (memblock_is_memory(res->start)) {
205ffe0e526SNick Kossifidis 			/* Re-use this pre-allocated resource */
206ffe0e526SNick Kossifidis 			res_idx++;
20700ab027aSNick Kossifidis 			continue;
208797f0375SAtish Patra 		}
20900ab027aSNick Kossifidis 
21000ab027aSNick Kossifidis 		ret = add_resource(&iomem_resource, res);
21100ab027aSNick Kossifidis 		if (ret < 0)
21200ab027aSNick Kossifidis 			goto error;
21300ab027aSNick Kossifidis 	}
21400ab027aSNick Kossifidis 
21500ab027aSNick Kossifidis 	/* Add /memory regions to the resource tree */
21600ab027aSNick Kossifidis 	for_each_mem_region(region) {
217ffe0e526SNick Kossifidis 		res = &mem_res[res_idx--];
21800ab027aSNick Kossifidis 
21900ab027aSNick Kossifidis 		if (unlikely(memblock_is_nomap(region))) {
22000ab027aSNick Kossifidis 			res->name = "Reserved";
221e61bf5c0SXianting Tian 			res->flags = IORESOURCE_MEM | IORESOURCE_EXCLUSIVE;
22200ab027aSNick Kossifidis 		} else {
22300ab027aSNick Kossifidis 			res->name = "System RAM";
22400ab027aSNick Kossifidis 			res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
22500ab027aSNick Kossifidis 		}
22600ab027aSNick Kossifidis 
22700ab027aSNick Kossifidis 		res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
22800ab027aSNick Kossifidis 		res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
22900ab027aSNick Kossifidis 
23000ab027aSNick Kossifidis 		ret = add_resource(&iomem_resource, res);
23100ab027aSNick Kossifidis 		if (ret < 0)
23200ab027aSNick Kossifidis 			goto error;
23300ab027aSNick Kossifidis 	}
23400ab027aSNick Kossifidis 
235ffe0e526SNick Kossifidis 	/* Clean-up any unused pre-allocated resources */
236aa3e1ba3SPetr Pavlu 	if (res_idx >= 0)
2374421cca0SMike Rapoport 		memblock_free(mem_res, (res_idx + 1) * sizeof(*mem_res));
23800ab027aSNick Kossifidis 	return;
23900ab027aSNick Kossifidis 
24000ab027aSNick Kossifidis  error:
24100ab027aSNick Kossifidis 	/* Better an empty resource tree than an inconsistent one */
24200ab027aSNick Kossifidis 	release_child_resources(&iomem_resource);
2434421cca0SMike Rapoport 	memblock_free(mem_res, mem_res_sz);
24400ab027aSNick Kossifidis }
24500ab027aSNick Kossifidis 
24600ab027aSNick Kossifidis 
parse_dtb(void)2478f3a2b4aSAnup Patel static void __init parse_dtb(void)
24876d2a049SPalmer Dabbelt {
2498f3a2b4aSAnup Patel 	/* Early scan of device tree from init memory */
250aa9b1d0dSAlexandre Ghiti 	if (early_init_dt_scan(dtb_early_va, dtb_early_pa)) {
25146ad48e8SKefeng Wang 		const char *name = of_flat_dt_get_machine_name();
25246ad48e8SKefeng Wang 
25346ad48e8SKefeng Wang 		if (name) {
25446ad48e8SKefeng Wang 			pr_info("Machine model: %s\n", name);
25546ad48e8SKefeng Wang 			dump_stack_set_arch_desc("%s (DT)", name);
25646ad48e8SKefeng Wang 		}
25710f6913cSWenting Zhang 	} else {
25810f6913cSWenting Zhang 		pr_err("No DTB passed to the kernel\n");
25946ad48e8SKefeng Wang 	}
2608fd6e05cSPaul Walmsley 
2618fd6e05cSPaul Walmsley #ifdef CONFIG_CMDLINE_FORCE
262803930eeSJason Wang 	strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
2638fd6e05cSPaul Walmsley 	pr_info("Forcing kernel command line to: %s\n", boot_command_line);
2648fd6e05cSPaul Walmsley #endif
26576d2a049SPalmer Dabbelt }
26676d2a049SPalmer Dabbelt 
2678ee0b418SGreentime Hu extern void __init init_rt_signal_env(void);
2688ee0b418SGreentime Hu 
setup_arch(char ** cmdline_p)26976d2a049SPalmer Dabbelt void __init setup_arch(char **cmdline_p)
27076d2a049SPalmer Dabbelt {
2718f3a2b4aSAnup Patel 	parse_dtb();
272723a42f4SKefeng Wang 	setup_initial_init_mm(_stext, _etext, _edata, _end);
27376d2a049SPalmer Dabbelt 
274680f9b8eSAnup Patel 	*cmdline_p = boot_command_line;
275680f9b8eSAnup Patel 
2766262f661SAtish Patra 	early_ioremap_setup();
27724fc1808SJisheng Zhang 	sbi_init();
2786134b110SAnup Patel 	jump_label_init();
279680f9b8eSAnup Patel 	parse_early_param();
280680f9b8eSAnup Patel 
281b91540d5SAtish Patra 	efi_init();
28276d2a049SPalmer Dabbelt 	paging_init();
283724f4c0dSSunil V L 
284724f4c0dSSunil V L 	/* Parse the ACPI tables for possible boot-time configuration */
285724f4c0dSSunil V L 	acpi_boot_table_init();
286724f4c0dSSunil V L 
2872d268251SPalmer Dabbelt #if IS_ENABLED(CONFIG_BUILTIN_DTB)
2882d268251SPalmer Dabbelt 	unflatten_and_copy_device_tree();
2892d268251SPalmer Dabbelt #else
29076d2a049SPalmer Dabbelt 	unflatten_device_tree();
2912d268251SPalmer Dabbelt #endif
292cbd34f4bSAtish Patra 	misc_mem_init();
29351858aafSZong Li 
294e53d2818SNick Kossifidis 	init_resources();
29562149f35SAtish Patra 
2968ad8b727SNick Hu #ifdef CONFIG_KASAN
2978ad8b727SNick Hu 	kasan_init();
2988ad8b727SNick Hu #endif
2998ad8b727SNick Hu 
30076d2a049SPalmer Dabbelt #ifdef CONFIG_SMP
30176d2a049SPalmer Dabbelt 	setup_smp();
30276d2a049SPalmer Dabbelt #endif
30376d2a049SPalmer Dabbelt 
304f9956119SSunil V L 	if (!acpi_disabled)
305f9956119SSunil V L 		acpi_init_rintc_map();
306f9956119SSunil V L 
3077ea5a736SAndrew Jones 	riscv_init_cbo_blocksizes();
3088f7e001eSPalmer Dabbelt 	riscv_fill_hwcap();
309ffb0b0afSHeiko Stuebner 	apply_boot_alternatives();
310*dd8aad26SYong-Xuan Wang 	init_rt_signal_env();
3111b0a08a4SAndrew Jones 
312abcc445aSJisheng Zhang 	if (IS_ENABLED(CONFIG_RISCV_ISA_ZICBOM) &&
313abcc445aSJisheng Zhang 	    riscv_isa_extension_available(NULL, ZICBOM))
314abcc445aSJisheng Zhang 		riscv_noncoherent_supported();
31529267151SJisheng Zhang 	riscv_set_dma_cache_alignment();
3161b0a08a4SAndrew Jones 
3171b0a08a4SAndrew Jones 	riscv_user_isa_enable();
31876d2a049SPalmer Dabbelt }
319f1e58583SAtish Patra 
topology_init(void)320f1e58583SAtish Patra static int __init topology_init(void)
321f1e58583SAtish Patra {
3224f0e8eefSAtish Patra 	int i, ret;
3234f0e8eefSAtish Patra 
324f1e58583SAtish Patra 	for_each_possible_cpu(i) {
325f1e58583SAtish Patra 		struct cpu *cpu = &per_cpu(cpu_devices, i);
326f1e58583SAtish Patra 
327f1e58583SAtish Patra 		cpu->hotpluggable = cpu_has_hotplug(i);
3284f0e8eefSAtish Patra 		ret = register_cpu(cpu, i);
3294f0e8eefSAtish Patra 		if (unlikely(ret))
3304f0e8eefSAtish Patra 			pr_warn("Warning: %s: register_cpu %d failed (%d)\n",
3314f0e8eefSAtish Patra 			       __func__, i, ret);
332f1e58583SAtish Patra 	}
333f1e58583SAtish Patra 
334f1e58583SAtish Patra 	return 0;
335f1e58583SAtish Patra }
336f1e58583SAtish Patra subsys_initcall(topology_init);
33719a00869SAtish Patra 
free_initmem(void)33819a00869SAtish Patra void free_initmem(void)
33919a00869SAtish Patra {
3406fdd5d2fSBjörn Töpel 	if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)) {
3416fdd5d2fSBjörn Töpel 		set_kernel_memory(lm_alias(__init_begin), lm_alias(__init_end), set_memory_rw_nx);
3426fdd5d2fSBjörn Töpel 		if (IS_ENABLED(CONFIG_64BIT))
3436fdd5d2fSBjörn Töpel 			set_kernel_memory(__init_begin, __init_end, set_memory_nx);
3446fdd5d2fSBjörn Töpel 	}
345f105ea98SAtish Patra 
34619a00869SAtish Patra 	free_initmem_default(POISON_FREE_INITMEM);
34719a00869SAtish Patra }
34854a519e6SAlexandre Ghiti 
dump_kernel_offset(struct notifier_block * self,unsigned long v,void * p)34954a519e6SAlexandre Ghiti static int dump_kernel_offset(struct notifier_block *self,
35054a519e6SAlexandre Ghiti 			      unsigned long v, void *p)
35154a519e6SAlexandre Ghiti {
35254a519e6SAlexandre Ghiti 	pr_emerg("Kernel Offset: 0x%lx from 0x%lx\n",
35354a519e6SAlexandre Ghiti 		 kernel_map.virt_offset,
35454a519e6SAlexandre Ghiti 		 KERNEL_LINK_ADDR);
35554a519e6SAlexandre Ghiti 
35654a519e6SAlexandre Ghiti 	return 0;
35754a519e6SAlexandre Ghiti }
35854a519e6SAlexandre Ghiti 
35954a519e6SAlexandre Ghiti static struct notifier_block kernel_offset_notifier = {
36054a519e6SAlexandre Ghiti 	.notifier_call = dump_kernel_offset
36154a519e6SAlexandre Ghiti };
36254a519e6SAlexandre Ghiti 
register_kernel_offset_dumper(void)36354a519e6SAlexandre Ghiti static int __init register_kernel_offset_dumper(void)
36454a519e6SAlexandre Ghiti {
36554a519e6SAlexandre Ghiti 	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
36654a519e6SAlexandre Ghiti 		atomic_notifier_chain_register(&panic_notifier_list,
36754a519e6SAlexandre Ghiti 					       &kernel_offset_notifier);
36854a519e6SAlexandre Ghiti 
36954a519e6SAlexandre Ghiti 	return 0;
37054a519e6SAlexandre Ghiti }
37154a519e6SAlexandre Ghiti device_initcall(register_kernel_offset_dumper);
372