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
74707c13dSBaoquan He #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
84707c13dSBaoquan 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
kimage_crash_copy_vmcoreinfo(struct kimage * image)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
kexec_should_crash(struct task_struct * p)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
kexec_crash_loaded(void)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 */
__crash_kexec(struct pt_regs * regs)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
crash_kexec(struct pt_regs * regs)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
crash_resource_size(const struct resource * res)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
crash_prepare_elf64_headers(struct crash_mem * mem,int need_kernel_map,void ** addr,unsigned long * sz)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
crash_exclude_mem_range(struct crash_mem * mem,unsigned long long mstart,unsigned long long mend)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
crash_get_memory_size(void)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
__crash_shrink_memory(struct resource * old_res,unsigned long new_size)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
crash_shrink_memory(unsigned long new_size)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
crash_save_cpu(struct pt_regs * regs,int cpu)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);
439*0de47f28SAkihiko Odaki buf = append_elf_note(buf, NN_PRSTATUS, NT_PRSTATUS,
44002aff848SBaoquan He &prstatus, sizeof(prstatus));
44102aff848SBaoquan He final_note(buf);
44202aff848SBaoquan He }
44302aff848SBaoquan He
44402aff848SBaoquan He
44502aff848SBaoquan He
crash_notes_memory_init(void)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.
49879365026SSourabh Jain * It reflects the kernel's ability/permission to update the kdump
49979365026SSourabh Jain * image directly.
500a72bbec7SEric DeVolder */
crash_check_hotplug_support(void)50179365026SSourabh Jain int crash_check_hotplug_support(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()) {
5086efbd5ddSSourabh Jain if (!kexec_in_progress)
509c91c6062SSourabh Jain pr_info("kexec_trylock() failed, kdump image may be inaccurate\n");
510e2a8f20dSBaoquan He crash_hotplug_unlock();
511a72bbec7SEric DeVolder return 0;
512a72bbec7SEric DeVolder }
513a72bbec7SEric DeVolder if (kexec_crash_image) {
51479365026SSourabh Jain rc = kexec_crash_image->hotplug_support;
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 /*
524c91c6062SSourabh Jain * To accurately reflect hot un/plug changes of CPU and Memory resources
525c91c6062SSourabh Jain * (including onling and offlining of those resources), the relevant
526c91c6062SSourabh Jain * kexec segments must be updated with latest CPU and Memory resources.
52724726275SEric DeVolder *
528c91c6062SSourabh Jain * Architectures must ensure two things for all segments that need
529c91c6062SSourabh Jain * updating during hotplug events:
530c91c6062SSourabh Jain *
531c91c6062SSourabh Jain * 1. Segments must be large enough to accommodate a growing number of
532c91c6062SSourabh Jain * resources.
533c91c6062SSourabh Jain * 2. Exclude the segments from SHA verification.
534c91c6062SSourabh Jain *
535c91c6062SSourabh Jain * For example, on most architectures, the elfcorehdr (which is passed
536c91c6062SSourabh Jain * to the crash kernel via the elfcorehdr= parameter) must include the
537c91c6062SSourabh Jain * new list of CPUs and memory. To make changes to the elfcorehdr, it
538c91c6062SSourabh Jain * should be large enough to permit a growing number of CPU and Memory
539c91c6062SSourabh Jain * resources. One can estimate the elfcorehdr memory size based on
540c91c6062SSourabh Jain * NR_CPUS_DEFAULT and CRASH_MAX_MEMORY_RANGES. The elfcorehdr is
541c91c6062SSourabh Jain * excluded from SHA verification by default if the architecture
542c91c6062SSourabh Jain * supports crash hotplug.
54324726275SEric DeVolder */
crash_handle_hotplug_event(unsigned int hp_action,unsigned int cpu,void * arg)54411800571SSourabh Jain static void crash_handle_hotplug_event(unsigned int hp_action, unsigned int cpu, void *arg)
54524726275SEric DeVolder {
54624726275SEric DeVolder struct kimage *image;
54724726275SEric DeVolder
548e2a8f20dSBaoquan He crash_hotplug_lock();
54924726275SEric DeVolder /* Obtain lock while changing crash information */
55024726275SEric DeVolder if (!kexec_trylock()) {
5516efbd5ddSSourabh Jain if (!kexec_in_progress)
552c91c6062SSourabh Jain pr_info("kexec_trylock() failed, kdump image may be inaccurate\n");
553e2a8f20dSBaoquan He crash_hotplug_unlock();
55424726275SEric DeVolder return;
55524726275SEric DeVolder }
55624726275SEric DeVolder
55724726275SEric DeVolder /* Check kdump is not loaded */
55824726275SEric DeVolder if (!kexec_crash_image)
55924726275SEric DeVolder goto out;
56024726275SEric DeVolder
56124726275SEric DeVolder image = kexec_crash_image;
56224726275SEric DeVolder
56379365026SSourabh Jain /* Check that kexec segments update is permitted */
56479365026SSourabh Jain if (!image->hotplug_support)
565a72bbec7SEric DeVolder goto out;
566a72bbec7SEric DeVolder
56724726275SEric DeVolder if (hp_action == KEXEC_CRASH_HP_ADD_CPU ||
56824726275SEric DeVolder hp_action == KEXEC_CRASH_HP_REMOVE_CPU)
56924726275SEric DeVolder pr_debug("hp_action %u, cpu %u\n", hp_action, cpu);
57024726275SEric DeVolder else
57124726275SEric DeVolder pr_debug("hp_action %u\n", hp_action);
57224726275SEric DeVolder
57324726275SEric DeVolder /*
57424726275SEric DeVolder * The elfcorehdr_index is set to -1 when the struct kimage
57524726275SEric DeVolder * is allocated. Find the segment containing the elfcorehdr,
57624726275SEric DeVolder * if not already found.
57724726275SEric DeVolder */
57824726275SEric DeVolder if (image->elfcorehdr_index < 0) {
57924726275SEric DeVolder unsigned long mem;
58024726275SEric DeVolder unsigned char *ptr;
58124726275SEric DeVolder unsigned int n;
58224726275SEric DeVolder
58324726275SEric DeVolder for (n = 0; n < image->nr_segments; n++) {
58424726275SEric DeVolder mem = image->segment[n].mem;
58524726275SEric DeVolder ptr = kmap_local_page(pfn_to_page(mem >> PAGE_SHIFT));
58624726275SEric DeVolder if (ptr) {
58724726275SEric DeVolder /* The segment containing elfcorehdr */
58824726275SEric DeVolder if (memcmp(ptr, ELFMAG, SELFMAG) == 0)
58924726275SEric DeVolder image->elfcorehdr_index = (int)n;
59024726275SEric DeVolder kunmap_local(ptr);
59124726275SEric DeVolder }
59224726275SEric DeVolder }
59324726275SEric DeVolder }
59424726275SEric DeVolder
59524726275SEric DeVolder if (image->elfcorehdr_index < 0) {
59624726275SEric DeVolder pr_err("unable to locate elfcorehdr segment");
59724726275SEric DeVolder goto out;
59824726275SEric DeVolder }
59924726275SEric DeVolder
60024726275SEric DeVolder /* Needed in order for the segments to be updated */
60124726275SEric DeVolder arch_kexec_unprotect_crashkres();
60224726275SEric DeVolder
60324726275SEric DeVolder /* Differentiate between normal load and hotplug update */
60424726275SEric DeVolder image->hp_action = hp_action;
60524726275SEric DeVolder
60624726275SEric DeVolder /* Now invoke arch-specific update handler */
60711800571SSourabh Jain arch_crash_handle_hotplug_event(image, arg);
60824726275SEric DeVolder
60924726275SEric DeVolder /* No longer handling a hotplug event */
61024726275SEric DeVolder image->hp_action = KEXEC_CRASH_HP_NONE;
61124726275SEric DeVolder image->elfcorehdr_updated = true;
61224726275SEric DeVolder
61324726275SEric DeVolder /* Change back to read-only */
61424726275SEric DeVolder arch_kexec_protect_crashkres();
61524726275SEric DeVolder
61624726275SEric DeVolder /* Errors in the callback is not a reason to rollback state */
61724726275SEric DeVolder out:
61824726275SEric DeVolder /* Release lock now that update complete */
61924726275SEric DeVolder kexec_unlock();
620e2a8f20dSBaoquan He crash_hotplug_unlock();
62124726275SEric DeVolder }
62224726275SEric DeVolder
crash_memhp_notifier(struct notifier_block * nb,unsigned long val,void * arg)62311800571SSourabh Jain static int crash_memhp_notifier(struct notifier_block *nb, unsigned long val, void *arg)
62424726275SEric DeVolder {
62524726275SEric DeVolder switch (val) {
62624726275SEric DeVolder case MEM_ONLINE:
62724726275SEric DeVolder crash_handle_hotplug_event(KEXEC_CRASH_HP_ADD_MEMORY,
62811800571SSourabh Jain KEXEC_CRASH_HP_INVALID_CPU, arg);
62924726275SEric DeVolder break;
63024726275SEric DeVolder
63124726275SEric DeVolder case MEM_OFFLINE:
63224726275SEric DeVolder crash_handle_hotplug_event(KEXEC_CRASH_HP_REMOVE_MEMORY,
63311800571SSourabh Jain KEXEC_CRASH_HP_INVALID_CPU, arg);
63424726275SEric DeVolder break;
63524726275SEric DeVolder }
63624726275SEric DeVolder return NOTIFY_OK;
63724726275SEric DeVolder }
63824726275SEric DeVolder
63924726275SEric DeVolder static struct notifier_block crash_memhp_nb = {
64024726275SEric DeVolder .notifier_call = crash_memhp_notifier,
64124726275SEric DeVolder .priority = 0
64224726275SEric DeVolder };
64324726275SEric DeVolder
crash_cpuhp_online(unsigned int cpu)64424726275SEric DeVolder static int crash_cpuhp_online(unsigned int cpu)
64524726275SEric DeVolder {
64611800571SSourabh Jain crash_handle_hotplug_event(KEXEC_CRASH_HP_ADD_CPU, cpu, NULL);
64724726275SEric DeVolder return 0;
64824726275SEric DeVolder }
64924726275SEric DeVolder
crash_cpuhp_offline(unsigned int cpu)65024726275SEric DeVolder static int crash_cpuhp_offline(unsigned int cpu)
65124726275SEric DeVolder {
65211800571SSourabh Jain crash_handle_hotplug_event(KEXEC_CRASH_HP_REMOVE_CPU, cpu, NULL);
65324726275SEric DeVolder return 0;
65424726275SEric DeVolder }
65524726275SEric DeVolder
crash_hotplug_init(void)65624726275SEric DeVolder static int __init crash_hotplug_init(void)
65724726275SEric DeVolder {
65824726275SEric DeVolder int result = 0;
65924726275SEric DeVolder
66024726275SEric DeVolder if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
66124726275SEric DeVolder register_memory_notifier(&crash_memhp_nb);
66224726275SEric DeVolder
66324726275SEric DeVolder if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) {
66424726275SEric DeVolder result = cpuhp_setup_state_nocalls(CPUHP_BP_PREPARE_DYN,
66524726275SEric DeVolder "crash/cpuhp", crash_cpuhp_online, crash_cpuhp_offline);
66624726275SEric DeVolder }
66724726275SEric DeVolder
66824726275SEric DeVolder return result;
66924726275SEric DeVolder }
67024726275SEric DeVolder
67124726275SEric DeVolder subsys_initcall(crash_hotplug_init);
67224726275SEric DeVolder #endif
673