summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kexec/arch/ppc64/crashdump-ppc64.c33
-rw-r--r--kexec/arch/ppc64/crashdump-ppc64.h2
-rw-r--r--kexec/arch/ppc64/fs2dt.c1
-rw-r--r--kexec/arch/ppc64/kexec-ppc64.c99
-rw-r--r--kexec/arch/ppc64/kexec-ppc64.h8
5 files changed, 124 insertions, 19 deletions
diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
index e84aee1..00740dc 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.c
+++ b/kexec/arch/ppc64/crashdump-ppc64.c
@@ -62,13 +62,16 @@ extern struct arch_options_t arch_options;
/* Stores a sorted list of RAM memory ranges for which to create elf headers.
* A separate program header is created for backup region
*/
-static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
+static struct memory_range *crash_memory_range = NULL;
+
+/* Define a variable to replace the CRASH_MAX_MEMORY_RANGES macro */
+static int crash_max_memory_ranges;
/*
* Used to save various memory ranges/regions needed for the captured
* kernel to boot. (lime memmap= option in other archs)
*/
-mem_rgns_t usablemem_rgns = {0, };
+mem_rgns_t usablemem_rgns = {0, NULL};
/*
* To store the memory size of the first kernel and this value will be
@@ -105,6 +108,15 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
int i, n;
unsigned long long start, end, cstart, cend;
+ crash_max_memory_ranges = max_memory_ranges + 6;
+
+ crash_memory_range = (struct memory_range *) malloc(
+ (sizeof(struct memory_range) * (crash_max_memory_ranges)));
+ if (!crash_memory_range) {
+ fprintf(stderr, "Allocation for crash memory range failed\n");
+ return -1;
+ }
+
/* create a separate program header for the backup region */
crash_memory_range[0].start = BACKUP_SRC_START;
crash_memory_range[0].end = BACKUP_SRC_END;
@@ -113,7 +125,7 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
if ((dir = opendir(device_tree)) == NULL) {
perror(device_tree);
- return -1;
+ goto err;
}
while ((dentry = readdir(dir)) != NULL) {
if (strncmp(dentry->d_name, "memory@", 7))
@@ -123,7 +135,7 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
if ((dmem = opendir(fname)) == NULL) {
perror(fname);
closedir(dir);
- return -1;
+ goto err;
}
while ((mentry = readdir(dmem)) != NULL) {
if (strcmp(mentry->d_name, "reg"))
@@ -133,21 +145,21 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
perror(fname);
closedir(dmem);
closedir(dir);
- return -1;
+ goto err;
}
if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
perror(fname);
fclose(file);
closedir(dmem);
closedir(dir);
- return -1;
+ goto err;
}
- if (memory_ranges >= MAX_MEMORY_RANGES) {
+ if (memory_ranges >= max_memory_ranges) {
/* No space to insert another element. */
fprintf(stderr,
"Error: Number of crash memory ranges"
" excedeed the max limit\n");
- return -1;
+ goto err;
}
start = ((unsigned long long *)buf)[0];
@@ -228,6 +240,11 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
}
#endif
return 0;
+
+err:
+ if (crash_memory_range)
+ free(crash_memory_range);
+ return -1;
}
/* Converts unsigned long to ascii string. */
diff --git a/kexec/arch/ppc64/crashdump-ppc64.h b/kexec/arch/ppc64/crashdump-ppc64.h
index 209f6da..db44df2 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.h
+++ b/kexec/arch/ppc64/crashdump-ppc64.h
@@ -13,8 +13,6 @@ void add_usable_mem_rgns(unsigned long long base, unsigned long long size);
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
#define MAXMEM (-KERNELBASE-VMALLOCBASE)
-#define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 6)
-
#define COMMAND_LINE_SIZE 512 /* from kernel */
/* Backup Region, First 64K of System RAM. */
#define BACKUP_SRC_START 0x0000
diff --git a/kexec/arch/ppc64/fs2dt.c b/kexec/arch/ppc64/fs2dt.c
index 7c07e19..61a3638 100644
--- a/kexec/arch/ppc64/fs2dt.c
+++ b/kexec/arch/ppc64/fs2dt.c
@@ -36,6 +36,7 @@
#define NAMESPACE 16384 /* max bytes for property names */
#define TREEWORDS 65536 /* max 32 bit words for property values */
#define MEMRESERVE 256 /* max number of reserved memory blocks */
+#define MAX_MEMORY_RANGES 1024
static char pathname[MAXPATH], *pathstart;
static char propnames[NAMESPACE] = { 0 };
diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
index fdd5385..592a4d6 100644
--- a/kexec/arch/ppc64/kexec-ppc64.c
+++ b/kexec/arch/ppc64/kexec-ppc64.c
@@ -20,6 +20,7 @@
#include <stddef.h>
#include <stdio.h>
+#include <stdlib.h>
#include <errno.h>
#include <stdint.h>
#include <string.h>
@@ -34,17 +35,92 @@
#include "crashdump-ppc64.h"
#include <arch/options.h>
-static struct exclude_range exclude_range[MAX_MEMORY_RANGES];
+static struct exclude_range *exclude_range = NULL;
+static struct memory_range *memory_range = NULL;
+static struct memory_range *base_memory_range = NULL;
static unsigned long long rmo_top;
-static struct memory_range memory_range[MAX_MEMORY_RANGES];
-static struct memory_range base_memory_range[MAX_MEMORY_RANGES];
unsigned long long memory_max = 0;
static int nr_memory_ranges, nr_exclude_ranges;
unsigned long long crash_base, crash_size;
unsigned int rtas_base, rtas_size;
+int max_memory_ranges;
static int sort_base_ranges();
+
+static void cleanup_memory_ranges()
+{
+ if (memory_range)
+ free(memory_range);
+ if (base_memory_range)
+ free(base_memory_range);
+ if (exclude_range)
+ free(exclude_range);
+ if (usablemem_rgns.ranges)
+ free(usablemem_rgns.ranges);
+}
+
+/*
+ * Allocate memory for various data structures used to hold
+ * values of different memory ranges
+ */
+static int alloc_memory_ranges()
+{
+ memory_range = (struct memory_range *) malloc(
+ (sizeof(struct memory_range) * max_memory_ranges));
+ if (!memory_range)
+ goto err1;
+
+ base_memory_range = (struct memory_range *) malloc(
+ (sizeof(struct memory_range) * max_memory_ranges));
+ if (!base_memory_range)
+ goto err1;
+
+ exclude_range = (struct exclude_range *) malloc(
+ (sizeof(struct exclude_range) * max_memory_ranges));
+ if (!exclude_range)
+ goto err1;
+
+ usablemem_rgns.ranges = (struct exclude_range *) malloc(
+ (sizeof(struct exclude_range) * max_memory_ranges));
+ if (!(usablemem_rgns.ranges))
+ goto err1;
+
+ return 0;
+
+err1:
+ fprintf(stderr, "memory range structure allocation failure\n");
+ cleanup_memory_ranges();
+ return -1;
+
+}
+
+/*
+ * Count the memory@ nodes under /proc/device-tree and populate the
+ * max_memory_ranges variable. This variable replaces MAX_MEMORY_RANGES
+ * macro used earlier.
+ */
+static int count_memory_ranges()
+{
+ char device_tree[256] = "/proc/device-tree/";
+ struct dirent *dentry;
+ DIR *dir;
+
+ if ((dir = opendir(device_tree)) == NULL) {
+ perror(device_tree);
+ return -1;
+ }
+
+ while ((dentry = readdir(dir)) != NULL) {
+ if (strncmp(dentry->d_name, "memory@", 7))
+ continue;
+ max_memory_ranges++;
+ }
+ closedir(dir);
+
+ return 0;
+}
+
/* Get base memory ranges */
static int get_base_ranges()
{
@@ -88,7 +164,7 @@ static int get_base_ranges()
closedir(dir);
return -1;
}
- if (local_memory_ranges >= MAX_MEMORY_RANGES) {
+ if (local_memory_ranges >= max_memory_ranges) {
fclose(file);
break;
}
@@ -447,8 +523,10 @@ int setup_memory_ranges(unsigned long kexec_flags)
* nodes. Build list of ranges to be excluded from valid memory
*/
- get_base_ranges();
- get_devtree_details(kexec_flags);
+ if (get_base_ranges())
+ goto out;
+ if (get_devtree_details(kexec_flags))
+ goto out;
for (i = 0; i < nr_exclude_ranges; i++) {
/* If first exclude range does not start with 0, include the
@@ -511,12 +589,21 @@ int setup_memory_ranges(unsigned long kexec_flags)
fprintf(stderr, "setup_memory_ranges memory_range[%d] start:%lx, end:%lx\n", k, memory_range[k].start, memory_range[k].end);
#endif
return 0;
+
+out:
+ cleanup_memory_ranges();
+ return -1;
}
/* Return a list of valid memory ranges */
int get_memory_ranges(struct memory_range **range, int *ranges,
unsigned long kexec_flags)
{
+ if (count_memory_ranges())
+ return -1;
+ if (alloc_memory_ranges())
+ return -1;
+
setup_memory_ranges(kexec_flags);
*range = memory_range;
*ranges = nr_memory_ranges;
diff --git a/kexec/arch/ppc64/kexec-ppc64.h b/kexec/arch/ppc64/kexec-ppc64.h
index c74c95c..9776cb1 100644
--- a/kexec/arch/ppc64/kexec-ppc64.h
+++ b/kexec/arch/ppc64/kexec-ppc64.h
@@ -1,8 +1,6 @@
#ifndef KEXEC_PPC64_H
#define KEXEC_PPC64_H
-#define MAX_MEMORY_RANGES 1024 /* TO FIX - needs to be dynamically set */
-
#define MAXBYTES 128
#define MAX_LINE 160
#define CORE_TYPE_ELF32 1
@@ -17,6 +15,8 @@ void elf_ppc64_usage(void);
void reserve(unsigned long long where, unsigned long long length);
extern unsigned long initrd_base, initrd_size;
+extern int max_memory_ranges;
+
/* boot block version 2 as defined by the linux kernel */
struct bootblock {
unsigned magic,
@@ -39,7 +39,9 @@ struct exclude_range {
typedef struct mem_rgns {
unsigned int size;
- struct exclude_range ranges[MAX_MEMORY_RANGES];
+ struct exclude_range *ranges;
} mem_rgns_t;
+extern mem_rgns_t usablemem_rgns;
+
#endif /* KEXEC_PPC64_H */