diff options
-rw-r--r-- | kexec/arch/ppc64/crashdump-ppc64.c | 33 | ||||
-rw-r--r-- | kexec/arch/ppc64/crashdump-ppc64.h | 2 | ||||
-rw-r--r-- | kexec/arch/ppc64/fs2dt.c | 1 | ||||
-rw-r--r-- | kexec/arch/ppc64/kexec-ppc64.c | 99 | ||||
-rw-r--r-- | kexec/arch/ppc64/kexec-ppc64.h | 8 |
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 */ |