|
|
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 |
|