aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/crash_dump.c
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>2013-09-11 17:24:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-11 18:59:10 -0400
commit97b0f6f9cd73ff8285835c5e295d3c4b0e2dbf78 (patch)
treed2cfbfb9c7f465e862425f233e74192edc6e7a29 /arch/s390/kernel/crash_dump.c
parentbe8a8d069e508d4408125e2b1471f549e7813d25 (diff)
s390/vmcore: use ELF header in new memory feature
Exchange the old relocate mechanism with the new arch function call override mechanism that allows to create the ELF core header in the 2nd kernel. Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Cc: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com> Cc: Jan Willeke <willeke@de.ibm.com> Cc: Vivek Goyal <vgoyal@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/s390/kernel/crash_dump.c')
-rw-r--r--arch/s390/kernel/crash_dump.c81
1 files changed, 54 insertions, 27 deletions
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index d8f355657171..0c9a897a1fb5 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -64,6 +64,11 @@ static ssize_t copy_page_real(void *buf, void *src, size_t csize)
64} 64}
65 65
66/* 66/*
67 * Pointer to ELF header in new kernel
68 */
69static void *elfcorehdr_newmem;
70
71/*
67 * Copy one page from "oldmem" 72 * Copy one page from "oldmem"
68 * 73 *
69 * For the kdump reserved memory this functions performs a swap operation: 74 * For the kdump reserved memory this functions performs a swap operation:
@@ -368,14 +373,6 @@ static int get_mem_chunk_cnt(void)
368} 373}
369 374
370/* 375/*
371 * Relocate pointer in order to allow vmcore code access the data
372 */
373static inline unsigned long relocate(unsigned long addr)
374{
375 return OLDMEM_BASE + addr;
376}
377
378/*
379 * Initialize ELF loads (new kernel) 376 * Initialize ELF loads (new kernel)
380 */ 377 */
381static int loads_init(Elf64_Phdr *phdr, u64 loads_offset) 378static int loads_init(Elf64_Phdr *phdr, u64 loads_offset)
@@ -426,7 +423,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
426 ptr = nt_vmcoreinfo(ptr); 423 ptr = nt_vmcoreinfo(ptr);
427 memset(phdr, 0, sizeof(*phdr)); 424 memset(phdr, 0, sizeof(*phdr));
428 phdr->p_type = PT_NOTE; 425 phdr->p_type = PT_NOTE;
429 phdr->p_offset = relocate(notes_offset); 426 phdr->p_offset = notes_offset;
430 phdr->p_filesz = (unsigned long) PTR_SUB(ptr, ptr_start); 427 phdr->p_filesz = (unsigned long) PTR_SUB(ptr, ptr_start);
431 phdr->p_memsz = phdr->p_filesz; 428 phdr->p_memsz = phdr->p_filesz;
432 return ptr; 429 return ptr;
@@ -435,7 +432,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
435/* 432/*
436 * Create ELF core header (new kernel) 433 * Create ELF core header (new kernel)
437 */ 434 */
438static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz) 435int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
439{ 436{
440 Elf64_Phdr *phdr_notes, *phdr_loads; 437 Elf64_Phdr *phdr_notes, *phdr_loads;
441 int mem_chunk_cnt; 438 int mem_chunk_cnt;
@@ -443,6 +440,11 @@ static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
443 u32 alloc_size; 440 u32 alloc_size;
444 u64 hdr_off; 441 u64 hdr_off;
445 442
443 if (!OLDMEM_BASE)
444 return 0;
445 /* If elfcorehdr= has been passed via cmdline, we use that one */
446 if (elfcorehdr_addr != ELFCORE_ADDR_MAX)
447 return 0;
446 mem_chunk_cnt = get_mem_chunk_cnt(); 448 mem_chunk_cnt = get_mem_chunk_cnt();
447 449
448 alloc_size = 0x1000 + get_cpu_cnt() * 0x300 + 450 alloc_size = 0x1000 + get_cpu_cnt() * 0x300 +
@@ -460,27 +462,52 @@ static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
460 ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off); 462 ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off);
461 /* Init loads */ 463 /* Init loads */
462 hdr_off = PTR_DIFF(ptr, hdr); 464 hdr_off = PTR_DIFF(ptr, hdr);
463 loads_init(phdr_loads, ((unsigned long) hdr) + hdr_off); 465 loads_init(phdr_loads, hdr_off);
464 *elfcorebuf_sz = hdr_off; 466 *addr = (unsigned long long) hdr;
465 *elfcorebuf = (void *) relocate((unsigned long) hdr); 467 elfcorehdr_newmem = hdr;
466 BUG_ON(*elfcorebuf_sz > alloc_size); 468 *size = (unsigned long long) hdr_off;
469 BUG_ON(elfcorehdr_size > alloc_size);
470 return 0;
467} 471}
468 472
469/* 473/*
470 * Create kdump ELF core header in new kernel, if it has not been passed via 474 * Free ELF core header (new kernel)
471 * the "elfcorehdr" kernel parameter
472 */ 475 */
473static int setup_kdump_elfcorehdr(void) 476void elfcorehdr_free(unsigned long long addr)
474{ 477{
475 size_t elfcorebuf_sz; 478 if (!elfcorehdr_newmem)
476 char *elfcorebuf; 479 return;
477 480 kfree((void *)(unsigned long)addr);
478 if (!OLDMEM_BASE || is_kdump_kernel()) 481}
479 return -EINVAL; 482
480 s390_elf_corehdr_create(&elfcorebuf, &elfcorebuf_sz); 483/*
481 elfcorehdr_addr = (unsigned long long) elfcorebuf; 484 * Read from ELF header
482 elfcorehdr_size = elfcorebuf_sz; 485 */
483 return 0; 486ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos)
487{
488 void *src = (void *)(unsigned long)*ppos;
489
490 src = elfcorehdr_newmem ? src : src - OLDMEM_BASE;
491 memcpy(buf, src, count);
492 *ppos += count;
493 return count;
484} 494}
485 495
486subsys_initcall(setup_kdump_elfcorehdr); 496/*
497 * Read from ELF notes data
498 */
499ssize_t elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos)
500{
501 void *src = (void *)(unsigned long)*ppos;
502 int rc;
503
504 if (elfcorehdr_newmem) {
505 memcpy(buf, src, count);
506 } else {
507 rc = copy_from_oldmem(buf, src, count);
508 if (rc)
509 return rc;
510 }
511 *ppos += count;
512 return count;
513}