You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
4.2 KiB
123 lines
4.2 KiB
From: Hari Bathini <hbathini@linux.vnet.ibm.com> |
|
Date: Wed, 26 Jul 2017 22:49:41 +0530 |
|
Subject: [PATCH] kexec-tools: ppc64: fix how RMA top is deduced |
|
|
|
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@linux.vnet.ibm.com> |
|
Cc: Michael Ellerman <mpe@ellerman.id.au> |
|
Cc: Geoff Levand <geoff@infradead.org> |
|
Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com> |
|
Signed-off-by: Simon Horman <horms@verge.net.au> |
|
Signed-off-by: Pingfan Liu <piliu@redhat.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; |
|
} |
|
} |
|
-- |
|
2.7.4 |
|
|
|
|