diff options
Diffstat (limited to 'kexec/arch/ppc64/kexec-ppc64.c')
-rw-r--r-- | kexec/arch/ppc64/kexec-ppc64.c | 135 |
1 files changed, 123 insertions, 12 deletions
diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c index 21bd0a8..6e79f52 100644 --- a/kexec/arch/ppc64/kexec-ppc64.c +++ b/kexec/arch/ppc64/kexec-ppc64.c @@ -31,6 +31,7 @@ #include "../../kexec.h" #include "../../kexec-syscall.h" #include "kexec-ppc64.h" +#include "../../fs2dt.h" #include "crashdump-ppc64.h" #include <arch/options.h> @@ -43,6 +44,7 @@ uint64_t memory_limit; static int nr_memory_ranges, nr_exclude_ranges; uint64_t crash_base, crash_size; unsigned int rtas_base, rtas_size; +uint64_t opal_base, opal_size; int max_memory_ranges; static void cleanup_memory_ranges(void) @@ -167,7 +169,7 @@ static int get_dyn_reconf_base_ranges(void) * lmb_size, num_of_lmbs(global variables) are * initialized once here. */ - lmb_size = ((uint64_t *)buf)[0]; + lmb_size = be64_to_cpu(((uint64_t *)buf)[0]); fclose(file); strcpy(fname, "/proc/device-tree/"); @@ -183,7 +185,7 @@ static int get_dyn_reconf_base_ranges(void) fclose(file); return -1; } - num_of_lmbs = ((unsigned int *)buf)[0]; + num_of_lmbs = be32_to_cpu(((unsigned int *)buf)[0]); for (i = 0; i < num_of_lmbs; i++) { if ((n = fread(buf, 1, 24, file)) < 0) { @@ -194,7 +196,7 @@ static int get_dyn_reconf_base_ranges(void) if (nr_memory_ranges >= max_memory_ranges) return -1; - start = ((uint64_t *)buf)[0]; + start = be64_to_cpu(((uint64_t *)buf)[0]); end = start + lmb_size; add_base_memory_range(start, end); } @@ -278,8 +280,8 @@ static int get_base_ranges(void) if (realloc_memory_ranges() < 0) break; } - start = ((uint64_t *)buf)[0]; - end = start + ((uint64_t *)buf)[1]; + start = be64_to_cpu(((uint64_t *)buf)[0]); + end = start + be64_to_cpu(((uint64_t *)buf)[1]); add_base_memory_range(start, end); fclose(file); } @@ -313,6 +315,47 @@ static int sort_ranges(void) return 0; } +void scan_reserved_ranges(unsigned long kexec_flags, int *range_index) +{ + char fname[256], buf[16]; + FILE *file; + int i = *range_index; + + strcpy(fname, "/proc/device-tree/reserved-ranges"); + + file = fopen(fname, "r"); + if (file == NULL) { + if (errno != ENOENT) { + perror(fname); + return; + } + errno = 0; + /* File not present. Non PowerKVM system. */ + return; + } + + /* + * Each reserved range is an (address,size) pair, 2 cells each, + * totalling 4 cells per range. + */ + while (fread(buf, sizeof(uint64_t) * 2, 1, file) == 1) { + uint64_t base, size; + + base = be64_to_cpu(((uint64_t *)buf)[0]); + size = be64_to_cpu(((uint64_t *)buf)[1]); + + exclude_range[i].start = base; + exclude_range[i].end = base + size; + i++; + if (i >= max_memory_ranges) + realloc_memory_ranges(); + + reserve(base, size); + } + fclose(file); + *range_index = i; +} + /* Get devtree details and create exclude_range array * Also create usablemem_ranges for KEXEC_ON_CRASH */ @@ -338,12 +381,15 @@ static int get_devtree_details(unsigned long kexec_flags) return -1; } + scan_reserved_ranges(kexec_flags, &i); + while ((dentry = readdir(dir)) != NULL) { if (strncmp(dentry->d_name, "chosen", 6) && strncmp(dentry->d_name, "memory@", 7) && strcmp(dentry->d_name, "memory") && strncmp(dentry->d_name, "pci@", 4) && - strncmp(dentry->d_name, "rtas", 4)) + strncmp(dentry->d_name, "rtas", 4) && + strncmp(dentry->d_name, "ibm,opal", 8)) continue; strcpy(fname, device_tree); strcat(fname, dentry->d_name); @@ -363,6 +409,7 @@ static int get_devtree_details(unsigned long kexec_flags) goto error_openfile; } fclose(file); + kernel_end = be64_to_cpu(kernel_end); /* Add kernel memory to exclude_range */ exclude_range[i].start = 0x0UL; @@ -386,6 +433,7 @@ static int get_devtree_details(unsigned long kexec_flags) goto error_openfile; } fclose(file); + crash_base = be64_to_cpu(crash_base); memset(fname, 0, sizeof(fname)); strcpy(fname, device_tree); @@ -400,6 +448,8 @@ static int get_devtree_details(unsigned long kexec_flags) perror(fname); goto error_openfile; } + fclose(file); + crash_size = be64_to_cpu(crash_size); if (crash_base > mem_min) mem_min = crash_base; @@ -430,10 +480,14 @@ static int get_devtree_details(unsigned long kexec_flags) * fall through. On older kernel this file * is not present. */ - } else if (fread(&memory_limit, sizeof(uint64_t), 1, - file) != 1) { - perror(fname); - goto error_openfile; + } else { + if (fread(&memory_limit, sizeof(uint64_t), 1, + file) != 1) { + perror(fname); + goto error_openfile; + } + fclose(file); + memory_limit = be64_to_cpu(memory_limit); } memset(fname, 0, sizeof(fname)); @@ -454,6 +508,9 @@ static int get_devtree_details(unsigned long kexec_flags) perror(fname); goto error_openfile; } + fclose(file); + htab_base = be64_to_cpu(htab_base); + memset(fname, 0, sizeof(fname)); strcpy(fname, device_tree); strcat(fname, dentry->d_name); @@ -466,6 +523,9 @@ static int get_devtree_details(unsigned long kexec_flags) perror(fname); goto error_openfile; } + fclose(file); + htab_size = be64_to_cpu(htab_size); + /* Add htab address to exclude_range - NON-LPAR only */ exclude_range[i].start = htab_base; exclude_range[i].end = htab_base + htab_size; @@ -492,6 +552,7 @@ static int get_devtree_details(unsigned long kexec_flags) perror(fname); goto error_openfile; } + initrd_start = be64_to_cpu(initrd_start); fclose(file); memset(fname, 0, sizeof(fname)); @@ -511,6 +572,7 @@ static int get_devtree_details(unsigned long kexec_flags) perror(fname); goto error_openfile; } + initrd_end = be64_to_cpu(initrd_end); fclose(file); /* Add initrd address to exclude_range */ @@ -532,6 +594,8 @@ static int get_devtree_details(unsigned long kexec_flags) perror(fname); goto error_openfile; } + fclose(file); + rtas_base = be32_to_cpu(rtas_base); memset(fname, 0, sizeof(fname)); strcpy(fname, device_tree); strcat(fname, dentry->d_name); @@ -544,7 +608,9 @@ static int get_devtree_details(unsigned long kexec_flags) perror(fname); goto error_openfile; } + fclose(file); closedir(cdir); + rtas_size = be32_to_cpu(rtas_size); /* Add rtas to exclude_range */ exclude_range[i].start = rtas_base; exclude_range[i].end = rtas_base + rtas_size; @@ -555,6 +621,46 @@ static int get_devtree_details(unsigned long kexec_flags) add_usable_mem_rgns(rtas_base, rtas_size); } /* rtas */ + if (strncmp(dentry->d_name, "ibm,opal", 8) == 0) { + strcat(fname, "/opal-base-address"); + file = fopen(fname, "r"); + if (file == NULL) { + perror(fname); + goto error_opencdir; + } + if (fread(&opal_base, sizeof(uint64_t), 1, file) != 1) { + perror(fname); + goto error_openfile; + } + opal_base = be64_to_cpu(opal_base); + fclose(file); + + memset(fname, 0, sizeof(fname)); + strcpy(fname, device_tree); + strcat(fname, dentry->d_name); + strcat(fname, "/opal-runtime-size"); + file = fopen(fname, "r"); + if (file == NULL) { + perror(fname); + goto error_opencdir; + } + if (fread(&opal_size, sizeof(uint64_t), 1, file) != 1) { + perror(fname); + goto error_openfile; + } + fclose(file); + closedir(cdir); + opal_size = be64_to_cpu(opal_size); + /* Add OPAL to exclude_range */ + exclude_range[i].start = opal_base; + exclude_range[i].end = opal_base + opal_size; + i++; + if (i >= max_memory_ranges) + realloc_memory_ranges(); + if (kexec_flags & KEXEC_ON_CRASH) + add_usable_mem_rgns(opal_base, opal_size); + } /* ibm,opal */ + if (!strncmp(dentry->d_name, "memory@", 7) || !strcmp(dentry->d_name, "memory")) { strcat(fname, "/reg"); @@ -566,8 +672,8 @@ static int get_devtree_details(unsigned long kexec_flags) perror(fname); goto error_openfile; } - rmo_base = ((uint64_t *)buf)[0]; - rmo_top = rmo_base + ((uint64_t *)buf)[1]; + 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; @@ -591,6 +697,8 @@ static int get_devtree_details(unsigned long kexec_flags) perror(fname); goto error_openfile; } + fclose(file); + tce_base = be64_to_cpu(tce_base); memset(fname, 0, sizeof(fname)); strcpy(fname, device_tree); strcat(fname, dentry->d_name); @@ -603,6 +711,8 @@ static int get_devtree_details(unsigned long kexec_flags) perror(fname); goto error_openfile; } + fclose(file); + tce_size = be32_to_cpu(tce_size); /* Add tce to exclude_range - NON-LPAR only */ exclude_range[i].start = tce_base; exclude_range[i].end = tce_base + tce_size; @@ -798,6 +908,7 @@ const struct arch_map_entry arches[] = { * So pass KEXEC_ARCH_PPC64 here */ { "ppc64", KEXEC_ARCH_PPC64 }, + { "ppc64le", KEXEC_ARCH_PPC64 }, { NULL, 0 }, }; |