[PATCH] PPC64: ensure that extra rtas segment is a multiple of PAGE_SIZE

Neil Horman nhorman at tuxdriver.com
Tue May 20 11:26:40 EDT 2008


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 at tuxdriver.com>

diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
index e425346..1b88577 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;
 	}
-- 
/****************************************************
 * Neil Horman <nhorman at tuxdriver.com>
 * Software Engineer, Red Hat
 ****************************************************/



More information about the kexec mailing list