230 lines
6.5 KiB
Diff
230 lines
6.5 KiB
Diff
From 1d19ca0c4306c3c684cf4d277781975e4ad1c193 Mon Sep 17 00:00:00 2001
|
|
From: Chandru <chandru@in.ibm.com>
|
|
Date: Wed, 24 Sep 2008 17:19:29 +0530
|
|
Subject: [PATCH] kexec/kdump : get details of ibm, dynamic-reconfiguration-memory node of device tree
|
|
|
|
Get number of lmb's (logical memory blocks) , size of each lmb from
|
|
ibm,dynamic-memory property , get base memory ranges from
|
|
ibm,dynamic-reconfiguration-memory node.
|
|
|
|
Signed-off-by: Chandru Siddalingappa <chandru@in.ibm.com>
|
|
Signed-off-by: Simon Horman <horms@verge.net.au>
|
|
Acked-by: Bernhard Walle <bwalle@suse.de>
|
|
|
|
---
|
|
kexec/arch/ppc64/kexec-ppc64.c | 145 ++++++++++++++++++++++++++++++++++++-----
|
|
1 file changed, 130 insertions(+), 15 deletions(-)
|
|
|
|
--- a/kexec/arch/ppc64/kexec-ppc64.c
|
|
+++ b/kexec/arch/ppc64/kexec-ppc64.c
|
|
@@ -96,6 +96,49 @@ err1:
|
|
|
|
}
|
|
|
|
+static int count_dyn_reconf_memory_ranges(void)
|
|
+{
|
|
+ char device_tree[] = "/proc/device-tree/";
|
|
+ char fname[128];
|
|
+ char buf[32];
|
|
+ FILE *file;
|
|
+
|
|
+ strcpy(fname, device_tree);
|
|
+ strcat(fname, "ibm,dynamic-reconfiguration-memory/ibm,lmb-size");
|
|
+ if ((file = fopen(fname, "r")) == NULL) {
|
|
+ perror(fname);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (fread(buf, 1, 8, file) < 0) {
|
|
+ perror(fname);
|
|
+ fclose(file);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ lmb_size = ((uint64_t *)buf)[0];
|
|
+ fclose(file);
|
|
+
|
|
+ /* Get number of lmbs from ibm,dynamic-memory */
|
|
+ strcpy(fname, device_tree);
|
|
+ strcat(fname, "ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory");
|
|
+ if ((file = fopen(fname, "r")) == NULL) {
|
|
+ perror(fname);
|
|
+ return -1;
|
|
+ }
|
|
+ /*
|
|
+ * first 4 bytes provide number of entries(lmbs)
|
|
+ */
|
|
+ if (fread(buf, 1, 4, file) < 0) {
|
|
+ perror(fname);
|
|
+ fclose(file);
|
|
+ return -1;
|
|
+ }
|
|
+ num_of_lmbs = ((unsigned int *)buf)[0];
|
|
+ max_memory_ranges += num_of_lmbs;
|
|
+ fclose(file);
|
|
+}
|
|
+
|
|
/*
|
|
* Count the memory nodes under /proc/device-tree and populate the
|
|
* max_memory_ranges variable. This variable replaces MAX_MEMORY_RANGES
|
|
@@ -113,6 +156,12 @@ static int count_memory_ranges(void)
|
|
}
|
|
|
|
while ((dentry = readdir(dir)) != NULL) {
|
|
+ if (!strncmp(dentry->d_name,
|
|
+ "ibm,dynamic-reconfiguration-memory", 35)){
|
|
+ count_dyn_reconf_memory_ranges();
|
|
+ continue;
|
|
+ }
|
|
+
|
|
if (strncmp(dentry->d_name, "memory@", 7) &&
|
|
strcmp(dentry->d_name, "memory") &&
|
|
strncmp(dentry->d_name, "pci@", 4))
|
|
@@ -128,7 +177,52 @@ static int count_memory_ranges(void)
|
|
|
|
return 0;
|
|
}
|
|
+static void add_base_memory_range(uint64_t start, uint64_t end)
|
|
+{
|
|
+ base_memory_range[nr_memory_ranges].start = start;
|
|
+ base_memory_range[nr_memory_ranges].end = end;
|
|
+ base_memory_range[nr_memory_ranges].type = RANGE_RAM;
|
|
+ nr_memory_ranges++;
|
|
+
|
|
+ dbgprintf("%016llx-%016llx : %x\n",
|
|
+ base_memory_range[nr_memory_ranges-1].start,
|
|
+ base_memory_range[nr_memory_ranges-1].end,
|
|
+ base_memory_range[nr_memory_ranges-1].type);
|
|
+}
|
|
+
|
|
+static int get_dyn_reconf_base_ranges(void)
|
|
+{
|
|
+ uint64_t start, end;
|
|
+ char fname[128], buf[32];
|
|
+ FILE *file;
|
|
+ int i, n;
|
|
+
|
|
|
|
+ strcpy(fname, "/proc/device-tree/");
|
|
+ strcat(fname,
|
|
+ "ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory");
|
|
+ if ((file = fopen(fname, "r")) == NULL) {
|
|
+ perror(fname);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ fseek(file, 4, SEEK_SET);
|
|
+ for (i = 0; i < num_of_lmbs; i++) {
|
|
+ if ((n = fread(buf, 1, 24, file)) < 0) {
|
|
+ perror(fname);
|
|
+ fclose(file);
|
|
+ return -1;
|
|
+ }
|
|
+ if (nr_memory_ranges >= max_memory_ranges)
|
|
+ return -1;
|
|
+
|
|
+ start = ((uint64_t *)buf)[0];
|
|
+ end = start + lmb_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
|
|
@@ -156,7 +250,7 @@ static int sort_base_ranges(void)
|
|
/* Get base memory ranges */
|
|
static int get_base_ranges(void)
|
|
{
|
|
- int local_memory_ranges = 0;
|
|
+ uint64_t start, end;
|
|
char device_tree[256] = "/proc/device-tree/";
|
|
char fname[256];
|
|
char buf[MAXBYTES];
|
|
@@ -170,6 +264,11 @@ static int get_base_ranges(void)
|
|
return -1;
|
|
}
|
|
while ((dentry = readdir(dir)) != NULL) {
|
|
+ if (!strncmp(dentry->d_name,
|
|
+ "ibm,dynamic-reconfiguration-memory", 35)) {
|
|
+ get_dyn_reconf_base_ranges();
|
|
+ continue;
|
|
+ }
|
|
if (strncmp(dentry->d_name, "memory@", 7) &&
|
|
strcmp(dentry->d_name, "memory"))
|
|
continue;
|
|
@@ -197,27 +296,18 @@ static int get_base_ranges(void)
|
|
closedir(dir);
|
|
return -1;
|
|
}
|
|
- if (local_memory_ranges >= max_memory_ranges) {
|
|
+ if (nr_memory_ranges >= max_memory_ranges) {
|
|
fclose(file);
|
|
break;
|
|
}
|
|
- base_memory_range[local_memory_ranges].start =
|
|
- ((uint64_t *)buf)[0];
|
|
- base_memory_range[local_memory_ranges].end =
|
|
- base_memory_range[local_memory_ranges].start +
|
|
- ((uint64_t *)buf)[1];
|
|
- base_memory_range[local_memory_ranges].type = RANGE_RAM;
|
|
- local_memory_ranges++;
|
|
- dbgprintf("%016llx-%016llx : %x\n",
|
|
- base_memory_range[local_memory_ranges-1].start,
|
|
- base_memory_range[local_memory_ranges-1].end,
|
|
- base_memory_range[local_memory_ranges-1].type);
|
|
+ start = ((uint64_t *)buf)[0];
|
|
+ end = start + ((uint64_t *)buf)[1];
|
|
+ add_base_memory_range(start, end);
|
|
fclose(file);
|
|
}
|
|
closedir(dmem);
|
|
}
|
|
closedir(dir);
|
|
- nr_memory_ranges = local_memory_ranges;
|
|
sort_base_ranges();
|
|
memory_max = base_memory_range[nr_memory_ranges - 1].end;
|
|
#ifdef DEBUG
|
|
@@ -276,7 +366,9 @@ static int get_devtree_details(unsigned
|
|
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,dynamic-reconfiguration-memory", 35))
|
|
continue;
|
|
strcpy(fname, device_tree);
|
|
strcat(fname, dentry->d_name);
|
|
@@ -474,6 +566,29 @@ static int get_devtree_details(unsigned
|
|
closedir(cdir);
|
|
} /* memory */
|
|
|
|
+ if (!strncmp(dentry->d_name,
|
|
+ "ibm,dynamic-reconfiguration-memory", 35)) {
|
|
+ unsigned int k;
|
|
+ strcat(fname, "/ibm,dynamic-memory");
|
|
+ if ((file = fopen(fname, "r")) == NULL) {
|
|
+ perror(fname);
|
|
+ goto error_opencdir;
|
|
+ }
|
|
+ fseek(file, 4, SEEK_SET);
|
|
+ for (k = 0; k < num_of_lmbs; k++) {
|
|
+ if ((n = fread(buf, 1, 24, file)) < 0) {
|
|
+ perror(fname);
|
|
+ goto error_openfile;
|
|
+ }
|
|
+ rmo_base = ((uint64_t *)buf)[0];
|
|
+ rmo_top = rmo_base + lmb_size;
|
|
+ if (rmo_top > 0x30000000UL)
|
|
+ rmo_top = 0x30000000UL;
|
|
+ }
|
|
+ fclose(file);
|
|
+ closedir(cdir);
|
|
+ } /* ibm,dynamic-reconfiguration-memory */
|
|
+
|
|
if (strncmp(dentry->d_name, "pci@", 4) == 0) {
|
|
strcat(fname, "/linux,tce-base");
|
|
if ((file = fopen(fname, "r")) == NULL) {
|