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.
124 lines
4.2 KiB
124 lines
4.2 KiB
6 years ago
|
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
|
||
|
|