xref: /linux-6.15/kernel/crash_core.c (revision 02aff848)
140b0b3f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2692f66f2SHari Bathini /*
3692f66f2SHari Bathini  * crash.c - kernel crash support code.
4692f66f2SHari Bathini  * Copyright (C) 2002-2004 Eric Biederman  <[email protected]>
5692f66f2SHari Bathini  */
6692f66f2SHari Bathini 
744e8a5e9SStephen Boyd #include <linux/buildid.h>
871d2bcecSPhilipp Rudo #include <linux/init.h>
9692f66f2SHari Bathini #include <linux/utsname.h>
10692f66f2SHari Bathini #include <linux/vmalloc.h>
1146d36b1bSTao Liu #include <linux/sizes.h>
126f991cc3SEric DeVolder #include <linux/kexec.h>
1324726275SEric DeVolder #include <linux/memory.h>
14*02aff848SBaoquan He #include <linux/mm.h>
1524726275SEric DeVolder #include <linux/cpuhotplug.h>
160ab97169SBaoquan He #include <linux/memblock.h>
170ab97169SBaoquan He #include <linux/kmemleak.h>
18*02aff848SBaoquan He #include <linux/crash_core.h>
19*02aff848SBaoquan He #include <linux/reboot.h>
20*02aff848SBaoquan He #include <linux/btf.h>
21*02aff848SBaoquan He #include <linux/objtool.h>
22692f66f2SHari Bathini 
23692f66f2SHari Bathini #include <asm/page.h>
24692f66f2SHari Bathini #include <asm/sections.h>
25692f66f2SHari Bathini 
26a24d22b2SEric Biggers #include <crypto/sha1.h>
270935288cSVijay Balakrishna 
285fd8fea9SStephen Brennan #include "kallsyms_internal.h"
2924726275SEric DeVolder #include "kexec_internal.h"
305fd8fea9SStephen Brennan 
316f991cc3SEric DeVolder /* Per cpu memory for storing cpu states in case of system crash. */
326f991cc3SEric DeVolder note_buf_t __percpu *crash_notes;
33692f66f2SHari Bathini 
34*02aff848SBaoquan He #ifdef CONFIG_CRASH_DUMP
35*02aff848SBaoquan He 
36*02aff848SBaoquan He int kimage_crash_copy_vmcoreinfo(struct kimage *image)
37*02aff848SBaoquan He {
38*02aff848SBaoquan He 	struct page *vmcoreinfo_page;
39*02aff848SBaoquan He 	void *safecopy;
40*02aff848SBaoquan He 
41*02aff848SBaoquan He 	if (!IS_ENABLED(CONFIG_CRASH_DUMP))
42*02aff848SBaoquan He 		return 0;
43*02aff848SBaoquan He 	if (image->type != KEXEC_TYPE_CRASH)
44*02aff848SBaoquan He 		return 0;
45*02aff848SBaoquan He 
46*02aff848SBaoquan He 	/*
47*02aff848SBaoquan He 	 * For kdump, allocate one vmcoreinfo safe copy from the
48*02aff848SBaoquan He 	 * crash memory. as we have arch_kexec_protect_crashkres()
49*02aff848SBaoquan He 	 * after kexec syscall, we naturally protect it from write
50*02aff848SBaoquan He 	 * (even read) access under kernel direct mapping. But on
51*02aff848SBaoquan He 	 * the other hand, we still need to operate it when crash
52*02aff848SBaoquan He 	 * happens to generate vmcoreinfo note, hereby we rely on
53*02aff848SBaoquan He 	 * vmap for this purpose.
54*02aff848SBaoquan He 	 */
55*02aff848SBaoquan He 	vmcoreinfo_page = kimage_alloc_control_pages(image, 0);
56*02aff848SBaoquan He 	if (!vmcoreinfo_page) {
57*02aff848SBaoquan He 		pr_warn("Could not allocate vmcoreinfo buffer\n");
58*02aff848SBaoquan He 		return -ENOMEM;
59*02aff848SBaoquan He 	}
60*02aff848SBaoquan He 	safecopy = vmap(&vmcoreinfo_page, 1, VM_MAP, PAGE_KERNEL);
61*02aff848SBaoquan He 	if (!safecopy) {
62*02aff848SBaoquan He 		pr_warn("Could not vmap vmcoreinfo buffer\n");
63*02aff848SBaoquan He 		return -ENOMEM;
64*02aff848SBaoquan He 	}
65*02aff848SBaoquan He 
66*02aff848SBaoquan He 	image->vmcoreinfo_data_copy = safecopy;
67*02aff848SBaoquan He 	crash_update_vmcoreinfo_safecopy(safecopy);
68*02aff848SBaoquan He 
69*02aff848SBaoquan He 	return 0;
70*02aff848SBaoquan He }
71*02aff848SBaoquan He 
72*02aff848SBaoquan He 
73*02aff848SBaoquan He 
74*02aff848SBaoquan He int kexec_should_crash(struct task_struct *p)
75*02aff848SBaoquan He {
76*02aff848SBaoquan He 	/*
77*02aff848SBaoquan He 	 * If crash_kexec_post_notifiers is enabled, don't run
78*02aff848SBaoquan He 	 * crash_kexec() here yet, which must be run after panic
79*02aff848SBaoquan He 	 * notifiers in panic().
80*02aff848SBaoquan He 	 */
81*02aff848SBaoquan He 	if (crash_kexec_post_notifiers)
82*02aff848SBaoquan He 		return 0;
83*02aff848SBaoquan He 	/*
84*02aff848SBaoquan He 	 * There are 4 panic() calls in make_task_dead() path, each of which
85*02aff848SBaoquan He 	 * corresponds to each of these 4 conditions.
86*02aff848SBaoquan He 	 */
87*02aff848SBaoquan He 	if (in_interrupt() || !p->pid || is_global_init(p) || panic_on_oops)
88*02aff848SBaoquan He 		return 1;
89*02aff848SBaoquan He 	return 0;
90*02aff848SBaoquan He }
91*02aff848SBaoquan He 
92*02aff848SBaoquan He int kexec_crash_loaded(void)
93*02aff848SBaoquan He {
94*02aff848SBaoquan He 	return !!kexec_crash_image;
95*02aff848SBaoquan He }
96*02aff848SBaoquan He EXPORT_SYMBOL_GPL(kexec_crash_loaded);
97*02aff848SBaoquan He 
98*02aff848SBaoquan He /*
99*02aff848SBaoquan He  * No panic_cpu check version of crash_kexec().  This function is called
100*02aff848SBaoquan He  * only when panic_cpu holds the current CPU number; this is the only CPU
101*02aff848SBaoquan He  * which processes crash_kexec routines.
102*02aff848SBaoquan He  */
103*02aff848SBaoquan He void __noclone __crash_kexec(struct pt_regs *regs)
104*02aff848SBaoquan He {
105*02aff848SBaoquan He 	/* Take the kexec_lock here to prevent sys_kexec_load
106*02aff848SBaoquan He 	 * running on one cpu from replacing the crash kernel
107*02aff848SBaoquan He 	 * we are using after a panic on a different cpu.
108*02aff848SBaoquan He 	 *
109*02aff848SBaoquan He 	 * If the crash kernel was not located in a fixed area
110*02aff848SBaoquan He 	 * of memory the xchg(&kexec_crash_image) would be
111*02aff848SBaoquan He 	 * sufficient.  But since I reuse the memory...
112*02aff848SBaoquan He 	 */
113*02aff848SBaoquan He 	if (kexec_trylock()) {
114*02aff848SBaoquan He 		if (kexec_crash_image) {
115*02aff848SBaoquan He 			struct pt_regs fixed_regs;
116*02aff848SBaoquan He 
117*02aff848SBaoquan He 			crash_setup_regs(&fixed_regs, regs);
118*02aff848SBaoquan He 			crash_save_vmcoreinfo();
119*02aff848SBaoquan He 			machine_crash_shutdown(&fixed_regs);
120*02aff848SBaoquan He 			machine_kexec(kexec_crash_image);
121*02aff848SBaoquan He 		}
122*02aff848SBaoquan He 		kexec_unlock();
123*02aff848SBaoquan He 	}
124*02aff848SBaoquan He }
125*02aff848SBaoquan He STACK_FRAME_NON_STANDARD(__crash_kexec);
126*02aff848SBaoquan He 
127*02aff848SBaoquan He __bpf_kfunc void crash_kexec(struct pt_regs *regs)
128*02aff848SBaoquan He {
129*02aff848SBaoquan He 	int old_cpu, this_cpu;
130*02aff848SBaoquan He 
131*02aff848SBaoquan He 	/*
132*02aff848SBaoquan He 	 * Only one CPU is allowed to execute the crash_kexec() code as with
133*02aff848SBaoquan He 	 * panic().  Otherwise parallel calls of panic() and crash_kexec()
134*02aff848SBaoquan He 	 * may stop each other.  To exclude them, we use panic_cpu here too.
135*02aff848SBaoquan He 	 */
136*02aff848SBaoquan He 	old_cpu = PANIC_CPU_INVALID;
137*02aff848SBaoquan He 	this_cpu = raw_smp_processor_id();
138*02aff848SBaoquan He 
139*02aff848SBaoquan He 	if (atomic_try_cmpxchg(&panic_cpu, &old_cpu, this_cpu)) {
140*02aff848SBaoquan He 		/* This is the 1st CPU which comes here, so go ahead. */
141*02aff848SBaoquan He 		__crash_kexec(regs);
142*02aff848SBaoquan He 
143*02aff848SBaoquan He 		/*
144*02aff848SBaoquan He 		 * Reset panic_cpu to allow another panic()/crash_kexec()
145*02aff848SBaoquan He 		 * call.
146*02aff848SBaoquan He 		 */
147*02aff848SBaoquan He 		atomic_set(&panic_cpu, PANIC_CPU_INVALID);
148*02aff848SBaoquan He 	}
149*02aff848SBaoquan He }
150*02aff848SBaoquan He 
151*02aff848SBaoquan He static inline resource_size_t crash_resource_size(const struct resource *res)
152*02aff848SBaoquan He {
153*02aff848SBaoquan He 	return !res->end ? 0 : resource_size(res);
154*02aff848SBaoquan He }
155*02aff848SBaoquan He 
156*02aff848SBaoquan He 
157*02aff848SBaoquan He 
158*02aff848SBaoquan He 
1596f991cc3SEric DeVolder int crash_prepare_elf64_headers(struct crash_mem *mem, int need_kernel_map,
1606f991cc3SEric DeVolder 			  void **addr, unsigned long *sz)
1616f991cc3SEric DeVolder {
1626f991cc3SEric DeVolder 	Elf64_Ehdr *ehdr;
1636f991cc3SEric DeVolder 	Elf64_Phdr *phdr;
1646f991cc3SEric DeVolder 	unsigned long nr_cpus = num_possible_cpus(), nr_phdr, elf_sz;
1656f991cc3SEric DeVolder 	unsigned char *buf;
1666f991cc3SEric DeVolder 	unsigned int cpu, i;
1676f991cc3SEric DeVolder 	unsigned long long notes_addr;
1686f991cc3SEric DeVolder 	unsigned long mstart, mend;
1696f991cc3SEric DeVolder 
1706f991cc3SEric DeVolder 	/* extra phdr for vmcoreinfo ELF note */
1716f991cc3SEric DeVolder 	nr_phdr = nr_cpus + 1;
1726f991cc3SEric DeVolder 	nr_phdr += mem->nr_ranges;
1736f991cc3SEric DeVolder 
1746f991cc3SEric DeVolder 	/*
1756f991cc3SEric DeVolder 	 * kexec-tools creates an extra PT_LOAD phdr for kernel text mapping
1766f991cc3SEric DeVolder 	 * area (for example, ffffffff80000000 - ffffffffa0000000 on x86_64).
1776f991cc3SEric DeVolder 	 * I think this is required by tools like gdb. So same physical
1786f991cc3SEric DeVolder 	 * memory will be mapped in two ELF headers. One will contain kernel
1796f991cc3SEric DeVolder 	 * text virtual addresses and other will have __va(physical) addresses.
1806f991cc3SEric DeVolder 	 */
1816f991cc3SEric DeVolder 
1826f991cc3SEric DeVolder 	nr_phdr++;
1836f991cc3SEric DeVolder 	elf_sz = sizeof(Elf64_Ehdr) + nr_phdr * sizeof(Elf64_Phdr);
1846f991cc3SEric DeVolder 	elf_sz = ALIGN(elf_sz, ELF_CORE_HEADER_ALIGN);
1856f991cc3SEric DeVolder 
1866f991cc3SEric DeVolder 	buf = vzalloc(elf_sz);
1876f991cc3SEric DeVolder 	if (!buf)
1886f991cc3SEric DeVolder 		return -ENOMEM;
1896f991cc3SEric DeVolder 
1906f991cc3SEric DeVolder 	ehdr = (Elf64_Ehdr *)buf;
1916f991cc3SEric DeVolder 	phdr = (Elf64_Phdr *)(ehdr + 1);
1926f991cc3SEric DeVolder 	memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
1936f991cc3SEric DeVolder 	ehdr->e_ident[EI_CLASS] = ELFCLASS64;
1946f991cc3SEric DeVolder 	ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
1956f991cc3SEric DeVolder 	ehdr->e_ident[EI_VERSION] = EV_CURRENT;
1966f991cc3SEric DeVolder 	ehdr->e_ident[EI_OSABI] = ELF_OSABI;
1976f991cc3SEric DeVolder 	memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD);
1986f991cc3SEric DeVolder 	ehdr->e_type = ET_CORE;
1996f991cc3SEric DeVolder 	ehdr->e_machine = ELF_ARCH;
2006f991cc3SEric DeVolder 	ehdr->e_version = EV_CURRENT;
2016f991cc3SEric DeVolder 	ehdr->e_phoff = sizeof(Elf64_Ehdr);
2026f991cc3SEric DeVolder 	ehdr->e_ehsize = sizeof(Elf64_Ehdr);
2036f991cc3SEric DeVolder 	ehdr->e_phentsize = sizeof(Elf64_Phdr);
2046f991cc3SEric DeVolder 
205a396d0f8SEric DeVolder 	/* Prepare one phdr of type PT_NOTE for each possible CPU */
206a396d0f8SEric DeVolder 	for_each_possible_cpu(cpu) {
2076f991cc3SEric DeVolder 		phdr->p_type = PT_NOTE;
2086f991cc3SEric DeVolder 		notes_addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpu));
2096f991cc3SEric DeVolder 		phdr->p_offset = phdr->p_paddr = notes_addr;
2106f991cc3SEric DeVolder 		phdr->p_filesz = phdr->p_memsz = sizeof(note_buf_t);
2116f991cc3SEric DeVolder 		(ehdr->e_phnum)++;
2126f991cc3SEric DeVolder 		phdr++;
2136f991cc3SEric DeVolder 	}
2146f991cc3SEric DeVolder 
2156f991cc3SEric DeVolder 	/* Prepare one PT_NOTE header for vmcoreinfo */
2166f991cc3SEric DeVolder 	phdr->p_type = PT_NOTE;
2176f991cc3SEric DeVolder 	phdr->p_offset = phdr->p_paddr = paddr_vmcoreinfo_note();
2186f991cc3SEric DeVolder 	phdr->p_filesz = phdr->p_memsz = VMCOREINFO_NOTE_SIZE;
2196f991cc3SEric DeVolder 	(ehdr->e_phnum)++;
2206f991cc3SEric DeVolder 	phdr++;
2216f991cc3SEric DeVolder 
2226f991cc3SEric DeVolder 	/* Prepare PT_LOAD type program header for kernel text region */
2236f991cc3SEric DeVolder 	if (need_kernel_map) {
2246f991cc3SEric DeVolder 		phdr->p_type = PT_LOAD;
2256f991cc3SEric DeVolder 		phdr->p_flags = PF_R|PF_W|PF_X;
2266f991cc3SEric DeVolder 		phdr->p_vaddr = (unsigned long) _text;
2276f991cc3SEric DeVolder 		phdr->p_filesz = phdr->p_memsz = _end - _text;
2286f991cc3SEric DeVolder 		phdr->p_offset = phdr->p_paddr = __pa_symbol(_text);
2296f991cc3SEric DeVolder 		ehdr->e_phnum++;
2306f991cc3SEric DeVolder 		phdr++;
2316f991cc3SEric DeVolder 	}
2326f991cc3SEric DeVolder 
2336f991cc3SEric DeVolder 	/* Go through all the ranges in mem->ranges[] and prepare phdr */
2346f991cc3SEric DeVolder 	for (i = 0; i < mem->nr_ranges; i++) {
2356f991cc3SEric DeVolder 		mstart = mem->ranges[i].start;
2366f991cc3SEric DeVolder 		mend = mem->ranges[i].end;
2376f991cc3SEric DeVolder 
2386f991cc3SEric DeVolder 		phdr->p_type = PT_LOAD;
2396f991cc3SEric DeVolder 		phdr->p_flags = PF_R|PF_W|PF_X;
2406f991cc3SEric DeVolder 		phdr->p_offset  = mstart;
2416f991cc3SEric DeVolder 
2426f991cc3SEric DeVolder 		phdr->p_paddr = mstart;
2436f991cc3SEric DeVolder 		phdr->p_vaddr = (unsigned long) __va(mstart);
2446f991cc3SEric DeVolder 		phdr->p_filesz = phdr->p_memsz = mend - mstart + 1;
2456f991cc3SEric DeVolder 		phdr->p_align = 0;
2466f991cc3SEric DeVolder 		ehdr->e_phnum++;
247a85ee18cSBaoquan He #ifdef CONFIG_KEXEC_FILE
248a85ee18cSBaoquan He 		kexec_dprintk("Crash PT_LOAD ELF header. phdr=%p vaddr=0x%llx, paddr=0x%llx, sz=0x%llx e_phnum=%d p_offset=0x%llx\n",
2496f991cc3SEric DeVolder 			      phdr, phdr->p_vaddr, phdr->p_paddr, phdr->p_filesz,
2506f991cc3SEric DeVolder 			      ehdr->e_phnum, phdr->p_offset);
251a85ee18cSBaoquan He #endif
2526f991cc3SEric DeVolder 		phdr++;
2536f991cc3SEric DeVolder 	}
2546f991cc3SEric DeVolder 
2556f991cc3SEric DeVolder 	*addr = buf;
2566f991cc3SEric DeVolder 	*sz = elf_sz;
2576f991cc3SEric DeVolder 	return 0;
2586f991cc3SEric DeVolder }
2596f991cc3SEric DeVolder 
2606f991cc3SEric DeVolder int crash_exclude_mem_range(struct crash_mem *mem,
2616f991cc3SEric DeVolder 			    unsigned long long mstart, unsigned long long mend)
2626f991cc3SEric DeVolder {
2636dff3159SYuntao Wang 	int i;
2646f991cc3SEric DeVolder 	unsigned long long start, end, p_start, p_end;
2656f991cc3SEric DeVolder 
2666f991cc3SEric DeVolder 	for (i = 0; i < mem->nr_ranges; i++) {
2676f991cc3SEric DeVolder 		start = mem->ranges[i].start;
2686f991cc3SEric DeVolder 		end = mem->ranges[i].end;
2696f991cc3SEric DeVolder 		p_start = mstart;
2706f991cc3SEric DeVolder 		p_end = mend;
2716f991cc3SEric DeVolder 
2726dff3159SYuntao Wang 		if (p_start > end)
2736f991cc3SEric DeVolder 			continue;
2746f991cc3SEric DeVolder 
2756dff3159SYuntao Wang 		/*
2766dff3159SYuntao Wang 		 * Because the memory ranges in mem->ranges are stored in
2776dff3159SYuntao Wang 		 * ascending order, when we detect `p_end < start`, we can
2786dff3159SYuntao Wang 		 * immediately exit the for loop, as the subsequent memory
2796dff3159SYuntao Wang 		 * ranges will definitely be outside the range we are looking
2806dff3159SYuntao Wang 		 * for.
2816dff3159SYuntao Wang 		 */
2826dff3159SYuntao Wang 		if (p_end < start)
2836dff3159SYuntao Wang 			break;
2846dff3159SYuntao Wang 
2856f991cc3SEric DeVolder 		/* Truncate any area outside of range */
2866dff3159SYuntao Wang 		if (p_start < start)
2876f991cc3SEric DeVolder 			p_start = start;
2886dff3159SYuntao Wang 		if (p_end > end)
2896f991cc3SEric DeVolder 			p_end = end;
2906f991cc3SEric DeVolder 
2916f991cc3SEric DeVolder 		/* Found completely overlapping range */
2926f991cc3SEric DeVolder 		if (p_start == start && p_end == end) {
2936dff3159SYuntao Wang 			memmove(&mem->ranges[i], &mem->ranges[i + 1],
2946dff3159SYuntao Wang 				(mem->nr_ranges - (i + 1)) * sizeof(mem->ranges[i]));
2956f991cc3SEric DeVolder 			i--;
2966f991cc3SEric DeVolder 			mem->nr_ranges--;
2976dff3159SYuntao Wang 		} else if (p_start > start && p_end < end) {
2986f991cc3SEric DeVolder 			/* Split original range */
2996dff3159SYuntao Wang 			if (mem->nr_ranges >= mem->max_nr_ranges)
3006dff3159SYuntao Wang 				return -ENOMEM;
3016dff3159SYuntao Wang 
3026dff3159SYuntao Wang 			memmove(&mem->ranges[i + 2], &mem->ranges[i + 1],
3036dff3159SYuntao Wang 				(mem->nr_ranges - (i + 1)) * sizeof(mem->ranges[i]));
3046dff3159SYuntao Wang 
3056f991cc3SEric DeVolder 			mem->ranges[i].end = p_start - 1;
3066dff3159SYuntao Wang 			mem->ranges[i + 1].start = p_end + 1;
3076dff3159SYuntao Wang 			mem->ranges[i + 1].end = end;
3086dff3159SYuntao Wang 
3096dff3159SYuntao Wang 			i++;
3106dff3159SYuntao Wang 			mem->nr_ranges++;
3116f991cc3SEric DeVolder 		} else if (p_start != start)
3126f991cc3SEric DeVolder 			mem->ranges[i].end = p_start - 1;
3136f991cc3SEric DeVolder 		else
3146f991cc3SEric DeVolder 			mem->ranges[i].start = p_end + 1;
3156f991cc3SEric DeVolder 	}
3166f991cc3SEric DeVolder 
3176f991cc3SEric DeVolder 	return 0;
3186f991cc3SEric DeVolder }
3196f991cc3SEric DeVolder 
320*02aff848SBaoquan He ssize_t crash_get_memory_size(void)
321*02aff848SBaoquan He {
322*02aff848SBaoquan He 	ssize_t size = 0;
323*02aff848SBaoquan He 
324*02aff848SBaoquan He 	if (!kexec_trylock())
325*02aff848SBaoquan He 		return -EBUSY;
326*02aff848SBaoquan He 
327*02aff848SBaoquan He 	size += crash_resource_size(&crashk_res);
328*02aff848SBaoquan He 	size += crash_resource_size(&crashk_low_res);
329*02aff848SBaoquan He 
330*02aff848SBaoquan He 	kexec_unlock();
331*02aff848SBaoquan He 	return size;
332*02aff848SBaoquan He }
333*02aff848SBaoquan He 
334*02aff848SBaoquan He static int __crash_shrink_memory(struct resource *old_res,
335*02aff848SBaoquan He 				 unsigned long new_size)
336*02aff848SBaoquan He {
337*02aff848SBaoquan He 	struct resource *ram_res;
338*02aff848SBaoquan He 
339*02aff848SBaoquan He 	ram_res = kzalloc(sizeof(*ram_res), GFP_KERNEL);
340*02aff848SBaoquan He 	if (!ram_res)
341*02aff848SBaoquan He 		return -ENOMEM;
342*02aff848SBaoquan He 
343*02aff848SBaoquan He 	ram_res->start = old_res->start + new_size;
344*02aff848SBaoquan He 	ram_res->end   = old_res->end;
345*02aff848SBaoquan He 	ram_res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM;
346*02aff848SBaoquan He 	ram_res->name  = "System RAM";
347*02aff848SBaoquan He 
348*02aff848SBaoquan He 	if (!new_size) {
349*02aff848SBaoquan He 		release_resource(old_res);
350*02aff848SBaoquan He 		old_res->start = 0;
351*02aff848SBaoquan He 		old_res->end   = 0;
352*02aff848SBaoquan He 	} else {
353*02aff848SBaoquan He 		crashk_res.end = ram_res->start - 1;
354*02aff848SBaoquan He 	}
355*02aff848SBaoquan He 
356*02aff848SBaoquan He 	crash_free_reserved_phys_range(ram_res->start, ram_res->end);
357*02aff848SBaoquan He 	insert_resource(&iomem_resource, ram_res);
358*02aff848SBaoquan He 
359*02aff848SBaoquan He 	return 0;
360*02aff848SBaoquan He }
361*02aff848SBaoquan He 
362*02aff848SBaoquan He int crash_shrink_memory(unsigned long new_size)
363*02aff848SBaoquan He {
364*02aff848SBaoquan He 	int ret = 0;
365*02aff848SBaoquan He 	unsigned long old_size, low_size;
366*02aff848SBaoquan He 
367*02aff848SBaoquan He 	if (!kexec_trylock())
368*02aff848SBaoquan He 		return -EBUSY;
369*02aff848SBaoquan He 
370*02aff848SBaoquan He 	if (kexec_crash_image) {
371*02aff848SBaoquan He 		ret = -ENOENT;
372*02aff848SBaoquan He 		goto unlock;
373*02aff848SBaoquan He 	}
374*02aff848SBaoquan He 
375*02aff848SBaoquan He 	low_size = crash_resource_size(&crashk_low_res);
376*02aff848SBaoquan He 	old_size = crash_resource_size(&crashk_res) + low_size;
377*02aff848SBaoquan He 	new_size = roundup(new_size, KEXEC_CRASH_MEM_ALIGN);
378*02aff848SBaoquan He 	if (new_size >= old_size) {
379*02aff848SBaoquan He 		ret = (new_size == old_size) ? 0 : -EINVAL;
380*02aff848SBaoquan He 		goto unlock;
381*02aff848SBaoquan He 	}
382*02aff848SBaoquan He 
383*02aff848SBaoquan He 	/*
384*02aff848SBaoquan He 	 * (low_size > new_size) implies that low_size is greater than zero.
385*02aff848SBaoquan He 	 * This also means that if low_size is zero, the else branch is taken.
386*02aff848SBaoquan He 	 *
387*02aff848SBaoquan He 	 * If low_size is greater than 0, (low_size > new_size) indicates that
388*02aff848SBaoquan He 	 * crashk_low_res also needs to be shrunken. Otherwise, only crashk_res
389*02aff848SBaoquan He 	 * needs to be shrunken.
390*02aff848SBaoquan He 	 */
391*02aff848SBaoquan He 	if (low_size > new_size) {
392*02aff848SBaoquan He 		ret = __crash_shrink_memory(&crashk_res, 0);
393*02aff848SBaoquan He 		if (ret)
394*02aff848SBaoquan He 			goto unlock;
395*02aff848SBaoquan He 
396*02aff848SBaoquan He 		ret = __crash_shrink_memory(&crashk_low_res, new_size);
397*02aff848SBaoquan He 	} else {
398*02aff848SBaoquan He 		ret = __crash_shrink_memory(&crashk_res, new_size - low_size);
399*02aff848SBaoquan He 	}
400*02aff848SBaoquan He 
401*02aff848SBaoquan He 	/* Swap crashk_res and crashk_low_res if needed */
402*02aff848SBaoquan He 	if (!crashk_res.end && crashk_low_res.end) {
403*02aff848SBaoquan He 		crashk_res.start = crashk_low_res.start;
404*02aff848SBaoquan He 		crashk_res.end   = crashk_low_res.end;
405*02aff848SBaoquan He 		release_resource(&crashk_low_res);
406*02aff848SBaoquan He 		crashk_low_res.start = 0;
407*02aff848SBaoquan He 		crashk_low_res.end   = 0;
408*02aff848SBaoquan He 		insert_resource(&iomem_resource, &crashk_res);
409*02aff848SBaoquan He 	}
410*02aff848SBaoquan He 
411*02aff848SBaoquan He unlock:
412*02aff848SBaoquan He 	kexec_unlock();
413*02aff848SBaoquan He 	return ret;
414*02aff848SBaoquan He }
415*02aff848SBaoquan He 
416*02aff848SBaoquan He void crash_save_cpu(struct pt_regs *regs, int cpu)
417*02aff848SBaoquan He {
418*02aff848SBaoquan He 	struct elf_prstatus prstatus;
419*02aff848SBaoquan He 	u32 *buf;
420*02aff848SBaoquan He 
421*02aff848SBaoquan He 	if ((cpu < 0) || (cpu >= nr_cpu_ids))
422*02aff848SBaoquan He 		return;
423*02aff848SBaoquan He 
424*02aff848SBaoquan He 	/* Using ELF notes here is opportunistic.
425*02aff848SBaoquan He 	 * I need a well defined structure format
426*02aff848SBaoquan He 	 * for the data I pass, and I need tags
427*02aff848SBaoquan He 	 * on the data to indicate what information I have
428*02aff848SBaoquan He 	 * squirrelled away.  ELF notes happen to provide
429*02aff848SBaoquan He 	 * all of that, so there is no need to invent something new.
430*02aff848SBaoquan He 	 */
431*02aff848SBaoquan He 	buf = (u32 *)per_cpu_ptr(crash_notes, cpu);
432*02aff848SBaoquan He 	if (!buf)
433*02aff848SBaoquan He 		return;
434*02aff848SBaoquan He 	memset(&prstatus, 0, sizeof(prstatus));
435*02aff848SBaoquan He 	prstatus.common.pr_pid = current->pid;
436*02aff848SBaoquan He 	elf_core_copy_regs(&prstatus.pr_reg, regs);
437*02aff848SBaoquan He 	buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS,
438*02aff848SBaoquan He 			      &prstatus, sizeof(prstatus));
439*02aff848SBaoquan He 	final_note(buf);
440*02aff848SBaoquan He }
441*02aff848SBaoquan He 
442*02aff848SBaoquan He 
443*02aff848SBaoquan He 
4446f991cc3SEric DeVolder static int __init crash_notes_memory_init(void)
4456f991cc3SEric DeVolder {
4466f991cc3SEric DeVolder 	/* Allocate memory for saving cpu registers. */
4476f991cc3SEric DeVolder 	size_t size, align;
4486f991cc3SEric DeVolder 
4496f991cc3SEric DeVolder 	/*
4506f991cc3SEric DeVolder 	 * crash_notes could be allocated across 2 vmalloc pages when percpu
4516f991cc3SEric DeVolder 	 * is vmalloc based . vmalloc doesn't guarantee 2 continuous vmalloc
4526f991cc3SEric DeVolder 	 * pages are also on 2 continuous physical pages. In this case the
4536f991cc3SEric DeVolder 	 * 2nd part of crash_notes in 2nd page could be lost since only the
4546f991cc3SEric DeVolder 	 * starting address and size of crash_notes are exported through sysfs.
4556f991cc3SEric DeVolder 	 * Here round up the size of crash_notes to the nearest power of two
4566f991cc3SEric DeVolder 	 * and pass it to __alloc_percpu as align value. This can make sure
4576f991cc3SEric DeVolder 	 * crash_notes is allocated inside one physical page.
4586f991cc3SEric DeVolder 	 */
4596f991cc3SEric DeVolder 	size = sizeof(note_buf_t);
4606f991cc3SEric DeVolder 	align = min(roundup_pow_of_two(sizeof(note_buf_t)), PAGE_SIZE);
4616f991cc3SEric DeVolder 
4626f991cc3SEric DeVolder 	/*
4636f991cc3SEric DeVolder 	 * Break compile if size is bigger than PAGE_SIZE since crash_notes
4646f991cc3SEric DeVolder 	 * definitely will be in 2 pages with that.
4656f991cc3SEric DeVolder 	 */
4666f991cc3SEric DeVolder 	BUILD_BUG_ON(size > PAGE_SIZE);
4676f991cc3SEric DeVolder 
4686f991cc3SEric DeVolder 	crash_notes = __alloc_percpu(size, align);
4696f991cc3SEric DeVolder 	if (!crash_notes) {
4706f991cc3SEric DeVolder 		pr_warn("Memory allocation for saving cpu register states failed\n");
4716f991cc3SEric DeVolder 		return -ENOMEM;
4726f991cc3SEric DeVolder 	}
4736f991cc3SEric DeVolder 	return 0;
4746f991cc3SEric DeVolder }
4756f991cc3SEric DeVolder subsys_initcall(crash_notes_memory_init);
47624726275SEric DeVolder 
477*02aff848SBaoquan He #endif /*CONFIG_CRASH_DUMP*/
478*02aff848SBaoquan He 
47924726275SEric DeVolder #ifdef CONFIG_CRASH_HOTPLUG
48024726275SEric DeVolder #undef pr_fmt
48124726275SEric DeVolder #define pr_fmt(fmt) "crash hp: " fmt
482a72bbec7SEric DeVolder 
483a72bbec7SEric DeVolder /*
484e2a8f20dSBaoquan He  * Different than kexec/kdump loading/unloading/jumping/shrinking which
485e2a8f20dSBaoquan He  * usually rarely happen, there will be many crash hotplug events notified
486e2a8f20dSBaoquan He  * during one short period, e.g one memory board is hot added and memory
487e2a8f20dSBaoquan He  * regions are online. So mutex lock  __crash_hotplug_lock is used to
488e2a8f20dSBaoquan He  * serialize the crash hotplug handling specifically.
489e2a8f20dSBaoquan He  */
4904e87ff59SAndrew Morton static DEFINE_MUTEX(__crash_hotplug_lock);
491e2a8f20dSBaoquan He #define crash_hotplug_lock() mutex_lock(&__crash_hotplug_lock)
492e2a8f20dSBaoquan He #define crash_hotplug_unlock() mutex_unlock(&__crash_hotplug_lock)
493e2a8f20dSBaoquan He 
494e2a8f20dSBaoquan He /*
495a72bbec7SEric DeVolder  * This routine utilized when the crash_hotplug sysfs node is read.
496a72bbec7SEric DeVolder  * It reflects the kernel's ability/permission to update the crash
497a72bbec7SEric DeVolder  * elfcorehdr directly.
498a72bbec7SEric DeVolder  */
499a72bbec7SEric DeVolder int crash_check_update_elfcorehdr(void)
500a72bbec7SEric DeVolder {
501a72bbec7SEric DeVolder 	int rc = 0;
502a72bbec7SEric DeVolder 
503e2a8f20dSBaoquan He 	crash_hotplug_lock();
504a72bbec7SEric DeVolder 	/* Obtain lock while reading crash information */
505a72bbec7SEric DeVolder 	if (!kexec_trylock()) {
506a72bbec7SEric DeVolder 		pr_info("kexec_trylock() failed, elfcorehdr may be inaccurate\n");
507e2a8f20dSBaoquan He 		crash_hotplug_unlock();
508a72bbec7SEric DeVolder 		return 0;
509a72bbec7SEric DeVolder 	}
510a72bbec7SEric DeVolder 	if (kexec_crash_image) {
511a72bbec7SEric DeVolder 		if (kexec_crash_image->file_mode)
512a72bbec7SEric DeVolder 			rc = 1;
513a72bbec7SEric DeVolder 		else
514a72bbec7SEric DeVolder 			rc = kexec_crash_image->update_elfcorehdr;
515a72bbec7SEric DeVolder 	}
516a72bbec7SEric DeVolder 	/* Release lock now that update complete */
517a72bbec7SEric DeVolder 	kexec_unlock();
518e2a8f20dSBaoquan He 	crash_hotplug_unlock();
519a72bbec7SEric DeVolder 
520a72bbec7SEric DeVolder 	return rc;
521a72bbec7SEric DeVolder }
522a72bbec7SEric DeVolder 
52324726275SEric DeVolder /*
52424726275SEric DeVolder  * To accurately reflect hot un/plug changes of cpu and memory resources
52524726275SEric DeVolder  * (including onling and offlining of those resources), the elfcorehdr
52624726275SEric DeVolder  * (which is passed to the crash kernel via the elfcorehdr= parameter)
52724726275SEric DeVolder  * must be updated with the new list of CPUs and memories.
52824726275SEric DeVolder  *
52924726275SEric DeVolder  * In order to make changes to elfcorehdr, two conditions are needed:
53024726275SEric DeVolder  * First, the segment containing the elfcorehdr must be large enough
53124726275SEric DeVolder  * to permit a growing number of resources; the elfcorehdr memory size
53224726275SEric DeVolder  * is based on NR_CPUS_DEFAULT and CRASH_MAX_MEMORY_RANGES.
53324726275SEric DeVolder  * Second, purgatory must explicitly exclude the elfcorehdr from the
53424726275SEric DeVolder  * list of segments it checks (since the elfcorehdr changes and thus
53524726275SEric DeVolder  * would require an update to purgatory itself to update the digest).
53624726275SEric DeVolder  */
53724726275SEric DeVolder static void crash_handle_hotplug_event(unsigned int hp_action, unsigned int cpu)
53824726275SEric DeVolder {
53924726275SEric DeVolder 	struct kimage *image;
54024726275SEric DeVolder 
541e2a8f20dSBaoquan He 	crash_hotplug_lock();
54224726275SEric DeVolder 	/* Obtain lock while changing crash information */
54324726275SEric DeVolder 	if (!kexec_trylock()) {
54424726275SEric DeVolder 		pr_info("kexec_trylock() failed, elfcorehdr may be inaccurate\n");
545e2a8f20dSBaoquan He 		crash_hotplug_unlock();
54624726275SEric DeVolder 		return;
54724726275SEric DeVolder 	}
54824726275SEric DeVolder 
54924726275SEric DeVolder 	/* Check kdump is not loaded */
55024726275SEric DeVolder 	if (!kexec_crash_image)
55124726275SEric DeVolder 		goto out;
55224726275SEric DeVolder 
55324726275SEric DeVolder 	image = kexec_crash_image;
55424726275SEric DeVolder 
555a72bbec7SEric DeVolder 	/* Check that updating elfcorehdr is permitted */
556a72bbec7SEric DeVolder 	if (!(image->file_mode || image->update_elfcorehdr))
557a72bbec7SEric DeVolder 		goto out;
558a72bbec7SEric DeVolder 
55924726275SEric DeVolder 	if (hp_action == KEXEC_CRASH_HP_ADD_CPU ||
56024726275SEric DeVolder 		hp_action == KEXEC_CRASH_HP_REMOVE_CPU)
56124726275SEric DeVolder 		pr_debug("hp_action %u, cpu %u\n", hp_action, cpu);
56224726275SEric DeVolder 	else
56324726275SEric DeVolder 		pr_debug("hp_action %u\n", hp_action);
56424726275SEric DeVolder 
56524726275SEric DeVolder 	/*
56624726275SEric DeVolder 	 * The elfcorehdr_index is set to -1 when the struct kimage
56724726275SEric DeVolder 	 * is allocated. Find the segment containing the elfcorehdr,
56824726275SEric DeVolder 	 * if not already found.
56924726275SEric DeVolder 	 */
57024726275SEric DeVolder 	if (image->elfcorehdr_index < 0) {
57124726275SEric DeVolder 		unsigned long mem;
57224726275SEric DeVolder 		unsigned char *ptr;
57324726275SEric DeVolder 		unsigned int n;
57424726275SEric DeVolder 
57524726275SEric DeVolder 		for (n = 0; n < image->nr_segments; n++) {
57624726275SEric DeVolder 			mem = image->segment[n].mem;
57724726275SEric DeVolder 			ptr = kmap_local_page(pfn_to_page(mem >> PAGE_SHIFT));
57824726275SEric DeVolder 			if (ptr) {
57924726275SEric DeVolder 				/* The segment containing elfcorehdr */
58024726275SEric DeVolder 				if (memcmp(ptr, ELFMAG, SELFMAG) == 0)
58124726275SEric DeVolder 					image->elfcorehdr_index = (int)n;
58224726275SEric DeVolder 				kunmap_local(ptr);
58324726275SEric DeVolder 			}
58424726275SEric DeVolder 		}
58524726275SEric DeVolder 	}
58624726275SEric DeVolder 
58724726275SEric DeVolder 	if (image->elfcorehdr_index < 0) {
58824726275SEric DeVolder 		pr_err("unable to locate elfcorehdr segment");
58924726275SEric DeVolder 		goto out;
59024726275SEric DeVolder 	}
59124726275SEric DeVolder 
59224726275SEric DeVolder 	/* Needed in order for the segments to be updated */
59324726275SEric DeVolder 	arch_kexec_unprotect_crashkres();
59424726275SEric DeVolder 
59524726275SEric DeVolder 	/* Differentiate between normal load and hotplug update */
59624726275SEric DeVolder 	image->hp_action = hp_action;
59724726275SEric DeVolder 
59824726275SEric DeVolder 	/* Now invoke arch-specific update handler */
59924726275SEric DeVolder 	arch_crash_handle_hotplug_event(image);
60024726275SEric DeVolder 
60124726275SEric DeVolder 	/* No longer handling a hotplug event */
60224726275SEric DeVolder 	image->hp_action = KEXEC_CRASH_HP_NONE;
60324726275SEric DeVolder 	image->elfcorehdr_updated = true;
60424726275SEric DeVolder 
60524726275SEric DeVolder 	/* Change back to read-only */
60624726275SEric DeVolder 	arch_kexec_protect_crashkres();
60724726275SEric DeVolder 
60824726275SEric DeVolder 	/* Errors in the callback is not a reason to rollback state */
60924726275SEric DeVolder out:
61024726275SEric DeVolder 	/* Release lock now that update complete */
61124726275SEric DeVolder 	kexec_unlock();
612e2a8f20dSBaoquan He 	crash_hotplug_unlock();
61324726275SEric DeVolder }
61424726275SEric DeVolder 
61524726275SEric DeVolder static int crash_memhp_notifier(struct notifier_block *nb, unsigned long val, void *v)
61624726275SEric DeVolder {
61724726275SEric DeVolder 	switch (val) {
61824726275SEric DeVolder 	case MEM_ONLINE:
61924726275SEric DeVolder 		crash_handle_hotplug_event(KEXEC_CRASH_HP_ADD_MEMORY,
62024726275SEric DeVolder 			KEXEC_CRASH_HP_INVALID_CPU);
62124726275SEric DeVolder 		break;
62224726275SEric DeVolder 
62324726275SEric DeVolder 	case MEM_OFFLINE:
62424726275SEric DeVolder 		crash_handle_hotplug_event(KEXEC_CRASH_HP_REMOVE_MEMORY,
62524726275SEric DeVolder 			KEXEC_CRASH_HP_INVALID_CPU);
62624726275SEric DeVolder 		break;
62724726275SEric DeVolder 	}
62824726275SEric DeVolder 	return NOTIFY_OK;
62924726275SEric DeVolder }
63024726275SEric DeVolder 
63124726275SEric DeVolder static struct notifier_block crash_memhp_nb = {
63224726275SEric DeVolder 	.notifier_call = crash_memhp_notifier,
63324726275SEric DeVolder 	.priority = 0
63424726275SEric DeVolder };
63524726275SEric DeVolder 
63624726275SEric DeVolder static int crash_cpuhp_online(unsigned int cpu)
63724726275SEric DeVolder {
63824726275SEric DeVolder 	crash_handle_hotplug_event(KEXEC_CRASH_HP_ADD_CPU, cpu);
63924726275SEric DeVolder 	return 0;
64024726275SEric DeVolder }
64124726275SEric DeVolder 
64224726275SEric DeVolder static int crash_cpuhp_offline(unsigned int cpu)
64324726275SEric DeVolder {
64424726275SEric DeVolder 	crash_handle_hotplug_event(KEXEC_CRASH_HP_REMOVE_CPU, cpu);
64524726275SEric DeVolder 	return 0;
64624726275SEric DeVolder }
64724726275SEric DeVolder 
64824726275SEric DeVolder static int __init crash_hotplug_init(void)
64924726275SEric DeVolder {
65024726275SEric DeVolder 	int result = 0;
65124726275SEric DeVolder 
65224726275SEric DeVolder 	if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
65324726275SEric DeVolder 		register_memory_notifier(&crash_memhp_nb);
65424726275SEric DeVolder 
65524726275SEric DeVolder 	if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) {
65624726275SEric DeVolder 		result = cpuhp_setup_state_nocalls(CPUHP_BP_PREPARE_DYN,
65724726275SEric DeVolder 			"crash/cpuhp", crash_cpuhp_online, crash_cpuhp_offline);
65824726275SEric DeVolder 	}
65924726275SEric DeVolder 
66024726275SEric DeVolder 	return result;
66124726275SEric DeVolder }
66224726275SEric DeVolder 
66324726275SEric DeVolder subsys_initcall(crash_hotplug_init);
66424726275SEric DeVolder #endif
665