From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756515Ab3A2DxF (ORCPT ); Mon, 28 Jan 2013 22:53:05 -0500 Received: from szxga02-in.huawei.com ([119.145.14.65]:50811 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753592Ab3A2DxD (ORCPT ); Mon, 28 Jan 2013 22:53:03 -0500 Message-ID: <51074786.5030007@huawei.com> Date: Tue, 29 Jan 2013 11:52:38 +0800 From: Xishi Qiu User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20120428 Thunderbird/12.0.1 MIME-Version: 1.0 To: "Luck, Tony" , , , Xishi Qiu , Liujiang , Andrew Morton CC: , , , Subject: [PATCH] ia64/mm: fix a bad_page bug when crash kernel booting Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit X-Originating-IP: [10.135.74.196] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On ia64 platform, I set "crashkernel=1024M-:600M", and dmesg shows 128M-728M memory is reserved for crash kernel. Then "echo c > /proc/sysrq-trigger" to test kdump. When crash kernel booting, efi_init() will aligns the memory address in IA64_GRANULE_SIZE(16M), so 720M-728M memory will be dropped, It means crash kernel only manage 128M-720M memory. But initrd start and end are fixed in boot loader, it is before efi_init(), so initrd size maybe overflow when free_initrd_mem(). Here is the dmesg when crash kernel booting: ... Ignoring memory below 128MB Ignoring memory above 720MB // aligns the address in IA64_GRANULE_SIZE(16M) ... Initial ramdisk at: 0xe00000002c3f0000 (20176579 bytes) // initrd uses 707M-726M memory ... Kernel command line: root=/dev/disk/by-id/ata-STEC_MACH16_M16ISD2-100UCT_STM000142A2D-part3 console=ttyS0,115200n8 console=tty0 initcall_debug elevator=deadline sysrq=1 reset_devices irqpoll maxcpus=1 initcall_debug linuxrc=trace elfcorehdr=745216K max_addr=728M min_addr=128M // show crash kernel parameters ... Unpacking initramfs... // called by populate_rootfs() Freeing initrd memory: 19648kB freed // called by free_initrd()->free_initrd_mem() BUG: Bad page state in process swapper pfn:02d00 // it is a mistake to free over 720M memory to OS (ia64's page size is 64KB) page:e0000000102dd800 flags:(null) count:0 mapcount:1 mapping:(null) index:0 Call Trace: [] show_stack+0x80/0xa0 sp=e000000021e8fbd0 bsp=e000000021e81360 [] dump_stack+0x30/0x50 sp=e000000021e8fda0 bsp=e000000021e81348 [] bad_page+0x280/0x380 sp=e000000021e8fda0 bsp=e000000021e81308 [] free_hot_cold_page+0x3a0/0x5c0 sp=e000000021e8fda0 bsp=e000000021e812a0 [] free_hot_page+0x30/0x60 sp=e000000021e8fda0 bsp=e000000021e81280 [] __free_pages+0xb0/0xe0 sp=e000000021e8fda0 bsp=e000000021e81258 [] free_pages+0xa0/0xc0 sp=e000000021e8fda0 bsp=e000000021e81230 [] free_initrd_mem+0x230/0x290 sp=e000000021e8fda0 bsp=e000000021e811d8 [] populate_rootfs+0x1c0/0x280 sp=e000000021e8fdb0 bsp=e000000021e811a0 [] do_one_initcall+0x3b0/0x3e0 sp=e000000021e8fdb0 bsp=e000000021e81158 [] kernel_init+0x3f0/0x4b0 sp=e000000021e8fdb0 bsp=e000000021e81108 [] kernel_thread_helper+0xd0/0x100 sp=e000000021e8fe30 bsp=e000000021e810e0 [] start_kernel_thread+0x20/0x40 sp=e000000021e8fe30 bsp=e000000021e810e0 Disabling lock debugging due to kernel taint BUG: Bad page state in process swapper pfn:02d01 page:e0000000102dd838 flags:(null) count:0 mapcount:1 mapping:(null) index:0 Call Trace: [] show_stack+0x80/0xa0 sp=e000000021e8fbd0 bsp=e000000021e81360 [] dump_stack+0x30/0x50 sp=e000000021e8fda0 bsp=e000000021e81348 [] bad_page+0x280/0x380 sp=e000000021e8fda0 bsp=e000000021e81308 [] free_hot_cold_page+0x3a0/0x5c0 sp=e000000021e8fda0 bsp=e000000021e812a0 [] free_hot_page+0x30/0x60 sp=e000000021e8fda0 bsp=e000000021e81280 [] __free_pages+0xb0/0xe0 sp=e000000021e8fda0 bsp=e000000021e81258 [] free_pages+0xa0/0xc0 sp=e000000021e8fda0 bsp=e000000021e81230 [] free_initrd_mem+0x230/0x290 sp=e000000021e8fda0 bsp=e000000021e811d8 [] populate_rootfs+0x1c0/0x280 sp=e000000021e8fdb0 bsp=e000000021e811a0 [] do_one_initcall+0x3b0/0x3e0 sp=e000000021e8fdb0 bsp=e000000021e81158 [] kernel_init+0x3f0/0x4b0 sp=e000000021e8fdb0 bsp=e000000021e81108 [] kernel_thread_helper+0xd0/0x100 sp=e000000021e8fe30 bsp=e000000021e810e0 [] start_kernel_thread+0x20/0x40 sp=e000000021e8fe30 bsp=e000000021e810e0 ... Signed-off-by: Xishi Qiu --- arch/ia64/include/asm/meminit.h | 2 ++ arch/ia64/kernel/efi.c | 2 +- arch/ia64/mm/init.c | 11 +++++++++++ 3 files changed, 14 insertions(+), 1 deletions(-) diff --git a/arch/ia64/include/asm/meminit.h b/arch/ia64/include/asm/meminit.h index 61c7b17..925ecb5 100644 --- a/arch/ia64/include/asm/meminit.h +++ b/arch/ia64/include/asm/meminit.h @@ -49,6 +49,8 @@ extern int reserve_elfcorehdr(u64 *start, u64 *end); #define GRANULEROUNDDOWN(n) ((n) & ~(IA64_GRANULE_SIZE-1)) #define GRANULEROUNDUP(n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1)) +extern u64 max_addr; + #ifdef CONFIG_NUMA extern void call_pernode_memory (unsigned long start, unsigned long len, void *func); #else diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index f034563..f6522cb 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -49,7 +49,7 @@ extern efi_status_t efi_call_phys (void *, ...); struct efi efi; EXPORT_SYMBOL(efi); static efi_runtime_services_t *runtime; -static u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; +u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; #define efi_call_virt(f, args...) (*(f))(args) diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index b755ea9..cfdb1eb 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -207,6 +207,17 @@ free_initrd_mem (unsigned long start, unsigned long end) start = PAGE_ALIGN(start); end = end & PAGE_MASK; + /* + * Initrd size is fixed in boot loader, but kernel parameter max_addr + * which aligns in granules is fixed after boot loader, so initrd size + * maybe overflow. + */ + if (max_addr != ~0UL) { + end = GRANULEROUNDDOWN(end); + if (start > end) + start = end; + } + if (start < end) printk(KERN_INFO "Freeing initrd memory: %ldkB freed\n", (end - start) >> 10); -- 1.7.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Xishi Qiu Subject: [PATCH] ia64/mm: fix a bad_page bug when crash kernel booting Date: Tue, 29 Jan 2013 11:52:38 +0800 Message-ID: <51074786.5030007@huawei.com> Mime-Version: 1.0 Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit Return-path: Sender: linux-efi-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: "Luck, Tony" , fenghua.yu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org, matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org, Xishi Qiu , Liujiang , Andrew Morton Cc: linux-ia64-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org List-Id: linux-efi@vger.kernel.org On ia64 platform, I set "crashkernel=1024M-:600M", and dmesg shows 128M-728M memory is reserved for crash kernel. Then "echo c > /proc/sysrq-trigger" to test kdump. When crash kernel booting, efi_init() will aligns the memory address in IA64_GRANULE_SIZE(16M), so 720M-728M memory will be dropped, It means crash kernel only manage 128M-720M memory. But initrd start and end are fixed in boot loader, it is before efi_init(), so initrd size maybe overflow when free_initrd_mem(). Here is the dmesg when crash kernel booting: ... Ignoring memory below 128MB Ignoring memory above 720MB // aligns the address in IA64_GRANULE_SIZE(16M) ... Initial ramdisk at: 0xe00000002c3f0000 (20176579 bytes) // initrd uses 707M-726M memory ... Kernel command line: root=/dev/disk/by-id/ata-STEC_MACH16_M16ISD2-100UCT_STM000142A2D-part3 console=ttyS0,115200n8 console=tty0 initcall_debug elevator=deadline sysrq=1 reset_devices irqpoll maxcpus=1 initcall_debug linuxrc=trace elfcorehdr=745216K max_addr=728M min_addr=128M // show crash kernel parameters ... Unpacking initramfs... // called by populate_rootfs() Freeing initrd memory: 19648kB freed // called by free_initrd()->free_initrd_mem() BUG: Bad page state in process swapper pfn:02d00 // it is a mistake to free over 720M memory to OS (ia64's page size is 64KB) page:e0000000102dd800 flags:(null) count:0 mapcount:1 mapping:(null) index:0 Call Trace: [] show_stack+0x80/0xa0 sp=e000000021e8fbd0 bsp=e000000021e81360 [] dump_stack+0x30/0x50 sp=e000000021e8fda0 bsp=e000000021e81348 [] bad_page+0x280/0x380 sp=e000000021e8fda0 bsp=e000000021e81308 [] free_hot_cold_page+0x3a0/0x5c0 sp=e000000021e8fda0 bsp=e000000021e812a0 [] free_hot_page+0x30/0x60 sp=e000000021e8fda0 bsp=e000000021e81280 [] __free_pages+0xb0/0xe0 sp=e000000021e8fda0 bsp=e000000021e81258 [] free_pages+0xa0/0xc0 sp=e000000021e8fda0 bsp=e000000021e81230 [] free_initrd_mem+0x230/0x290 sp=e000000021e8fda0 bsp=e000000021e811d8 [] populate_rootfs+0x1c0/0x280 sp=e000000021e8fdb0 bsp=e000000021e811a0 [] do_one_initcall+0x3b0/0x3e0 sp=e000000021e8fdb0 bsp=e000000021e81158 [] kernel_init+0x3f0/0x4b0 sp=e000000021e8fdb0 bsp=e000000021e81108 [] kernel_thread_helper+0xd0/0x100 sp=e000000021e8fe30 bsp=e000000021e810e0 [] start_kernel_thread+0x20/0x40 sp=e000000021e8fe30 bsp=e000000021e810e0 Disabling lock debugging due to kernel taint BUG: Bad page state in process swapper pfn:02d01 page:e0000000102dd838 flags:(null) count:0 mapcount:1 mapping:(null) index:0 Call Trace: [] show_stack+0x80/0xa0 sp=e000000021e8fbd0 bsp=e000000021e81360 [] dump_stack+0x30/0x50 sp=e000000021e8fda0 bsp=e000000021e81348 [] bad_page+0x280/0x380 sp=e000000021e8fda0 bsp=e000000021e81308 [] free_hot_cold_page+0x3a0/0x5c0 sp=e000000021e8fda0 bsp=e000000021e812a0 [] free_hot_page+0x30/0x60 sp=e000000021e8fda0 bsp=e000000021e81280 [] __free_pages+0xb0/0xe0 sp=e000000021e8fda0 bsp=e000000021e81258 [] free_pages+0xa0/0xc0 sp=e000000021e8fda0 bsp=e000000021e81230 [] free_initrd_mem+0x230/0x290 sp=e000000021e8fda0 bsp=e000000021e811d8 [] populate_rootfs+0x1c0/0x280 sp=e000000021e8fdb0 bsp=e000000021e811a0 [] do_one_initcall+0x3b0/0x3e0 sp=e000000021e8fdb0 bsp=e000000021e81158 [] kernel_init+0x3f0/0x4b0 sp=e000000021e8fdb0 bsp=e000000021e81108 [] kernel_thread_helper+0xd0/0x100 sp=e000000021e8fe30 bsp=e000000021e810e0 [] start_kernel_thread+0x20/0x40 sp=e000000021e8fe30 bsp=e000000021e810e0 ... Signed-off-by: Xishi Qiu --- arch/ia64/include/asm/meminit.h | 2 ++ arch/ia64/kernel/efi.c | 2 +- arch/ia64/mm/init.c | 11 +++++++++++ 3 files changed, 14 insertions(+), 1 deletions(-) diff --git a/arch/ia64/include/asm/meminit.h b/arch/ia64/include/asm/meminit.h index 61c7b17..925ecb5 100644 --- a/arch/ia64/include/asm/meminit.h +++ b/arch/ia64/include/asm/meminit.h @@ -49,6 +49,8 @@ extern int reserve_elfcorehdr(u64 *start, u64 *end); #define GRANULEROUNDDOWN(n) ((n) & ~(IA64_GRANULE_SIZE-1)) #define GRANULEROUNDUP(n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1)) +extern u64 max_addr; + #ifdef CONFIG_NUMA extern void call_pernode_memory (unsigned long start, unsigned long len, void *func); #else diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index f034563..f6522cb 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -49,7 +49,7 @@ extern efi_status_t efi_call_phys (void *, ...); struct efi efi; EXPORT_SYMBOL(efi); static efi_runtime_services_t *runtime; -static u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; +u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; #define efi_call_virt(f, args...) (*(f))(args) diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index b755ea9..cfdb1eb 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -207,6 +207,17 @@ free_initrd_mem (unsigned long start, unsigned long end) start = PAGE_ALIGN(start); end = end & PAGE_MASK; + /* + * Initrd size is fixed in boot loader, but kernel parameter max_addr + * which aligns in granules is fixed after boot loader, so initrd size + * maybe overflow. + */ + if (max_addr != ~0UL) { + end = GRANULEROUNDDOWN(end); + if (start > end) + start = end; + } + if (start < end) printk(KERN_INFO "Freeing initrd memory: %ldkB freed\n", (end - start) >> 10); -- 1.7.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from psmtp.com (na3sys010amx190.postini.com [74.125.245.190]) by kanga.kvack.org (Postfix) with SMTP id 01BF56B0005 for ; Mon, 28 Jan 2013 22:53:05 -0500 (EST) Message-ID: <51074786.5030007@huawei.com> Date: Tue, 29 Jan 2013 11:52:38 +0800 From: Xishi Qiu MIME-Version: 1.0 Subject: [PATCH] ia64/mm: fix a bad_page bug when crash kernel booting Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit Sender: owner-linux-mm@kvack.org List-ID: To: "Luck, Tony" , fenghua.yu@intel.com, matt.fleming@intel.com, Xishi Qiu , Liujiang , Andrew Morton Cc: linux-ia64@vger.kernel.org, linux-kernel@vger.kernel.org, linux-efi@vger.kernel.org, linux-mm@kvack.org On ia64 platform, I set "crashkernel=1024M-:600M", and dmesg shows 128M-728M memory is reserved for crash kernel. Then "echo c > /proc/sysrq-trigger" to test kdump. When crash kernel booting, efi_init() will aligns the memory address in IA64_GRANULE_SIZE(16M), so 720M-728M memory will be dropped, It means crash kernel only manage 128M-720M memory. But initrd start and end are fixed in boot loader, it is before efi_init(), so initrd size maybe overflow when free_initrd_mem(). Here is the dmesg when crash kernel booting: ... Ignoring memory below 128MB Ignoring memory above 720MB // aligns the address in IA64_GRANULE_SIZE(16M) ... Initial ramdisk at: 0xe00000002c3f0000 (20176579 bytes) // initrd uses 707M-726M memory ... Kernel command line: root=/dev/disk/by-id/ata-STEC_MACH16_M16ISD2-100UCT_STM000142A2D-part3 console=ttyS0,115200n8 console=tty0 initcall_debug elevator=deadline sysrq=1 reset_devices irqpoll maxcpus=1 initcall_debug linuxrc=trace elfcorehdr=745216K max_addr=728M min_addr=128M // show crash kernel parameters ... Unpacking initramfs... // called by populate_rootfs() Freeing initrd memory: 19648kB freed // called by free_initrd()->free_initrd_mem() BUG: Bad page state in process swapper pfn:02d00 // it is a mistake to free over 720M memory to OS (ia64's page size is 64KB) page:e0000000102dd800 flags:(null) count:0 mapcount:1 mapping:(null) index:0 Call Trace: [] show_stack+0x80/0xa0 sp=e000000021e8fbd0 bsp=e000000021e81360 [] dump_stack+0x30/0x50 sp=e000000021e8fda0 bsp=e000000021e81348 [] bad_page+0x280/0x380 sp=e000000021e8fda0 bsp=e000000021e81308 [] free_hot_cold_page+0x3a0/0x5c0 sp=e000000021e8fda0 bsp=e000000021e812a0 [] free_hot_page+0x30/0x60 sp=e000000021e8fda0 bsp=e000000021e81280 [] __free_pages+0xb0/0xe0 sp=e000000021e8fda0 bsp=e000000021e81258 [] free_pages+0xa0/0xc0 sp=e000000021e8fda0 bsp=e000000021e81230 [] free_initrd_mem+0x230/0x290 sp=e000000021e8fda0 bsp=e000000021e811d8 [] populate_rootfs+0x1c0/0x280 sp=e000000021e8fdb0 bsp=e000000021e811a0 [] do_one_initcall+0x3b0/0x3e0 sp=e000000021e8fdb0 bsp=e000000021e81158 [] kernel_init+0x3f0/0x4b0 sp=e000000021e8fdb0 bsp=e000000021e81108 [] kernel_thread_helper+0xd0/0x100 sp=e000000021e8fe30 bsp=e000000021e810e0 [] start_kernel_thread+0x20/0x40 sp=e000000021e8fe30 bsp=e000000021e810e0 Disabling lock debugging due to kernel taint BUG: Bad page state in process swapper pfn:02d01 page:e0000000102dd838 flags:(null) count:0 mapcount:1 mapping:(null) index:0 Call Trace: [] show_stack+0x80/0xa0 sp=e000000021e8fbd0 bsp=e000000021e81360 [] dump_stack+0x30/0x50 sp=e000000021e8fda0 bsp=e000000021e81348 [] bad_page+0x280/0x380 sp=e000000021e8fda0 bsp=e000000021e81308 [] free_hot_cold_page+0x3a0/0x5c0 sp=e000000021e8fda0 bsp=e000000021e812a0 [] free_hot_page+0x30/0x60 sp=e000000021e8fda0 bsp=e000000021e81280 [] __free_pages+0xb0/0xe0 sp=e000000021e8fda0 bsp=e000000021e81258 [] free_pages+0xa0/0xc0 sp=e000000021e8fda0 bsp=e000000021e81230 [] free_initrd_mem+0x230/0x290 sp=e000000021e8fda0 bsp=e000000021e811d8 [] populate_rootfs+0x1c0/0x280 sp=e000000021e8fdb0 bsp=e000000021e811a0 [] do_one_initcall+0x3b0/0x3e0 sp=e000000021e8fdb0 bsp=e000000021e81158 [] kernel_init+0x3f0/0x4b0 sp=e000000021e8fdb0 bsp=e000000021e81108 [] kernel_thread_helper+0xd0/0x100 sp=e000000021e8fe30 bsp=e000000021e810e0 [] start_kernel_thread+0x20/0x40 sp=e000000021e8fe30 bsp=e000000021e810e0 ... Signed-off-by: Xishi Qiu --- arch/ia64/include/asm/meminit.h | 2 ++ arch/ia64/kernel/efi.c | 2 +- arch/ia64/mm/init.c | 11 +++++++++++ 3 files changed, 14 insertions(+), 1 deletions(-) diff --git a/arch/ia64/include/asm/meminit.h b/arch/ia64/include/asm/meminit.h index 61c7b17..925ecb5 100644 --- a/arch/ia64/include/asm/meminit.h +++ b/arch/ia64/include/asm/meminit.h @@ -49,6 +49,8 @@ extern int reserve_elfcorehdr(u64 *start, u64 *end); #define GRANULEROUNDDOWN(n) ((n) & ~(IA64_GRANULE_SIZE-1)) #define GRANULEROUNDUP(n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1)) +extern u64 max_addr; + #ifdef CONFIG_NUMA extern void call_pernode_memory (unsigned long start, unsigned long len, void *func); #else diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index f034563..f6522cb 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -49,7 +49,7 @@ extern efi_status_t efi_call_phys (void *, ...); struct efi efi; EXPORT_SYMBOL(efi); static efi_runtime_services_t *runtime; -static u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; +u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; #define efi_call_virt(f, args...) (*(f))(args) diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index b755ea9..cfdb1eb 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -207,6 +207,17 @@ free_initrd_mem (unsigned long start, unsigned long end) start = PAGE_ALIGN(start); end = end & PAGE_MASK; + /* + * Initrd size is fixed in boot loader, but kernel parameter max_addr + * which aligns in granules is fixed after boot loader, so initrd size + * maybe overflow. + */ + if (max_addr != ~0UL) { + end = GRANULEROUNDDOWN(end); + if (start > end) + start = end; + } + if (start < end) printk(KERN_INFO "Freeing initrd memory: %ldkB freed\n", (end - start) >> 10); -- 1.7.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: email@kvack.org From mboxrd@z Thu Jan 1 00:00:00 1970 From: Xishi Qiu Date: Tue, 29 Jan 2013 03:52:38 +0000 Subject: [PATCH] ia64/mm: fix a bad_page bug when crash kernel booting Message-Id: <51074786.5030007@huawei.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable To: "Luck, Tony" , fenghua.yu@intel.com, matt.fleming@intel.com, Xishi Qiu , Liujiang , Andrew Morton Cc: linux-ia64@vger.kernel.org, linux-kernel@vger.kernel.org, linux-efi@vger.kernel.org, linux-mm@kvack.org On ia64 platform, I set "crashkernel=1024M-:600M", and dmesg shows 128M-728M memory is reserved for crash kernel. Then "echo c > /proc/sysrq-trigger" to test kdump. When crash kernel booting, efi_init() will aligns the memory address in IA64_GRANULE_SIZE(16M), so 720M-728M memory will be dropped, It means crash kernel only manage 128M-720M memory. But initrd start and end are fixed in boot loader, it is before efi_init(), so initrd size maybe overflow when free_initrd_mem(). Here is the dmesg when crash kernel booting: ... Ignoring memory below 128MB Ignoring memory above 720MB // aligns the address in IA64_GRANULE_SIZE(16M) ... Initial ramdisk at: 0xe00000002c3f0000 (20176579 bytes) // initrd uses 707M-726M memory ... Kernel command line: root=3D/dev/disk/by-id/ata-STEC_MACH16_M16ISD2-100UCT= _STM000142A2D-part3 console=3DttyS0,115200n8 console=3Dtty0 initcall_debug elevator=DEadline sy= srq=3D1 reset_devices irqpoll maxcpus=3D1 initcall_debug linuxrc=3Dtrace elfcorehdrt5216K max_add= rr8M min_addr=128M // show crash kernel parameters ... Unpacking initramfs... // called by populate_rootfs() Freeing initrd memory: 19648kB freed // called by free_initrd()->free_initrd_mem() BUG: Bad page state in process swapper pfn:02d00 // it is a mistake to free over 720M memory to OS (ia64's page size is = 64KB) page:e0000000102dd800 flags:(null) count:0 mapcount:1 mapping:(null) index:0 Call Trace: [] show_stack+0x80/0xa0 sp=E000000021e8fbd0 bsp=E000000021e81360 [] dump_stack+0x30/0x50 sp=E000000021e8fda0 bsp=E000000021e81348 [] bad_page+0x280/0x380 sp=E000000021e8fda0 bsp=E000000021e81308 [] free_hot_cold_page+0x3a0/0x5c0 sp=E000000021e8fda0 bsp=E000000021e812a0 [] free_hot_page+0x30/0x60 sp=E000000021e8fda0 bsp=E000000021e81280 [] __free_pages+0xb0/0xe0 sp=E000000021e8fda0 bsp=E000000021e81258 [] free_pages+0xa0/0xc0 sp=E000000021e8fda0 bsp=E000000021e81230 [] free_initrd_mem+0x230/0x290 sp=E000000021e8fda0 bsp=E000000021e811d8 [] populate_rootfs+0x1c0/0x280 sp=E000000021e8fdb0 bsp=E000000021e811a0 [] do_one_initcall+0x3b0/0x3e0 sp=E000000021e8fdb0 bsp=E000000021e81158 [] kernel_init+0x3f0/0x4b0 sp=E000000021e8fdb0 bsp=E000000021e81108 [] kernel_thread_helper+0xd0/0x100 sp=E000000021e8fe30 bsp=E000000021e810e0 [] start_kernel_thread+0x20/0x40 sp=E000000021e8fe30 bsp=E000000021e810e0 Disabling lock debugging due to kernel taint BUG: Bad page state in process swapper pfn:02d01 page:e0000000102dd838 flags:(null) count:0 mapcount:1 mapping:(null) index:0 Call Trace: [] show_stack+0x80/0xa0 sp=E000000021e8fbd0 bsp=E000000021e81360 [] dump_stack+0x30/0x50 sp=E000000021e8fda0 bsp=E000000021e81348 [] bad_page+0x280/0x380 sp=E000000021e8fda0 bsp=E000000021e81308 [] free_hot_cold_page+0x3a0/0x5c0 sp=E000000021e8fda0 bsp=E000000021e812a0 [] free_hot_page+0x30/0x60 sp=E000000021e8fda0 bsp=E000000021e81280 [] __free_pages+0xb0/0xe0 sp=E000000021e8fda0 bsp=E000000021e81258 [] free_pages+0xa0/0xc0 sp=E000000021e8fda0 bsp=E000000021e81230 [] free_initrd_mem+0x230/0x290 sp=E000000021e8fda0 bsp=E000000021e811d8 [] populate_rootfs+0x1c0/0x280 sp=E000000021e8fdb0 bsp=E000000021e811a0 [] do_one_initcall+0x3b0/0x3e0 sp=E000000021e8fdb0 bsp=E000000021e81158 [] kernel_init+0x3f0/0x4b0 sp=E000000021e8fdb0 bsp=E000000021e81108 [] kernel_thread_helper+0xd0/0x100 sp=E000000021e8fe30 bsp=E000000021e810e0 [] start_kernel_thread+0x20/0x40 sp=E000000021e8fe30 bsp=E000000021e810e0 ... Signed-off-by: Xishi Qiu --- arch/ia64/include/asm/meminit.h | 2 ++ arch/ia64/kernel/efi.c | 2 +- arch/ia64/mm/init.c | 11 +++++++++++ 3 files changed, 14 insertions(+), 1 deletions(-) diff --git a/arch/ia64/include/asm/meminit.h b/arch/ia64/include/asm/memini= t.h index 61c7b17..925ecb5 100644 --- a/arch/ia64/include/asm/meminit.h +++ b/arch/ia64/include/asm/meminit.h @@ -49,6 +49,8 @@ extern int reserve_elfcorehdr(u64 *start, u64 *end); #define GRANULEROUNDDOWN(n) ((n) & ~(IA64_GRANULE_SIZE-1)) #define GRANULEROUNDUP(n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE= -1)) +extern u64 max_addr; + #ifdef CONFIG_NUMA extern void call_pernode_memory (unsigned long start, unsigned long len,= void *func); #else diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index f034563..f6522cb 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -49,7 +49,7 @@ extern efi_status_t efi_call_phys (void *, ...); struct efi efi; EXPORT_SYMBOL(efi); static efi_runtime_services_t *runtime; -static u64 mem_limit =3D ~0UL, max_addr =3D ~0UL, min_addr =3D 0UL; +u64 mem_limit =3D ~0UL, max_addr =3D ~0UL, min_addr =3D 0UL; #define efi_call_virt(f, args...) (*(f))(args) diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index b755ea9..cfdb1eb 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -207,6 +207,17 @@ free_initrd_mem (unsigned long start, unsigned long en= d) start =3D PAGE_ALIGN(start); end =3D end & PAGE_MASK; + /* + * Initrd size is fixed in boot loader, but kernel parameter max_addr + * which aligns in granules is fixed after boot loader, so initrd size + * maybe overflow. + */ + if (max_addr !=3D ~0UL) { + end =3D GRANULEROUNDDOWN(end); + if (start > end) + start =3D end; + } + if (start < end) printk(KERN_INFO "Freeing initrd memory: %ldkB freed\n", (end - start) >= > 10); --=20 1.7.1