aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/aperture_64.c20
-rw-r--r--fs/proc/kcore.c27
-rw-r--r--include/linux/kcore.h2
3 files changed, 42 insertions, 7 deletions
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
index 58176b56354e..294ed4392a0e 100644
--- a/arch/x86/kernel/aperture_64.c
+++ b/arch/x86/kernel/aperture_64.c
@@ -14,6 +14,7 @@
14#define pr_fmt(fmt) "AGP: " fmt 14#define pr_fmt(fmt) "AGP: " fmt
15 15
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/kcore.h>
17#include <linux/types.h> 18#include <linux/types.h>
18#include <linux/init.h> 19#include <linux/init.h>
19#include <linux/memblock.h> 20#include <linux/memblock.h>
@@ -57,7 +58,7 @@ int fallback_aper_force __initdata;
57 58
58int fix_aperture __initdata = 1; 59int fix_aperture __initdata = 1;
59 60
60#ifdef CONFIG_PROC_VMCORE 61#if defined(CONFIG_PROC_VMCORE) || defined(CONFIG_PROC_KCORE)
61/* 62/*
62 * If the first kernel maps the aperture over e820 RAM, the kdump kernel will 63 * If the first kernel maps the aperture over e820 RAM, the kdump kernel will
63 * use the same range because it will remain configured in the northbridge. 64 * use the same range because it will remain configured in the northbridge.
@@ -66,20 +67,25 @@ int fix_aperture __initdata = 1;
66 */ 67 */
67static unsigned long aperture_pfn_start, aperture_page_count; 68static unsigned long aperture_pfn_start, aperture_page_count;
68 69
69static int gart_oldmem_pfn_is_ram(unsigned long pfn) 70static int gart_mem_pfn_is_ram(unsigned long pfn)
70{ 71{
71 return likely((pfn < aperture_pfn_start) || 72 return likely((pfn < aperture_pfn_start) ||
72 (pfn >= aperture_pfn_start + aperture_page_count)); 73 (pfn >= aperture_pfn_start + aperture_page_count));
73} 74}
74 75
75static void exclude_from_vmcore(u64 aper_base, u32 aper_order) 76static void __init exclude_from_core(u64 aper_base, u32 aper_order)
76{ 77{
77 aperture_pfn_start = aper_base >> PAGE_SHIFT; 78 aperture_pfn_start = aper_base >> PAGE_SHIFT;
78 aperture_page_count = (32 * 1024 * 1024) << aper_order >> PAGE_SHIFT; 79 aperture_page_count = (32 * 1024 * 1024) << aper_order >> PAGE_SHIFT;
79 WARN_ON(register_oldmem_pfn_is_ram(&gart_oldmem_pfn_is_ram)); 80#ifdef CONFIG_PROC_VMCORE
81 WARN_ON(register_oldmem_pfn_is_ram(&gart_mem_pfn_is_ram));
82#endif
83#ifdef CONFIG_PROC_KCORE
84 WARN_ON(register_mem_pfn_is_ram(&gart_mem_pfn_is_ram));
85#endif
80} 86}
81#else 87#else
82static void exclude_from_vmcore(u64 aper_base, u32 aper_order) 88static void exclude_from_core(u64 aper_base, u32 aper_order)
83{ 89{
84} 90}
85#endif 91#endif
@@ -474,7 +480,7 @@ out:
474 * may have allocated the range over its e820 RAM 480 * may have allocated the range over its e820 RAM
475 * and fixed up the northbridge 481 * and fixed up the northbridge
476 */ 482 */
477 exclude_from_vmcore(last_aper_base, last_aper_order); 483 exclude_from_core(last_aper_base, last_aper_order);
478 484
479 return 1; 485 return 1;
480 } 486 }
@@ -520,7 +526,7 @@ out:
520 * overlap with the first kernel's memory. We can't access the 526 * overlap with the first kernel's memory. We can't access the
521 * range through vmcore even though it should be part of the dump. 527 * range through vmcore even though it should be part of the dump.
522 */ 528 */
523 exclude_from_vmcore(aper_alloc, aper_order); 529 exclude_from_core(aper_alloc, aper_order);
524 530
525 /* Fix up the north bridges */ 531 /* Fix up the north bridges */
526 for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) { 532 for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) {
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index bbcc185062bb..d29d869abec1 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -54,6 +54,28 @@ static LIST_HEAD(kclist_head);
54static DECLARE_RWSEM(kclist_lock); 54static DECLARE_RWSEM(kclist_lock);
55static int kcore_need_update = 1; 55static int kcore_need_update = 1;
56 56
57/*
58 * Returns > 0 for RAM pages, 0 for non-RAM pages, < 0 on error
59 * Same as oldmem_pfn_is_ram in vmcore
60 */
61static int (*mem_pfn_is_ram)(unsigned long pfn);
62
63int __init register_mem_pfn_is_ram(int (*fn)(unsigned long pfn))
64{
65 if (mem_pfn_is_ram)
66 return -EBUSY;
67 mem_pfn_is_ram = fn;
68 return 0;
69}
70
71static int pfn_is_ram(unsigned long pfn)
72{
73 if (mem_pfn_is_ram)
74 return mem_pfn_is_ram(pfn);
75 else
76 return 1;
77}
78
57/* This doesn't grab kclist_lock, so it should only be used at init time. */ 79/* This doesn't grab kclist_lock, so it should only be used at init time. */
58void __init kclist_add(struct kcore_list *new, void *addr, size_t size, 80void __init kclist_add(struct kcore_list *new, void *addr, size_t size,
59 int type) 81 int type)
@@ -465,6 +487,11 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
465 goto out; 487 goto out;
466 } 488 }
467 m = NULL; /* skip the list anchor */ 489 m = NULL; /* skip the list anchor */
490 } else if (!pfn_is_ram(__pa(start) >> PAGE_SHIFT)) {
491 if (clear_user(buffer, tsz)) {
492 ret = -EFAULT;
493 goto out;
494 }
468 } else if (m->type == KCORE_VMALLOC) { 495 } else if (m->type == KCORE_VMALLOC) {
469 vread(buf, (char *)start, tsz); 496 vread(buf, (char *)start, tsz);
470 /* we have to zero-fill user buffer even if no read */ 497 /* we have to zero-fill user buffer even if no read */
diff --git a/include/linux/kcore.h b/include/linux/kcore.h
index 8c3f8c14eeaa..c843f4a9c512 100644
--- a/include/linux/kcore.h
+++ b/include/linux/kcore.h
@@ -44,6 +44,8 @@ void kclist_add_remap(struct kcore_list *m, void *addr, void *vaddr, size_t sz)
44 m->vaddr = (unsigned long)vaddr; 44 m->vaddr = (unsigned long)vaddr;
45 kclist_add(m, addr, sz, KCORE_REMAP); 45 kclist_add(m, addr, sz, KCORE_REMAP);
46} 46}
47
48extern int __init register_mem_pfn_is_ram(int (*fn)(unsigned long pfn));
47#else 49#else
48static inline 50static inline
49void kclist_add(struct kcore_list *new, void *addr, size_t size, int type) 51void kclist_add(struct kcore_list *new, void *addr, size_t size, int type)