aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2008-07-31 02:54:28 -0400
committerPaul Mackerras <paulus@samba.org>2008-08-19 19:50:21 -0400
commit7230ced4925b07c259a62b515d8278c6bb1ad98c (patch)
tree7d1afdc5dac4ccc3481a8a22b86d2bb2f548bd4d
parentd82bf490948eaf10023ff850d0b5c70e49e0ba76 (diff)
powerpc: Fix /dev/oldmem interface for kdump
A change to __ioremap() broke reading /dev/oldmem because we're no longer able to ioremap pfn 0 (d177c207, "[PATCH] powerpc: IOMMU: don't ioremap null addresses"). We actually don't need to ioremap for anything that's part of the linear mapping, so just read it directly. Also make sure we're only reading one page or less at a time. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Sachin Sant <sachinp@in.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/kernel/crash_dump.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index e0debcca0bfa..a323c9b32ee1 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -86,6 +86,19 @@ static int __init parse_savemaxmem(char *p)
86} 86}
87__setup("savemaxmem=", parse_savemaxmem); 87__setup("savemaxmem=", parse_savemaxmem);
88 88
89
90static size_t copy_oldmem_vaddr(void *vaddr, char *buf, size_t csize,
91 unsigned long offset, int userbuf)
92{
93 if (userbuf) {
94 if (copy_to_user((char __user *)buf, (vaddr + offset), csize))
95 return -EFAULT;
96 } else
97 memcpy(buf, (vaddr + offset), csize);
98
99 return csize;
100}
101
89/** 102/**
90 * copy_oldmem_page - copy one page from "oldmem" 103 * copy_oldmem_page - copy one page from "oldmem"
91 * @pfn: page frame number to be copied 104 * @pfn: page frame number to be copied
@@ -107,16 +120,16 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
107 if (!csize) 120 if (!csize)
108 return 0; 121 return 0;
109 122
110 vaddr = __ioremap(pfn << PAGE_SHIFT, PAGE_SIZE, 0); 123 csize = min(csize, PAGE_SIZE);
111 124
112 if (userbuf) { 125 if (pfn < max_pfn) {
113 if (copy_to_user((char __user *)buf, (vaddr + offset), csize)) { 126 vaddr = __va(pfn << PAGE_SHIFT);
114 iounmap(vaddr); 127 csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
115 return -EFAULT; 128 } else {
116 } 129 vaddr = __ioremap(pfn << PAGE_SHIFT, PAGE_SIZE, 0);
117 } else 130 csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
118 memcpy(buf, (vaddr + offset), csize); 131 iounmap(vaddr);
132 }
119 133
120 iounmap(vaddr);
121 return csize; 134 return csize;
122} 135}