summaryrefslogtreecommitdiff
path: root/kexec/arch
diff options
context:
space:
mode:
Diffstat (limited to 'kexec/arch')
-rw-r--r--kexec/arch/ppc64/crashdump-ppc64.c23
-rw-r--r--kexec/arch/ppc64/crashdump-ppc64.h16
-rw-r--r--kexec/arch/ppc64/kexec-ppc64.c35
3 files changed, 56 insertions, 18 deletions
diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
index bc9f948..50e3853 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.c
+++ b/kexec/arch/ppc64/crashdump-ppc64.c
@@ -39,6 +39,10 @@
#define DEVTREE_CRASHKERNEL_BASE "/proc/device-tree/chosen/linux,crashkernel-base"
#define DEVTREE_CRASHKERNEL_SIZE "/proc/device-tree/chosen/linux,crashkernel-size"
+unsigned int num_of_lmb_sets;
+unsigned int is_dyn_mem_v2;
+uint64_t lmb_size;
+
static struct crash_elf_info elf_info64 =
{
class: ELFCLASS64,
@@ -127,6 +131,7 @@ static int get_dyn_reconf_crash_memory_ranges(void)
{
uint64_t start, end;
uint64_t startrange, endrange;
+ uint64_t size;
char fname[128], buf[32];
FILE *file;
unsigned int i;
@@ -135,6 +140,8 @@ static int get_dyn_reconf_crash_memory_ranges(void)
strcpy(fname, "/proc/device-tree/");
strcat(fname, "ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory");
+ if (is_dyn_mem_v2)
+ strcat(fname, "-v2");
if ((file = fopen(fname, "r")) == NULL) {
perror(fname);
return -1;
@@ -142,8 +149,9 @@ static int get_dyn_reconf_crash_memory_ranges(void)
fseek(file, 4, SEEK_SET);
startrange = endrange = 0;
- for (i = 0; i < num_of_lmbs; i++) {
- if ((n = fread(buf, 1, 24, file)) < 0) {
+ size = lmb_size;
+ for (i = 0; i < num_of_lmb_sets; i++) {
+ if ((n = fread(buf, 1, LMB_ENTRY_SIZE, file)) < 0) {
perror(fname);
fclose(file);
return -1;
@@ -156,8 +164,15 @@ static int get_dyn_reconf_crash_memory_ranges(void)
return -1;
}
- start = be64_to_cpu(((uint64_t *)buf)[DRCONF_ADDR]);
- end = start + lmb_size;
+ /*
+ * If the property is ibm,dynamic-memory-v2, the first 4 bytes
+ * tell the number of sequential LMBs in this entry.
+ */
+ if (is_dyn_mem_v2)
+ size = be32_to_cpu(((unsigned int *)buf)[0]) * lmb_size;
+
+ start = be64_to_cpu(*((uint64_t *)&buf[DRCONF_ADDR]));
+ end = start + size;
if (start == 0 && end >= (BACKUP_SRC_END + 1))
start = BACKUP_SRC_END + 1;
diff --git a/kexec/arch/ppc64/crashdump-ppc64.h b/kexec/arch/ppc64/crashdump-ppc64.h
index 42ccc31..87beb39 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.h
+++ b/kexec/arch/ppc64/crashdump-ppc64.h
@@ -34,10 +34,18 @@ extern unsigned int rtas_size;
extern uint64_t opal_base;
extern uint64_t opal_size;
-uint64_t lmb_size;
-unsigned int num_of_lmbs;
-
-#define DRCONF_ADDR 0
+/*
+ * In case of ibm,dynamic-memory-v2 property, this is the number of LMB
+ * sets where each set represents a group of sequential LMB entries. In
+ * case of ibm,dynamic-memory property, the number of LMB sets is nothing
+ * but the total number of LMB entries.
+ */
+extern unsigned int num_of_lmb_sets;
+extern unsigned int is_dyn_mem_v2;
+extern uint64_t lmb_size;
+
+#define LMB_ENTRY_SIZE 24
+#define DRCONF_ADDR (is_dyn_mem_v2 ? 4 : 0)
#define DRCONF_FLAGS 20
#endif /* CRASHDUMP_PPC64_H */
diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
index a7d708b..4e70b13 100644
--- a/kexec/arch/ppc64/kexec-ppc64.c
+++ b/kexec/arch/ppc64/kexec-ppc64.c
@@ -149,6 +149,7 @@ static void add_base_memory_range(uint64_t start, uint64_t end)
static int get_dyn_reconf_base_ranges(void)
{
uint64_t start, end;
+ uint64_t size;
char fname[128], buf[32];
FILE *file;
unsigned int i;
@@ -166,29 +167,35 @@ static int get_dyn_reconf_base_ranges(void)
return -1;
}
/*
- * lmb_size, num_of_lmbs(global variables) are
+ * lmb_size, num_of_lmb_sets(global variables) are
* initialized once here.
*/
- lmb_size = be64_to_cpu(((uint64_t *)buf)[0]);
+ size = lmb_size = be64_to_cpu(((uint64_t *)buf)[0]);
fclose(file);
strcpy(fname, "/proc/device-tree/");
strcat(fname,
"ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory");
if ((file = fopen(fname, "r")) == NULL) {
- perror(fname);
- return -1;
+ strcat(fname, "-v2");
+ if ((file = fopen(fname, "r")) == NULL) {
+ perror(fname);
+ return -1;
+ }
+
+ is_dyn_mem_v2 = 1;
}
- /* first 4 bytes tell the number of lmbs */
+
+ /* first 4 bytes tell the number of lmb set entries */
if (fread(buf, 1, 4, file) != 4) {
perror(fname);
fclose(file);
return -1;
}
- num_of_lmbs = be32_to_cpu(((unsigned int *)buf)[0]);
+ num_of_lmb_sets = be32_to_cpu(((unsigned int *)buf)[0]);
- for (i = 0; i < num_of_lmbs; i++) {
- if ((n = fread(buf, 1, 24, file)) < 0) {
+ for (i = 0; i < num_of_lmb_sets; i++) {
+ if ((n = fread(buf, 1, LMB_ENTRY_SIZE, file)) < 0) {
perror(fname);
fclose(file);
return -1;
@@ -196,13 +203,21 @@ static int get_dyn_reconf_base_ranges(void)
if (nr_memory_ranges >= max_memory_ranges)
return -1;
- start = be64_to_cpu(((uint64_t *)buf)[0]);
- end = start + lmb_size;
+ /*
+ * If the property is ibm,dynamic-memory-v2, the first 4 bytes
+ * tell the number of sequential LMBs in this entry.
+ */
+ if (is_dyn_mem_v2)
+ size = be32_to_cpu(((unsigned int *)buf)[0]) * lmb_size;
+
+ start = be64_to_cpu(*((uint64_t *)&buf[DRCONF_ADDR]));
+ end = start + size;
add_base_memory_range(start, end);
}
fclose(file);
return 0;
}
+
/* Sort the base ranges in memory - this is useful for ensuring that our
* ranges are in ascending order, even if device-tree read of memory nodes
* is done differently. Also, could be used for other range coalescing later