[PATCH] kexec-tools: ppc64: fix how RMA top is deduced

Hari Bathini hbathini at linux.vnet.ibm.com
Wed Jul 26 10:19:41 PDT 2017


Hang was observed, in purgatory, on a machine configured with
single LPAR. This was because one of the segments was loaded
outside the actual Real Memory Area (RMA) due to wrongly
deduced RMA top value.

Currently, top of real memory area, which is crucial for loading
kexec/kdump kernel, is obtained by iterating through mem nodes
and setting its value based on the base and size values of the
last mem node in the iteration. That can't always be correct as
the order of iteration may not be same and RMA base & size are
always based on the first memory property. Fix this by setting
RMA top value based on the base and size values of the memory
node that has the smallest base value (first memory property)
among all the memory nodes.

Also, correct the misnomers rmo_base and rmo_top to rma_base
and rma_top respectively.

While how RMA top is deduced was broken for sometime, the issue
may not have been seen so far, for couple of possible reasons:

    1. Only one mem node was available.
    2. First memory property has been the last node in
       iteration when multiple mem nodes were present.

Fixes: 02f4088ffded ("kexec fix ppc64 device-tree mem node")
Reported-by: Ankit Kumar <ankit at linux.vnet.ibm.com>
Cc: Michael Ellerman <mpe at ellerman.id.au>
Cc: Geoff Levand <geoff at infradead.org>
Signed-off-by: Hari Bathini <hbathini at linux.vnet.ibm.com>
---
 kexec/arch/ppc64/kexec-ppc64.c |   35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
index 6e8c175..a7d708b 100644
--- a/kexec/arch/ppc64/kexec-ppc64.c
+++ b/kexec/arch/ppc64/kexec-ppc64.c
@@ -38,7 +38,7 @@
 static struct memory_range *exclude_range = NULL;
 static struct memory_range *memory_range = NULL;
 static struct memory_range *base_memory_range = NULL;
-static uint64_t rmo_top;
+static uint64_t rma_top;
 uint64_t memory_max = 0;
 uint64_t memory_limit;
 static int nr_memory_ranges, nr_exclude_ranges;
@@ -385,7 +385,7 @@ int get_devtree_value(const char *fname, unsigned long long *value)
  */
 static int get_devtree_details(unsigned long kexec_flags)
 {
-	uint64_t rmo_base;
+	uint64_t rma_base = -1, base;
 	uint64_t tce_base;
 	unsigned int tce_size;
 	uint64_t htab_base, htab_size;
@@ -696,10 +696,13 @@ static int get_devtree_details(unsigned long kexec_flags)
 				perror(fname);
 				goto error_openfile;
 			}
-			rmo_base = be64_to_cpu(((uint64_t *)buf)[0]);
-			rmo_top = rmo_base + be64_to_cpu(((uint64_t *)buf)[1]);
-			if (rmo_top > 0x30000000UL)
-				rmo_top = 0x30000000UL;
+			base = be64_to_cpu(((uint64_t *)buf)[0]);
+			if (base < rma_base) {
+				rma_base = base;
+				rma_top = base + be64_to_cpu(((uint64_t *)buf)[1]);
+				if (rma_top > 0x30000000UL)
+					rma_top = 0x30000000UL;
+			}
 
 			fclose(file);
 			closedir(cdir);
@@ -811,14 +814,14 @@ int setup_memory_ranges(unsigned long kexec_flags)
 				j++;
 				if (j >= max_memory_ranges)
 					realloc_memory_ranges();
-				/* Limit the end to rmo_top */
-				if (memory_range[j-1].start >= rmo_top) {
+				/* Limit the end to rma_top */
+				if (memory_range[j-1].start >= rma_top) {
 					j--;
 					break;
 				}
-				if ((memory_range[j-1].start < rmo_top) &&
-				(memory_range[j-1].end >= rmo_top)) {
-					memory_range[j-1].end = rmo_top;
+				if ((memory_range[j-1].start < rma_top) &&
+				(memory_range[j-1].end >= rma_top)) {
+					memory_range[j-1].end = rma_top;
 					break;
 				}
 				continue;
@@ -833,14 +836,14 @@ int setup_memory_ranges(unsigned long kexec_flags)
 		j++;
 		if (j >= max_memory_ranges)
 			realloc_memory_ranges();
-		/* Limit range to rmo_top */
-		if (memory_range[j-1].start >= rmo_top) {
+		/* Limit range to rma_top */
+		if (memory_range[j-1].start >= rma_top) {
 			j--;
 			break;
 		}
-		if ((memory_range[j-1].start < rmo_top) &&
-			(memory_range[j-1].end >= rmo_top)) {
-			memory_range[j-1].end = rmo_top;
+		if ((memory_range[j-1].start < rma_top) &&
+			(memory_range[j-1].end >= rma_top)) {
+			memory_range[j-1].end = rma_top;
 			break;
 		}
 	}




More information about the kexec mailing list