Blame SOURCES/kexec-tools-2.0.15-ppc64-fix-how-RMA-top-is-deduced.patch

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