Skip to content

Commit

Permalink
s390/vmcore: use ELF header in new memory feature
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Michael Holzheu authored and Linus Torvalds committed Sep 11, 2013
1 parent be8a8d0 commit 97b0f6f
Showing 1 changed file with 54 additions and 27 deletions.
81 changes: 54 additions & 27 deletions arch/s390/kernel/crash_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ static ssize_t copy_page_real(void *buf, void *src, size_t csize)
}
}

/*
* Pointer to ELF header in new kernel
*/
static void *elfcorehdr_newmem;

/*
* Copy one page from "oldmem"
*
Expand Down Expand Up @@ -367,14 +372,6 @@ static int get_mem_chunk_cnt(void)
return cnt;
}

/*
* Relocate pointer in order to allow vmcore code access the data
*/
static inline unsigned long relocate(unsigned long addr)
{
return OLDMEM_BASE + addr;
}

/*
* Initialize ELF loads (new kernel)
*/
Expand Down Expand Up @@ -426,7 +423,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
ptr = nt_vmcoreinfo(ptr);
memset(phdr, 0, sizeof(*phdr));
phdr->p_type = PT_NOTE;
phdr->p_offset = relocate(notes_offset);
phdr->p_offset = notes_offset;
phdr->p_filesz = (unsigned long) PTR_SUB(ptr, ptr_start);
phdr->p_memsz = phdr->p_filesz;
return ptr;
Expand All @@ -435,14 +432,19 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
/*
* Create ELF core header (new kernel)
*/
static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
{
Elf64_Phdr *phdr_notes, *phdr_loads;
int mem_chunk_cnt;
void *ptr, *hdr;
u32 alloc_size;
u64 hdr_off;

if (!OLDMEM_BASE)
return 0;
/* If elfcorehdr= has been passed via cmdline, we use that one */
if (elfcorehdr_addr != ELFCORE_ADDR_MAX)
return 0;
mem_chunk_cnt = get_mem_chunk_cnt();

alloc_size = 0x1000 + get_cpu_cnt() * 0x300 +
Expand All @@ -460,27 +462,52 @@ static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off);
/* Init loads */
hdr_off = PTR_DIFF(ptr, hdr);
loads_init(phdr_loads, ((unsigned long) hdr) + hdr_off);
*elfcorebuf_sz = hdr_off;
*elfcorebuf = (void *) relocate((unsigned long) hdr);
BUG_ON(*elfcorebuf_sz > alloc_size);
loads_init(phdr_loads, hdr_off);
*addr = (unsigned long long) hdr;
elfcorehdr_newmem = hdr;
*size = (unsigned long long) hdr_off;
BUG_ON(elfcorehdr_size > alloc_size);
return 0;
}

/*
* Create kdump ELF core header in new kernel, if it has not been passed via
* the "elfcorehdr" kernel parameter
* Free ELF core header (new kernel)
*/
static int setup_kdump_elfcorehdr(void)
void elfcorehdr_free(unsigned long long addr)
{
size_t elfcorebuf_sz;
char *elfcorebuf;

if (!OLDMEM_BASE || is_kdump_kernel())
return -EINVAL;
s390_elf_corehdr_create(&elfcorebuf, &elfcorebuf_sz);
elfcorehdr_addr = (unsigned long long) elfcorebuf;
elfcorehdr_size = elfcorebuf_sz;
return 0;
if (!elfcorehdr_newmem)
return;
kfree((void *)(unsigned long)addr);
}

/*
* Read from ELF header
*/
ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos)
{
void *src = (void *)(unsigned long)*ppos;

src = elfcorehdr_newmem ? src : src - OLDMEM_BASE;
memcpy(buf, src, count);
*ppos += count;
return count;
}

subsys_initcall(setup_kdump_elfcorehdr);
/*
* Read from ELF notes data
*/
ssize_t elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos)
{
void *src = (void *)(unsigned long)*ppos;
int rc;

if (elfcorehdr_newmem) {
memcpy(buf, src, count);
} else {
rc = copy_from_oldmem(buf, src, count);
if (rc)
return rc;
}
*ppos += count;
return count;
}

0 comments on commit 97b0f6f

Please sign in to comment.