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