[PATCH 2/6] ppc64-kdump-prepare-device-tree
R Sharada
sharada at in.ibm.com
Tue Jan 17 02:09:57 EST 2006
This patch provides the extra functionality and features in
the flattened device-tree that is required for crashdump
functionality.
- create add_usable_mem_property in device-tree which is
used by the second kernel for booting with restricted
memory. This provides similar feature as the
memmap= option on other archs
- move initrd creation/modification code to putnode
- add code to prepare correct commandline for bootargs.
If "root=" option is not specified in user cmdline,
add it from existing bootargs
- include mem_rgns_t definition in kexec-ppc64.h. Move
initrd variables out to .c file
Signed-off-by: R Sharada <sharada at in.ibm.com>
Signed-off-by: Haren Myneni <hbabu at us.ibm.com>
---
diff -puN kexec/arch/ppc64/fs2dt.c~ppc64-kdump-prepare-device-tree kexec/arch/ppc64/fs2dt.c
--- kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c~ppc64-kdump-prepare-device-tree 2006-01-15 06:22:47.000000000 +0530
+++ kexec-tools-1.101-sharada/kexec/arch/ppc64/fs2dt.c 2006-01-15 06:49:07.000000000 +0530
@@ -28,7 +28,9 @@
#include <string.h>
#include <errno.h>
#include <stdio.h>
+#include "../../kexec.h"
#include "kexec-ppc64.h"
+#include "crashdump-ppc64.h"
#define MAXPATH 1024 /* max path name length */
#define NAMESPACE 16384 /* max bytes for property names */
@@ -62,9 +64,12 @@ char propnames[NAMESPACE];
dvt dtstruct[TREEWORDS], *dt;
unsigned long long mem_rsrv[2*MEMRESERVE];
-extern unsigned long initrd_base;
-extern unsigned long initrd_size;
static int initrd_found = 0;
+static int crash_param = 0;
+char local_cmdline[COMMAND_LINE_SIZE] = { "" };
+dvt *dt_len; /* changed len of modified cmdline in flat device-tree */
+extern mem_rgns_t usablemem_rgns;
+struct bootblock bb[1];
void reserve(unsigned long long where, unsigned long long length)
{
@@ -88,26 +93,12 @@ void checkprop(char *name, dvt *data)
err((void *)data, ERR_RESERVE);
else if (!strcmp(name, "linux,rtas-base"))
base = *data;
- else if (!strcmp(name, "linux,initrd-start")) {
- if (initrd_base)
- *(unsigned long long *) data = initrd_base;
- base = *(unsigned long long *)data;
- initrd_found = 1;
- }
else if (!strcmp(name, "linux,tce-base"))
base = *(unsigned long long *) data;
else if (!strcmp(name, "rtas-size") ||
!strcmp(name, "linux,tce-size"))
size = *data;
- else if (!strcmp(name, "linux,initrd-end")) {
- if (initrd_size) {
- *(unsigned long long *) data = initrd_base +
- initrd_size;
- size = initrd_size;
- } else
- end = *(unsigned long long *)data;
- initrd_found = 1;
- }
+
if (size && end)
err(name, ERR_RESERVE);
if (base && size) {
@@ -139,6 +130,67 @@ dvt propnum(const char *name)
return offset;
}
+void add_usable_mem_property(int fd, int len)
+{
+ char fname[MAXPATH], *bname;
+ char buf[MAXBYTES +1];
+ unsigned long ranges[2*MAX_MEMORY_RANGES];
+ unsigned long long base, end, loc_base, loc_end;
+ int range, rlen = 0;
+
+ strcpy(fname, pathname);
+ bname = strrchr(fname,'/');
+ bname[0] = '\0';
+ bname = strrchr(fname,'/');
+ if (strncmp(bname, "/memory@", 8))
+ return;
+
+ lseek(fd, 0, SEEK_SET);
+ if (read(fd, buf, len) != len)
+ err(pathname, ERR_READ);
+
+ base = ((unsigned long long *)buf)[0];
+ end = base + ((unsigned long long *)buf)[1];
+
+ for (range = 0; range < usablemem_rgns.size; range++) {
+ loc_base = usablemem_rgns.ranges[range].start;
+ loc_end = usablemem_rgns.ranges[range].end;
+ if (loc_base >= base && loc_end <= end) {
+ ranges[rlen++] = loc_base;
+ ranges[rlen++] = loc_end - loc_base;
+ } else if (base < loc_end && end > loc_base) {
+ if (loc_base < base)
+ loc_base = base;
+ if (loc_end > end)
+ loc_end = end;
+ ranges[rlen++] = loc_base;
+ ranges[rlen++] = loc_end - loc_base;
+ }
+ }
+
+ if (!rlen) {
+ /*
+ * User did not pass any ranges for thsi region. Hence, write
+ * (0,0) duple in linux,usable-memory property such that
+ * this region will be ignored.
+ */
+ ranges[rlen++] = 0;
+ ranges[rlen++] = 0;
+ }
+
+ rlen = rlen * sizeof(unsigned long);
+ /*
+ * No add linux,usable-memory property.
+ */
+ *dt++ = 3;
+ *dt++ = rlen;
+ *dt++ = propnum("linux,usable-memory");
+ if ((rlen >= 8) && ((unsigned long)dt & 0x4))
+ dt++;
+ memcpy(dt,&ranges,rlen);
+ dt += (rlen + 3)/4;
+}
+
/* put all properties (files) in the property structure */
void putprops(char *fn, DIR *dir)
{
@@ -150,11 +202,10 @@ void putprops(char *fn, DIR *dir)
if (lstat(pathname, statbuf))
err(pathname, ERR_STAT);
- /* skip initrd entries if 2nd kernel does not need them */
- if (!initrd_base && !strcmp(fn,"linux,initrd-end"))
+ if (!crash_param && !strcmp(fn,"linux,crashkernel-base"))
continue;
- if (!initrd_base && !strcmp(fn,"linux,initrd-start"))
+ if (!crash_param && !strcmp(fn,"linux,crashkernel-size"))
continue;
/*
@@ -165,12 +216,20 @@ void putprops(char *fn, DIR *dir)
!strcmp(dp->d_name, "linux,htab-base") ||
!strcmp(dp->d_name, "linux,htab-size") ||
!strcmp(dp->d_name, "linux,kernel-end"))
- continue;
+ continue;
+
+ /* This property will be created/modified later in putnode()
+ * So ignore it.
+ */
+ if (!strcmp(dp->d_name, "linux,initrd-start") ||
+ !strcmp(dp->d_name, "linux,initrd-end"))
+ continue;
if (S_ISREG(statbuf[0].st_mode)) {
int fd, len = statbuf[0].st_size;
*dt++ = 3;
+ dt_len = dt;
*dt++ = len;
*dt++ = propnum(fn);
@@ -182,11 +241,45 @@ void putprops(char *fn, DIR *dir)
err(pathname, ERR_OPEN);
if (read(fd, dt, len) != len)
err(pathname, ERR_READ);
- close(fd);
checkprop(fn, dt);
+ /* Get the cmdline from the device-tree and modify it */
+ if (!strcmp(dp->d_name, "bootargs")) {
+ int cmd_len;
+ char temp_cmdline[COMMAND_LINE_SIZE] = { "" };
+ char *param = NULL;
+ cmd_len = strlen(local_cmdline);
+ if (cmd_len != 0) {
+ param = strstr(local_cmdline,
+ "crashkernel=");
+ if (param)
+ crash_param = 1;
+ param = NULL;
+ param = strstr(local_cmdline, "root=");
+ }
+ if (!param) {
+ char *old_param;
+ memcpy(temp_cmdline, dt, len);
+ param = strstr(temp_cmdline, "root=");
+ old_param = strtok(param, " ");
+ if (cmd_len != 0)
+ strcat(local_cmdline, " ");
+ strcat(local_cmdline, old_param);
+ }
+ strcat(local_cmdline, " ");
+ cmd_len = strlen(local_cmdline);
+ cmd_len = cmd_len + 1;
+ memcpy(dt,local_cmdline,cmd_len);
+ len = cmd_len;
+ *dt_len = cmd_len;
+ fprintf(stderr, "Modified cmdline:%s\n", local_cmdline);
+ }
+
dt += (len + 3)/4;
+ if (!strcmp(dp->d_name, "reg") && usablemem_rgns.size)
+ add_usable_mem_property(fd, len);
+ close(fd);
}
}
fn[0] = '\0';
@@ -252,7 +345,7 @@ void putnode(void)
if ((len >= 8) && ((unsigned long)dt & 0x4))
dt++;
- memcpy(dt,&initrd_end,8);
+ memcpy(dt,&initrd_end,len);
dt += (len + 3)/4;
reserve(initrd_base, initrd_size);
@@ -280,9 +373,8 @@ void putnode(void)
dn[-1] = '\0';
}
-struct bootblock bb[1];
-
-int create_flatten_tree(struct kexec_info *info, unsigned char **bufp, unsigned long *sizep)
+int create_flatten_tree(struct kexec_info *info, unsigned char **bufp,
+ unsigned long *sizep, char *cmdline)
{
unsigned long len;
unsigned long tlen;
@@ -296,6 +388,9 @@ int create_flatten_tree(struct kexec_inf
pathstart = pathname + strlen(pathname);
dt = dtstruct;
+ if (cmdline)
+ strcpy(local_cmdline, cmdline);
+
putnode();
*dt++ = 9;
diff -puN /dev/null kexec/arch/ppc64/crashdump-ppc64.h
--- /dev/null 2004-07-01 07:56:11.000000000 +0530
+++ kexec-tools-1.101-sharada/kexec/arch/ppc64/crashdump-ppc64.h 2006-01-15 06:51:55.000000000 +0530
@@ -0,0 +1,27 @@
+#ifndef CRASHDUMP_PPC64_H
+#define CRASHDUMP_PPC64_H
+
+void add_usable_mem_rgns(unsigned long long base, unsigned long long size);
+
+#define PAGE_OFFSET 0xC000000000000000
+#define KERNELBASE PAGE_OFFSET
+#define VMALLOCBASE 0xD000000000000000
+
+#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 32K of System RAM. */
+#define BACKUP_START 0x0000
+#define BACKUP_END 0x8000
+#define BACKUP_SIZE (BACKUP_END - BACKUP_START + 1)
+
+#define KDUMP_BACKUP_LIMIT 0x8000
+#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
+#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1)))
+#define PAGE_SIZE 4096
+
+#endif /* CRASHDUMP_PPC64_H */
diff -puN kexec/arch/ppc64/kexec-ppc64.h~ppc64-kdump-prepare-device-tree kexec/arch/ppc64/kexec-ppc64.h
--- kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.h~ppc64-kdump-prepare-device-tree 2006-01-15 06:56:31.000000000 +0530
+++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-ppc64.h 2006-01-15 06:59:07.000000000 +0530
@@ -5,9 +5,9 @@ int elf_ppc64_probe(const char *buf, off
int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
struct kexec_info *info);
void elf_ppc64_usage(void);
+void reserve(unsigned long long where, unsigned long long length);
-unsigned long initrd_base;
-unsigned long initrd_size;
+extern unsigned long initrd_base, initrd_size;
/* boot block version 2 as defined by the linux kernel */
struct bootblock {
unsigned magic,
@@ -19,4 +19,10 @@ struct bootblock {
last_comp_version,
boot_physid;
};
+
+typedef struct mem_rgns {
+ unsigned int size;
+ struct exclude_range ranges[MAX_MEMORY_RANGES];
+} mem_rgns_t;
+
#endif /* KEXEC_PPC64_H */
diff -puN kexec/arch/ppc64/kexec-elf-ppc64.c~ppc64-kdump-prepare-device-tree kexec/arch/ppc64/kexec-elf-ppc64.c
--- kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c~ppc64-kdump-prepare-device-tree 2006-01-15 07:00:11.000000000 +0530
+++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-elf-ppc64.c 2006-01-15 07:01:08.000000000 +0530
@@ -40,6 +40,8 @@
#define BOOTLOADER_VERSION VERSION
#define MAX_COMMAND_LINE 256
+unsigned long initrd_base, initrd_size;
+
int create_flatten_tree(struct kexec_info *, unsigned char **, unsigned long *);
int parse_options(char *);
int setup_memory_ranges(void);
_
More information about the Linuxppc64-dev
mailing list