Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758903Ab3EWS5L (ORCPT ); Thu, 23 May 2013 14:57:11 -0400 Received: from e06smtp15.uk.ibm.com ([195.75.94.111]:45289 "EHLO e06smtp15.uk.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752769Ab3EWS5G (ORCPT ); Thu, 23 May 2013 14:57:06 -0400 From: Michael Holzheu To: Vivek Goyal Cc: Jan Willeke , Martin Schwidefsky , Heiko Carstens , linux-kernel@vger.kernel.org, kexec@lists.infradead.org, Michael Holzheu Subject: [PATCH v3 1/3] kdump: Introduce ELF header in new memory feature Date: Thu, 23 May 2013 20:56:59 +0200 Message-Id: <1369335421-43058-2-git-send-email-holzheu@linux.vnet.ibm.com> X-Mailer: git-send-email 1.8.1.6 In-Reply-To: <1369335421-43058-1-git-send-email-holzheu@linux.vnet.ibm.com> References: <1369335421-43058-1-git-send-email-holzheu@linux.vnet.ibm.com> X-TM-AS-MML: No X-Content-Scanned: Fidelis XPS MAILER x-cbid: 13052318-0342-0000-0000-0000051E6CCF Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7513 Lines: 215 Currently for s390 we create the ELF core header in the 2nd kernel with a small trick. We relocate the addresses in the ELF header in a way that for the /proc/vmcore code it seems to be in the 1st kernel (old) memory and the read_from_oldmem() returns the correct data. This allows the /proc/vmcore code to use the ELF header in the 2nd kernel. This patch now exchanges the old mechanism with the new and much cleaner function call override feature that now offcially allows to create the ELF core header in the 2nd kernel. To use the new feature the following has to be done by the architecture backend code: * Override arch_get_crash_header() to return the address of the ELF header in new memory * Override arch_free_crash_header() to free the memory of the ELF header in new memory * Override arch_read_from_crash_header() to read from the ELF header in new memory * Set elfcorehdr_addr to the address of ELF header in new memory Signed-off-by: Michael Holzheu --- fs/proc/vmcore.c | 65 +++++++++++++++++++++++++++++++++------------- include/linux/crash_dump.h | 4 +++ 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 6ba32f8..a9e1b65 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -123,6 +123,28 @@ static ssize_t read_from_oldmem(char *buf, size_t count, return read; } +/* + * Architetures may override this function to read header data + */ +ssize_t __weak arch_read_from_crash_header(char *buf, size_t count, u64 *ppos) +{ + return read_from_oldmem(buf, count, ppos, 0); +} + +/* + * Architetures may override this function to get header address + */ +unsigned long long __weak arch_get_crash_header(void) +{ + return elfcorehdr_addr; +} + +/* + * Architetures may override this function to free header + */ +void __weak arch_free_crash_header(void) +{} + /* Read from the ELF header and then the crash dump. On error, negative value is * returned otherwise number of bytes read are returned. */ @@ -356,7 +378,8 @@ static int __init get_note_number_and_size_elf64(const Elf64_Ehdr *ehdr_ptr, notes_section = kmalloc(max_sz, GFP_KERNEL); if (!notes_section) return -ENOMEM; - rc = read_from_oldmem(notes_section, max_sz, &offset, 0); + rc = arch_read_from_crash_header(notes_section, max_sz, + &offset); if (rc < 0) { kfree(notes_section); return rc; @@ -412,7 +435,8 @@ static int __init copy_notes_elf64(const Elf64_Ehdr *ehdr_ptr, char *notes_buf) notes_section = kmalloc(max_sz, GFP_KERNEL); if (!notes_section) return -ENOMEM; - rc = read_from_oldmem(notes_section, max_sz, &offset, 0); + rc = arch_read_from_crash_header(notes_section, max_sz, + &offset); if (rc < 0) { kfree(notes_section); return rc; @@ -428,8 +452,8 @@ static int __init copy_notes_elf64(const Elf64_Ehdr *ehdr_ptr, char *notes_buf) nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz); } offset = phdr_ptr->p_offset; - rc = read_from_oldmem(notes_buf + phdr_sz, real_sz, - &offset, 0); + rc = arch_read_from_crash_header(notes_buf + phdr_sz, real_sz, + &offset); if (rc < 0) { kfree(notes_section); return rc; @@ -533,7 +557,8 @@ static int __init get_note_number_and_size_elf32(const Elf32_Ehdr *ehdr_ptr, notes_section = kmalloc(max_sz, GFP_KERNEL); if (!notes_section) return -ENOMEM; - rc = read_from_oldmem(notes_section, max_sz, &offset, 0); + rc = arch_read_from_crash_header(notes_section, max_sz, + &offset); if (rc < 0) { kfree(notes_section); return rc; @@ -589,7 +614,8 @@ static int __init copy_notes_elf32(const Elf32_Ehdr *ehdr_ptr, char *notes_buf) notes_section = kmalloc(max_sz, GFP_KERNEL); if (!notes_section) return -ENOMEM; - rc = read_from_oldmem(notes_section, max_sz, &offset, 0); + rc = arch_read_from_crash_header(notes_section, max_sz, + &offset); if (rc < 0) { kfree(notes_section); return rc; @@ -605,8 +631,8 @@ static int __init copy_notes_elf32(const Elf32_Ehdr *ehdr_ptr, char *notes_buf) nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz); } offset = phdr_ptr->p_offset; - rc = read_from_oldmem(notes_buf + phdr_sz, real_sz, - &offset, 0); + rc = arch_read_from_crash_header(notes_buf + phdr_sz, real_sz, + &offset); if (rc < 0) { kfree(notes_section); return rc; @@ -804,10 +830,11 @@ static int __init parse_crash_elf64_headers(void) Elf64_Ehdr ehdr; u64 addr; - addr = elfcorehdr_addr; + addr = arch_get_crash_header(); /* Read Elf header */ - rc = read_from_oldmem((char*)&ehdr, sizeof(Elf64_Ehdr), &addr, 0); + rc = arch_read_from_crash_header((char *)&ehdr, sizeof(Elf64_Ehdr), + &addr); if (rc < 0) return rc; @@ -832,8 +859,8 @@ static int __init parse_crash_elf64_headers(void) get_order(elfcorebuf_sz_orig)); if (!elfcorebuf) return -ENOMEM; - addr = elfcorehdr_addr; - rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz_orig, &addr, 0); + addr = arch_get_crash_header(); + rc = arch_read_from_crash_header(elfcorebuf, elfcorebuf_sz_orig, &addr); if (rc < 0) { free_pages((unsigned long)elfcorebuf, get_order(elfcorebuf_sz_orig)); @@ -867,10 +894,11 @@ static int __init parse_crash_elf32_headers(void) Elf32_Ehdr ehdr; u64 addr; - addr = elfcorehdr_addr; + addr = arch_get_crash_header(); /* Read Elf header */ - rc = read_from_oldmem((char*)&ehdr, sizeof(Elf32_Ehdr), &addr, 0); + rc = arch_read_from_crash_header((char *)&ehdr, sizeof(Elf32_Ehdr), + &addr); if (rc < 0) return rc; @@ -895,8 +923,8 @@ static int __init parse_crash_elf32_headers(void) get_order(elfcorebuf_sz_orig)); if (!elfcorebuf) return -ENOMEM; - addr = elfcorehdr_addr; - rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz_orig, &addr, 0); + addr = arch_get_crash_header(); + rc = arch_read_from_crash_header(elfcorebuf, elfcorebuf_sz_orig, &addr); if (rc < 0) { free_pages((unsigned long)elfcorebuf, get_order(elfcorebuf_sz_orig)); @@ -930,8 +958,8 @@ static int __init parse_crash_elf_headers(void) u64 addr; int rc=0; - addr = elfcorehdr_addr; - rc = read_from_oldmem(e_ident, EI_NIDENT, &addr, 0); + addr = arch_get_crash_header(); + rc = arch_read_from_crash_header(e_ident, EI_NIDENT, &addr); if (rc < 0) return rc; if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) { @@ -961,6 +989,7 @@ static int __init parse_crash_elf_headers(void) pr_warn("Warning: Core image elf header is not sane\n"); return -EINVAL; } + arch_free_crash_header(); return 0; } diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h index 37e4f8d..c66da41 100644 --- a/include/linux/crash_dump.h +++ b/include/linux/crash_dump.h @@ -14,6 +14,10 @@ extern unsigned long long elfcorehdr_size; extern ssize_t copy_oldmem_page(unsigned long, char *, size_t, unsigned long, int); +extern unsigned long long __weak arch_get_crash_header(void); +extern void __weak arch_free_crash_header(void); +extern ssize_t __weak arch_read_from_crash_header(char *buf, size_t count, + u64 *ppos); /* Architecture code defines this if there are other possible ELF * machine types, e.g. on bi-arch capable hardware. */ -- 1.8.1.6 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/