xref: /linux-6.15/kernel/crash_core.c (revision 4707c13d)
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 
7*4707c13dSBaoquan He #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8*4707c13dSBaoquan He 
944e8a5e9SStephen Boyd #include <linux/buildid.h>
1071d2bcecSPhilipp Rudo #include <linux/init.h>
11692f66f2SHari Bathini #include <linux/utsname.h>
12692f66f2SHari Bathini #include <linux/vmalloc.h>
1346d36b1bSTao Liu #include <linux/sizes.h>
146f991cc3SEric DeVolder #include <linux/kexec.h>
1524726275SEric DeVolder #include <linux/memory.h>
1602aff848SBaoquan He #include <linux/mm.h>
1724726275SEric DeVolder #include <linux/cpuhotplug.h>
180ab97169SBaoquan He #include <linux/memblock.h>
190ab97169SBaoquan He #include <linux/kmemleak.h>
2002aff848SBaoquan He #include <linux/crash_core.h>
2102aff848SBaoquan He #include <linux/reboot.h>
2202aff848SBaoquan He #include <linux/btf.h>
2302aff848SBaoquan He #include <linux/objtool.h>
24692f66f2SHari Bathini 
25692f66f2SHari Bathini #include <asm/page.h>
26692f66f2SHari Bathini #include <asm/sections.h>
27692f66f2SHari Bathini 
28a24d22b2SEric Biggers #include <crypto/sha1.h>
290935288cSVijay Balakrishna 
305fd8fea9SStephen Brennan #include "kallsyms_internal.h"
3124726275SEric DeVolder #include "kexec_internal.h"
325fd8fea9SStephen Brennan 
336f991cc3SEric DeVolder /* Per cpu memory for storing cpu states in case of system crash. */
346f991cc3SEric DeVolder note_buf_t __percpu *crash_notes;
35692f66f2SHari Bathini 
3602aff848SBaoquan He #ifdef CONFIG_CRASH_DUMP
3702aff848SBaoquan He 
3802aff848SBaoquan He int kimage_crash_copy_vmcoreinfo(struct kimage *image)
3902aff848SBaoquan He {
4002aff848SBaoquan He 	struct page *vmcoreinfo_page;
4102aff848SBaoquan He 	void *safecopy;
4202aff848SBaoquan He 
4302aff848SBaoquan He 	if (!IS_ENABLED(CONFIG_CRASH_DUMP))
4402aff848SBaoquan He 		return 0;
4502aff848SBaoquan He 	if (image->type != KEXEC_TYPE_CRASH)
4602aff848SBaoquan He 		return 0;
4702aff848SBaoquan He 
4802aff848SBaoquan He 	/*
4902aff848SBaoquan He 	 * For kdump, allocate one vmcoreinfo safe copy from the
5002aff848SBaoquan He 	 * crash memory. as we have arch_kexec_protect_crashkres()
5102aff848SBaoquan He 	 * after kexec syscall, we naturally protect it from write
5202aff848SBaoquan He 	 * (even read) access under kernel direct mapping. But on
5302aff848SBaoquan He 	 * the other hand, we still need to operate it when crash
5402aff848SBaoquan He 	 * happens to generate vmcoreinfo note, hereby we rely on
5502aff848SBaoquan He 	 * vmap for this purpose.
5602aff848SBaoquan He 	 */
5702aff848SBaoquan He 	vmcoreinfo_page = kimage_alloc_control_pages(image, 0);
5802aff848SBaoquan He 	if (!vmcoreinfo_page) {
5902aff848SBaoquan He 		pr_warn("Could not allocate vmcoreinfo buffer\n");
6002aff848SBaoquan He 		return -ENOMEM;
6102aff848SBaoquan He 	}
6202aff848SBaoquan He 	safecopy = vmap(&vmcoreinfo_page, 1, VM_MAP, PAGE_KERNEL);
6302aff848SBaoquan He 	if (!safecopy) {
6402aff848SBaoquan He 		pr_warn("Could not vmap vmcoreinfo buffer\n");
6502aff848SBaoquan He 		return -ENOMEM;
6602aff848SBaoquan He 	}
6702aff848SBaoquan He 
6802aff848SBaoquan He 	image->vmcoreinfo_data_copy = safecopy;
6902aff848SBaoquan He 	crash_update_vmcoreinfo_safecopy(safecopy);
7002aff848SBaoquan He 
7102aff848SBaoquan He 	return 0;
7202aff848SBaoquan He }
7302aff848SBaoquan He 
7402aff848SBaoquan He 
7502aff848SBaoquan He 
7602aff848SBaoquan He int kexec_should_crash(struct task_struct *p)
7702aff848SBaoquan He {
7802aff848SBaoquan He 	/*
7902aff848SBaoquan He 	 * If crash_kexec_post_notifiers is enabled, don't run
8002aff848SBaoquan He 	 * crash_kexec() here yet, which must be run after panic
8102aff848SBaoquan He 	 * notifiers in panic().
8202aff848SBaoquan He 	 */
8302aff848SBaoquan He 	if (crash_kexec_post_notifiers)
8402aff848SBaoquan He 		return 0;
8502aff848SBaoquan He 	/*
8602aff848SBaoquan He 	 * There are 4 panic() calls in make_task_dead() path, each of which
8702aff848SBaoquan He 	 * corresponds to each of these 4 conditions.
8802aff848SBaoquan He 	 */
8902aff848SBaoquan He 	if (in_interrupt() || !p->pid || is_global_init(p) || panic_on_oops)
9002aff848SBaoquan He 		return 1;
9102aff848SBaoquan He 	return 0;
9202aff848SBaoquan He }
9302aff848SBaoquan He 
9402aff848SBaoquan He int kexec_crash_loaded(void)
9502aff848SBaoquan He {
9602aff848SBaoquan He 	return !!kexec_crash_image;
9702aff848SBaoquan He }
9802aff848SBaoquan He EXPORT_SYMBOL_GPL(kexec_crash_loaded);
9902aff848SBaoquan He 
10002aff848SBaoquan He /*
10102aff848SBaoquan He  * No panic_cpu check version of crash_kexec().  This function is called
10202aff848SBaoquan He  * only when panic_cpu holds the current CPU number; this is the only CPU
10302aff848SBaoquan He  * which processes crash_kexec routines.
10402aff848SBaoquan He  */
10502aff848SBaoquan He void __noclone __crash_kexec(struct pt_regs *regs)
10602aff848SBaoquan He {
10702aff848SBaoquan He 	/* Take the kexec_lock here to prevent sys_kexec_load
10802aff848SBaoquan He 	 * running on one cpu from replacing the crash kernel
10902aff848SBaoquan He 	 * we are using after a panic on a different cpu.
11002aff848SBaoquan He 	 *
11102aff848SBaoquan He 	 * If the crash kernel was not located in a fixed area
11202aff848SBaoquan He 	 * of memory the xchg(&kexec_crash_image) would be
11302aff848SBaoquan He 	 * sufficient.  But since I reuse the memory...
11402aff848SBaoquan He 	 */
11502aff848SBaoquan He 	if (kexec_trylock()) {
11602aff848SBaoquan He 		if (kexec_crash_image) {
11702aff848SBaoquan He 			struct pt_regs fixed_regs;
11802aff848SBaoquan He 
11902aff848SBaoquan He 			crash_setup_regs(&fixed_regs, regs);
12002aff848SBaoquan He 			crash_save_vmcoreinfo();
12102aff848SBaoquan He 			machine_crash_shutdown(&fixed_regs);
12202aff848SBaoquan He 			machine_kexec(kexec_crash_image);
12302aff848SBaoquan He 		}
12402aff848SBaoquan He 		kexec_unlock();
12502aff848SBaoquan He 	}
12602aff848SBaoquan He }
12702aff848SBaoquan He STACK_FRAME_NON_STANDARD(__crash_kexec);
12802aff848SBaoquan He 
12902aff848SBaoquan He __bpf_kfunc void crash_kexec(struct pt_regs *regs)
13002aff848SBaoquan He {
13102aff848SBaoquan He 	int old_cpu, this_cpu;
13202aff848SBaoquan He 
13302aff848SBaoquan He 	/*
13402aff848SBaoquan He 	 * Only one CPU is allowed to execute the crash_kexec() code as with
13502aff848SBaoquan He 	 * panic().  Otherwise parallel calls of panic() and crash_kexec()
13602aff848SBaoquan He 	 * may stop each other.  To exclude them, we use panic_cpu here too.
13702aff848SBaoquan He 	 */
13802aff848SBaoquan He 	old_cpu = PANIC_CPU_INVALID;
13902aff848SBaoquan He 	this_cpu = raw_smp_processor_id();
14002aff848SBaoquan He 
14102aff848SBaoquan He 	if (atomic_try_cmpxchg(&panic_cpu, &old_cpu, this_cpu)) {
14202aff848SBaoquan He 		/* This is the 1st CPU which comes here, so go ahead. */
14302aff848SBaoquan He 		__crash_kexec(regs);
14402aff848SBaoquan He 
14502aff848SBaoquan He 		/*
14602aff848SBaoquan He 		 * Reset panic_cpu to allow another panic()/crash_kexec()
14702aff848SBaoquan He 		 * call.
14802aff848SBaoquan He 		 */
14902aff848SBaoquan He 		atomic_set(&panic_cpu, PANIC_CPU_INVALID);
15002aff848SBaoquan He 	}
15102aff848SBaoquan He }
15202aff848SBaoquan He 
15302aff848SBaoquan He static inline resource_size_t crash_resource_size(const struct resource *res)
15402aff848SBaoquan He {
15502aff848SBaoquan He 	return !res->end ? 0 : resource_size(res);
15602aff848SBaoquan He }
15702aff848SBaoquan He 
15802aff848SBaoquan He 
15902aff848SBaoquan He 
16002aff848SBaoquan He 
1616f991cc3SEric DeVolder int crash_prepare_elf64_headers(struct crash_mem *mem, int need_kernel_map,
1626f991cc3SEric DeVolder 			  void **addr, unsigned long *sz)
1636f991cc3SEric DeVolder {
1646f991cc3SEric DeVolder 	Elf64_Ehdr *ehdr;
1656f991cc3SEric DeVolder 	Elf64_Phdr *phdr;
1666f991cc3SEric DeVolder 	unsigned long nr_cpus = num_possible_cpus(), nr_phdr, elf_sz;
1676f991cc3SEric DeVolder 	unsigned char *buf;
1686f991cc3SEric DeVolder 	unsigned int cpu, i;
1696f991cc3SEric DeVolder 	unsigned long long notes_addr;
1706f991cc3SEric DeVolder 	unsigned long mstart, mend;
1716f991cc3SEric DeVolder 
1726f991cc3SEric DeVolder 	/* extra phdr for vmcoreinfo ELF note */
1736f991cc3SEric DeVolder 	nr_phdr = nr_cpus + 1;
1746f991cc3SEric DeVolder 	nr_phdr += mem->nr_ranges;
1756f991cc3SEric DeVolder 
1766f991cc3SEric DeVolder 	/*
1776f991cc3SEric DeVolder 	 * kexec-tools creates an extra PT_LOAD phdr for kernel text mapping
1786f991cc3SEric DeVolder 	 * area (for example, ffffffff80000000 - ffffffffa0000000 on x86_64).
1796f991cc3SEric DeVolder 	 * I think this is required by tools like gdb. So same physical
1806f991cc3SEric DeVolder 	 * memory will be mapped in two ELF headers. One will contain kernel
1816f991cc3SEric DeVolder 	 * text virtual addresses and other will have __va(physical) addresses.
1826f991cc3SEric DeVolder 	 */
1836f991cc3SEric DeVolder 
1846f991cc3SEric DeVolder 	nr_phdr++;
1856f991cc3SEric DeVolder 	elf_sz = sizeof(Elf64_Ehdr) + nr_phdr * sizeof(Elf64_Phdr);
1866f991cc3SEric DeVolder 	elf_sz = ALIGN(elf_sz, ELF_CORE_HEADER_ALIGN);
1876f991cc3SEric DeVolder 
1886f991cc3SEric DeVolder 	buf = vzalloc(elf_sz);
1896f991cc3SEric DeVolder 	if (!buf)
1906f991cc3SEric DeVolder 		return -ENOMEM;
1916f991cc3SEric DeVolder 
1926f991cc3SEric DeVolder 	ehdr = (Elf64_Ehdr *)buf;
1936f991cc3SEric DeVolder 	phdr = (Elf64_Phdr *)(ehdr + 1);
1946f991cc3SEric DeVolder 	memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
1956f991cc3SEric DeVolder 	ehdr->e_ident[EI_CLASS] = ELFCLASS64;
1966f991cc3SEric DeVolder 	ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
1976f991cc3SEric DeVolder 	ehdr->e_ident[EI_VERSION] = EV_CURRENT;
1986f991cc3SEric DeVolder 	ehdr->e_ident[EI_OSABI] = ELF_OSABI;
1996f991cc3SEric DeVolder 	memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD);
2006f991cc3SEric DeVolder 	ehdr->e_type = ET_CORE;
2016f991cc3SEric DeVolder 	ehdr->e_machine = ELF_ARCH;
2026f991cc3SEric DeVolder 	ehdr->e_version = EV_CURRENT;
2036f991cc3SEric DeVolder 	ehdr->e_phoff = sizeof(Elf64_Ehdr);
2046f991cc3SEric DeVolder 	ehdr->e_ehsize = sizeof(Elf64_Ehdr);
2056f991cc3SEric DeVolder 	ehdr->e_phentsize = sizeof(Elf64_Phdr);
2066f991cc3SEric DeVolder 
207a396d0f8SEric DeVolder 	/* Prepare one phdr of type PT_NOTE for each possible CPU */
208a396d0f8SEric DeVolder 	for_each_possible_cpu(cpu) {
2096f991cc3SEric DeVolder 		phdr->p_type = PT_NOTE;
2106f991cc3SEric DeVolder 		notes_addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpu));
2116f991cc3SEric DeVolder 		phdr->p_offset = phdr->p_paddr = notes_addr;
2126f991cc3SEric DeVolder 		phdr->p_filesz = phdr->p_memsz = sizeof(note_buf_t);
2136f991cc3SEric DeVolder 		(ehdr->e_phnum)++;
2146f991cc3SEric DeVolder 		phdr++;
2156f991cc3SEric DeVolder 	}
2166f991cc3SEric DeVolder 
2176f991cc3SEric DeVolder 	/* Prepare one PT_NOTE header for vmcoreinfo */
2186f991cc3SEric DeVolder 	phdr->p_type = PT_NOTE;
2196f991cc3SEric DeVolder 	phdr->p_offset = phdr->p_paddr = paddr_vmcoreinfo_note();
2206f991cc3SEric DeVolder 	phdr->p_filesz = phdr->p_memsz = VMCOREINFO_NOTE_SIZE;
2216f991cc3SEric DeVolder 	(ehdr->e_phnum)++;
2226f991cc3SEric DeVolder 	phdr++;
2236f991cc3SEric DeVolder 
2246f991cc3SEric DeVolder 	/* Prepare PT_LOAD type program header for kernel text region */
2256f991cc3SEric DeVolder 	if (need_kernel_map) {
2266f991cc3SEric DeVolder 		phdr->p_type = PT_LOAD;
2276f991cc3SEric DeVolder 		phdr->p_flags = PF_R|PF_W|PF_X;
2286f991cc3SEric DeVolder 		phdr->p_vaddr = (unsigned long) _text;
2296f991cc3SEric DeVolder 		phdr->p_filesz = phdr->p_memsz = _end - _text;
2306f991cc3SEric DeVolder 		phdr->p_offset = phdr->p_paddr = __pa_symbol(_text);
2316f991cc3SEric DeVolder 		ehdr->e_phnum++;
2326f991cc3SEric DeVolder 		phdr++;
2336f991cc3SEric DeVolder 	}
2346f991cc3SEric DeVolder 
2356f991cc3SEric DeVolder 	/* Go through all the ranges in mem->ranges[] and prepare phdr */
2366f991cc3SEric DeVolder 	for (i = 0; i < mem->nr_ranges; i++) {
2376f991cc3SEric DeVolder 		mstart = mem->ranges[i].start;
2386f991cc3SEric DeVolder 		mend = mem->ranges[i].end;
2396f991cc3SEric DeVolder 
2406f991cc3SEric DeVolder 		phdr->p_type = PT_LOAD;
2416f991cc3SEric DeVolder 		phdr->p_flags = PF_R|PF_W|PF_X;
2426f991cc3SEric DeVolder 		phdr->p_offset  = mstart;
2436f991cc3SEric DeVolder 
2446f991cc3SEric DeVolder 		phdr->p_paddr = mstart;
2456f991cc3SEric DeVolder 		phdr->p_vaddr = (unsigned long) __va(mstart);
2466f991cc3SEric DeVolder 		phdr->p_filesz = phdr->p_memsz = mend - mstart + 1;
2476f991cc3SEric DeVolder 		phdr->p_align = 0;
2486f991cc3SEric DeVolder 		ehdr->e_phnum++;
249a85ee18cSBaoquan He #ifdef CONFIG_KEXEC_FILE
250a85ee18cSBaoquan 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",
2516f991cc3SEric DeVolder 			      phdr, phdr->p_vaddr, phdr->p_paddr, phdr->p_filesz,
2526f991cc3SEric DeVolder 			      ehdr->e_phnum, phdr->p_offset);
253a85ee18cSBaoquan He #endif
2546f991cc3SEric DeVolder 		phdr++;
2556f991cc3SEric DeVolder 	}
2566f991cc3SEric DeVolder 
2576f991cc3SEric DeVolder 	*addr = buf;
2586f991cc3SEric DeVolder 	*sz = elf_sz;
2596f991cc3SEric DeVolder 	return 0;
2606f991cc3SEric DeVolder }
2616f991cc3SEric DeVolder 
2626f991cc3SEric DeVolder int crash_exclude_mem_range(struct crash_mem *mem,
2636f991cc3SEric DeVolder 			    unsigned long long mstart, unsigned long long mend)
2646f991cc3SEric DeVolder {
2656dff3159SYuntao Wang 	int i;
2666f991cc3SEric DeVolder 	unsigned long long start, end, p_start, p_end;
2676f991cc3SEric DeVolder 
2686f991cc3SEric DeVolder 	for (i = 0; i < mem->nr_ranges; i++) {
2696f991cc3SEric DeVolder 		start = mem->ranges[i].start;
2706f991cc3SEric DeVolder 		end = mem->ranges[i].end;
2716f991cc3SEric DeVolder 		p_start = mstart;
2726f991cc3SEric DeVolder 		p_end = mend;
2736f991cc3SEric DeVolder 
2746dff3159SYuntao Wang 		if (p_start > end)
2756f991cc3SEric DeVolder 			continue;
2766f991cc3SEric DeVolder 
2776dff3159SYuntao Wang 		/*
2786dff3159SYuntao Wang 		 * Because the memory ranges in mem->ranges are stored in
2796dff3159SYuntao Wang 		 * ascending order, when we detect `p_end < start`, we can
2806dff3159SYuntao Wang 		 * immediately exit the for loop, as the subsequent memory
2816dff3159SYuntao Wang 		 * ranges will definitely be outside the range we are looking
2826dff3159SYuntao Wang 		 * for.
2836dff3159SYuntao Wang 		 */
2846dff3159SYuntao Wang 		if (p_end < start)
2856dff3159SYuntao Wang 			break;
2866dff3159SYuntao Wang 
2876f991cc3SEric DeVolder 		/* Truncate any area outside of range */
2886dff3159SYuntao Wang 		if (p_start < start)
2896f991cc3SEric DeVolder 			p_start = start;
2906dff3159SYuntao Wang 		if (p_end > end)
2916f991cc3SEric DeVolder 			p_end = end;
2926f991cc3SEric DeVolder 
2936f991cc3SEric DeVolder 		/* Found completely overlapping range */
2946f991cc3SEric DeVolder 		if (p_start == start && p_end == end) {
2956dff3159SYuntao Wang 			memmove(&mem->ranges[i], &mem->ranges[i + 1],
2966dff3159SYuntao Wang 				(mem->nr_ranges - (i + 1)) * sizeof(mem->ranges[i]));
2976f991cc3SEric DeVolder 			i--;
2986f991cc3SEric DeVolder 			mem->nr_ranges--;
2996dff3159SYuntao Wang 		} else if (p_start > start && p_end < end) {
3006f991cc3SEric DeVolder 			/* Split original range */
3016dff3159SYuntao Wang 			if (mem->nr_ranges >= mem->max_nr_ranges)
3026dff3159SYuntao Wang 				return -ENOMEM;
3036dff3159SYuntao Wang 
3046dff3159SYuntao Wang 			memmove(&mem->ranges[i + 2], &mem->ranges[i + 1],
3056dff3159SYuntao Wang 				(mem->nr_ranges - (i + 1)) * sizeof(mem->ranges[i]));
3066dff3159SYuntao Wang 
3076f991cc3SEric DeVolder 			mem->ranges[i].end = p_start - 1;
3086dff3159SYuntao Wang 			mem->ranges[i + 1].start = p_end + 1;
3096dff3159SYuntao Wang 			mem->ranges[i + 1].end = end;
3106dff3159SYuntao Wang 
3116dff3159SYuntao Wang 			i++;
3126dff3159SYuntao Wang 			mem->nr_ranges++;
3136f991cc3SEric DeVolder 		} else if (p_start != start)
3146f991cc3SEric DeVolder 			mem->ranges[i].end = p_start - 1;
3156f991cc3SEric DeVolder 		else
3166f991cc3SEric DeVolder 			mem->ranges[i].start = p_end + 1;
3176f991cc3SEric DeVolder 	}
3186f991cc3SEric DeVolder 
3196f991cc3SEric DeVolder 	return 0;
3206f991cc3SEric DeVolder }
3216f991cc3SEric DeVolder 
32202aff848SBaoquan He ssize_t crash_get_memory_size(void)
32302aff848SBaoquan He {
32402aff848SBaoquan He 	ssize_t size = 0;
32502aff848SBaoquan He 
32602aff848SBaoquan He 	if (!kexec_trylock())
32702aff848SBaoquan He 		return -EBUSY;
32802aff848SBaoquan He 
32902aff848SBaoquan He 	size += crash_resource_size(&crashk_res);
33002aff848SBaoquan He 	size += crash_resource_size(&crashk_low_res);
33102aff848SBaoquan He 
33202aff848SBaoquan He 	kexec_unlock();
33302aff848SBaoquan He 	return size;
33402aff848SBaoquan He }
33502aff848SBaoquan He 
33602aff848SBaoquan He static int __crash_shrink_memory(struct resource *old_res,
33702aff848SBaoquan He 				 unsigned long new_size)
33802aff848SBaoquan He {
33902aff848SBaoquan He 	struct resource *ram_res;
34002aff848SBaoquan He 
34102aff848SBaoquan He 	ram_res = kzalloc(sizeof(*ram_res), GFP_KERNEL);
34202aff848SBaoquan He 	if (!ram_res)
34302aff848SBaoquan He 		return -ENOMEM;
34402aff848SBaoquan He 
34502aff848SBaoquan He 	ram_res->start = old_res->start + new_size;
34602aff848SBaoquan He 	ram_res->end   = old_res->end;
34702aff848SBaoquan He 	ram_res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM;
34802aff848SBaoquan He 	ram_res->name  = "System RAM";
34902aff848SBaoquan He 
35002aff848SBaoquan He 	if (!new_size) {
35102aff848SBaoquan He 		release_resource(old_res);
35202aff848SBaoquan He 		old_res->start = 0;
35302aff848SBaoquan He 		old_res->end   = 0;
35402aff848SBaoquan He 	} else {
35502aff848SBaoquan He 		crashk_res.end = ram_res->start - 1;
35602aff848SBaoquan He 	}
35702aff848SBaoquan He 
35802aff848SBaoquan He 	crash_free_reserved_phys_range(ram_res->start, ram_res->end);
35902aff848SBaoquan He 	insert_resource(&iomem_resource, ram_res);
36002aff848SBaoquan He 
36102aff848SBaoquan He 	return 0;
36202aff848SBaoquan He }
36302aff848SBaoquan He 
36402aff848SBaoquan He int crash_shrink_memory(unsigned long new_size)
36502aff848SBaoquan He {
36602aff848SBaoquan He 	int ret = 0;
36702aff848SBaoquan He 	unsigned long old_size, low_size;
36802aff848SBaoquan He 
36902aff848SBaoquan He 	if (!kexec_trylock())
37002aff848SBaoquan He 		return -EBUSY;
37102aff848SBaoquan He 
37202aff848SBaoquan He 	if (kexec_crash_image) {
37302aff848SBaoquan He 		ret = -ENOENT;
37402aff848SBaoquan He 		goto unlock;
37502aff848SBaoquan He 	}
37602aff848SBaoquan He 
37702aff848SBaoquan He 	low_size = crash_resource_size(&crashk_low_res);
37802aff848SBaoquan He 	old_size = crash_resource_size(&crashk_res) + low_size;
37902aff848SBaoquan He 	new_size = roundup(new_size, KEXEC_CRASH_MEM_ALIGN);
38002aff848SBaoquan He 	if (new_size >= old_size) {
38102aff848SBaoquan He 		ret = (new_size == old_size) ? 0 : -EINVAL;
38202aff848SBaoquan He 		goto unlock;
38302aff848SBaoquan He 	}
38402aff848SBaoquan He 
38502aff848SBaoquan He 	/*
38602aff848SBaoquan He 	 * (low_size > new_size) implies that low_size is greater than zero.
38702aff848SBaoquan He 	 * This also means that if low_size is zero, the else branch is taken.
38802aff848SBaoquan He 	 *
38902aff848SBaoquan He 	 * If low_size is greater than 0, (low_size > new_size) indicates that
39002aff848SBaoquan He 	 * crashk_low_res also needs to be shrunken. Otherwise, only crashk_res
39102aff848SBaoquan He 	 * needs to be shrunken.
39202aff848SBaoquan He 	 */
39302aff848SBaoquan He 	if (low_size > new_size) {
39402aff848SBaoquan He 		ret = __crash_shrink_memory(&crashk_res, 0);
39502aff848SBaoquan He 		if (ret)
39602aff848SBaoquan He 			goto unlock;
39702aff848SBaoquan He 
39802aff848SBaoquan He 		ret = __crash_shrink_memory(&crashk_low_res, new_size);
39902aff848SBaoquan He 	} else {
40002aff848SBaoquan He 		ret = __crash_shrink_memory(&crashk_res, new_size - low_size);
40102aff848SBaoquan He 	}
40202aff848SBaoquan He 
40302aff848SBaoquan He 	/* Swap crashk_res and crashk_low_res if needed */
40402aff848SBaoquan He 	if (!crashk_res.end && crashk_low_res.end) {
40502aff848SBaoquan He 		crashk_res.start = crashk_low_res.start;
40602aff848SBaoquan He 		crashk_res.end   = crashk_low_res.end;
40702aff848SBaoquan He 		release_resource(&crashk_low_res);
40802aff848SBaoquan He 		crashk_low_res.start = 0;
40902aff848SBaoquan He 		crashk_low_res.end   = 0;
41002aff848SBaoquan He 		insert_resource(&iomem_resource, &crashk_res);
41102aff848SBaoquan He 	}
41202aff848SBaoquan He 
41302aff848SBaoquan He unlock:
41402aff848SBaoquan He 	kexec_unlock();
41502aff848SBaoquan He 	return ret;
41602aff848SBaoquan He }
41702aff848SBaoquan He 
41802aff848SBaoquan He void crash_save_cpu(struct pt_regs *regs, int cpu)
41902aff848SBaoquan He {
42002aff848SBaoquan He 	struct elf_prstatus prstatus;
42102aff848SBaoquan He 	u32 *buf;
42202aff848SBaoquan He 
42302aff848SBaoquan He 	if ((cpu < 0) || (cpu >= nr_cpu_ids))
42402aff848SBaoquan He 		return;
42502aff848SBaoquan He 
42602aff848SBaoquan He 	/* Using ELF notes here is opportunistic.
42702aff848SBaoquan He 	 * I need a well defined structure format
42802aff848SBaoquan He 	 * for the data I pass, and I need tags
42902aff848SBaoquan He 	 * on the data to indicate what information I have
43002aff848SBaoquan He 	 * squirrelled away.  ELF notes happen to provide
43102aff848SBaoquan He 	 * all of that, so there is no need to invent something new.
43202aff848SBaoquan He 	 */
43302aff848SBaoquan He 	buf = (u32 *)per_cpu_ptr(crash_notes, cpu);
43402aff848SBaoquan He 	if (!buf)
43502aff848SBaoquan He 		return;
43602aff848SBaoquan He 	memset(&prstatus, 0, sizeof(prstatus));
43702aff848SBaoquan He 	prstatus.common.pr_pid = current->pid;
43802aff848SBaoquan He 	elf_core_copy_regs(&prstatus.pr_reg, regs);
43902aff848SBaoquan He 	buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS,
44002aff848SBaoquan He 			      &prstatus, sizeof(prstatus));
44102aff848SBaoquan He 	final_note(buf);
44202aff848SBaoquan He }
44302aff848SBaoquan He 
44402aff848SBaoquan He 
44502aff848SBaoquan He 
4466f991cc3SEric DeVolder static int __init crash_notes_memory_init(void)
4476f991cc3SEric DeVolder {
4486f991cc3SEric DeVolder 	/* Allocate memory for saving cpu registers. */
4496f991cc3SEric DeVolder 	size_t size, align;
4506f991cc3SEric DeVolder 
4516f991cc3SEric DeVolder 	/*
4526f991cc3SEric DeVolder 	 * crash_notes could be allocated across 2 vmalloc pages when percpu
4536f991cc3SEric DeVolder 	 * is vmalloc based . vmalloc doesn't guarantee 2 continuous vmalloc
4546f991cc3SEric DeVolder 	 * pages are also on 2 continuous physical pages. In this case the
4556f991cc3SEric DeVolder 	 * 2nd part of crash_notes in 2nd page could be lost since only the
4566f991cc3SEric DeVolder 	 * starting address and size of crash_notes are exported through sysfs.
4576f991cc3SEric DeVolder 	 * Here round up the size of crash_notes to the nearest power of two
4586f991cc3SEric DeVolder 	 * and pass it to __alloc_percpu as align value. This can make sure
4596f991cc3SEric DeVolder 	 * crash_notes is allocated inside one physical page.
4606f991cc3SEric DeVolder 	 */
4616f991cc3SEric DeVolder 	size = sizeof(note_buf_t);
4626f991cc3SEric DeVolder 	align = min(roundup_pow_of_two(sizeof(note_buf_t)), PAGE_SIZE);
4636f991cc3SEric DeVolder 
4646f991cc3SEric DeVolder 	/*
4656f991cc3SEric DeVolder 	 * Break compile if size is bigger than PAGE_SIZE since crash_notes
4666f991cc3SEric DeVolder 	 * definitely will be in 2 pages with that.
4676f991cc3SEric DeVolder 	 */
4686f991cc3SEric DeVolder 	BUILD_BUG_ON(size > PAGE_SIZE);
4696f991cc3SEric DeVolder 
4706f991cc3SEric DeVolder 	crash_notes = __alloc_percpu(size, align);
4716f991cc3SEric DeVolder 	if (!crash_notes) {
4726f991cc3SEric DeVolder 		pr_warn("Memory allocation for saving cpu register states failed\n");
4736f991cc3SEric DeVolder 		return -ENOMEM;
4746f991cc3SEric DeVolder 	}
4756f991cc3SEric DeVolder 	return 0;
4766f991cc3SEric DeVolder }
4776f991cc3SEric DeVolder subsys_initcall(crash_notes_memory_init);
47824726275SEric DeVolder 
47902aff848SBaoquan He #endif /*CONFIG_CRASH_DUMP*/
48002aff848SBaoquan He 
48124726275SEric DeVolder #ifdef CONFIG_CRASH_HOTPLUG
48224726275SEric DeVolder #undef pr_fmt
48324726275SEric DeVolder #define pr_fmt(fmt) "crash hp: " fmt
484a72bbec7SEric DeVolder 
485a72bbec7SEric DeVolder /*
486e2a8f20dSBaoquan He  * Different than kexec/kdump loading/unloading/jumping/shrinking which
487e2a8f20dSBaoquan He  * usually rarely happen, there will be many crash hotplug events notified
488e2a8f20dSBaoquan He  * during one short period, e.g one memory board is hot added and memory
489e2a8f20dSBaoquan He  * regions are online. So mutex lock  __crash_hotplug_lock is used to
490e2a8f20dSBaoquan He  * serialize the crash hotplug handling specifically.
491e2a8f20dSBaoquan He  */
4924e87ff59SAndrew Morton static DEFINE_MUTEX(__crash_hotplug_lock);
493e2a8f20dSBaoquan He #define crash_hotplug_lock() mutex_lock(&__crash_hotplug_lock)
494e2a8f20dSBaoquan He #define crash_hotplug_unlock() mutex_unlock(&__crash_hotplug_lock)
495e2a8f20dSBaoquan He 
496e2a8f20dSBaoquan He /*
497a72bbec7SEric DeVolder  * This routine utilized when the crash_hotplug sysfs node is read.
498a72bbec7SEric DeVolder  * It reflects the kernel's ability/permission to update the crash
499a72bbec7SEric DeVolder  * elfcorehdr directly.
500a72bbec7SEric DeVolder  */
501a72bbec7SEric DeVolder int crash_check_update_elfcorehdr(void)
502a72bbec7SEric DeVolder {
503a72bbec7SEric DeVolder 	int rc = 0;
504a72bbec7SEric DeVolder 
505e2a8f20dSBaoquan He 	crash_hotplug_lock();
506a72bbec7SEric DeVolder 	/* Obtain lock while reading crash information */
507a72bbec7SEric DeVolder 	if (!kexec_trylock()) {
508a72bbec7SEric DeVolder 		pr_info("kexec_trylock() failed, elfcorehdr may be inaccurate\n");
509e2a8f20dSBaoquan He 		crash_hotplug_unlock();
510a72bbec7SEric DeVolder 		return 0;
511a72bbec7SEric DeVolder 	}
512a72bbec7SEric DeVolder 	if (kexec_crash_image) {
513a72bbec7SEric DeVolder 		if (kexec_crash_image->file_mode)
514a72bbec7SEric DeVolder 			rc = 1;
515a72bbec7SEric DeVolder 		else
516a72bbec7SEric DeVolder 			rc = kexec_crash_image->update_elfcorehdr;
517a72bbec7SEric DeVolder 	}
518a72bbec7SEric DeVolder 	/* Release lock now that update complete */
519a72bbec7SEric DeVolder 	kexec_unlock();
520e2a8f20dSBaoquan He 	crash_hotplug_unlock();
521a72bbec7SEric DeVolder 
522a72bbec7SEric DeVolder 	return rc;
523a72bbec7SEric DeVolder }
524a72bbec7SEric DeVolder 
52524726275SEric DeVolder /*
52624726275SEric DeVolder  * To accurately reflect hot un/plug changes of cpu and memory resources
52724726275SEric DeVolder  * (including onling and offlining of those resources), the elfcorehdr
52824726275SEric DeVolder  * (which is passed to the crash kernel via the elfcorehdr= parameter)
52924726275SEric DeVolder  * must be updated with the new list of CPUs and memories.
53024726275SEric DeVolder  *
53124726275SEric DeVolder  * In order to make changes to elfcorehdr, two conditions are needed:
53224726275SEric DeVolder  * First, the segment containing the elfcorehdr must be large enough
53324726275SEric DeVolder  * to permit a growing number of resources; the elfcorehdr memory size
53424726275SEric DeVolder  * is based on NR_CPUS_DEFAULT and CRASH_MAX_MEMORY_RANGES.
53524726275SEric DeVolder  * Second, purgatory must explicitly exclude the elfcorehdr from the
53624726275SEric DeVolder  * list of segments it checks (since the elfcorehdr changes and thus
53724726275SEric DeVolder  * would require an update to purgatory itself to update the digest).
53824726275SEric DeVolder  */
53924726275SEric DeVolder static void crash_handle_hotplug_event(unsigned int hp_action, unsigned int cpu)
54024726275SEric DeVolder {
54124726275SEric DeVolder 	struct kimage *image;
54224726275SEric DeVolder 
543e2a8f20dSBaoquan He 	crash_hotplug_lock();
54424726275SEric DeVolder 	/* Obtain lock while changing crash information */
54524726275SEric DeVolder 	if (!kexec_trylock()) {
54624726275SEric DeVolder 		pr_info("kexec_trylock() failed, elfcorehdr may be inaccurate\n");
547e2a8f20dSBaoquan He 		crash_hotplug_unlock();
54824726275SEric DeVolder 		return;
54924726275SEric DeVolder 	}
55024726275SEric DeVolder 
55124726275SEric DeVolder 	/* Check kdump is not loaded */
55224726275SEric DeVolder 	if (!kexec_crash_image)
55324726275SEric DeVolder 		goto out;
55424726275SEric DeVolder 
55524726275SEric DeVolder 	image = kexec_crash_image;
55624726275SEric DeVolder 
557a72bbec7SEric DeVolder 	/* Check that updating elfcorehdr is permitted */
558a72bbec7SEric DeVolder 	if (!(image->file_mode || image->update_elfcorehdr))
559a72bbec7SEric DeVolder 		goto out;
560a72bbec7SEric DeVolder 
56124726275SEric DeVolder 	if (hp_action == KEXEC_CRASH_HP_ADD_CPU ||
56224726275SEric DeVolder 		hp_action == KEXEC_CRASH_HP_REMOVE_CPU)
56324726275SEric DeVolder 		pr_debug("hp_action %u, cpu %u\n", hp_action, cpu);
56424726275SEric DeVolder 	else
56524726275SEric DeVolder 		pr_debug("hp_action %u\n", hp_action);
56624726275SEric DeVolder 
56724726275SEric DeVolder 	/*
56824726275SEric DeVolder 	 * The elfcorehdr_index is set to -1 when the struct kimage
56924726275SEric DeVolder 	 * is allocated. Find the segment containing the elfcorehdr,
57024726275SEric DeVolder 	 * if not already found.
57124726275SEric DeVolder 	 */
57224726275SEric DeVolder 	if (image->elfcorehdr_index < 0) {
57324726275SEric DeVolder 		unsigned long mem;
57424726275SEric DeVolder 		unsigned char *ptr;
57524726275SEric DeVolder 		unsigned int n;
57624726275SEric DeVolder 
57724726275SEric DeVolder 		for (n = 0; n < image->nr_segments; n++) {
57824726275SEric DeVolder 			mem = image->segment[n].mem;
57924726275SEric DeVolder 			ptr = kmap_local_page(pfn_to_page(mem >> PAGE_SHIFT));
58024726275SEric DeVolder 			if (ptr) {
58124726275SEric DeVolder 				/* The segment containing elfcorehdr */
58224726275SEric DeVolder 				if (memcmp(ptr, ELFMAG, SELFMAG) == 0)
58324726275SEric DeVolder 					image->elfcorehdr_index = (int)n;
58424726275SEric DeVolder 				kunmap_local(ptr);
58524726275SEric DeVolder 			}
58624726275SEric DeVolder 		}
58724726275SEric DeVolder 	}
58824726275SEric DeVolder 
58924726275SEric DeVolder 	if (image->elfcorehdr_index < 0) {
59024726275SEric DeVolder 		pr_err("unable to locate elfcorehdr segment");
59124726275SEric DeVolder 		goto out;
59224726275SEric DeVolder 	}
59324726275SEric DeVolder 
59424726275SEric DeVolder 	/* Needed in order for the segments to be updated */
59524726275SEric DeVolder 	arch_kexec_unprotect_crashkres();
59624726275SEric DeVolder 
59724726275SEric DeVolder 	/* Differentiate between normal load and hotplug update */
59824726275SEric DeVolder 	image->hp_action = hp_action;
59924726275SEric DeVolder 
60024726275SEric DeVolder 	/* Now invoke arch-specific update handler */
60124726275SEric DeVolder 	arch_crash_handle_hotplug_event(image);
60224726275SEric DeVolder 
60324726275SEric DeVolder 	/* No longer handling a hotplug event */
60424726275SEric DeVolder 	image->hp_action = KEXEC_CRASH_HP_NONE;
60524726275SEric DeVolder 	image->elfcorehdr_updated = true;
60624726275SEric DeVolder 
60724726275SEric DeVolder 	/* Change back to read-only */
60824726275SEric DeVolder 	arch_kexec_protect_crashkres();
60924726275SEric DeVolder 
61024726275SEric DeVolder 	/* Errors in the callback is not a reason to rollback state */
61124726275SEric DeVolder out:
61224726275SEric DeVolder 	/* Release lock now that update complete */
61324726275SEric DeVolder 	kexec_unlock();
614e2a8f20dSBaoquan He 	crash_hotplug_unlock();
61524726275SEric DeVolder }
61624726275SEric DeVolder 
61724726275SEric DeVolder static int crash_memhp_notifier(struct notifier_block *nb, unsigned long val, void *v)
61824726275SEric DeVolder {
61924726275SEric DeVolder 	switch (val) {
62024726275SEric DeVolder 	case MEM_ONLINE:
62124726275SEric DeVolder 		crash_handle_hotplug_event(KEXEC_CRASH_HP_ADD_MEMORY,
62224726275SEric DeVolder 			KEXEC_CRASH_HP_INVALID_CPU);
62324726275SEric DeVolder 		break;
62424726275SEric DeVolder 
62524726275SEric DeVolder 	case MEM_OFFLINE:
62624726275SEric DeVolder 		crash_handle_hotplug_event(KEXEC_CRASH_HP_REMOVE_MEMORY,
62724726275SEric DeVolder 			KEXEC_CRASH_HP_INVALID_CPU);
62824726275SEric DeVolder 		break;
62924726275SEric DeVolder 	}
63024726275SEric DeVolder 	return NOTIFY_OK;
63124726275SEric DeVolder }
63224726275SEric DeVolder 
63324726275SEric DeVolder static struct notifier_block crash_memhp_nb = {
63424726275SEric DeVolder 	.notifier_call = crash_memhp_notifier,
63524726275SEric DeVolder 	.priority = 0
63624726275SEric DeVolder };
63724726275SEric DeVolder 
63824726275SEric DeVolder static int crash_cpuhp_online(unsigned int cpu)
63924726275SEric DeVolder {
64024726275SEric DeVolder 	crash_handle_hotplug_event(KEXEC_CRASH_HP_ADD_CPU, cpu);
64124726275SEric DeVolder 	return 0;
64224726275SEric DeVolder }
64324726275SEric DeVolder 
64424726275SEric DeVolder static int crash_cpuhp_offline(unsigned int cpu)
64524726275SEric DeVolder {
64624726275SEric DeVolder 	crash_handle_hotplug_event(KEXEC_CRASH_HP_REMOVE_CPU, cpu);
64724726275SEric DeVolder 	return 0;
64824726275SEric DeVolder }
64924726275SEric DeVolder 
65024726275SEric DeVolder static int __init crash_hotplug_init(void)
65124726275SEric DeVolder {
65224726275SEric DeVolder 	int result = 0;
65324726275SEric DeVolder 
65424726275SEric DeVolder 	if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
65524726275SEric DeVolder 		register_memory_notifier(&crash_memhp_nb);
65624726275SEric DeVolder 
65724726275SEric DeVolder 	if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) {
65824726275SEric DeVolder 		result = cpuhp_setup_state_nocalls(CPUHP_BP_PREPARE_DYN,
65924726275SEric DeVolder 			"crash/cpuhp", crash_cpuhp_online, crash_cpuhp_offline);
66024726275SEric DeVolder 	}
66124726275SEric DeVolder 
66224726275SEric DeVolder 	return result;
66324726275SEric DeVolder }
66424726275SEric DeVolder 
66524726275SEric DeVolder subsys_initcall(crash_hotplug_init);
66624726275SEric DeVolder #endif
667