06c2a2
From: Hari Bathini <hbathini@linux.vnet.ibm.com>
06c2a2
Date: Wed, 26 Jul 2017 22:49:41 +0530
06c2a2
Subject: [PATCH] kexec-tools: ppc64: fix how RMA top is deduced
06c2a2
06c2a2
Hang was observed, in purgatory, on a machine configured with
06c2a2
single LPAR. This was because one of the segments was loaded
06c2a2
outside the actual Real Memory Area (RMA) due to wrongly
06c2a2
deduced RMA top value.
06c2a2
06c2a2
Currently, top of real memory area, which is crucial for loading
06c2a2
kexec/kdump kernel, is obtained by iterating through mem nodes
06c2a2
and setting its value based on the base and size values of the
06c2a2
last mem node in the iteration. That can't always be correct as
06c2a2
the order of iteration may not be same and RMA base & size are
06c2a2
always based on the first memory property. Fix this by setting
06c2a2
RMA top value based on the base and size values of the memory
06c2a2
node that has the smallest base value (first memory property)
06c2a2
among all the memory nodes.
06c2a2
06c2a2
Also, correct the misnomers rmo_base and rmo_top to rma_base
06c2a2
and rma_top respectively.
06c2a2
06c2a2
While how RMA top is deduced was broken for sometime, the issue
06c2a2
may not have been seen so far, for couple of possible reasons:
06c2a2
06c2a2
    1. Only one mem node was available.
06c2a2
    2. First memory property has been the last node in
06c2a2
       iteration when multiple mem nodes were present.
06c2a2
06c2a2
Fixes: 02f4088ffded ("kexec fix ppc64 device-tree mem node")
06c2a2
Reported-by: Ankit Kumar <ankit@linux.vnet.ibm.com>
06c2a2
Cc: Michael Ellerman <mpe@ellerman.id.au>
06c2a2
Cc: Geoff Levand <geoff@infradead.org>
06c2a2
Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
06c2a2
Signed-off-by: Simon Horman <horms@verge.net.au>
06c2a2
Signed-off-by: Pingfan Liu <piliu@redhat.com>
06c2a2
---
06c2a2
 kexec/arch/ppc64/kexec-ppc64.c | 35 +++++++++++++++++++----------------
06c2a2
 1 file changed, 19 insertions(+), 16 deletions(-)
06c2a2
06c2a2
diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
06c2a2
index 6e8c175..a7d708b 100644
06c2a2
--- a/kexec/arch/ppc64/kexec-ppc64.c
06c2a2
+++ b/kexec/arch/ppc64/kexec-ppc64.c
06c2a2
@@ -38,7 +38,7 @@
06c2a2
 static struct memory_range *exclude_range = NULL;
06c2a2
 static struct memory_range *memory_range = NULL;
06c2a2
 static struct memory_range *base_memory_range = NULL;
06c2a2
-static uint64_t rmo_top;
06c2a2
+static uint64_t rma_top;
06c2a2
 uint64_t memory_max = 0;
06c2a2
 uint64_t memory_limit;
06c2a2
 static int nr_memory_ranges, nr_exclude_ranges;
06c2a2
@@ -385,7 +385,7 @@ int get_devtree_value(const char *fname, unsigned long long *value)
06c2a2
  */
06c2a2
 static int get_devtree_details(unsigned long kexec_flags)
06c2a2
 {
06c2a2
-	uint64_t rmo_base;
06c2a2
+	uint64_t rma_base = -1, base;
06c2a2
 	uint64_t tce_base;
06c2a2
 	unsigned int tce_size;
06c2a2
 	uint64_t htab_base, htab_size;
06c2a2
@@ -696,10 +696,13 @@ static int get_devtree_details(unsigned long kexec_flags)
06c2a2
 				perror(fname);
06c2a2
 				goto error_openfile;
06c2a2
 			}
06c2a2
-			rmo_base = be64_to_cpu(((uint64_t *)buf)[0]);
06c2a2
-			rmo_top = rmo_base + be64_to_cpu(((uint64_t *)buf)[1]);
06c2a2
-			if (rmo_top > 0x30000000UL)
06c2a2
-				rmo_top = 0x30000000UL;
06c2a2
+			base = be64_to_cpu(((uint64_t *)buf)[0]);
06c2a2
+			if (base < rma_base) {
06c2a2
+				rma_base = base;
06c2a2
+				rma_top = base + be64_to_cpu(((uint64_t *)buf)[1]);
06c2a2
+				if (rma_top > 0x30000000UL)
06c2a2
+					rma_top = 0x30000000UL;
06c2a2
+			}
06c2a2
 
06c2a2
 			fclose(file);
06c2a2
 			closedir(cdir);
06c2a2
@@ -811,14 +814,14 @@ int setup_memory_ranges(unsigned long kexec_flags)
06c2a2
 				j++;
06c2a2
 				if (j >= max_memory_ranges)
06c2a2
 					realloc_memory_ranges();
06c2a2
-				/* Limit the end to rmo_top */
06c2a2
-				if (memory_range[j-1].start >= rmo_top) {
06c2a2
+				/* Limit the end to rma_top */
06c2a2
+				if (memory_range[j-1].start >= rma_top) {
06c2a2
 					j--;
06c2a2
 					break;
06c2a2
 				}
06c2a2
-				if ((memory_range[j-1].start < rmo_top) &&
06c2a2
-				(memory_range[j-1].end >= rmo_top)) {
06c2a2
-					memory_range[j-1].end = rmo_top;
06c2a2
+				if ((memory_range[j-1].start < rma_top) &&
06c2a2
+				(memory_range[j-1].end >= rma_top)) {
06c2a2
+					memory_range[j-1].end = rma_top;
06c2a2
 					break;
06c2a2
 				}
06c2a2
 				continue;
06c2a2
@@ -833,14 +836,14 @@ int setup_memory_ranges(unsigned long kexec_flags)
06c2a2
 		j++;
06c2a2
 		if (j >= max_memory_ranges)
06c2a2
 			realloc_memory_ranges();
06c2a2
-		/* Limit range to rmo_top */
06c2a2
-		if (memory_range[j-1].start >= rmo_top) {
06c2a2
+		/* Limit range to rma_top */
06c2a2
+		if (memory_range[j-1].start >= rma_top) {
06c2a2
 			j--;
06c2a2
 			break;
06c2a2
 		}
06c2a2
-		if ((memory_range[j-1].start < rmo_top) &&
06c2a2
-			(memory_range[j-1].end >= rmo_top)) {
06c2a2
-			memory_range[j-1].end = rmo_top;
06c2a2
+		if ((memory_range[j-1].start < rma_top) &&
06c2a2
+			(memory_range[j-1].end >= rma_top)) {
06c2a2
+			memory_range[j-1].end = rma_top;
06c2a2
 			break;
06c2a2
 		}
06c2a2
 	}
06c2a2
-- 
06c2a2
2.7.4
06c2a2