From 4ae362be509306eafa6441603686d33fefe321c1 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Mon, 9 Jan 2006 20:51:50 -0800 Subject: [PATCH] [PATCH] kdump: read previous kernel's memory - Moving the crash_dump.c file to arch dependent part as kmap_atomic_pfn is specific to i386 and highmem may not exist in other archs. - Use ioremap for x86_64 to map the previous kernel memory. - In copy_oldmem_page(), we now directly copy to the user/kernel buffer and avoid the unneccesary copy to a kmalloc'd page. Signed-off-by: Rachita Kothiyal Signed-off-by: Vivek Goyal Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/Makefile | 1 + {kernel => arch/i386/kernel}/crash_dump.c | 56 +++++++++++++++++------------ arch/x86_64/kernel/Makefile | 1 + {kernel => arch/x86_64/kernel}/crash_dump.c | 35 +++++------------- fs/proc/vmcore.c | 3 ++ kernel/Makefile | 1 - 6 files changed, 47 insertions(+), 50 deletions(-) copy {kernel => arch/i386/kernel}/crash_dump.c (53%) rename {kernel => arch/x86_64/kernel}/crash_dump.c (60%) diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index be1880bb75b..60c3f76dfca 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o +obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o obj-$(CONFIG_KPROBES) += kprobes.o diff --git a/kernel/crash_dump.c b/arch/i386/kernel/crash_dump.c similarity index 53% copy from kernel/crash_dump.c copy to arch/i386/kernel/crash_dump.c index fccb27dbc62..3f532df488b 100644 --- a/kernel/crash_dump.c +++ b/arch/i386/kernel/crash_dump.c @@ -5,21 +5,14 @@ * Copyright (C) IBM Corporation, 2004. All rights reserved */ -#include #include -#include -#include #include #include -#include #include -#include -/* Stores the physical address of elf header of crash image. */ -unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; +static void *kdump_buf_page; -#ifndef HAVE_ARCH_COPY_OLDMEM_PAGE /** * copy_oldmem_page - copy one page from "oldmem" * @pfn: page frame number to be copied @@ -32,33 +25,50 @@ unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; * * Copy a page from "oldmem". For this page, there is no pte mapped * in the current kernel. We stitch up a pte, similar to kmap_atomic. + * + * Calling copy_to_user() in atomic context is not desirable. Hence first + * copying the data to a pre-allocated kernel page and then copying to user + * space in non-atomic context. */ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, - size_t csize, unsigned long offset, int userbuf) + size_t csize, unsigned long offset, int userbuf) { - void *page, *vaddr; + void *vaddr; if (!csize) return 0; - page = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!page) - return -ENOMEM; - vaddr = kmap_atomic_pfn(pfn, KM_PTE0); - copy_page(page, vaddr); - kunmap_atomic(vaddr, KM_PTE0); - if (userbuf) { - if (copy_to_user(buf, (page + offset), csize)) { - kfree(page); + if (!userbuf) { + memcpy(buf, (vaddr + offset), csize); + kunmap_atomic(vaddr, KM_PTE0); + } else { + if (!kdump_buf_page) { + printk(KERN_WARNING "Kdump: Kdump buffer page not" + " allocated\n"); return -EFAULT; } - } else { - memcpy(buf, (page + offset), csize); + copy_page(kdump_buf_page, vaddr); + kunmap_atomic(vaddr, KM_PTE0); + if (copy_to_user(buf, (kdump_buf_page + offset), csize)) + return -EFAULT; } - kfree(page); return csize; } -#endif + +static int __init kdump_buf_page_init(void) +{ + int ret = 0; + + kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!kdump_buf_page) { + printk(KERN_WARNING "Kdump: Failed to allocate kdump buffer" + " page\n"); + ret = -ENOMEM; + } + + return ret; +} +arch_initcall(kdump_buf_page_init); diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index fe4cbd1c4b2..12bc54005e2 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o \ genapic.o genapic_cluster.o genapic_flat.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o +obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_PM) += suspend.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend_asm.o obj-$(CONFIG_CPU_FREQ) += cpufreq/ diff --git a/kernel/crash_dump.c b/arch/x86_64/kernel/crash_dump.c similarity index 60% rename from kernel/crash_dump.c rename to arch/x86_64/kernel/crash_dump.c index fccb27dbc62..942deac4d43 100644 --- a/kernel/crash_dump.c +++ b/arch/x86_64/kernel/crash_dump.c @@ -5,21 +5,12 @@ * Copyright (C) IBM Corporation, 2004. All rights reserved */ -#include #include -#include -#include -#include #include -#include #include -#include - -/* Stores the physical address of elf header of crash image. */ -unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; +#include -#ifndef HAVE_ARCH_COPY_OLDMEM_PAGE /** * copy_oldmem_page - copy one page from "oldmem" * @pfn: page frame number to be copied @@ -34,31 +25,23 @@ unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; * in the current kernel. We stitch up a pte, similar to kmap_atomic. */ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, - size_t csize, unsigned long offset, int userbuf) + size_t csize, unsigned long offset, int userbuf) { - void *page, *vaddr; + void *vaddr; if (!csize) return 0; - page = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!page) - return -ENOMEM; - - vaddr = kmap_atomic_pfn(pfn, KM_PTE0); - copy_page(page, vaddr); - kunmap_atomic(vaddr, KM_PTE0); + vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE); if (userbuf) { - if (copy_to_user(buf, (page + offset), csize)) { - kfree(page); + if (copy_to_user(buf, (vaddr + offset), csize)) { + iounmap(vaddr); return -EFAULT; } - } else { - memcpy(buf, (page + offset), csize); - } + } else + memcpy(buf, (vaddr + offset), csize); - kfree(page); + iounmap(vaddr); return csize; } -#endif diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 3b2e7b69e63..5378d7c7841 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -35,6 +35,9 @@ static size_t elfcorebuf_sz; /* Total size of vmcore file. */ static u64 vmcore_size; +/* Stores the physical address of elf header of crash image. */ +unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; + struct proc_dir_entry *proc_vmcore = NULL; /* Reads a page from the oldmem device from given offset. */ diff --git a/kernel/Makefile b/kernel/Makefile index a940bac0283..1e039700c0a 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -30,7 +30,6 @@ obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_SYSFS) += ksysfs.o obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ -obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_SECCOMP) += seccomp.o obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o -- 2.11.4.GIT