| 1 | |
| 2 | |
| 3 | * crash.c - kernel crash support code.
|
| 4 | * Copyright (C) 2002-2004 Eric Biederman <[email protected]>
|
| 5 |
|
| 6 |
|
| 7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
| 8 |
|
| 9 | #include <linux/buildid.h>
|
| 10 | #include <linux/init.h>
|
| 11 | #include <linux/utsname.h>
|
| 12 | #include <linux/vmalloc.h>
|
| 13 | #include <linux/sizes.h>
|
| 14 | #include <linux/kexec.h>
|
| 15 | #include <linux/memory.h>
|
| 16 | #include <linux/mm.h>
|
| 17 | #include <linux/cpuhotplug.h>
|
| 18 | #include <linux/memblock.h>
|
| 19 | #include <linux/kmemleak.h>
|
| 20 | #include <linux/crash_core.h>
|
| 21 | #include <linux/reboot.h>
|
| 22 | #include <linux/btf.h>
|
| 23 | #include <linux/objtool.h>
|
| 24 | #include <linux/delay.h>
|
| 25 | #include <linux/panic.h>
|
| 26 |
|
| 27 | #include <asm/page.h>
|
| 28 | #include <asm/sections.h>
|
| 29 |
|
| 30 | #include "kallsyms_internal.h"
|
| 31 | #include "kexec_internal.h"
|
| 32 |
|
| 33 |
|
| 34 | note_buf_t __percpu *crash_notes;
|
| 35 |
|
| 36 | |
| 37 | * when a CMA reservation is used
|
| 38 |
|
| 39 | #define CMA_DMA_TIMEOUT_SEC 10
|
| 40 |
|
| 41 | #ifdef CONFIG_CRASH_DUMP
|
| 42 |
|
| 43 | int kimage_crash_copy_vmcoreinfo(struct kimage *image)
|
| 44 | {
|
| 45 | struct page *vmcoreinfo_base;
|
| 46 | struct page *vmcoreinfo_pages[DIV_ROUND_UP(VMCOREINFO_BYTES, PAGE_SIZE)];
|
| 47 | unsigned int order, nr_pages;
|
| 48 | int i;
|
| 49 | void *safecopy;
|
| 50 |
|
| 51 | nr_pages = DIV_ROUND_UP(VMCOREINFO_BYTES, PAGE_SIZE);
|
| 52 | order = get_order(VMCOREINFO_BYTES);
|
| 53 |
|
| 54 | if (!IS_ENABLED(CONFIG_CRASH_DUMP))
|
| 55 | return 0;
|
| 56 | if (image->type != KEXEC_TYPE_CRASH)
|
| 57 | return 0;
|
| 58 |
|
| 59 | |
| 60 | * For kdump, allocate one vmcoreinfo safe copy from the
|
| 61 | * crash memory. as we have arch_kexec_protect_crashkres()
|
| 62 | * after kexec syscall, we naturally protect it from write
|
| 63 | * (even read) access under kernel direct mapping. But on
|
| 64 | * the other hand, we still need to operate it when crash
|
| 65 | * happens to generate vmcoreinfo note, hereby we rely on
|
| 66 | * vmap for this purpose.
|
| 67 |
|
| 68 | vmcoreinfo_base = kimage_alloc_control_pages(image, order);
|
| 69 | if (!vmcoreinfo_base) {
|
| 70 | pr_warn("Could not allocate vmcoreinfo buffer\n");
|
| 71 | return -ENOMEM;
|
| 72 | }
|
| 73 | for (i = 0; i < nr_pages; i++)
|
| 74 | vmcoreinfo_pages[i] = vmcoreinfo_base + i;
|
| 75 |
|
| 76 | safecopy = vmap(vmcoreinfo_pages, nr_pages, VM_MAP, PAGE_KERNEL);
|
| 77 | if (!safecopy) {
|
| 78 | pr_warn("Could not vmap vmcoreinfo buffer\n");
|
| 79 | return -ENOMEM;
|
| 80 | }
|
| 81 |
|
| 82 | image->vmcoreinfo_data_copy = safecopy;
|
| 83 | crash_update_vmcoreinfo_safecopy(safecopy);
|
| 84 |
|
| 85 | return 0;
|
| 86 | }
|
| 87 |
|
| 88 |
|
| 89 |
|
| 90 | int kexec_should_crash(struct task_struct *p)
|
| 91 | {
|
| 92 | |
| 93 | * If crash_kexec_post_notifiers is enabled, don't run
|
| 94 | * crash_kexec() here yet, which must be run after panic
|
| 95 | * notifiers in panic().
|
| 96 |
|
| 97 | if (crash_kexec_post_notifiers)
|
| 98 | return 0;
|
| 99 | |
| 100 | * There are 4 panic() calls in make_task_dead() path, each of which
|
| 101 | * corresponds to each of these 4 conditions.
|
| 102 |
|
| 103 | if (in_interrupt() || !p->pid || is_global_init(p) || panic_on_oops)
|
| 104 | return 1;
|
| 105 | return 0;
|
| 106 | }
|
| 107 |
|
| 108 | int kexec_crash_loaded(void)
|
| 109 | {
|
| 110 | return !!kexec_crash_image;
|
| 111 | }
|
| 112 | EXPORT_SYMBOL_GPL(kexec_crash_loaded);
|
| 113 |
|
| 114 | static void crash_cma_clear_pending_dma(void)
|
| 115 | {
|
| 116 | if (!crashk_cma_cnt)
|
| 117 | return;
|
| 118 |
|
| 119 | mdelay(CMA_DMA_TIMEOUT_SEC * 1000);
|
| 120 | }
|
| 121 |
|
| 122 | |
| 123 | * No panic_cpu check version of crash_kexec(). This function is called
|
| 124 | * only when panic_cpu holds the current CPU number; this is the only CPU
|
| 125 | * which processes crash_kexec routines.
|
| 126 |
|
| 127 | void __noclone __crash_kexec(struct pt_regs *regs)
|
| 128 | {
|
| 129 | |
| 130 | * running on one cpu from replacing the crash kernel
|
| 131 | * we are using after a panic on a different cpu.
|
| 132 | *
|
| 133 | * If the crash kernel was not located in a fixed area
|
| 134 | * of memory the xchg(&kexec_crash_image) would be
|
| 135 | * sufficient. But since I reuse the memory...
|
| 136 |
|
| 137 | if (kexec_trylock()) {
|
| 138 | if (kexec_crash_image) {
|
| 139 | struct pt_regs fixed_regs;
|
| 140 |
|
| 141 | crash_setup_regs(&fixed_regs, regs);
|
| 142 | crash_save_vmcoreinfo();
|
| 143 | machine_crash_shutdown(&fixed_regs);
|
| 144 | crash_cma_clear_pending_dma();
|
| 145 | machine_kexec(kexec_crash_image);
|
| 146 | }
|
| 147 | kexec_unlock();
|
| 148 | }
|
| 149 | }
|
| 150 | STACK_FRAME_NON_STANDARD(__crash_kexec);
|
| 151 |
|
| 152 | __bpf_kfunc void crash_kexec(struct pt_regs *regs)
|
| 153 | {
|
| 154 | if (panic_try_start()) {
|
| 155 |
|
| 156 | __crash_kexec(regs);
|
| 157 |
|
| 158 | |
| 159 | * Reset panic_cpu to allow another panic()/crash_kexec()
|
| 160 | * call.
|
| 161 |
|
| 162 | panic_reset();
|
| 163 | }
|
| 164 | }
|
| 165 |
|
| 166 | static inline resource_size_t crash_resource_size(const struct resource *res)
|
| 167 | {
|
| 168 | return !res->end ? 0 : resource_size(res);
|
| 169 | }
|
| 170 |
|
| 171 | int crash_prepare_elf64_headers(struct crash_mem *mem, int need_kernel_map,
|
| 172 | void **addr, unsigned long *sz)
|
| 173 | {
|
| 174 | Elf64_Ehdr *ehdr;
|
| 175 | Elf64_Phdr *phdr;
|
| 176 | unsigned long nr_cpus = num_possible_cpus(), nr_phdr, elf_sz;
|
| 177 | unsigned char *buf;
|
| 178 | unsigned int cpu, i;
|
| 179 | unsigned long long notes_addr;
|
| 180 | unsigned long mstart, mend;
|
| 181 |
|
| 182 |
|
| 183 | nr_phdr = nr_cpus + 1;
|
| 184 | nr_phdr += mem->nr_ranges;
|
| 185 |
|
| 186 | |
| 187 | * kexec-tools creates an extra PT_LOAD phdr for kernel text mapping
|
| 188 | * area (for example, ffffffff80000000 - ffffffffa0000000 on x86_64).
|
| 189 | * I think this is required by tools like gdb. So same physical
|
| 190 | * memory will be mapped in two ELF headers. One will contain kernel
|
| 191 | * text virtual addresses and other will have __va(physical) addresses.
|
| 192 |
|
| 193 |
|
| 194 | nr_phdr++;
|
| 195 | elf_sz = sizeof(Elf64_Ehdr) + nr_phdr * sizeof(Elf64_Phdr);
|
| 196 | elf_sz = ALIGN(elf_sz, ELF_CORE_HEADER_ALIGN);
|
| 197 |
|
| 198 | buf = vzalloc(elf_sz);
|
| 199 | if (!buf)
|
| 200 | return -ENOMEM;
|
| 201 |
|
| 202 | ehdr = (Elf64_Ehdr *)buf;
|
| 203 | phdr = (Elf64_Phdr *)(ehdr + 1);
|
| 204 | memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
|
| 205 | ehdr->e_ident[EI_CLASS] = ELFCLASS64;
|
| 206 | ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
|
| 207 | ehdr->e_ident[EI_VERSION] = EV_CURRENT;
|
| 208 | ehdr->e_ident[EI_OSABI] = ELF_OSABI;
|
| 209 | memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD);
|
| 210 | ehdr->e_type = ET_CORE;
|
| 211 | ehdr->e_machine = ELF_ARCH;
|
| 212 | ehdr->e_version = EV_CURRENT;
|
| 213 | ehdr->e_phoff = sizeof(Elf64_Ehdr);
|
| 214 | ehdr->e_ehsize = sizeof(Elf64_Ehdr);
|
| 215 | ehdr->e_phentsize = sizeof(Elf64_Phdr);
|
| 216 |
|
| 217 |
|
| 218 | for_each_possible_cpu(cpu) {
|
| 219 | phdr->p_type = PT_NOTE;
|
| 220 | notes_addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpu));
|
| 221 | phdr->p_offset = phdr->p_paddr = notes_addr;
|
| 222 | phdr->p_filesz = phdr->p_memsz = sizeof(note_buf_t);
|
| 223 | (ehdr->e_phnum)++;
|
| 224 | phdr++;
|
| 225 | }
|
| 226 |
|
| 227 |
|
| 228 | phdr->p_type = PT_NOTE;
|
| 229 | phdr->p_offset = phdr->p_paddr = paddr_vmcoreinfo_note();
|
| 230 | phdr->p_filesz = phdr->p_memsz = VMCOREINFO_NOTE_SIZE;
|
| 231 | (ehdr->e_phnum)++;
|
| 232 | phdr++;
|
| 233 |
|
| 234 |
|
| 235 | if (need_kernel_map) {
|
| 236 | phdr->p_type = PT_LOAD;
|
| 237 | phdr->p_flags = PF_R|PF_W|PF_X;
|
| 238 | phdr->p_vaddr = (unsigned long) _text;
|
| 239 | phdr->p_filesz = phdr->p_memsz = _end - _text;
|
| 240 | phdr->p_offset = phdr->p_paddr = __pa_symbol(_text);
|
| 241 | ehdr->e_phnum++;
|
| 242 | phdr++;
|
| 243 | }
|
| 244 |
|
| 245 |
|
| 246 | for (i = 0; i < mem->nr_ranges; i++) {
|
| 247 | mstart = mem->ranges[i].start;
|
| 248 | mend = mem->ranges[i].end;
|
| 249 |
|
| 250 | phdr->p_type = PT_LOAD;
|
| 251 | phdr->p_flags = PF_R|PF_W|PF_X;
|
| 252 | phdr->p_offset = mstart;
|
| 253 |
|
| 254 | phdr->p_paddr = mstart;
|
| 255 | phdr->p_vaddr = (unsigned long) __va(mstart);
|
| 256 | phdr->p_filesz = phdr->p_memsz = mend - mstart + 1;
|
| 257 | phdr->p_align = 0;
|
| 258 | ehdr->e_phnum++;
|
| 259 | #ifdef CONFIG_KEXEC_FILE
|
| 260 | 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",
|
| 261 | phdr, phdr->p_vaddr, phdr->p_paddr, phdr->p_filesz,
|
| 262 | ehdr->e_phnum, phdr->p_offset);
|
| 263 | #endif
|
| 264 | phdr++;
|
| 265 | }
|
| 266 |
|
| 267 | *addr = buf;
|
| 268 | *sz = elf_sz;
|
| 269 | return 0;
|
| 270 | }
|
| 271 |
|
| 272 | static struct crash_mem *alloc_cmem(unsigned int nr_ranges)
|
| 273 | {
|
| 274 | struct crash_mem *cmem;
|
| 275 |
|
| 276 | cmem = kvzalloc_flex(*cmem, ranges, nr_ranges);
|
| 277 | if (!cmem)
|
| 278 | return NULL;
|
| 279 |
|
| 280 | cmem->max_nr_ranges = nr_ranges;
|
| 281 | return cmem;
|
| 282 | }
|
| 283 |
|
| 284 | unsigned int __weak arch_get_system_nr_ranges(void) { return 0; }
|
| 285 | int __weak arch_crash_populate_cmem(struct crash_mem *cmem) { return -1; }
|
| 286 | int __weak arch_crash_exclude_ranges(struct crash_mem *cmem) { return 0; }
|
| 287 |
|
| 288 | int __weak arch_crash_exclude_mem_range(struct crash_mem **mem,
|
| 289 | unsigned long long mstart,
|
| 290 | unsigned long long mend)
|
| 291 | {
|
| 292 | return crash_exclude_mem_range(*mem, mstart, mend);
|
| 293 | }
|
| 294 |
|
| 295 | int crash_exclude_core_ranges(struct crash_mem **cmem)
|
| 296 | {
|
| 297 | int ret, i;
|
| 298 |
|
| 299 |
|
| 300 | ret = arch_crash_exclude_mem_range(cmem, crashk_res.start, crashk_res.end);
|
| 301 | if (ret)
|
| 302 | return ret;
|
| 303 |
|
| 304 | if (crashk_low_res.end) {
|
| 305 | ret = arch_crash_exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end);
|
| 306 | if (ret)
|
| 307 | return ret;
|
| 308 | }
|
| 309 |
|
| 310 | for (i = 0; i < crashk_cma_cnt; ++i) {
|
| 311 | ret = arch_crash_exclude_mem_range(cmem, crashk_cma_ranges[i].start,
|
| 312 | crashk_cma_ranges[i].end);
|
| 313 | if (ret)
|
| 314 | return ret;
|
| 315 | }
|
| 316 |
|
| 317 | return 0;
|
| 318 | }
|
| 319 |
|
| 320 | int crash_prepare_headers(int need_kernel_map, void **addr, unsigned long *sz,
|
| 321 | unsigned long *nr_mem_ranges)
|
| 322 | {
|
| 323 | unsigned int max_nr_ranges;
|
| 324 | struct crash_mem *cmem;
|
| 325 | int ret;
|
| 326 |
|
| 327 | max_nr_ranges = arch_get_system_nr_ranges();
|
| 328 | if (!max_nr_ranges)
|
| 329 | return -ENOMEM;
|
| 330 |
|
| 331 | cmem = alloc_cmem(max_nr_ranges);
|
| 332 | if (!cmem)
|
| 333 | return -ENOMEM;
|
| 334 |
|
| 335 | ret = arch_crash_populate_cmem(cmem);
|
| 336 | if (ret)
|
| 337 | goto out;
|
| 338 |
|
| 339 | ret = crash_exclude_core_ranges(&cmem);
|
| 340 | if (ret)
|
| 341 | goto out;
|
| 342 |
|
| 343 | ret = arch_crash_exclude_ranges(cmem);
|
| 344 | if (ret)
|
| 345 | goto out;
|
| 346 |
|
| 347 |
|
| 348 | if (nr_mem_ranges)
|
| 349 | *nr_mem_ranges = cmem->nr_ranges;
|
| 350 |
|
| 351 | ret = crash_prepare_elf64_headers(cmem, need_kernel_map, addr, sz);
|
| 352 |
|
| 353 | out:
|
| 354 | kvfree(cmem);
|
| 355 | return ret;
|
| 356 | }
|
| 357 |
|
| 358 | |
| 359 | * crash_exclude_mem_range - exclude a mem range for existing ranges
|
| 360 | * @mem: mem->range contains an array of ranges sorted in ascending order
|
| 361 | * @mstart: the start of to-be-excluded range
|
| 362 | * @mend: the start of to-be-excluded range
|
| 363 | *
|
| 364 | * If you are unsure if a range split will happen, to avoid function call
|
| 365 | * failure because of -ENOMEM, always make sure
|
| 366 | * mem->max_nr_ranges == mem->nr_ranges + 1
|
| 367 | * before calling the function each time.
|
| 368 | *
|
| 369 | * returns 0 if a memory range is excluded successfully
|
| 370 | * return -ENOMEM if mem->ranges doesn't have space to hold split ranges
|
| 371 |
|
| 372 | int crash_exclude_mem_range(struct crash_mem *mem,
|
| 373 | unsigned long long mstart, unsigned long long mend)
|
| 374 | {
|
| 375 | int i;
|
| 376 | unsigned long long start, end, p_start, p_end;
|
| 377 |
|
| 378 | for (i = 0; i < mem->nr_ranges; i++) {
|
| 379 | start = mem->ranges[i].start;
|
| 380 | end = mem->ranges[i].end;
|
| 381 | p_start = mstart;
|
| 382 | p_end = mend;
|
| 383 |
|
| 384 | if (p_start > end)
|
| 385 | continue;
|
| 386 |
|
| 387 | |
| 388 | * Because the memory ranges in mem->ranges are stored in
|
| 389 | * ascending order, when we detect `p_end < start`, we can
|
| 390 | * immediately exit the for loop, as the subsequent memory
|
| 391 | * ranges will definitely be outside the range we are looking
|
| 392 | * for.
|
| 393 |
|
| 394 | if (p_end < start)
|
| 395 | break;
|
| 396 |
|
| 397 |
|
| 398 | if (p_start < start)
|
| 399 | p_start = start;
|
| 400 | if (p_end > end)
|
| 401 | p_end = end;
|
| 402 |
|
| 403 |
|
| 404 | if (p_start == start && p_end == end) {
|
| 405 | memmove(&mem->ranges[i], &mem->ranges[i + 1],
|
| 406 | (mem->nr_ranges - (i + 1)) * sizeof(mem->ranges[i]));
|
| 407 | i--;
|
| 408 | mem->nr_ranges--;
|
| 409 | } else if (p_start > start && p_end < end) {
|
| 410 |
|
| 411 | if (mem->nr_ranges >= mem->max_nr_ranges)
|
| 412 | return -ENOMEM;
|
| 413 |
|
| 414 | memmove(&mem->ranges[i + 2], &mem->ranges[i + 1],
|
| 415 | (mem->nr_ranges - (i + 1)) * sizeof(mem->ranges[i]));
|
| 416 |
|
| 417 | mem->ranges[i].end = p_start - 1;
|
| 418 | mem->ranges[i + 1].start = p_end + 1;
|
| 419 | mem->ranges[i + 1].end = end;
|
| 420 |
|
| 421 | i++;
|
| 422 | mem->nr_ranges++;
|
| 423 | } else if (p_start != start)
|
| 424 | mem->ranges[i].end = p_start - 1;
|
| 425 | else
|
| 426 | mem->ranges[i].start = p_end + 1;
|
| 427 | }
|
| 428 |
|
| 429 | return 0;
|
| 430 | }
|
| 431 | EXPORT_SYMBOL_GPL(crash_exclude_mem_range);
|
| 432 |
|
| 433 | ssize_t crash_get_memory_size(void)
|
| 434 | {
|
| 435 | ssize_t size = 0;
|
| 436 |
|
| 437 | if (!kexec_trylock())
|
| 438 | return -EBUSY;
|
| 439 |
|
| 440 | size += crash_resource_size(&crashk_res);
|
| 441 | size += crash_resource_size(&crashk_low_res);
|
| 442 |
|
| 443 | kexec_unlock();
|
| 444 | return size;
|
| 445 | }
|
| 446 |
|
| 447 | static int __crash_shrink_memory(struct resource *old_res,
|
| 448 | unsigned long new_size)
|
| 449 | {
|
| 450 | struct resource *ram_res;
|
| 451 |
|
| 452 | ram_res = kzalloc_obj(*ram_res);
|
| 453 | if (!ram_res)
|
| 454 | return -ENOMEM;
|
| 455 |
|
| 456 | ram_res->start = old_res->start + new_size;
|
| 457 | ram_res->end = old_res->end;
|
| 458 | ram_res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM;
|
| 459 | ram_res->name = "System RAM";
|
| 460 |
|
| 461 | if (!new_size) {
|
| 462 | release_resource(old_res);
|
| 463 | old_res->start = 0;
|
| 464 | old_res->end = 0;
|
| 465 | } else {
|
| 466 | old_res->end = ram_res->start - 1;
|
| 467 | }
|
| 468 |
|
| 469 | crash_free_reserved_phys_range(ram_res->start, ram_res->end);
|
| 470 | insert_resource(&iomem_resource, ram_res);
|
| 471 |
|
| 472 | return 0;
|
| 473 | }
|
| 474 |
|
| 475 | int crash_shrink_memory(unsigned long new_size)
|
| 476 | {
|
| 477 | int ret = 0;
|
| 478 | unsigned long old_size, low_size;
|
| 479 |
|
| 480 | if (!kexec_trylock())
|
| 481 | return -EBUSY;
|
| 482 |
|
| 483 | if (kexec_crash_image) {
|
| 484 | ret = -ENOENT;
|
| 485 | goto unlock;
|
| 486 | }
|
| 487 |
|
| 488 | low_size = crash_resource_size(&crashk_low_res);
|
| 489 | old_size = crash_resource_size(&crashk_res) + low_size;
|
| 490 | new_size = roundup(new_size, KEXEC_CRASH_MEM_ALIGN);
|
| 491 | if (new_size >= old_size) {
|
| 492 | ret = (new_size == old_size) ? 0 : -EINVAL;
|
| 493 | goto unlock;
|
| 494 | }
|
| 495 |
|
| 496 | |
| 497 | * (low_size > new_size) implies that low_size is greater than zero.
|
| 498 | * This also means that if low_size is zero, the else branch is taken.
|
| 499 | *
|
| 500 | * If low_size is greater than 0, (low_size > new_size) indicates that
|
| 501 | * crashk_low_res also needs to be shrunken. Otherwise, only crashk_res
|
| 502 | * needs to be shrunken.
|
| 503 |
|
| 504 | if (low_size > new_size) {
|
| 505 | ret = __crash_shrink_memory(&crashk_res, 0);
|
| 506 | if (ret)
|
| 507 | goto unlock;
|
| 508 |
|
| 509 | ret = __crash_shrink_memory(&crashk_low_res, new_size);
|
| 510 | } else {
|
| 511 | ret = __crash_shrink_memory(&crashk_res, new_size - low_size);
|
| 512 | }
|
| 513 |
|
| 514 |
|
| 515 | if (!crashk_res.end && crashk_low_res.end) {
|
| 516 | crashk_res.start = crashk_low_res.start;
|
| 517 | crashk_res.end = crashk_low_res.end;
|
| 518 | release_resource(&crashk_low_res);
|
| 519 | crashk_low_res.start = 0;
|
| 520 | crashk_low_res.end = 0;
|
| 521 | insert_resource(&iomem_resource, &crashk_res);
|
| 522 | }
|
| 523 |
|
| 524 | unlock:
|
| 525 | kexec_unlock();
|
| 526 | return ret;
|
| 527 | }
|
| 528 |
|
| 529 | void crash_save_cpu(struct pt_regs *regs, int cpu)
|
| 530 | {
|
| 531 | struct elf_prstatus prstatus;
|
| 532 | u32 *buf;
|
| 533 |
|
| 534 | if ((cpu < 0) || (cpu >= nr_cpu_ids))
|
| 535 | return;
|
| 536 |
|
| 537 | |
| 538 | * I need a well defined structure format
|
| 539 | * for the data I pass, and I need tags
|
| 540 | * on the data to indicate what information I have
|
| 541 | * squirrelled away. ELF notes happen to provide
|
| 542 | * all of that, so there is no need to invent something new.
|
| 543 |
|
| 544 | buf = (u32 *)per_cpu_ptr(crash_notes, cpu);
|
| 545 | if (!buf)
|
| 546 | return;
|
| 547 | memset(&prstatus, 0, sizeof(prstatus));
|
| 548 | prstatus.common.pr_pid = current->pid;
|
| 549 | elf_core_copy_regs(&prstatus.pr_reg, regs);
|
| 550 | buf = append_elf_note(buf, NN_PRSTATUS, NT_PRSTATUS,
|
| 551 | &prstatus, sizeof(prstatus));
|
| 552 | final_note(buf);
|
| 553 | }
|
| 554 |
|
| 555 |
|
| 556 |
|
| 557 | static int __init crash_notes_memory_init(void)
|
| 558 | {
|
| 559 |
|
| 560 | size_t size, align;
|
| 561 |
|
| 562 | |
| 563 | * crash_notes could be allocated across 2 vmalloc pages when percpu
|
| 564 | * is vmalloc based . vmalloc doesn't guarantee 2 continuous vmalloc
|
| 565 | * pages are also on 2 continuous physical pages. In this case the
|
| 566 | * 2nd part of crash_notes in 2nd page could be lost since only the
|
| 567 | * starting address and size of crash_notes are exported through sysfs.
|
| 568 | * Here round up the size of crash_notes to the nearest power of two
|
| 569 | * and pass it to __alloc_percpu as align value. This can make sure
|
| 570 | * crash_notes is allocated inside one physical page.
|
| 571 |
|
| 572 | size = sizeof(note_buf_t);
|
| 573 | align = min(roundup_pow_of_two(sizeof(note_buf_t)), PAGE_SIZE);
|
| 574 |
|
| 575 | |
| 576 | * Break compile if size is bigger than PAGE_SIZE since crash_notes
|
| 577 | * definitely will be in 2 pages with that.
|
| 578 |
|
| 579 | BUILD_BUG_ON(size > PAGE_SIZE);
|
| 580 |
|
| 581 | crash_notes = __alloc_percpu(size, align);
|
| 582 | if (!crash_notes) {
|
| 583 | pr_warn("Memory allocation for saving cpu register states failed\n");
|
| 584 | return -ENOMEM;
|
| 585 | }
|
| 586 | return 0;
|
| 587 | }
|
| 588 | subsys_initcall(crash_notes_memory_init);
|
| 589 |
|
| 590 | #endif
|
| 591 |
|
| 592 | #ifdef CONFIG_CRASH_HOTPLUG
|
| 593 | #undef pr_fmt
|
| 594 | #define pr_fmt(fmt) "crash hp: " fmt
|
| 595 |
|
| 596 | |
| 597 | * Different than kexec/kdump loading/unloading/jumping/shrinking which
|
| 598 | * usually rarely happen, there will be many crash hotplug events notified
|
| 599 | * during one short period, e.g one memory board is hot added and memory
|
| 600 | * regions are online. So mutex lock __crash_hotplug_lock is used to
|
| 601 | * serialize the crash hotplug handling specifically.
|
| 602 |
|
| 603 | static DEFINE_MUTEX(__crash_hotplug_lock);
|
| 604 | #define crash_hotplug_lock() mutex_lock(&__crash_hotplug_lock)
|
| 605 | #define crash_hotplug_unlock() mutex_unlock(&__crash_hotplug_lock)
|
| 606 |
|
| 607 | |
| 608 | * This routine utilized when the crash_hotplug sysfs node is read.
|
| 609 | * It reflects the kernel's ability/permission to update the kdump
|
| 610 | * image directly.
|
| 611 |
|
| 612 | int crash_check_hotplug_support(void)
|
| 613 | {
|
| 614 | int rc = 0;
|
| 615 |
|
| 616 | crash_hotplug_lock();
|
| 617 |
|
| 618 | if (!kexec_trylock()) {
|
| 619 | if (!kexec_in_progress)
|
| 620 | pr_info("kexec_trylock() failed, kdump image may be inaccurate\n");
|
| 621 | crash_hotplug_unlock();
|
| 622 | return 0;
|
| 623 | }
|
| 624 | if (kexec_crash_image) {
|
| 625 | rc = kexec_crash_image->hotplug_support;
|
| 626 | }
|
| 627 |
|
| 628 | kexec_unlock();
|
| 629 | crash_hotplug_unlock();
|
| 630 |
|
| 631 | return rc;
|
| 632 | }
|
| 633 |
|
| 634 | |
| 635 | * To accurately reflect hot un/plug changes of CPU and Memory resources
|
| 636 | * (including onling and offlining of those resources), the relevant
|
| 637 | * kexec segments must be updated with latest CPU and Memory resources.
|
| 638 | *
|
| 639 | * Architectures must ensure two things for all segments that need
|
| 640 | * updating during hotplug events:
|
| 641 | *
|
| 642 | * 1. Segments must be large enough to accommodate a growing number of
|
| 643 | * resources.
|
| 644 | * 2. Exclude the segments from SHA verification.
|
| 645 | *
|
| 646 | * For example, on most architectures, the elfcorehdr (which is passed
|
| 647 | * to the crash kernel via the elfcorehdr= parameter) must include the
|
| 648 | * new list of CPUs and memory. To make changes to the elfcorehdr, it
|
| 649 | * should be large enough to permit a growing number of CPU and Memory
|
| 650 | * resources. One can estimate the elfcorehdr memory size based on
|
| 651 | * NR_CPUS and CRASH_MAX_MEMORY_RANGES. The elfcorehdr is
|
| 652 | * excluded from SHA verification by default if the architecture
|
| 653 | * supports crash hotplug.
|
| 654 |
|
| 655 | static void crash_handle_hotplug_event(unsigned int hp_action, unsigned int cpu, void *arg)
|
| 656 | {
|
| 657 | struct kimage *image;
|
| 658 |
|
| 659 | crash_hotplug_lock();
|
| 660 |
|
| 661 | if (!kexec_trylock()) {
|
| 662 | if (!kexec_in_progress)
|
| 663 | pr_info("kexec_trylock() failed, kdump image may be inaccurate\n");
|
| 664 | crash_hotplug_unlock();
|
| 665 | return;
|
| 666 | }
|
| 667 |
|
| 668 |
|
| 669 | if (!kexec_crash_image)
|
| 670 | goto out;
|
| 671 |
|
| 672 | image = kexec_crash_image;
|
| 673 |
|
| 674 |
|
| 675 | if (!image->hotplug_support)
|
| 676 | goto out;
|
| 677 |
|
| 678 | if (hp_action == KEXEC_CRASH_HP_ADD_CPU ||
|
| 679 | hp_action == KEXEC_CRASH_HP_REMOVE_CPU)
|
| 680 | pr_debug("hp_action %u, cpu %u\n", hp_action, cpu);
|
| 681 | else
|
| 682 | pr_debug("hp_action %u\n", hp_action);
|
| 683 |
|
| 684 | |
| 685 | * The elfcorehdr_index is set to -1 when the struct kimage
|
| 686 | * is allocated. Find the segment containing the elfcorehdr,
|
| 687 | * if not already found.
|
| 688 |
|
| 689 | if (image->elfcorehdr_index < 0) {
|
| 690 | unsigned long mem;
|
| 691 | unsigned char *ptr;
|
| 692 | unsigned int n;
|
| 693 |
|
| 694 | for (n = 0; n < image->nr_segments; n++) {
|
| 695 | mem = image->segment[n].mem;
|
| 696 | ptr = kmap_local_page(pfn_to_page(mem >> PAGE_SHIFT));
|
| 697 | if (ptr) {
|
| 698 |
|
| 699 | if (memcmp(ptr, ELFMAG, SELFMAG) == 0)
|
| 700 | image->elfcorehdr_index = (int)n;
|
| 701 | kunmap_local(ptr);
|
| 702 | }
|
| 703 | }
|
| 704 | }
|
| 705 |
|
| 706 | if (image->elfcorehdr_index < 0) {
|
| 707 | pr_err("unable to locate elfcorehdr segment");
|
| 708 | goto out;
|
| 709 | }
|
| 710 |
|
| 711 |
|
| 712 | arch_kexec_unprotect_crashkres();
|
| 713 |
|
| 714 |
|
| 715 | image->hp_action = hp_action;
|
| 716 |
|
| 717 |
|
| 718 | arch_crash_handle_hotplug_event(image, arg);
|
| 719 |
|
| 720 |
|
| 721 | image->hp_action = KEXEC_CRASH_HP_NONE;
|
| 722 | image->elfcorehdr_updated = true;
|
| 723 |
|
| 724 |
|
| 725 | arch_kexec_protect_crashkres();
|
| 726 |
|
| 727 |
|
| 728 | out:
|
| 729 |
|
| 730 | kexec_unlock();
|
| 731 | crash_hotplug_unlock();
|
| 732 | }
|
| 733 |
|
| 734 | static int crash_memhp_notifier(struct notifier_block *nb, unsigned long val, void *arg)
|
| 735 | {
|
| 736 | switch (val) {
|
| 737 | case MEM_ONLINE:
|
| 738 | crash_handle_hotplug_event(KEXEC_CRASH_HP_ADD_MEMORY,
|
| 739 | KEXEC_CRASH_HP_INVALID_CPU, arg);
|
| 740 | break;
|
| 741 |
|
| 742 | case MEM_OFFLINE:
|
| 743 | crash_handle_hotplug_event(KEXEC_CRASH_HP_REMOVE_MEMORY,
|
| 744 | KEXEC_CRASH_HP_INVALID_CPU, arg);
|
| 745 | break;
|
| 746 | }
|
| 747 | return NOTIFY_OK;
|
| 748 | }
|
| 749 |
|
| 750 | static struct notifier_block crash_memhp_nb = {
|
| 751 | .notifier_call = crash_memhp_notifier,
|
| 752 | .priority = 0
|
| 753 | };
|
| 754 |
|
| 755 | static int crash_cpuhp_online(unsigned int cpu)
|
| 756 | {
|
| 757 | crash_handle_hotplug_event(KEXEC_CRASH_HP_ADD_CPU, cpu, NULL);
|
| 758 | return 0;
|
| 759 | }
|
| 760 |
|
| 761 | static int crash_cpuhp_offline(unsigned int cpu)
|
| 762 | {
|
| 763 | crash_handle_hotplug_event(KEXEC_CRASH_HP_REMOVE_CPU, cpu, NULL);
|
| 764 | return 0;
|
| 765 | }
|
| 766 |
|
| 767 | static int __init crash_hotplug_init(void)
|
| 768 | {
|
| 769 | int result = 0;
|
| 770 |
|
| 771 | if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
|
| 772 | register_memory_notifier(&crash_memhp_nb);
|
| 773 |
|
| 774 | if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) {
|
| 775 | result = cpuhp_setup_state_nocalls(CPUHP_BP_PREPARE_DYN,
|
| 776 | "crash/cpuhp", crash_cpuhp_online, crash_cpuhp_offline);
|
| 777 | }
|
| 778 |
|
| 779 | return result;
|
| 780 | }
|
| 781 |
|
| 782 | subsys_initcall(crash_hotplug_init);
|
| 783 | #endif
|