summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2008-05-20 11:26:40 -0400
committerSimon Horman <horms@verge.net.au>2008-05-21 10:49:51 +1000
commitdad9f01c556c69c432f3b145e2947dcd5e7626ca (patch)
treee1089d57bce40563b2c44c408446c75e897cf08a
parent595994920f19891f50b41d24cbd808beb0ae8ea9 (diff)
PPC64: ensure that extra rtas segment is a multiple of PAGE_SIZE
kexec on ppc64 systems, include an extra PT_LOAD segment if the rtas memory hits the stored kdump kernel image. While the rtas area is memory mapped (implying that it begins and ends on a page boundary), the whole of the mapped region is not consumed by the rtas features (the remaining area just returns 0's). This unused area is not accounted in the rtas prom, which is used to populate the proc files which export the size information that is used to define the mapped memory region (/proc/device-tree/rtas/rtas-size). Since this is the data that kexec uses to generate the PT_LOAD segment, we wind up with a PT_LOAD segment that incorrectly contains a partial page. This causes things like makedumpfile to fail, since it reads memory in page sized chunks, and fails on the inability to read only part of a page. This patch corrects that by rounding the extra segment size up the next whole page size. This is safe, since the rtas area is mapped to a whole page range. I've tested on both 4k and 64k configured kernels on ppc64 and found that it works well. Regards Neil Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--kexec/arch/ppc64/crashdump-ppc64.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
index e425346..a1963e1 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.c
+++ b/kexec/arch/ppc64/crashdump-ppc64.c
@@ -107,6 +107,7 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
struct dirent *dentry, *mentry;
int i, n, crash_rng_len = 0;
unsigned long long start, end, cstart, cend;
+ int page_size;
crash_max_memory_ranges = max_memory_ranges + 6;
crash_rng_len = sizeof(struct memory_range) * crash_max_memory_ranges;
@@ -213,12 +214,25 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
*/
if (crash_base < rtas_base + rtas_size &&
rtas_base < crash_base + crash_size) {
+ page_size = getpagesize();
cstart = rtas_base;
cend = rtas_base + rtas_size;
if (cstart < crash_base)
cstart = crash_base;
if (cend > crash_base + crash_size)
cend = crash_base + crash_size;
+ /*
+ * The rtas section created here is formed by reading rtas-base
+ * and rtas-size from /proc/device-tree/rtas. Unfortunately
+ * rtas-size is not required to be a multiple of PAGE_SIZE
+ * The remainder of the page it ends on is just garbage, and is
+ * safe to read, its just not accounted in rtas-size. Since
+ * we're creating an elf section here though, lets round it up
+ * to the next page size boundary though, so makedumpfile can
+ * read it safely without going south on us.
+ */
+ cend = (cend + page_size - 1) & (~(page_size - 1));
+
crash_memory_range[memory_ranges].start = cstart;
crash_memory_range[memory_ranges++].end = cend;
}