summaryrefslogtreecommitdiff
path: root/kexec/arch/ppc64/kexec-ppc64.c
diff options
context:
space:
mode:
Diffstat (limited to 'kexec/arch/ppc64/kexec-ppc64.c')
-rw-r--r--kexec/arch/ppc64/kexec-ppc64.c135
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 },
};