* [RFC][PATCH 0/3] Embed vmcoreinfo into kernel file
@ 2007-08-13 7:32 Ken'ichi Ohmichi
2007-08-13 7:36 ` [RFC][PATCH 1/3] " Ken'ichi Ohmichi
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: Ken'ichi Ohmichi @ 2007-08-13 7:32 UTC (permalink / raw)
To: kexec-ml; +Cc: Don Zickus, Bernhard Walle, Vivek Goyal, Neil Horman, Dan Aloni
Hi all,
# I resend this mail, because former mail had a suspicious header.
I updated Dan Aloni's patches for adding the feature that embeds
vmcoreinfo (information for dump filtering) into a kernel file.
This feature frees the restriction that makedumpfile user should
install a vmlinux file (including the debugging information).
Please test it. Your opinions/comments are welcome.
makedumpfile command is the dump filtering feature for kdump.
It creates a small dumpfile by filtering unnecessary pages
for the analysis. To distinguish unnecessary pages, it needs
a vmlinux file including the debugging information.
Now, the debugging package becomes a huge file, and it is hard
to install it into each system. Then, Dan Aloni created the patch
set to embed only necessary information into a kernel binary file,
and a vmlinux file including the debugging informaion is not
necessary.
Dan Aloni's patch:
http://lists.infradead.org/pipermail/kexec/2007-July/000303.html
Patches:
- [1/3] patch for linux-2.6.22.
Changelog:
* Rename "mkdfinfo" to "vmcoreinfo".
* Multi memory models (FLATMEM, DISCONTIGMEM, and SPASEMEM) are
supported.
* The elf note typedef for vmcoreinfo is added because the original
elf note size is limited to 1024.
* The generation of the elf note is moved to boot time instead of
crash time.
- [2/3] patch for kexec-tools-testing-20070330.
Changelog:
* Rename "mkdfinfo" to "vmcoreinfo".
- [3/3] patch for makedumpfile-v1.1.6.
Usage:
- Run the kernel applied the attached patch as the first kernel.
- Preload the second kernel by the kexec-tools applied the attached patch.
- Panic and switch to the second kernel.
- Get a dumpfile by the makedumpfile applied the attached patch:
(Ex.) # makedumpfile -cd31 /proc/vmcore dumpfile
Todo:
- ia64 support.
Translating the virtual address of "vmcoreinfo_note" to the physical address.
(kernel-vmcoreinfo-note.patch)
- ppc64 support
Thanks
Ken'ichi Ohmichi
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC][PATCH 1/3] Embed vmcoreinfo into kernel file
2007-08-13 7:32 [RFC][PATCH 0/3] Embed vmcoreinfo into kernel file Ken'ichi Ohmichi
@ 2007-08-13 7:36 ` Ken'ichi Ohmichi
2007-08-13 17:38 ` Dan Aloni
2007-08-16 4:20 ` Vivek Goyal
2007-08-13 7:38 ` [RFC][PATCH 2/3] " Ken'ichi Ohmichi
2007-08-13 7:39 ` [RFC][PATCH 3/3] " Ken'ichi Ohmichi
2 siblings, 2 replies; 14+ messages in thread
From: Ken'ichi Ohmichi @ 2007-08-13 7:36 UTC (permalink / raw)
To: kexec-ml; +Cc: Don Zickus, Bernhard Walle, Vivek Goyal, Neil Horman, Dan Aloni
Patches:
- [1/3] patch for linux-2.6.22.
Changelog:
* Rename "mkdfinfo" to "vmcoreinfo".
* Multi memory models (FLATMEM, DISCONTIGMEM, and SPASEMEM) are
supported.
* The elf note typedef for vmcoreinfo is added because the original
elf note size is limited to 1024.
* The generation of the elf note is moved to boot time instead of
crash time.
---
Signed-off-by: Dan Aloni <da-x@monatomic.org>
Signed-off-by: Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp>
---
diff -rpuN linux-2.6.22.org/arch/ia64/mm/discontig.c linux-2.6.22/arch/ia64/mm/discontig.c
--- linux-2.6.22.org/arch/ia64/mm/discontig.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/arch/ia64/mm/discontig.c 2007-08-07 00:34:50.000000000 +0900
@@ -47,7 +47,7 @@ struct early_node_data {
static struct early_node_data mem_data[MAX_NUMNODES] __initdata;
static nodemask_t memory_less_mask __initdata;
-static pg_data_t *pgdat_list[MAX_NUMNODES];
+pg_data_t *pgdat_list[MAX_NUMNODES];
/*
* To prevent cache aliasing effects, align per-node structures so that they
diff -rpuN linux-2.6.22.org/include/linux/kexec.h linux-2.6.22/include/linux/kexec.h
--- linux-2.6.22.org/include/linux/kexec.h 2007-08-04 00:22:35.000000000 +0900
+++ linux-2.6.22/include/linux/kexec.h 2007-08-07 00:34:50.000000000 +0900
@@ -121,6 +121,8 @@ extern struct page *kimage_alloc_control
extern void crash_kexec(struct pt_regs *);
int kexec_should_crash(struct task_struct *);
void crash_save_cpu(struct pt_regs *regs, int cpu);
+void crash_save_vmcoreinfo(void);
+
extern struct kimage *kexec_image;
extern struct kimage *kexec_crash_image;
@@ -148,11 +150,19 @@ extern struct kimage *kexec_crash_image;
#define KEXEC_FLAGS (KEXEC_ON_CRASH) /* List of defined/legal kexec flags */
+#define VMCOREINFO_BYTES (4096)
+#define VMCOREINFO_NOTE_NAME "VMCOREINFO"
+#define VMCOREINFO_NOTE_NAME_BYTES ALIGN(sizeof(VMCOREINFO_NOTE_NAME), 4)
+#define VMCOREINFO_NOTE_SIZE (KEXEC_NOTE_HEAD_BYTES*2 + VMCOREINFO_BYTES \
+ + VMCOREINFO_NOTE_NAME_BYTES)
+
/* Location of a reserved region to hold the crash kernel.
*/
extern struct resource crashk_res;
typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];
extern note_buf_t *crash_notes;
+extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+extern unsigned int vmcoreinfo_size;
#else /* !CONFIG_KEXEC */
diff -rpuN linux-2.6.22.org/kernel/kexec.c linux-2.6.22/kernel/kexec.c
--- linux-2.6.22.org/kernel/kexec.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/kernel/kexec.c 2007-08-07 00:35:10.000000000 +0900
@@ -22,6 +22,10 @@
#include <linux/hardirq.h>
#include <linux/elf.h>
#include <linux/elfcore.h>
+#include <linux/utsrelease.h>
+#include <linux/utsname.h>
+#include <linux/mmzone.h>
+#include <linux/numa.h>
#include <asm/page.h>
#include <asm/uaccess.h>
@@ -32,6 +36,12 @@
/* Per cpu memory for storing cpu states in case of system crash. */
note_buf_t* crash_notes;
+/* vmcoreinfo stuff */
+unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
+u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+unsigned int vmcoreinfo_size = 0;
+unsigned int vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
+
/* Location of the reserved area for the crash kernel */
struct resource crashk_res = {
.name = "Crash kernel",
@@ -1135,3 +1145,133 @@ static int __init crash_notes_memory_ini
return 0;
}
module_init(crash_notes_memory_init)
+
+void crash_save_vmcoreinfo(void)
+{
+ u32 *buf;
+
+ if (!vmcoreinfo_size)
+ return;
+
+ buf = (u32 *)vmcoreinfo_note;
+
+ buf = append_elf_note(buf, VMCOREINFO_NOTE_NAME, 0, vmcoreinfo_data,
+ vmcoreinfo_size);
+
+ final_note(buf);
+}
+
+void vmcoreinfo_append_str(const char *fmt, ...)
+{
+ va_list args;
+ char buf[0x50];
+ int r;
+
+ va_start(args, fmt);
+ r = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ if (r + vmcoreinfo_size > vmcoreinfo_max_size)
+ r = vmcoreinfo_max_size - vmcoreinfo_size;
+
+ memcpy(&vmcoreinfo_data[vmcoreinfo_size], buf, r);
+
+ vmcoreinfo_size += r;
+}
+
+#define SYMBOL(name) \
+ vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #name, (unsigned long)&name)
+#define SIZE(name) \
+ vmcoreinfo_append_str("SIZE(%s)=%d\n", #name, sizeof(struct name))
+#define OFFSET(name, field) \
+ vmcoreinfo_append_str("OFFSET(%s.%s)=%d\n", #name, #field, &(((struct name *)0)->field))
+#define LENGTH(name, value) \
+ vmcoreinfo_append_str("LENGTH(%s)=%d\n", #name, value)
+
+static int __init crash_save_vmcoreinfo_init(void)
+{
+#ifndef CONFIG_X86_32
+ extern char _stext;
+#endif
+#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+#ifdef CONFIG_IA64
+ extern pg_data_t *pgdat_list[MAX_NUMNODES];
+#endif
+#endif
+ vmcoreinfo_append_str("OSRELEASE=%s\n", UTS_RELEASE);
+ vmcoreinfo_append_str("PAGESIZE=%d\n", PAGE_SIZE);
+
+ SYMBOL(init_uts_ns);
+ SYMBOL(node_online_map);
+ SYMBOL(swapper_pg_dir);
+ SYMBOL(_stext);
+
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+ SYMBOL(mem_map);
+ SYMBOL(contig_page_data);
+#endif
+#ifdef CONFIG_SPARSEMEM
+ SYMBOL(mem_section);
+ LENGTH(mem_section, NR_SECTION_ROOTS);
+ SIZE(mem_section);
+ OFFSET(mem_section, section_mem_map);
+#endif
+
+#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+#ifdef CONFIG_IA64
+ SYMBOL(pgdat_list);
+ LENGTH(pgdat_list, MAX_NUMNODES);
+ SYMBOL(node_memblk);
+ LENGTH(node_memblk, NR_NODE_MEMBLKS);
+ SIZE(node_memblk_s);
+ OFFSET(node_memblk_s, start_paddr);
+ OFFSET(node_memblk_s, size);
+ OFFSET(node_memblk_s, nid);
+#else
+ SYMBOL(node_data);
+ LENGTH(node_data, MAX_NUMNODES);
+#endif
+#endif
+
+ SIZE(page);
+ SIZE(pglist_data);
+ SIZE(zone);
+ SIZE(free_area);
+ SIZE(list_head);
+
+ OFFSET(page, flags);
+ OFFSET(page, _count);
+ OFFSET(page, mapping);
+ OFFSET(page, lru);
+ OFFSET(pglist_data, node_zones);
+ OFFSET(pglist_data, nr_zones);
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
+ OFFSET(pglist_data, node_mem_map);
+#endif
+ OFFSET(pglist_data, node_start_pfn);
+ OFFSET(pglist_data, node_spanned_pages);
+ OFFSET(pglist_data, node_id);
+ OFFSET(zone, free_area);
+ OFFSET(zone, vm_stat);
+ OFFSET(zone, spanned_pages);
+ OFFSET(free_area, free_list);
+ OFFSET(list_head, next);
+ OFFSET(list_head, prev);
+ LENGTH(zone.free_area, MAX_ORDER);
+#ifdef CONFIG_X86_PAE
+ vmcoreinfo_append_str("CONFIG_X86_PAE=y\n");
+#endif
+
+#ifdef CONFIG_IA64
+#ifdef CONFIG_PGTABLE_3
+ vmcoreinfo_append_str("CONFIG_PGTABLE_3=y\n");
+#elif CONFIG_PGTABLE_4
+ vmcoreinfo_append_str("CONFIG_PGTABLE_4=y\n");
+#endif
+#endif
+ crash_save_vmcoreinfo();
+
+ return 0;
+}
+
+module_init(crash_save_vmcoreinfo_init)
diff -rpuN linux-2.6.22.org/kernel/ksysfs.c linux-2.6.22/kernel/ksysfs.c
--- linux-2.6.22.org/kernel/ksysfs.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/kernel/ksysfs.c 2007-08-07 00:34:50.000000000 +0900
@@ -60,6 +60,15 @@ static ssize_t kexec_crash_loaded_show(s
return sprintf(page, "%d\n", !!kexec_crash_image);
}
KERNEL_ATTR_RO(kexec_crash_loaded);
+
+static ssize_t vmcoreinfo_show(struct kset *kset, char *page)
+{
+ return sprintf(page, "%lx %x\n",
+ __pa((unsigned long)(char *)&vmcoreinfo_note),
+ vmcoreinfo_size);
+}
+KERNEL_ATTR_RO(vmcoreinfo);
+
#endif /* CONFIG_KEXEC */
decl_subsys(kernel, NULL, NULL);
@@ -73,6 +82,7 @@ static struct attribute * kernel_attrs[]
#ifdef CONFIG_KEXEC
&kexec_loaded_attr.attr,
&kexec_crash_loaded_attr.attr,
+ &vmcoreinfo_attr.attr,
#endif
NULL
};
_
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC][PATCH 2/3] Embed vmcoreinfo into kernel file
2007-08-13 7:32 [RFC][PATCH 0/3] Embed vmcoreinfo into kernel file Ken'ichi Ohmichi
2007-08-13 7:36 ` [RFC][PATCH 1/3] " Ken'ichi Ohmichi
@ 2007-08-13 7:38 ` Ken'ichi Ohmichi
2007-08-13 7:39 ` [RFC][PATCH 3/3] " Ken'ichi Ohmichi
2 siblings, 0 replies; 14+ messages in thread
From: Ken'ichi Ohmichi @ 2007-08-13 7:38 UTC (permalink / raw)
To: kexec-ml; +Cc: Don Zickus, Bernhard Walle, Vivek Goyal, Neil Horman, Dan Aloni
Patches:
- [2/3] patch for kexec-tools-testing-20070330.
Changelog:
* Rename "mkdfinfo" to "vmcoreinfo".
---
Signed-off-by: Dan Aloni <da-x@monatomic.org>
Signed-off-by: Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp>
---
diff -rpuN backup/kexec-tools-testing-20070330/kexec/crashdump-elf.c kexec-tools/kexec/crashdump-elf.c
--- backup/kexec-tools-testing-20070330/kexec/crashdump-elf.c 2007-03-30 13:34:36.000000000 +0900
+++ kexec-tools/kexec/crashdump-elf.c 2007-08-03 14:45:47.000000000 +0900
@@ -36,6 +36,8 @@ int FUNC(struct kexec_info *info,
char *bufp;
long int nr_cpus = 0;
uint64_t notes_addr, notes_len;
+ uint64_t vmcoreinfo_addr, vmcoreinfo_len;
+ int has_vmcoreinfo = 0;
int (*get_note_info)(int cpu, uint64_t *addr, uint64_t *len);
if (xen_present())
@@ -47,7 +49,11 @@ int FUNC(struct kexec_info *info,
return -1;
}
- sz = sizeof(EHDR) + nr_cpus * sizeof(PHDR) + ranges * sizeof(PHDR);
+ if (get_kernel_vmcoreinfo(&vmcoreinfo_addr, &vmcoreinfo_len) == 0) {
+ has_vmcoreinfo = 1;
+ }
+
+ sz = sizeof(EHDR) + (nr_cpus + has_vmcoreinfo) * sizeof(PHDR) + ranges * sizeof(PHDR);
/*
* Certain architectures such as x86_64 and ia64 require a separate
@@ -148,6 +154,21 @@ int FUNC(struct kexec_info *info,
dfprintf_phdr(stdout, "Elf header", phdr);
}
+ if (has_vmcoreinfo) {
+ phdr = (PHDR *) bufp;
+ bufp += sizeof(PHDR);
+ phdr->p_type = PT_NOTE;
+ phdr->p_flags = 0;
+ phdr->p_offset = phdr->p_paddr = vmcoreinfo_addr;
+ phdr->p_vaddr = 0;
+ phdr->p_filesz = phdr->p_memsz = vmcoreinfo_len;
+ /* Do we need any alignment of segments? */
+ phdr->p_align = 0;
+
+ (elf->e_phnum)++;
+ dfprintf_phdr(stdout, "vmcoreinfo header", phdr);
+ }
+
/* Setup an PT_LOAD type program header for the region where
* Kernel is mapped if info->kern_size is non-zero.
*/
diff -rpuN backup/kexec-tools-testing-20070330/kexec/crashdump.c kexec-tools/kexec/crashdump.c
--- backup/kexec-tools-testing-20070330/kexec/crashdump.c 2007-03-30 13:34:36.000000000 +0900
+++ kexec-tools/kexec/crashdump.c 2007-08-03 14:45:05.000000000 +0900
@@ -108,3 +108,35 @@ int get_crash_notes_per_cpu(int cpu, uin
return 0;
}
+
+/* Returns the physical address of start of crash notes buffer for a kernel. */
+int get_kernel_vmcoreinfo(uint64_t *addr, uint64_t *len)
+{
+ char kdump_info[PATH_MAX];
+ char line[MAX_LINE];
+ int count;
+ FILE *fp;
+ unsigned long long temp, temp2;
+
+ *addr = 0;
+ *len = 0;
+
+ sprintf(kdump_info, "/sys/kernel/vmcoreinfo");
+ fp = fopen(kdump_info, "r");
+ if (!fp) {
+ die("Could not open \"%s\": %s\n", kdump_info,
+ strerror(errno));
+ return -1;
+ }
+
+ if (!fgets(line, sizeof(line), fp))
+ die("Cannot parse %s: %s\n", kdump_info, strerror(errno));
+ count = sscanf(line, "%Lx %Lx", &temp, &temp2);
+ if (count != 2)
+ die("Cannot parse %s: %s\n", kdump_info, strerror(errno));
+
+ *addr = (uint64_t) temp;
+ *len = (uint64_t) temp2;
+
+ return 0;
+}
diff -rpuN backup/kexec-tools-testing-20070330/kexec/crashdump.h kexec-tools/kexec/crashdump.h
--- backup/kexec-tools-testing-20070330/kexec/crashdump.h 2007-03-30 13:34:36.000000000 +0900
+++ kexec-tools/kexec/crashdump.h 2007-08-03 14:45:05.000000000 +0900
@@ -2,6 +2,7 @@
#define CRASHDUMP_H
extern int get_crash_notes_per_cpu(int cpu, uint64_t *addr, uint64_t *len);
+extern int get_kernel_vmcoreinfo(uint64_t *addr, uint64_t *len);
/* Need to find a better way to determine per cpu notes section size. */
#define MAX_NOTE_BYTES 1024
_
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC][PATCH 3/3] Embed vmcoreinfo into kernel file
2007-08-13 7:32 [RFC][PATCH 0/3] Embed vmcoreinfo into kernel file Ken'ichi Ohmichi
2007-08-13 7:36 ` [RFC][PATCH 1/3] " Ken'ichi Ohmichi
2007-08-13 7:38 ` [RFC][PATCH 2/3] " Ken'ichi Ohmichi
@ 2007-08-13 7:39 ` Ken'ichi Ohmichi
2007-08-14 21:59 ` Bernhard Walle
2 siblings, 1 reply; 14+ messages in thread
From: Ken'ichi Ohmichi @ 2007-08-13 7:39 UTC (permalink / raw)
To: kexec-ml; +Cc: Don Zickus, Bernhard Walle, Vivek Goyal, Neil Horman, Dan Aloni
Patches:
- [3/3] patch for makedumpfile-v1.1.6.
---
Signed-off-by: Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp>
---
diff -puN backup/v1.1.6/ia64.c makedumpfile/ia64.c
--- backup/v1.1.6/ia64.c 2007-08-13 12:01:55.000000000 +0900
+++ makedumpfile/ia64.c 2007-08-13 12:03:00.000000000 +0900
@@ -70,6 +70,10 @@ get_machdep_info_ia64()
else
info->vmalloc_start = KERNEL_VMALLOC_BASE;
+ if ((vt.mem_flags & MEMORY_PAGETABLE_4L)
+ || (vt.mem_flags & MEMORY_PAGETABLE_3L))
+ return TRUE;
+
/*
* Check the pgtable (3 Levels or 4 Levels).
*/
diff -puN backup/v1.1.6/makedumpfile.c makedumpfile/makedumpfile.c
--- backup/v1.1.6/makedumpfile.c 2007-08-13 12:01:55.000000000 +0900
+++ makedumpfile/makedumpfile.c 2007-08-13 12:03:00.000000000 +0900
@@ -608,7 +608,7 @@ open_files_for_creating_dumpfile()
if (info->flag_read_vmcoreinfo) {
if (!open_vmcoreinfo("r"))
return FALSE;
- } else if (info->dump_level > DL_EXCLUDE_ZERO) {
+ } else if (dwarf_info.vmlinux_name) {
if (!open_kernel_file())
return FALSE;
}
@@ -2053,8 +2053,17 @@ read_vmcoreinfo_basic_info()
return FALSE;
}
}
- if (get_release && page_size)
- break;
+ if (strncmp(buf, STR_CONFIG_X86_PAE,
+ strlen(STR_CONFIG_X86_PAE)) == 0)
+ vt.mem_flags |= MEMORY_X86_PAE;
+
+ if (strncmp(buf, STR_CONFIG_PGTABLE_3,
+ strlen(STR_CONFIG_PGTABLE_3)) == 0)
+ vt.mem_flags |= MEMORY_PAGETABLE_4L;
+
+ if (strncmp(buf, STR_CONFIG_PGTABLE_4,
+ strlen(STR_CONFIG_PGTABLE_4)) == 0)
+ vt.mem_flags |= MEMORY_PAGETABLE_3L;
}
info->page_size = page_size;
info->page_shift = ffs(info->page_size) - 1;
@@ -2215,6 +2224,173 @@ read_vmcoreinfo()
return TRUE;
}
+int
+get_pt_note_info(int *flag_elf64, off_t *offset, unsigned long *size)
+{
+ Elf64_Phdr phdr64;
+ Elf32_Phdr phdr32;
+ int i, phnum, num_load, elf_format;
+
+ (*offset) = 0;
+ (*size) = 0;
+
+ elf_format = check_elf_format(info->fd_memory, info->name_memory,
+ &phnum, &num_load);
+
+ if (elf_format == ELF64)
+ (*flag_elf64) = TRUE;
+ else if (elf_format == ELF32)
+ (*flag_elf64) = FALSE;
+ else {
+ return FALSE;
+ }
+ for (i = 0; i < phnum; i++) {
+ if (flag_elf64) { /* ELF64 */
+ if (!get_elf64_phdr(info->fd_memory, info->name_memory,
+ i, &phdr64)) {
+ ERRMSG("Can't find Phdr %d.\n", i);
+ return FALSE;
+ }
+ if (phdr64.p_type != PT_NOTE)
+ continue;
+
+ (*offset) = phdr64.p_offset;
+ (*size) = phdr64.p_filesz;
+ break;
+ } else { /* ELF32 */
+ if (!get_elf32_phdr(info->fd_memory, info->name_memory,
+ i, &phdr32)) {
+ ERRMSG("Can't find Phdr %d.\n", i);
+ return FALSE;
+ }
+ if (phdr32.p_type != PT_NOTE)
+ continue;
+
+ (*offset) = phdr32.p_offset;
+ (*size) = phdr32.p_filesz;
+ break;
+ }
+ }
+ if (offset == 0 || size == 0) {
+ ERRMSG("Can't find PT_NOTE Phdr.\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int
+is_vmcoreinfo_in_vmcore(int *flag_found)
+{
+ off_t offset, off_note;
+ int flag_elf64;
+ unsigned long sz_note;
+ char buf[VMCOREINFO_NOTE_NAME_BYTES];
+ Elf64_Nhdr note64;
+ Elf32_Nhdr note32;
+
+ const off_t failed = (off_t)-1;
+
+ (*flag_found) = FALSE;
+
+ /*
+ * Get information about PT_NOTE segment.
+ */
+ if (!get_pt_note_info(&flag_elf64, &off_note, &sz_note))
+ return FALSE;
+
+ offset = off_note;
+ while (offset < off_note + sz_note) {
+ if (lseek(info->fd_memory, offset, SEEK_SET) == failed) {
+ ERRMSG("Can't seek the dump memory(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ if (flag_elf64) {
+ if (read(info->fd_memory, ¬e64, sizeof(note64))
+ != sizeof(note64)) {
+ ERRMSG("Can't read the dump memory(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ } else {
+ if (read(info->fd_memory, ¬e32, sizeof(note32))
+ != sizeof(note32)) {
+ ERRMSG("Can't read the dump memory(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ }
+ if (read(info->fd_memory, &buf, sizeof(buf)) != sizeof(buf)) {
+ ERRMSG("Can't read the dump memory(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ if (strncmp(VMCOREINFO_NOTE_NAME, buf,
+ VMCOREINFO_NOTE_NAME_BYTES)) {
+ offset += sizeof(Elf64_Nhdr)
+ + ((note64.n_namesz + 3) & ~3)
+ + ((note64.n_descsz + 3) & ~3);
+ continue;
+ }
+ if (flag_elf64) {
+ info->offset_vmcoreinfo = offset + (sizeof(note64)
+ + ((note64.n_namesz + 3) & ~3));
+ info->size_vmcoreinfo = note64.n_descsz;
+ } else {
+ info->offset_vmcoreinfo = offset + (sizeof(note64)
+ + ((note32.n_namesz + 3) & ~3));
+ info->size_vmcoreinfo = note32.n_descsz;
+ }
+ (*flag_found) = TRUE;
+ break;
+ }
+ return TRUE;
+}
+
+/*
+ * Extract vmcoreinfo from /proc/vmcore and output it to /tmp/vmcoreinfo.tmp.
+ */
+int
+copy_vmcoreinfo()
+{
+ int fd;
+ char buf[VMCOREINFO_BYTES];
+ const off_t failed = (off_t)-1;
+
+ if (!info->offset_vmcoreinfo || !info->size_vmcoreinfo)
+ return FALSE;
+
+ if ((fd = open(info->name_vmcoreinfo, O_RDWR|O_CREAT,
+ S_IRUSR|S_IWUSR)) < 0) {
+ ERRMSG("Can't open the vmcoreinfo file(%s). %s\n",
+ info->name_vmcoreinfo, strerror(errno));
+ return FALSE;
+ }
+ if (lseek(info->fd_memory, info->offset_vmcoreinfo, SEEK_SET)
+ == failed) {
+ ERRMSG("Can't seek the dump memory(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ if (read(info->fd_memory, &buf, info->size_vmcoreinfo)
+ != info->size_vmcoreinfo) {
+ ERRMSG("Can't read the dump memory(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ if (write(fd, &buf, info->size_vmcoreinfo) != info->size_vmcoreinfo) {
+ ERRMSG("Can't write the vmcoreinfo file(%s). %s\n",
+ info->name_vmcoreinfo, strerror(errno));
+ return FALSE;
+ }
+ if (close(fd) < 0) {
+ ERRMSG("Can't close the vmcoreinfo file(%s). %s\n",
+ info->name_vmcoreinfo, strerror(errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
/*
* Get the number of online nodes.
*/
@@ -2892,12 +3068,20 @@ get_mem_map()
int
initial()
{
+ int vmcoreinfo_in_vmcore = FALSE;
+
if (!get_elf_info())
return FALSE;
if (!get_phys_base())
return FALSE;
+ if (info->dump_level <= DL_EXCLUDE_ZERO) {
+ if (!get_mem_map_without_mm())
+ return FALSE;
+ else
+ return TRUE;
+ }
/*
* Get the debug information for analysis from the vmcoreinfo file
*/
@@ -2907,22 +3091,53 @@ initial()
/*
* Get the debug information for analysis from the kernel file
*/
- } else {
- if (info->dump_level <= DL_EXCLUDE_ZERO) {
- if (!get_mem_map_without_mm())
- return FALSE;
- else
- return TRUE;
- } else {
- if (!get_symbol_info())
- return FALSE;
- }
+ } else if (info->flag_vmlinux) {
+ if (!get_symbol_info())
+ return FALSE;
+
if (!get_structure_info())
return FALSE;
if (!get_srcfile_info())
return FALSE;
+ /*
+ * Get the debug information for analysis from /proc/vmcore
+ */
+ } else {
+ /*
+ * Check weather /proc/vmcore contains vmcoreinfo,
+ * and get both the offset and the size.
+ */
+ if (!is_vmcoreinfo_in_vmcore(&vmcoreinfo_in_vmcore))
+ return FALSE;
+
+ if (!vmcoreinfo_in_vmcore) {
+ MSG("%s doesn't contain vmcoreinfo.\n", info->name_memory);
+ MSG("'-x' or '-i' must be specified.\n");
+ return FALSE;
+ }
+ /*
+ * Copy vmcoreinfo to /tmp/vmcoreinfo.
+ */
+ if ((info->name_vmcoreinfo
+ = malloc(sizeof(FILENAME_VMCOREINFO))) == NULL) {
+ ERRMSG("Can't allocate memory for the filename. %s\n",
+ strerror(errno));
+ return FALSE;
+ }
+ strcpy(info->name_vmcoreinfo, FILENAME_VMCOREINFO);
+ if (!copy_vmcoreinfo())
+ return FALSE;
+ /*
+ * Read vmcoreinfo from /tmp/vmcoreinfo.
+ */
+ if (!open_vmcoreinfo("r"))
+ return FALSE;
+ if (!read_vmcoreinfo())
+ return FALSE;
+ unlink(info->name_vmcoreinfo);
}
+
if (!get_machdep_info())
return FALSE;
diff -puN backup/v1.1.6/makedumpfile.h makedumpfile/makedumpfile.h
--- backup/v1.1.6/makedumpfile.h 2007-08-13 12:01:55.000000000 +0900
+++ makedumpfile/makedumpfile.h 2007-08-13 12:03:00.000000000 +0900
@@ -70,6 +70,7 @@ enum {
*/
#define MEMORY_PAGETABLE_4L (1 << 0)
#define MEMORY_PAGETABLE_3L (1 << 1)
+#define MEMORY_X86_PAE (1 << 2)
/*
* Type of address
@@ -366,15 +367,26 @@ do { \
#define LATEST_VERSION (0x02060016) /* linux-2.6.22 */
/*
+ * vmcoreinfo in /proc/vmcore
+ */
+#define VMCOREINFO_BYTES (4096)
+#define VMCOREINFO_NOTE_NAME "VMCOREINFO"
+#define VMCOREINFO_NOTE_NAME_BYTES (sizeof(VMCOREINFO_NOTE_NAME))
+#define FILENAME_VMCOREINFO "/tmp/vmcoreinfo.tmp"
+
+/*
* field name of vmcoreinfo file
*/
-#define STR_OSRELEASE "OSRELEASE="
-#define STR_PAGESIZE "PAGESIZE="
-#define STR_SYMBOL(X) "SYMBOL("X")="
-#define STR_SIZE(X) "SIZE("X")="
-#define STR_OFFSET(X) "OFFSET("X")="
-#define STR_LENGTH(X) "LENGTH("X")="
-#define STR_SRCFILE(X) "SRCFILE("X")="
+#define STR_OSRELEASE "OSRELEASE="
+#define STR_PAGESIZE "PAGESIZE="
+#define STR_SYMBOL(X) "SYMBOL("X")="
+#define STR_SIZE(X) "SIZE("X")="
+#define STR_OFFSET(X) "OFFSET("X")="
+#define STR_LENGTH(X) "LENGTH("X")="
+#define STR_SRCFILE(X) "SRCFILE("X")="
+#define STR_CONFIG_X86_PAE "CONFIG_X86_PAE=y"
+#define STR_CONFIG_PGTABLE_4 "CONFIG_PGTABLE_4=y"
+#define STR_CONFIG_PGTABLE_3 "CONFIG_PGTABLE_3=y"
/*
* common value
@@ -664,6 +676,12 @@ struct DumpInfo {
char release[STRLEN_OSRELEASE];
/*
+ * vmcoreinfo in dump memory image info:
+ */
+ off_t offset_vmcoreinfo;
+ unsigned long size_vmcoreinfo;
+
+ /*
* for Xen extraction
*/
unsigned long xen_heap_start; /* start mfn of xen heap area */
diff -puN backup/v1.1.6/x86.c makedumpfile/x86.c
--- backup/v1.1.6/x86.c 2007-08-13 12:01:55.000000000 +0900
+++ makedumpfile/x86.c 2007-08-13 12:03:00.000000000 +0900
@@ -21,10 +21,11 @@ int
get_machdep_info_x86()
{
/* PAE */
- if ((SYMBOL(pkmap_count) != NOT_FOUND_SYMBOL)
- && (SYMBOL(pkmap_count_next) != NOT_FOUND_SYMBOL)
- && ((SYMBOL(pkmap_count_next)-SYMBOL(pkmap_count))/sizeof(int))
- == 512) {
+ if ((vt.mem_flags & MEMORY_X86_PAE)
+ || ((SYMBOL(pkmap_count) != NOT_FOUND_SYMBOL)
+ && (SYMBOL(pkmap_count_next) != NOT_FOUND_SYMBOL)
+ && ((SYMBOL(pkmap_count_next)-SYMBOL(pkmap_count))/sizeof(int))
+ == 512)) {
DEBUG_MSG("\n");
DEBUG_MSG("PAE : ON\n");
info->section_size_bits = _SECTION_SIZE_BITS_PAE;
_
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC][PATCH 1/3] Embed vmcoreinfo into kernel file
2007-08-13 7:36 ` [RFC][PATCH 1/3] " Ken'ichi Ohmichi
@ 2007-08-13 17:38 ` Dan Aloni
2007-08-14 22:00 ` Bernhard Walle
2007-08-16 4:20 ` Vivek Goyal
1 sibling, 1 reply; 14+ messages in thread
From: Dan Aloni @ 2007-08-13 17:38 UTC (permalink / raw)
To: Ken'ichi Ohmichi
Cc: Don Zickus, Bernhard Walle, Vivek Goyal, kexec-ml, Neil Horman
On Mon, Aug 13, 2007 at 04:36:53PM +0900, Ken'ichi Ohmichi wrote:
>[..]
> Patches:
> - [1/3] patch for linux-2.6.22.
> Changelog:
> * Rename "mkdfinfo" to "vmcoreinfo".
> * Multi memory models (FLATMEM, DISCONTIGMEM, and SPASEMEM) are
> supported.
> * The elf note typedef for vmcoreinfo is added because the original
> elf note size is limited to 1024.
> * The generation of the elf note is moved to boot time instead of
> crash time.
This looks very good. Just one suggestion - in order to reduce clutter
from kernel/kexec.c (as to avoid #ifdefs) perhaps it might be better
to have crash_save_vmcoreinfo_init() additionally call an arch-specific
arch_crash_save_vmcoreinfo_init() function and have that append all
the arch-specific stuff.
--
Dan Aloni
XIV LTD, http://www.xivstorage.com
da-x (at) monatomic.org, dan (at) xiv.co.il
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC][PATCH 3/3] Embed vmcoreinfo into kernel file
2007-08-13 7:39 ` [RFC][PATCH 3/3] " Ken'ichi Ohmichi
@ 2007-08-14 21:59 ` Bernhard Walle
2007-08-17 7:09 ` Ken'ichi Ohmichi
0 siblings, 1 reply; 14+ messages in thread
From: Bernhard Walle @ 2007-08-14 21:59 UTC (permalink / raw)
To: Ken'ichi Ohmichi
Cc: Don Zickus, Neil Horman, Vivek Goyal, kexec-ml, Dan Aloni
Hello,
* Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp> [2007-08-13 09:39]:
> +#define FILENAME_VMCOREINFO "/tmp/vmcoreinfo.tmp"
Wouldn't it be better to use mkstemp() here? It also makes sense to
copy the whole vmcore first and run makedumpfile after this in a full
featured system, e.g. before sending the dump file via FTP.
Then, you have the well-known security problems when using a temporary
file with a static name -- as well as two makedumpfile processes
running in parallel. While this all is not very likely, it's also not
guaranteed that this doesn't happen.
Thanks,
Bernhard
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC][PATCH 1/3] Embed vmcoreinfo into kernel file
2007-08-13 17:38 ` Dan Aloni
@ 2007-08-14 22:00 ` Bernhard Walle
0 siblings, 0 replies; 14+ messages in thread
From: Bernhard Walle @ 2007-08-14 22:00 UTC (permalink / raw)
To: Dan Aloni
Cc: Don Zickus, Ken'ichi Ohmichi, Neil Horman, Vivek Goyal,
kexec-ml
* Dan Aloni <da-x@monatomic.org> [2007-08-13 19:38]:
> On Mon, Aug 13, 2007 at 04:36:53PM +0900, Ken'ichi Ohmichi wrote:
> >[..]
> > Patches:
> > - [1/3] patch for linux-2.6.22.
> > Changelog:
> > * Rename "mkdfinfo" to "vmcoreinfo".
> > * Multi memory models (FLATMEM, DISCONTIGMEM, and SPASEMEM) are
> > supported.
> > * The elf note typedef for vmcoreinfo is added because the original
> > elf note size is limited to 1024.
> > * The generation of the elf note is moved to boot time instead of
> > crash time.
>
> This looks very good. Just one suggestion - in order to reduce clutter
> from kernel/kexec.c (as to avoid #ifdefs) perhaps it might be better
> to have crash_save_vmcoreinfo_init() additionally call an arch-specific
> arch_crash_save_vmcoreinfo_init() function and have that append all
> the arch-specific stuff.
Because the only architecture that is really different is IA64, it may
make sense here to provide a default implementation that is used on
any architecture and declared as __attribute__((weak)). Then, any
architecture (here: IA64) can override that implementation. That would
avoid code duplication.
The rest looks good from my point of view. I'd like to see that in the
mainline kernel. :)
Thanks,
Bernhard
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC][PATCH 1/3] Embed vmcoreinfo into kernel file
2007-08-13 7:36 ` [RFC][PATCH 1/3] " Ken'ichi Ohmichi
2007-08-13 17:38 ` Dan Aloni
@ 2007-08-16 4:20 ` Vivek Goyal
2007-08-17 6:43 ` Ken'ichi Ohmichi
1 sibling, 1 reply; 14+ messages in thread
From: Vivek Goyal @ 2007-08-16 4:20 UTC (permalink / raw)
To: Ken'ichi Ohmichi
Cc: Don Zickus, Bernhard Walle, kexec-ml, Neil Horman, Dan Aloni
On Mon, Aug 13, 2007 at 04:36:53PM +0900, Ken'ichi Ohmichi wrote:
>
> Patches:
> - [1/3] patch for linux-2.6.22.
> Changelog:
> * Rename "mkdfinfo" to "vmcoreinfo".
> * Multi memory models (FLATMEM, DISCONTIGMEM, and SPASEMEM) are
> supported.
> * The elf note typedef for vmcoreinfo is added because the original
> elf note size is limited to 1024.
> * The generation of the elf note is moved to boot time instead of
> crash time.
>
Hi Keni'chi,
Overall it looks good. Few thougts inline.
> +#define SIZE(name) \
> + vmcoreinfo_append_str("SIZE(%s)=%d\n", #name, sizeof(struct name))
> +#define OFFSET(name, field) \
> + vmcoreinfo_append_str("OFFSET(%s.%s)=%d\n", #name, #field, &(((struct name *)0)->field))
> +#define LENGTH(name, value) \
> + vmcoreinfo_append_str("LENGTH(%s)=%d\n", #name, value)
> +
> +static int __init crash_save_vmcoreinfo_init(void)
> +{
> +#ifndef CONFIG_X86_32
> + extern char _stext;
> +#endif
In general, there are too many #ifdef in a single function. Code looks too
cluttered. Some suggestions are inlined.
Can't we put the definition of extern _stext in a header file and then
include it here?
> +#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
> +#ifdef CONFIG_IA64
> + extern pg_data_t *pgdat_list[MAX_NUMNODES];
> +#endif
This extern declaration also should be part of some header file and that
file should be included.
> +#endif
> + vmcoreinfo_append_str("OSRELEASE=%s\n", UTS_RELEASE);
> + vmcoreinfo_append_str("PAGESIZE=%d\n", PAGE_SIZE);
> +
> + SYMBOL(init_uts_ns);
> + SYMBOL(node_online_map);
> + SYMBOL(swapper_pg_dir);
> + SYMBOL(_stext);
> +
> +#ifndef CONFIG_NEED_MULTIPLE_NODES
> + SYMBOL(mem_map);
> + SYMBOL(contig_page_data);
> +#endif
> +#ifdef CONFIG_SPARSEMEM
> + SYMBOL(mem_section);
> + LENGTH(mem_section, NR_SECTION_ROOTS);
> + SIZE(mem_section);
> + OFFSET(mem_section, section_mem_map);
> +#endif
> +
> +#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
> +#ifdef CONFIG_IA64
> + SYMBOL(pgdat_list);
> + LENGTH(pgdat_list, MAX_NUMNODES);
> + SYMBOL(node_memblk);
> + LENGTH(node_memblk, NR_NODE_MEMBLKS);
> + SIZE(node_memblk_s);
> + OFFSET(node_memblk_s, start_paddr);
> + OFFSET(node_memblk_s, size);
> + OFFSET(node_memblk_s, nid);
> +#else
> + SYMBOL(node_data);
> + LENGTH(node_data, MAX_NUMNODES);
> +#endif
There is too much IA64 specific stuff in arch independent function. I think
we can create an arch specific function also which is called from here.
Something like arch_save_vmcoreinfo(). IA64 can fill all the IA64 specific
details in that function. Rest of the kdump supporting arch will define
this function as do{}while().
> +#endif
> +
> + SIZE(page);
> + SIZE(pglist_data);
> + SIZE(zone);
> + SIZE(free_area);
> + SIZE(list_head);
> +
> + OFFSET(page, flags);
> + OFFSET(page, _count);
> + OFFSET(page, mapping);
> + OFFSET(page, lru);
> + OFFSET(pglist_data, node_zones);
> + OFFSET(pglist_data, nr_zones);
> +#ifdef CONFIG_FLAT_NODE_MEM_MAP
> + OFFSET(pglist_data, node_mem_map);
> +#endif
> + OFFSET(pglist_data, node_start_pfn);
> + OFFSET(pglist_data, node_spanned_pages);
> + OFFSET(pglist_data, node_id);
> + OFFSET(zone, free_area);
> + OFFSET(zone, vm_stat);
> + OFFSET(zone, spanned_pages);
> + OFFSET(free_area, free_list);
> + OFFSET(list_head, next);
> + OFFSET(list_head, prev);
> + LENGTH(zone.free_area, MAX_ORDER);
> +#ifdef CONFIG_X86_PAE
> + vmcoreinfo_append_str("CONFIG_X86_PAE=y\n");
> +#endif
> +
> +#ifdef CONFIG_IA64
> +#ifdef CONFIG_PGTABLE_3
> + vmcoreinfo_append_str("CONFIG_PGTABLE_3=y\n");
> +#elif CONFIG_PGTABLE_4
> + vmcoreinfo_append_str("CONFIG_PGTABLE_4=y\n");
For config variables we can possibly define another preprocessor macro.
Something like
#define CONFIG(name)
vmcoreinfo_append_str("CONFIG_#name = %c\n", if(CONFIG_#name =='y'?'y':n)
This should get rid of config option specific #ifdef.
- There is another important field which I would like to see in vmcoreinfo
and that is time of crash (lets say CRASH_TIME). This will indicate the
timestamp when did system actually crash. One can read the time in
crash_kexec(), fill in the field and then save vmcore info note.
For this, either you need to scan the vmcoreinfo note again and fill in
the time stamp. Or you need to do vmcoreinfo note saving after crash
instead of boot time.
Thanks
Vivek
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC][PATCH 1/3] Embed vmcoreinfo into kernel file
2007-08-16 4:20 ` Vivek Goyal
@ 2007-08-17 6:43 ` Ken'ichi Ohmichi
2007-08-17 9:44 ` Bernhard Walle
2007-08-17 12:28 ` Vivek Goyal
0 siblings, 2 replies; 14+ messages in thread
From: Ken'ichi Ohmichi @ 2007-08-17 6:43 UTC (permalink / raw)
To: vgoyal; +Cc: Don Zickus, Bernhard Walle, kexec-ml, Neil Horman, Dan Aloni
Hi Dan Aloni, Vivek, and Bernhard,
Thank you for good comments.
I updated the patch for applying your comments.
2007/08/16 09:50:08 +0530, Vivek Goyal <vgoyal@in.ibm.com> wrote:
>> +#define SIZE(name) \
>> + vmcoreinfo_append_str("SIZE(%s)=%d\n", #name, sizeof(struct name))
>> +#define OFFSET(name, field) \
>> + vmcoreinfo_append_str("OFFSET(%s.%s)=%d\n", #name, #field, &(((struct name *)0)->field))
>> +#define LENGTH(name, value) \
>> + vmcoreinfo_append_str("LENGTH(%s)=%d\n", #name, value)
>> +
>> +static int __init crash_save_vmcoreinfo_init(void)
>> +{
>> +#ifndef CONFIG_X86_32
>> + extern char _stext;
>> +#endif
>
>In general, there are too many #ifdef in a single function. Code looks too
>cluttered. Some suggestions are inlined.
>
>Can't we put the definition of extern _stext in a header file and then
>include it here?
All right.
There is the definition of extern _stext in asm/sections.h,
and kernel/kexec.c includes it in a new patch.
>> +#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
>> +#ifdef CONFIG_IA64
>> + extern pg_data_t *pgdat_list[MAX_NUMNODES];
>> +#endif
>
>This extern declaration also should be part of some header file and that
>file should be included.
All right, it is added at include/asm-ia64/numa.h.
>> +#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
>> +#ifdef CONFIG_IA64
>> + SYMBOL(pgdat_list);
>> + LENGTH(pgdat_list, MAX_NUMNODES);
>> + SYMBOL(node_memblk);
>> + LENGTH(node_memblk, NR_NODE_MEMBLKS);
>> + SIZE(node_memblk_s);
>> + OFFSET(node_memblk_s, start_paddr);
>> + OFFSET(node_memblk_s, size);
>> + OFFSET(node_memblk_s, nid);
>> +#else
>> + SYMBOL(node_data);
>> + LENGTH(node_data, MAX_NUMNODES);
>> +#endif
>
>There is too much IA64 specific stuff in arch independent function. I think
>we can create an arch specific function also which is called from here.
>Something like arch_save_vmcoreinfo(). IA64 can fill all the IA64 specific
>details in that function. Rest of the kdump supporting arch will define
>this function as do{}while().
Good idea. Each arch_crash_save_vmcoreinfo() is added to machine_kexec.c
of each architecture.
>- There is another important field which I would like to see in vmcoreinfo
> and that is time of crash (lets say CRASH_TIME). This will indicate the
> timestamp when did system actually crash. One can read the time in
> crash_kexec(), fill in the field and then save vmcore info note.
>
> For this, either you need to scan the vmcoreinfo note again and fill in
> the time stamp. Or you need to do vmcoreinfo note saving after crash
> instead of boot time.
Is it necessary of the field for timestamp ?
The crash utility can display the time of crash already like the following.
# crash vmlinux vmcore
[snip]
KERNEL: vmlinux
DUMPFILE: vmcore
CPUS: 2
DATE: Tue Jul 10 20:41:50 2007 <- Here
UPTIME: 00:04:58
LOAD AVERAGE: 0.12, 0.22, 0.11
TASKS: 88
NODENAME: peak
RELEASE: 2.6.16.46-0.12-default
VERSION: #1 SMP Thu May 17 14:00:09 UTC 2007
MACHINE: ia64 (1000 Mhz)
MEMORY: 5.5 GB
PANIC: "SysRq : Trigger a crashdump"
PID: 3455
COMMAND: "bash"
TASK: e0000040f2f40000 [THREAD_INFO: e0000040f2f410d0]
CPU: 0
STATE: TASK_RUNNING (SYSRQ)
Thanks
Ken'ichi Ohmichi
---
Signed-off-by: Dan Aloni <da-x@monatomic.org>
Signed-off-by: Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp>
diff -rpuN linux-2.6.22.org/arch/arm/kernel/machine_kexec.c linux-2.6.22/arch/arm/kernel/machine_kexec.c
--- linux-2.6.22.org/arch/arm/kernel/machine_kexec.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/arch/arm/kernel/machine_kexec.c 2007-08-17 22:11:10.000000000 +0900
@@ -76,3 +76,8 @@ void machine_kexec(struct kimage *image)
setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
cpu_reset(reboot_code_buffer_phys);
}
+
+void arch_crash_save_vmcoreinfo(void)
+{
+}
+
diff -rpuN linux-2.6.22.org/arch/i386/kernel/machine_kexec.c linux-2.6.22/arch/i386/kernel/machine_kexec.c
--- linux-2.6.22.org/arch/i386/kernel/machine_kexec.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/arch/i386/kernel/machine_kexec.c 2007-08-17 22:11:10.000000000 +0900
@@ -10,6 +10,7 @@
#include <linux/kexec.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/numa.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
@@ -169,3 +170,15 @@ static int __init parse_crashkernel(char
return 0;
}
early_param("crashkernel", parse_crashkernel);
+
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+ SYMBOL(node_data);
+ LENGTH(node_data, MAX_NUMNODES);
+#endif
+#ifdef CONFIG_X86_PAE
+ CONFIG(X86_PAE);
+#endif
+}
+
diff -rpuN linux-2.6.22.org/arch/ia64/kernel/machine_kexec.c linux-2.6.22/arch/ia64/kernel/machine_kexec.c
--- linux-2.6.22.org/arch/ia64/kernel/machine_kexec.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/arch/ia64/kernel/machine_kexec.c 2007-08-17 22:11:10.000000000 +0900
@@ -15,10 +15,12 @@
#include <linux/cpu.h>
#include <linux/irq.h>
#include <linux/efi.h>
+#include <linux/numa.h>
#include <asm/mmu_context.h>
#include <asm/setup.h>
#include <asm/delay.h>
#include <asm/meminit.h>
+#include <asm/mmzone.h>
typedef NORET_TYPE void (*relocate_new_kernel_t)(
unsigned long indirection_page,
@@ -125,3 +127,23 @@ void machine_kexec(struct kimage *image)
unw_init_running(ia64_machine_kexec, image);
for(;;);
}
+
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+ SYMBOL(pgdat_list);
+ LENGTH(pgdat_list, MAX_NUMNODES);
+
+ SYMBOL(node_memblk);
+ LENGTH(node_memblk, NR_NODE_MEMBLKS);
+ SIZE(node_memblk_s);
+ OFFSET(node_memblk_s, start_paddr);
+ OFFSET(node_memblk_s, size);
+#endif
+#ifdef CONFIG_PGTABLE_3
+ CONFIG(PGTABLE_3);
+#elif CONFIG_PGTABLE_4
+ CONFIG(PGTABLE_4);
+#endif
+}
+
diff -rpuN linux-2.6.22.org/arch/ia64/mm/discontig.c linux-2.6.22/arch/ia64/mm/discontig.c
--- linux-2.6.22.org/arch/ia64/mm/discontig.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/arch/ia64/mm/discontig.c 2007-08-17 22:11:10.000000000 +0900
@@ -47,7 +47,7 @@ struct early_node_data {
static struct early_node_data mem_data[MAX_NUMNODES] __initdata;
static nodemask_t memory_less_mask __initdata;
-static pg_data_t *pgdat_list[MAX_NUMNODES];
+pg_data_t *pgdat_list[MAX_NUMNODES];
/*
* To prevent cache aliasing effects, align per-node structures so that they
diff -rpuN linux-2.6.22.org/arch/mips/kernel/machine_kexec.c linux-2.6.22/arch/mips/kernel/machine_kexec.c
--- linux-2.6.22.org/arch/mips/kernel/machine_kexec.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/arch/mips/kernel/machine_kexec.c 2007-08-17 22:11:10.000000000 +0900
@@ -83,3 +83,8 @@ machine_kexec(struct kimage *image)
flush_cache_all();
((void (*)(void))reboot_code_buffer)();
}
+
+void arch_crash_save_vmcoreinfo(void)
+{
+}
+
diff -rpuN linux-2.6.22.org/arch/powerpc/kernel/machine_kexec.c linux-2.6.22/arch/powerpc/kernel/machine_kexec.c
--- linux-2.6.22.org/arch/powerpc/kernel/machine_kexec.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/arch/powerpc/kernel/machine_kexec.c 2007-08-17 22:11:10.000000000 +0900
@@ -115,3 +115,8 @@ int overlaps_crashkernel(unsigned long s
{
return (start + size) > crashk_res.start && start <= crashk_res.end;
}
+
+void arch_crash_save_vmcoreinfo(void)
+{
+}
+
diff -rpuN linux-2.6.22.org/arch/ppc/kernel/machine_kexec.c linux-2.6.22/arch/ppc/kernel/machine_kexec.c
--- linux-2.6.22.org/arch/ppc/kernel/machine_kexec.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/arch/ppc/kernel/machine_kexec.c 2007-08-17 22:11:10.000000000 +0900
@@ -116,3 +116,7 @@ void machine_kexec_simple(struct kimage
(*rnk)(page_list, reboot_code_buffer_phys, image->start);
}
+void arch_crash_save_vmcoreinfo(void)
+{
+}
+
diff -rpuN linux-2.6.22.org/arch/s390/kernel/machine_kexec.c linux-2.6.22/arch/s390/kernel/machine_kexec.c
--- linux-2.6.22.org/arch/s390/kernel/machine_kexec.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/arch/s390/kernel/machine_kexec.c 2007-08-17 22:11:10.000000000 +0900
@@ -69,3 +69,8 @@ void machine_kexec(struct kimage *image)
(*data_mover)(&image->head, image->start);
for (;;);
}
+
+void arch_crash_save_vmcoreinfo(void)
+{
+}
+
diff -rpuN linux-2.6.22.org/arch/x86_64/kernel/machine_kexec.c linux-2.6.22/arch/x86_64/kernel/machine_kexec.c
--- linux-2.6.22.org/arch/x86_64/kernel/machine_kexec.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/arch/x86_64/kernel/machine_kexec.c 2007-08-17 22:11:10.000000000 +0900
@@ -10,6 +10,7 @@
#include <linux/kexec.h>
#include <linux/string.h>
#include <linux/reboot.h>
+#include <linux/numa.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
@@ -257,3 +258,11 @@ static int __init setup_crashkernel(char
}
early_param("crashkernel", setup_crashkernel);
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+ SYMBOL(node_data);
+ LENGTH(node_data, MAX_NUMNODES);
+#endif
+}
+
diff -rpuN linux-2.6.22.org/include/asm-ia64/numa.h linux-2.6.22/include/asm-ia64/numa.h
--- linux-2.6.22.org/include/asm-ia64/numa.h 2007-08-04 00:22:35.000000000 +0900
+++ linux-2.6.22/include/asm-ia64/numa.h 2007-08-17 22:11:10.000000000 +0900
@@ -24,6 +24,7 @@
extern u16 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
extern cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
+extern pg_data_t *pgdat_list[MAX_NUMNODES];
/* Stuff below this line could be architecture independent */
diff -rpuN linux-2.6.22.org/include/linux/kexec.h linux-2.6.22/include/linux/kexec.h
--- linux-2.6.22.org/include/linux/kexec.h 2007-08-04 00:22:35.000000000 +0900
+++ linux-2.6.22/include/linux/kexec.h 2007-08-17 22:11:10.000000000 +0900
@@ -121,6 +121,21 @@ extern struct page *kimage_alloc_control
extern void crash_kexec(struct pt_regs *);
int kexec_should_crash(struct task_struct *);
void crash_save_cpu(struct pt_regs *regs, int cpu);
+void crash_save_vmcoreinfo(void);
+void arch_crash_save_vmcoreinfo(void);
+void vmcoreinfo_append_str(const char *fmt, ...);
+
+#define SYMBOL(name) \
+ vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #name, (unsigned long)&name)
+#define SIZE(name) \
+ vmcoreinfo_append_str("SIZE(%s)=%d\n", #name, sizeof(struct name))
+#define OFFSET(name, field) \
+ vmcoreinfo_append_str("OFFSET(%s.%s)=%d\n", #name, #field, &(((struct name *)0)->field))
+#define LENGTH(name, value) \
+ vmcoreinfo_append_str("LENGTH(%s)=%d\n", #name, value)
+#define CONFIG(name) \
+ vmcoreinfo_append_str("CONFIG_%s=%c\n", #name, CONFIG_##name)
+
extern struct kimage *kexec_image;
extern struct kimage *kexec_crash_image;
@@ -148,11 +163,19 @@ extern struct kimage *kexec_crash_image;
#define KEXEC_FLAGS (KEXEC_ON_CRASH) /* List of defined/legal kexec flags */
+#define VMCOREINFO_BYTES (4096)
+#define VMCOREINFO_NOTE_NAME "VMCOREINFO"
+#define VMCOREINFO_NOTE_NAME_BYTES ALIGN(sizeof(VMCOREINFO_NOTE_NAME), 4)
+#define VMCOREINFO_NOTE_SIZE (KEXEC_NOTE_HEAD_BYTES*2 + VMCOREINFO_BYTES \
+ + VMCOREINFO_NOTE_NAME_BYTES)
+
/* Location of a reserved region to hold the crash kernel.
*/
extern struct resource crashk_res;
typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];
extern note_buf_t *crash_notes;
+extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+extern unsigned int vmcoreinfo_size;
#else /* !CONFIG_KEXEC */
diff -rpuN linux-2.6.22.org/kernel/kexec.c linux-2.6.22/kernel/kexec.c
--- linux-2.6.22.org/kernel/kexec.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/kernel/kexec.c 2007-08-17 22:11:10.000000000 +0900
@@ -22,16 +22,26 @@
#include <linux/hardirq.h>
#include <linux/elf.h>
#include <linux/elfcore.h>
+#include <linux/utsrelease.h>
+#include <linux/utsname.h>
+#include <linux/numa.h>
#include <asm/page.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/semaphore.h>
+#include <asm/sections.h>
/* Per cpu memory for storing cpu states in case of system crash. */
note_buf_t* crash_notes;
+/* vmcoreinfo stuff */
+unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
+u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+unsigned int vmcoreinfo_size = 0;
+unsigned int vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
+
/* Location of the reserved area for the crash kernel */
struct resource crashk_res = {
.name = "Crash kernel",
@@ -1135,3 +1145,89 @@ static int __init crash_notes_memory_ini
return 0;
}
module_init(crash_notes_memory_init)
+
+void crash_save_vmcoreinfo(void)
+{
+ u32 *buf;
+
+ if (!vmcoreinfo_size)
+ return;
+
+ buf = (u32 *)vmcoreinfo_note;
+
+ buf = append_elf_note(buf, VMCOREINFO_NOTE_NAME, 0, vmcoreinfo_data,
+ vmcoreinfo_size);
+
+ final_note(buf);
+}
+
+void vmcoreinfo_append_str(const char *fmt, ...)
+{
+ va_list args;
+ char buf[0x50];
+ int r;
+
+ va_start(args, fmt);
+ r = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ if (r + vmcoreinfo_size > vmcoreinfo_max_size)
+ r = vmcoreinfo_max_size - vmcoreinfo_size;
+
+ memcpy(&vmcoreinfo_data[vmcoreinfo_size], buf, r);
+
+ vmcoreinfo_size += r;
+}
+
+static int __init crash_save_vmcoreinfo_init(void)
+{
+ vmcoreinfo_append_str("OSRELEASE=%s\n", UTS_RELEASE);
+ vmcoreinfo_append_str("PAGESIZE=%d\n", PAGE_SIZE);
+
+ SYMBOL(init_uts_ns);
+ SYMBOL(node_online_map);
+ SYMBOL(swapper_pg_dir);
+ SYMBOL(_stext);
+
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+ SYMBOL(mem_map);
+ SYMBOL(contig_page_data);
+#endif
+#ifdef CONFIG_SPARSEMEM
+ SYMBOL(mem_section);
+ LENGTH(mem_section, NR_SECTION_ROOTS);
+ SIZE(mem_section);
+ OFFSET(mem_section, section_mem_map);
+#endif
+ SIZE(page);
+ SIZE(pglist_data);
+ SIZE(zone);
+ SIZE(free_area);
+ SIZE(list_head);
+ OFFSET(page, flags);
+ OFFSET(page, _count);
+ OFFSET(page, mapping);
+ OFFSET(page, lru);
+ OFFSET(pglist_data, node_zones);
+ OFFSET(pglist_data, nr_zones);
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
+ OFFSET(pglist_data, node_mem_map);
+#endif
+ OFFSET(pglist_data, node_start_pfn);
+ OFFSET(pglist_data, node_spanned_pages);
+ OFFSET(pglist_data, node_id);
+ OFFSET(zone, free_area);
+ OFFSET(zone, vm_stat);
+ OFFSET(zone, spanned_pages);
+ OFFSET(free_area, free_list);
+ OFFSET(list_head, next);
+ OFFSET(list_head, prev);
+ LENGTH(zone.free_area, MAX_ORDER);
+
+ arch_crash_save_vmcoreinfo();
+ crash_save_vmcoreinfo();
+
+ return 0;
+}
+
+module_init(crash_save_vmcoreinfo_init)
diff -rpuN linux-2.6.22.org/kernel/ksysfs.c linux-2.6.22/kernel/ksysfs.c
--- linux-2.6.22.org/kernel/ksysfs.c 2007-08-04 00:22:33.000000000 +0900
+++ linux-2.6.22/kernel/ksysfs.c 2007-08-17 22:11:22.000000000 +0900
@@ -60,6 +60,15 @@ static ssize_t kexec_crash_loaded_show(s
return sprintf(page, "%d\n", !!kexec_crash_image);
}
KERNEL_ATTR_RO(kexec_crash_loaded);
+
+static ssize_t vmcoreinfo_show(struct kset *kset, char *page)
+{
+ return sprintf(page, "%lx %x\n",
+ __pa((unsigned long)(char *)&vmcoreinfo_note),
+ vmcoreinfo_size);
+}
+KERNEL_ATTR_RO(vmcoreinfo);
+
#endif /* CONFIG_KEXEC */
decl_subsys(kernel, NULL, NULL);
@@ -73,6 +82,7 @@ static struct attribute * kernel_attrs[]
#ifdef CONFIG_KEXEC
&kexec_loaded_attr.attr,
&kexec_crash_loaded_attr.attr,
+ &vmcoreinfo_attr.attr,
#endif
NULL
};
_
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC][PATCH 3/3] Embed vmcoreinfo into kernel file
2007-08-14 21:59 ` Bernhard Walle
@ 2007-08-17 7:09 ` Ken'ichi Ohmichi
0 siblings, 0 replies; 14+ messages in thread
From: Ken'ichi Ohmichi @ 2007-08-17 7:09 UTC (permalink / raw)
To: Bernhard Walle; +Cc: Don Zickus, Neil Horman, Vivek Goyal, kexec-ml, Dan Aloni
Hi Bernhard,
Thank you for the review and a good comment.
2007/08/14 23:59:22 +0200, Bernhard Walle <bwalle@suse.de> wrote:
>Hello,
>
>* Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp> [2007-08-13 09:39]:
>> +#define FILENAME_VMCOREINFO "/tmp/vmcoreinfo.tmp"
>
>Wouldn't it be better to use mkstemp() here? It also makes sense to
>copy the whole vmcore first and run makedumpfile after this in a full
>featured system, e.g. before sending the dump file via FTP.
>
>Then, you have the well-known security problems when using a temporary
>file with a static name -- as well as two makedumpfile processes
>running in parallel. While this all is not very likely, it's also not
>guaranteed that this doesn't happen.
Good idea.
I updated the patch with your comment.
Thanks
Ken'ichi Ohmichi
---
Signed-off-by: Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp>
diff -puN backup/v1.1.6/ia64.c makedumpfile/ia64.c
--- backup/v1.1.6/ia64.c 2007-08-13 12:01:55.000000000 +0900
+++ makedumpfile/ia64.c 2007-08-17 14:23:32.000000000 +0900
@@ -70,6 +70,10 @@ get_machdep_info_ia64()
else
info->vmalloc_start = KERNEL_VMALLOC_BASE;
+ if ((vt.mem_flags & MEMORY_PAGETABLE_4L)
+ || (vt.mem_flags & MEMORY_PAGETABLE_3L))
+ return TRUE;
+
/*
* Check the pgtable (3 Levels or 4 Levels).
*/
diff -puN backup/v1.1.6/makedumpfile.c makedumpfile/makedumpfile.c
--- backup/v1.1.6/makedumpfile.c 2007-08-13 12:01:55.000000000 +0900
+++ makedumpfile/makedumpfile.c 2007-08-17 14:26:20.000000000 +0900
@@ -608,7 +608,7 @@ open_files_for_creating_dumpfile()
if (info->flag_read_vmcoreinfo) {
if (!open_vmcoreinfo("r"))
return FALSE;
- } else if (info->dump_level > DL_EXCLUDE_ZERO) {
+ } else if (dwarf_info.vmlinux_name) {
if (!open_kernel_file())
return FALSE;
}
@@ -2053,8 +2053,17 @@ read_vmcoreinfo_basic_info()
return FALSE;
}
}
- if (get_release && page_size)
- break;
+ if (strncmp(buf, STR_CONFIG_X86_PAE,
+ strlen(STR_CONFIG_X86_PAE)) == 0)
+ vt.mem_flags |= MEMORY_X86_PAE;
+
+ if (strncmp(buf, STR_CONFIG_PGTABLE_3,
+ strlen(STR_CONFIG_PGTABLE_3)) == 0)
+ vt.mem_flags |= MEMORY_PAGETABLE_4L;
+
+ if (strncmp(buf, STR_CONFIG_PGTABLE_4,
+ strlen(STR_CONFIG_PGTABLE_4)) == 0)
+ vt.mem_flags |= MEMORY_PAGETABLE_3L;
}
info->page_size = page_size;
info->page_shift = ffs(info->page_size) - 1;
@@ -2215,6 +2224,172 @@ read_vmcoreinfo()
return TRUE;
}
+int
+get_pt_note_info(int *flag_elf64, off_t *offset, unsigned long *size)
+{
+ Elf64_Phdr phdr64;
+ Elf32_Phdr phdr32;
+ int i, phnum, num_load, elf_format;
+
+ (*offset) = 0;
+ (*size) = 0;
+
+ elf_format = check_elf_format(info->fd_memory, info->name_memory,
+ &phnum, &num_load);
+
+ if (elf_format == ELF64)
+ (*flag_elf64) = TRUE;
+ else if (elf_format == ELF32)
+ (*flag_elf64) = FALSE;
+ else {
+ return FALSE;
+ }
+ for (i = 0; i < phnum; i++) {
+ if (flag_elf64) { /* ELF64 */
+ if (!get_elf64_phdr(info->fd_memory, info->name_memory,
+ i, &phdr64)) {
+ ERRMSG("Can't find Phdr %d.\n", i);
+ return FALSE;
+ }
+ if (phdr64.p_type != PT_NOTE)
+ continue;
+
+ (*offset) = phdr64.p_offset;
+ (*size) = phdr64.p_filesz;
+ break;
+ } else { /* ELF32 */
+ if (!get_elf32_phdr(info->fd_memory, info->name_memory,
+ i, &phdr32)) {
+ ERRMSG("Can't find Phdr %d.\n", i);
+ return FALSE;
+ }
+ if (phdr32.p_type != PT_NOTE)
+ continue;
+
+ (*offset) = phdr32.p_offset;
+ (*size) = phdr32.p_filesz;
+ break;
+ }
+ }
+ if (offset == 0 || size == 0) {
+ ERRMSG("Can't find PT_NOTE Phdr.\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int
+is_vmcoreinfo_in_vmcore(int *flag_found)
+{
+ off_t offset, off_note;
+ int flag_elf64;
+ unsigned long sz_note;
+ char buf[VMCOREINFO_NOTE_NAME_BYTES];
+ Elf64_Nhdr note64;
+ Elf32_Nhdr note32;
+
+ const off_t failed = (off_t)-1;
+
+ (*flag_found) = FALSE;
+
+ /*
+ * Get information about PT_NOTE segment.
+ */
+ if (!get_pt_note_info(&flag_elf64, &off_note, &sz_note))
+ return FALSE;
+
+ offset = off_note;
+ while (offset < off_note + sz_note) {
+ if (lseek(info->fd_memory, offset, SEEK_SET) == failed) {
+ ERRMSG("Can't seek the dump memory(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ if (flag_elf64) {
+ if (read(info->fd_memory, ¬e64, sizeof(note64))
+ != sizeof(note64)) {
+ ERRMSG("Can't read the dump memory(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ } else {
+ if (read(info->fd_memory, ¬e32, sizeof(note32))
+ != sizeof(note32)) {
+ ERRMSG("Can't read the dump memory(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ }
+ if (read(info->fd_memory, &buf, sizeof(buf)) != sizeof(buf)) {
+ ERRMSG("Can't read the dump memory(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ if (strncmp(VMCOREINFO_NOTE_NAME, buf,
+ VMCOREINFO_NOTE_NAME_BYTES)) {
+ offset += sizeof(Elf64_Nhdr)
+ + ((note64.n_namesz + 3) & ~3)
+ + ((note64.n_descsz + 3) & ~3);
+ continue;
+ }
+ if (flag_elf64) {
+ info->offset_vmcoreinfo = offset + (sizeof(note64)
+ + ((note64.n_namesz + 3) & ~3));
+ info->size_vmcoreinfo = note64.n_descsz;
+ } else {
+ info->offset_vmcoreinfo = offset + (sizeof(note64)
+ + ((note32.n_namesz + 3) & ~3));
+ info->size_vmcoreinfo = note32.n_descsz;
+ }
+ (*flag_found) = TRUE;
+ break;
+ }
+ return TRUE;
+}
+
+/*
+ * Extract vmcoreinfo from /proc/vmcore and output it to /tmp/vmcoreinfo.tmp.
+ */
+int
+copy_vmcoreinfo()
+{
+ int fd;
+ char buf[VMCOREINFO_BYTES];
+ const off_t failed = (off_t)-1;
+
+ if (!info->offset_vmcoreinfo || !info->size_vmcoreinfo)
+ return FALSE;
+
+ if ((fd = mkstemp(info->name_vmcoreinfo)) < 0) {
+ ERRMSG("Can't open the vmcoreinfo file(%s). %s\n",
+ info->name_vmcoreinfo, strerror(errno));
+ return FALSE;
+ }
+ if (lseek(info->fd_memory, info->offset_vmcoreinfo, SEEK_SET)
+ == failed) {
+ ERRMSG("Can't seek the dump memory(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ if (read(info->fd_memory, &buf, info->size_vmcoreinfo)
+ != info->size_vmcoreinfo) {
+ ERRMSG("Can't read the dump memory(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ if (write(fd, &buf, info->size_vmcoreinfo) != info->size_vmcoreinfo) {
+ ERRMSG("Can't write the vmcoreinfo file(%s). %s\n",
+ info->name_vmcoreinfo, strerror(errno));
+ return FALSE;
+ }
+ if (close(fd) < 0) {
+ ERRMSG("Can't close the vmcoreinfo file(%s). %s\n",
+ info->name_vmcoreinfo, strerror(errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
/*
* Get the number of online nodes.
*/
@@ -2892,12 +3067,20 @@ get_mem_map()
int
initial()
{
+ int vmcoreinfo_in_vmcore = FALSE;
+
if (!get_elf_info())
return FALSE;
if (!get_phys_base())
return FALSE;
+ if (info->dump_level <= DL_EXCLUDE_ZERO) {
+ if (!get_mem_map_without_mm())
+ return FALSE;
+ else
+ return TRUE;
+ }
/*
* Get the debug information for analysis from the vmcoreinfo file
*/
@@ -2907,22 +3090,53 @@ initial()
/*
* Get the debug information for analysis from the kernel file
*/
- } else {
- if (info->dump_level <= DL_EXCLUDE_ZERO) {
- if (!get_mem_map_without_mm())
- return FALSE;
- else
- return TRUE;
- } else {
- if (!get_symbol_info())
- return FALSE;
- }
+ } else if (info->flag_vmlinux) {
+ if (!get_symbol_info())
+ return FALSE;
+
if (!get_structure_info())
return FALSE;
if (!get_srcfile_info())
return FALSE;
+ /*
+ * Get the debug information for analysis from /proc/vmcore
+ */
+ } else {
+ /*
+ * Check weather /proc/vmcore contains vmcoreinfo,
+ * and get both the offset and the size.
+ */
+ if (!is_vmcoreinfo_in_vmcore(&vmcoreinfo_in_vmcore))
+ return FALSE;
+
+ if (!vmcoreinfo_in_vmcore) {
+ MSG("%s doesn't contain vmcoreinfo.\n", info->name_memory);
+ MSG("'-x' or '-i' must be specified.\n");
+ return FALSE;
+ }
+ /*
+ * Copy vmcoreinfo to /tmp/vmcoreinfoXXXXXX.
+ */
+ if ((info->name_vmcoreinfo
+ = malloc(sizeof(FILENAME_VMCOREINFO))) == NULL) {
+ ERRMSG("Can't allocate memory for the filename. %s\n",
+ strerror(errno));
+ return FALSE;
+ }
+ strcpy(info->name_vmcoreinfo, FILENAME_VMCOREINFO);
+ if (!copy_vmcoreinfo())
+ return FALSE;
+ /*
+ * Read vmcoreinfo from /tmp/vmcoreinfoXXXXXX.
+ */
+ if (!open_vmcoreinfo("r"))
+ return FALSE;
+ if (!read_vmcoreinfo())
+ return FALSE;
+ unlink(info->name_vmcoreinfo);
}
+
if (!get_machdep_info())
return FALSE;
diff -puN backup/v1.1.6/makedumpfile.h makedumpfile/makedumpfile.h
--- backup/v1.1.6/makedumpfile.h 2007-08-13 12:01:55.000000000 +0900
+++ makedumpfile/makedumpfile.h 2007-08-17 14:24:57.000000000 +0900
@@ -70,6 +70,7 @@ enum {
*/
#define MEMORY_PAGETABLE_4L (1 << 0)
#define MEMORY_PAGETABLE_3L (1 << 1)
+#define MEMORY_X86_PAE (1 << 2)
/*
* Type of address
@@ -366,15 +367,26 @@ do { \
#define LATEST_VERSION (0x02060016) /* linux-2.6.22 */
/*
+ * vmcoreinfo in /proc/vmcore
+ */
+#define VMCOREINFO_BYTES (4096)
+#define VMCOREINFO_NOTE_NAME "VMCOREINFO"
+#define VMCOREINFO_NOTE_NAME_BYTES (sizeof(VMCOREINFO_NOTE_NAME))
+#define FILENAME_VMCOREINFO "/tmp/vmcoreinfoXXXXXX"
+
+/*
* field name of vmcoreinfo file
*/
-#define STR_OSRELEASE "OSRELEASE="
-#define STR_PAGESIZE "PAGESIZE="
-#define STR_SYMBOL(X) "SYMBOL("X")="
-#define STR_SIZE(X) "SIZE("X")="
-#define STR_OFFSET(X) "OFFSET("X")="
-#define STR_LENGTH(X) "LENGTH("X")="
-#define STR_SRCFILE(X) "SRCFILE("X")="
+#define STR_OSRELEASE "OSRELEASE="
+#define STR_PAGESIZE "PAGESIZE="
+#define STR_SYMBOL(X) "SYMBOL("X")="
+#define STR_SIZE(X) "SIZE("X")="
+#define STR_OFFSET(X) "OFFSET("X")="
+#define STR_LENGTH(X) "LENGTH("X")="
+#define STR_SRCFILE(X) "SRCFILE("X")="
+#define STR_CONFIG_X86_PAE "CONFIG_X86_PAE=y"
+#define STR_CONFIG_PGTABLE_4 "CONFIG_PGTABLE_4=y"
+#define STR_CONFIG_PGTABLE_3 "CONFIG_PGTABLE_3=y"
/*
* common value
@@ -664,6 +676,12 @@ struct DumpInfo {
char release[STRLEN_OSRELEASE];
/*
+ * vmcoreinfo in dump memory image info:
+ */
+ off_t offset_vmcoreinfo;
+ unsigned long size_vmcoreinfo;
+
+ /*
* for Xen extraction
*/
unsigned long xen_heap_start; /* start mfn of xen heap area */
diff -puN backup/v1.1.6/x86.c makedumpfile/x86.c
--- backup/v1.1.6/x86.c 2007-08-13 12:01:55.000000000 +0900
+++ makedumpfile/x86.c 2007-08-17 14:23:32.000000000 +0900
@@ -21,10 +21,11 @@ int
get_machdep_info_x86()
{
/* PAE */
- if ((SYMBOL(pkmap_count) != NOT_FOUND_SYMBOL)
- && (SYMBOL(pkmap_count_next) != NOT_FOUND_SYMBOL)
- && ((SYMBOL(pkmap_count_next)-SYMBOL(pkmap_count))/sizeof(int))
- == 512) {
+ if ((vt.mem_flags & MEMORY_X86_PAE)
+ || ((SYMBOL(pkmap_count) != NOT_FOUND_SYMBOL)
+ && (SYMBOL(pkmap_count_next) != NOT_FOUND_SYMBOL)
+ && ((SYMBOL(pkmap_count_next)-SYMBOL(pkmap_count))/sizeof(int))
+ == 512)) {
DEBUG_MSG("\n");
DEBUG_MSG("PAE : ON\n");
info->section_size_bits = _SECTION_SIZE_BITS_PAE;
_
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC][PATCH 1/3] Embed vmcoreinfo into kernel file
2007-08-17 6:43 ` Ken'ichi Ohmichi
@ 2007-08-17 9:44 ` Bernhard Walle
2007-08-22 6:40 ` Ken'ichi Ohmichi
2007-08-17 12:28 ` Vivek Goyal
1 sibling, 1 reply; 14+ messages in thread
From: Bernhard Walle @ 2007-08-17 9:44 UTC (permalink / raw)
To: Ken'ichi Ohmichi; +Cc: Don Zickus, Neil Horman, vgoyal, kexec-ml, Dan Aloni
Hi,
* Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp> [2007-08-17 08:43]:
>
> Thank you for good comments.
> I updated the patch for applying your comments.
Instead of providing empty implementations of arch_save_vmcoreinfo()
for each architecture that doesn't need that hook, I'd suggest to use
one default implementation with __attribute((weak)) that gets
overwritten by architecture implementations. See my patch below:
Signed-off-by: Dan Aloni <da-x@monatomic.org>
Signed-off-by: Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp>
Signed-off-by: Bernhard Walle <bwalle@suse.de>
---
arch/i386/kernel/machine_kexec.c | 13 ++++
arch/ia64/kernel/machine_kexec.c | 22 +++++++
arch/ia64/mm/discontig.c | 2
arch/x86_64/kernel/machine_kexec.c | 9 +++
include/asm-ia64/numa.h | 1
include/linux/kexec.h | 23 ++++++++
kernel/kexec.c | 103 +++++++++++++++++++++++++++++++++++++
kernel/ksysfs.c | 10 +++
8 files changed, 182 insertions(+), 1 deletion(-)
--- a/arch/i386/kernel/machine_kexec.c
+++ b/arch/i386/kernel/machine_kexec.c
@@ -10,6 +10,7 @@
#include <linux/kexec.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/numa.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
@@ -169,3 +170,15 @@ static int __init parse_crashkernel(char
return 0;
}
early_param("crashkernel", parse_crashkernel);
+
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+ SYMBOL(node_data);
+ LENGTH(node_data, MAX_NUMNODES);
+#endif
+#ifdef CONFIG_X86_PAE
+ CONFIG(X86_PAE);
+#endif
+}
+
--- a/arch/ia64/kernel/machine_kexec.c
+++ b/arch/ia64/kernel/machine_kexec.c
@@ -15,10 +15,12 @@
#include <linux/cpu.h>
#include <linux/irq.h>
#include <linux/efi.h>
+#include <linux/numa.h>
#include <asm/mmu_context.h>
#include <asm/setup.h>
#include <asm/delay.h>
#include <asm/meminit.h>
+#include <asm/mmzone.h>
typedef NORET_TYPE void (*relocate_new_kernel_t)(
unsigned long indirection_page,
@@ -125,3 +127,23 @@ void machine_kexec(struct kimage *image)
unw_init_running(ia64_machine_kexec, image);
for(;;);
}
+
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+ SYMBOL(pgdat_list);
+ LENGTH(pgdat_list, MAX_NUMNODES);
+
+ SYMBOL(node_memblk);
+ LENGTH(node_memblk, NR_NODE_MEMBLKS);
+ SIZE(node_memblk_s);
+ OFFSET(node_memblk_s, start_paddr);
+ OFFSET(node_memblk_s, size);
+#endif
+#ifdef CONFIG_PGTABLE_3
+ CONFIG(PGTABLE_3);
+#elif CONFIG_PGTABLE_4
+ CONFIG(PGTABLE_4);
+#endif
+}
+
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -47,7 +47,7 @@ struct early_node_data {
static struct early_node_data mem_data[MAX_NUMNODES] __initdata;
static nodemask_t memory_less_mask __initdata;
-static pg_data_t *pgdat_list[MAX_NUMNODES];
+pg_data_t *pgdat_list[MAX_NUMNODES];
/*
* To prevent cache aliasing effects, align per-node structures so that they
--- a/arch/x86_64/kernel/machine_kexec.c
+++ b/arch/x86_64/kernel/machine_kexec.c
@@ -10,6 +10,7 @@
#include <linux/kexec.h>
#include <linux/string.h>
#include <linux/reboot.h>
+#include <linux/numa.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
@@ -257,3 +258,11 @@ static int __init setup_crashkernel(char
}
early_param("crashkernel", setup_crashkernel);
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+ SYMBOL(node_data);
+ LENGTH(node_data, MAX_NUMNODES);
+#endif
+}
+
--- a/include/asm-ia64/numa.h
+++ b/include/asm-ia64/numa.h
@@ -24,6 +24,7 @@
extern u16 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
extern cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
+extern pg_data_t *pgdat_list[MAX_NUMNODES];
/* Stuff below this line could be architecture independent */
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -121,6 +121,21 @@ extern struct page *kimage_alloc_control
extern void crash_kexec(struct pt_regs *);
int kexec_should_crash(struct task_struct *);
void crash_save_cpu(struct pt_regs *regs, int cpu);
+void crash_save_vmcoreinfo(void);
+void arch_crash_save_vmcoreinfo(void);
+void vmcoreinfo_append_str(const char *fmt, ...);
+
+#define SYMBOL(name) \
+ vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #name, (unsigned long)&name)
+#define SIZE(name) \
+ vmcoreinfo_append_str("SIZE(%s)=%d\n", #name, sizeof(struct name))
+#define OFFSET(name, field) \
+ vmcoreinfo_append_str("OFFSET(%s.%s)=%d\n", #name, #field, &(((struct name *)0)->field))
+#define LENGTH(name, value) \
+ vmcoreinfo_append_str("LENGTH(%s)=%d\n", #name, value)
+#define CONFIG(name) \
+ vmcoreinfo_append_str("CONFIG_%s=%c\n", #name, CONFIG_##name)
+
extern struct kimage *kexec_image;
extern struct kimage *kexec_crash_image;
@@ -148,11 +163,19 @@ extern struct kimage *kexec_crash_image;
#define KEXEC_FLAGS (KEXEC_ON_CRASH) /* List of defined/legal kexec flags */
+#define VMCOREINFO_BYTES (4096)
+#define VMCOREINFO_NOTE_NAME "VMCOREINFO"
+#define VMCOREINFO_NOTE_NAME_BYTES ALIGN(sizeof(VMCOREINFO_NOTE_NAME), 4)
+#define VMCOREINFO_NOTE_SIZE (KEXEC_NOTE_HEAD_BYTES*2 + VMCOREINFO_BYTES \
+ + VMCOREINFO_NOTE_NAME_BYTES)
+
/* Location of a reserved region to hold the crash kernel.
*/
extern struct resource crashk_res;
typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];
extern note_buf_t *crash_notes;
+extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+extern unsigned int vmcoreinfo_size;
#else /* !CONFIG_KEXEC */
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -22,16 +22,26 @@
#include <linux/hardirq.h>
#include <linux/elf.h>
#include <linux/elfcore.h>
+#include <linux/utsrelease.h>
+#include <linux/utsname.h>
+#include <linux/numa.h>
#include <asm/page.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/semaphore.h>
+#include <asm/sections.h>
/* Per cpu memory for storing cpu states in case of system crash. */
note_buf_t* crash_notes;
+/* vmcoreinfo stuff */
+unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
+u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+unsigned int vmcoreinfo_size = 0;
+unsigned int vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
+
/* Location of the reserved area for the crash kernel */
struct resource crashk_res = {
.name = "Crash kernel",
@@ -1135,3 +1145,96 @@ static int __init crash_notes_memory_ini
return 0;
}
module_init(crash_notes_memory_init)
+
+void crash_save_vmcoreinfo(void)
+{
+ u32 *buf;
+
+ if (!vmcoreinfo_size)
+ return;
+
+ buf = (u32 *)vmcoreinfo_note;
+
+ buf = append_elf_note(buf, VMCOREINFO_NOTE_NAME, 0, vmcoreinfo_data,
+ vmcoreinfo_size);
+
+ final_note(buf);
+}
+
+void vmcoreinfo_append_str(const char *fmt, ...)
+{
+ va_list args;
+ char buf[0x50];
+ int r;
+
+ va_start(args, fmt);
+ r = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ if (r + vmcoreinfo_size > vmcoreinfo_max_size)
+ r = vmcoreinfo_max_size - vmcoreinfo_size;
+
+ memcpy(&vmcoreinfo_data[vmcoreinfo_size], buf, r);
+
+ vmcoreinfo_size += r;
+}
+
+/*
+ * provide an empty default implementation here -- architecture
+ * code may override this
+ */
+void __attribute__ ((weak)) arch_crash_save_vmcoreinfo(void)
+{}
+
+static int __init crash_save_vmcoreinfo_init(void)
+{
+ vmcoreinfo_append_str("OSRELEASE=%s\n", UTS_RELEASE);
+ vmcoreinfo_append_str("PAGESIZE=%d\n", PAGE_SIZE);
+
+ SYMBOL(init_uts_ns);
+ SYMBOL(node_online_map);
+ SYMBOL(swapper_pg_dir);
+ SYMBOL(_stext);
+
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+ SYMBOL(mem_map);
+ SYMBOL(contig_page_data);
+#endif
+#ifdef CONFIG_SPARSEMEM
+ SYMBOL(mem_section);
+ LENGTH(mem_section, NR_SECTION_ROOTS);
+ SIZE(mem_section);
+ OFFSET(mem_section, section_mem_map);
+#endif
+ SIZE(page);
+ SIZE(pglist_data);
+ SIZE(zone);
+ SIZE(free_area);
+ SIZE(list_head);
+ OFFSET(page, flags);
+ OFFSET(page, _count);
+ OFFSET(page, mapping);
+ OFFSET(page, lru);
+ OFFSET(pglist_data, node_zones);
+ OFFSET(pglist_data, nr_zones);
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
+ OFFSET(pglist_data, node_mem_map);
+#endif
+ OFFSET(pglist_data, node_start_pfn);
+ OFFSET(pglist_data, node_spanned_pages);
+ OFFSET(pglist_data, node_id);
+ OFFSET(zone, free_area);
+ OFFSET(zone, vm_stat);
+ OFFSET(zone, spanned_pages);
+ OFFSET(free_area, free_list);
+ OFFSET(list_head, next);
+ OFFSET(list_head, prev);
+ LENGTH(zone.free_area, MAX_ORDER);
+
+ arch_crash_save_vmcoreinfo();
+ crash_save_vmcoreinfo();
+
+ return 0;
+}
+
+module_init(crash_save_vmcoreinfo_init)
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -60,6 +60,15 @@ static ssize_t kexec_crash_loaded_show(s
return sprintf(page, "%d\n", !!kexec_crash_image);
}
KERNEL_ATTR_RO(kexec_crash_loaded);
+
+static ssize_t vmcoreinfo_show(struct kset *kset, char *page)
+{
+ return sprintf(page, "%lx %x\n",
+ __pa((unsigned long)(char *)&vmcoreinfo_note),
+ vmcoreinfo_size);
+}
+KERNEL_ATTR_RO(vmcoreinfo);
+
#endif /* CONFIG_KEXEC */
decl_subsys(kernel, NULL, NULL);
@@ -73,6 +82,7 @@ static struct attribute * kernel_attrs[]
#ifdef CONFIG_KEXEC
&kexec_loaded_attr.attr,
&kexec_crash_loaded_attr.attr,
+ &vmcoreinfo_attr.attr,
#endif
NULL
};
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC][PATCH 1/3] Embed vmcoreinfo into kernel file
2007-08-17 6:43 ` Ken'ichi Ohmichi
2007-08-17 9:44 ` Bernhard Walle
@ 2007-08-17 12:28 ` Vivek Goyal
2007-08-22 10:54 ` Ken'ichi Ohmichi
1 sibling, 1 reply; 14+ messages in thread
From: Vivek Goyal @ 2007-08-17 12:28 UTC (permalink / raw)
To: Ken'ichi Ohmichi
Cc: Don Zickus, Bernhard Walle, kexec-ml, Neil Horman, Dan Aloni
On Fri, Aug 17, 2007 at 03:43:31PM +0900, Ken'ichi Ohmichi wrote:
[..]
> >- There is another important field which I would like to see in vmcoreinfo
> > and that is time of crash (lets say CRASH_TIME). This will indicate the
> > timestamp when did system actually crash. One can read the time in
> > crash_kexec(), fill in the field and then save vmcore info note.
> >
> > For this, either you need to scan the vmcoreinfo note again and fill in
> > the time stamp. Or you need to do vmcoreinfo note saving after crash
> > instead of boot time.
>
> Is it necessary of the field for timestamp ?
> The crash utility can display the time of crash already like the following.
>
> # crash vmlinux vmcore
> [snip]
> KERNEL: vmlinux
> DUMPFILE: vmcore
> CPUS: 2
> DATE: Tue Jul 10 20:41:50 2007 <- Here
> UPTIME: 00:04:58
> LOAD AVERAGE: 0.12, 0.22, 0.11
> TASKS: 88
> NODENAME: peak
> RELEASE: 2.6.16.46-0.12-default
> VERSION: #1 SMP Thu May 17 14:00:09 UTC 2007
> MACHINE: ia64 (1000 Mhz)
> MEMORY: 5.5 GB
> PANIC: "SysRq : Trigger a crashdump"
> PID: 3455
> COMMAND: "bash"
> TASK: e0000040f2f40000 [THREAD_INFO: e0000040f2f410d0]
> CPU: 0
> STATE: TASK_RUNNING (SYSRQ)
>
>
But this requires a debug compiled vmlinux to be available on the system
and that's a rarity. For example, we are exporting UTSNAME also which
can be retrieved by opening vmcore with crash.
By exporting this, now one can write a small utility in second kernel,
which can just look at the /proc/vmcore in second kernel, determine that
machine had crashed and send a notification over network to other machine
with crash time stamp.
[..]
> +#define SYMBOL(name) \
> + vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #name, (unsigned long)&name)
> +#define SIZE(name) \
> + vmcoreinfo_append_str("SIZE(%s)=%d\n", #name, sizeof(struct name))
> +#define OFFSET(name, field) \
> + vmcoreinfo_append_str("OFFSET(%s.%s)=%d\n", #name, #field, &(((struct name *)0)->field))
> +#define LENGTH(name, value) \
> + vmcoreinfo_append_str("LENGTH(%s)=%d\n", #name, value)
> +#define CONFIG(name) \
> + vmcoreinfo_append_str("CONFIG_%s=%c\n", #name, CONFIG_##name)
> +
Have you tested CONFIG(). For me it did not work? Are you getting output
like CONFIG_KEXEC=y with above macro?
Thanks
Vivek
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC][PATCH 1/3] Embed vmcoreinfo into kernel file
2007-08-17 9:44 ` Bernhard Walle
@ 2007-08-22 6:40 ` Ken'ichi Ohmichi
0 siblings, 0 replies; 14+ messages in thread
From: Ken'ichi Ohmichi @ 2007-08-22 6:40 UTC (permalink / raw)
To: Bernhard Walle; +Cc: Don Zickus, Neil Horman, vgoyal, kexec-ml, Dan Aloni
Hi Bernhard,
2007/08/17 11:44:07 +0200, Bernhard Walle <bwalle@suse.de> wrote:
>Hi,
>
>* Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp> [2007-08-17 08:43]:
>>
>> Thank you for good comments.
>> I updated the patch for applying your comments.
>
>Instead of providing empty implementations of arch_save_vmcoreinfo()
>for each architecture that doesn't need that hook, I'd suggest to use
>one default implementation with __attribute((weak)) that gets
>overwritten by architecture implementations. See my patch below:
Thank you for a good patch.
I'll update the patch based on yours.
Thanks
Ken'ichi Ohmichi
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC][PATCH 1/3] Embed vmcoreinfo into kernel file
2007-08-17 12:28 ` Vivek Goyal
@ 2007-08-22 10:54 ` Ken'ichi Ohmichi
0 siblings, 0 replies; 14+ messages in thread
From: Ken'ichi Ohmichi @ 2007-08-22 10:54 UTC (permalink / raw)
To: vgoyal; +Cc: Don Zickus, Bernhard Walle, kexec-ml, Neil Horman, Dan Aloni
Hi Vivek,
2007/08/17 17:58:03 +0530, Vivek Goyal <vgoyal@in.ibm.com> wrote:
>On Fri, Aug 17, 2007 at 03:43:31PM +0900, Ken'ichi Ohmichi wrote:
>[..]
>> >- There is another important field which I would like to see in vmcoreinfo
>> > and that is time of crash (lets say CRASH_TIME). This will indicate the
>> > timestamp when did system actually crash. One can read the time in
>> > crash_kexec(), fill in the field and then save vmcore info note.
>> >
>> > For this, either you need to scan the vmcoreinfo note again and fill in
>> > the time stamp. Or you need to do vmcoreinfo note saving after crash
>> > instead of boot time.
>>
>> Is it necessary of the field for timestamp ?
>> The crash utility can display the time of crash already like the following.
>>
>> # crash vmlinux vmcore
>> [snip]
>> KERNEL: vmlinux
>> DUMPFILE: vmcore
>> CPUS: 2
>> DATE: Tue Jul 10 20:41:50 2007 <- Here
>> UPTIME: 00:04:58
>> LOAD AVERAGE: 0.12, 0.22, 0.11
>> TASKS: 88
>> NODENAME: peak
>> RELEASE: 2.6.16.46-0.12-default
>> VERSION: #1 SMP Thu May 17 14:00:09 UTC 2007
>> MACHINE: ia64 (1000 Mhz)
>> MEMORY: 5.5 GB
>> PANIC: "SysRq : Trigger a crashdump"
>> PID: 3455
>> COMMAND: "bash"
>> TASK: e0000040f2f40000 [THREAD_INFO: e0000040f2f410d0]
>> CPU: 0
>> STATE: TASK_RUNNING (SYSRQ)
>>
>>
>
>But this requires a debug compiled vmlinux to be available on the system
>and that's a rarity. For example, we are exporting UTSNAME also which
>can be retrieved by opening vmcore with crash.
>
>By exporting this, now one can write a small utility in second kernel,
>which can just look at the /proc/vmcore in second kernel, determine that
>machine had crashed and send a notification over network to other machine
>with crash time stamp.
OK, the attached patch includes the field CRASHTIME.
>> +#define SYMBOL(name) \
>> + vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #name, (unsigned long)&name)
>> +#define SIZE(name) \
>> + vmcoreinfo_append_str("SIZE(%s)=%d\n", #name, sizeof(struct name))
>> +#define OFFSET(name, field) \
>> + vmcoreinfo_append_str("OFFSET(%s.%s)=%d\n", #name, #field, &(((struct name *)0)->field))
>> +#define LENGTH(name, value) \
>> + vmcoreinfo_append_str("LENGTH(%s)=%d\n", #name, value)
>> +#define CONFIG(name) \
>> + vmcoreinfo_append_str("CONFIG_%s=%c\n", #name, CONFIG_##name)
>> +
>
>Have you tested CONFIG(). For me it did not work? Are you getting output
>like CONFIG_KEXEC=y with above macro?
You're right, I fixed it.
And Daisuke Nishimura updated the patch for translating the virtual
address of vmcoreinfo_note into its physical address on ia64.
Thanks
Ken'ichi Ohmichi
---
Signed-off-by: Dan Aloni <da-x@monatomic.org>
Signed-off-by: Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp>
Signed-off-by: Bernhard Walle <bwalle@suse.de>
Signed-off-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
---
diff -rpuN a/arch/i386/kernel/machine_kexec.c b/arch/i386/kernel/machine_kexec.c
--- a/arch/i386/kernel/machine_kexec.c 2007-08-23 00:03:30.000000000 +0900
+++ b/arch/i386/kernel/machine_kexec.c 2007-08-23 00:47:38.000000000 +0900
@@ -10,6 +10,7 @@
#include <linux/kexec.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/numa.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
@@ -169,3 +170,15 @@ static int __init parse_crashkernel(char
return 0;
}
early_param("crashkernel", parse_crashkernel);
+
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+ SYMBOL(node_data);
+ LENGTH(node_data, MAX_NUMNODES);
+#endif
+#ifdef CONFIG_X86_PAE
+ CONFIG(X86_PAE);
+#endif
+}
+
diff -rpuN a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c
--- a/arch/ia64/kernel/machine_kexec.c 2007-08-23 00:03:30.000000000 +0900
+++ b/arch/ia64/kernel/machine_kexec.c 2007-08-23 00:47:38.000000000 +0900
@@ -15,6 +15,8 @@
#include <linux/cpu.h>
#include <linux/irq.h>
#include <linux/efi.h>
+#include <linux/numa.h>
+#include <linux/mmzone.h>
#include <asm/mmu_context.h>
#include <asm/setup.h>
#include <asm/delay.h>
@@ -125,3 +127,31 @@ void machine_kexec(struct kimage *image)
unw_init_running(ia64_machine_kexec, image);
for(;;);
}
+
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+ SYMBOL(pgdat_list);
+ LENGTH(pgdat_list, MAX_NUMNODES);
+
+ SYMBOL(node_memblk);
+ LENGTH(node_memblk, NR_NODE_MEMBLKS);
+ SIZE(node_memblk_s);
+ OFFSET(node_memblk_s, start_paddr);
+ OFFSET(node_memblk_s, size);
+#endif
+#ifdef CONFIG_PGTABLE_3
+ CONFIG(PGTABLE_3);
+#elif CONFIG_PGTABLE_4
+ CONFIG(PGTABLE_4);
+#endif
+}
+
+unsigned long paddr_vmcoreinfo_note(void)
+{
+ unsigned long vaddr, paddr;
+ vaddr = (unsigned long)(char *)&vmcoreinfo_note;
+ asm volatile ("tpa %0 = %1" : "=r"(paddr) : "r"(vaddr) : "memory");
+ return paddr;
+}
+
diff -rpuN a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
--- a/arch/ia64/mm/discontig.c 2007-08-23 00:03:30.000000000 +0900
+++ b/arch/ia64/mm/discontig.c 2007-08-23 00:47:38.000000000 +0900
@@ -47,7 +47,7 @@ struct early_node_data {
static struct early_node_data mem_data[MAX_NUMNODES] __initdata;
static nodemask_t memory_less_mask __initdata;
-static pg_data_t *pgdat_list[MAX_NUMNODES];
+pg_data_t *pgdat_list[MAX_NUMNODES];
/*
* To prevent cache aliasing effects, align per-node structures so that they
diff -rpuN a/arch/x86_64/kernel/machine_kexec.c b/arch/x86_64/kernel/machine_kexec.c
--- a/arch/x86_64/kernel/machine_kexec.c 2007-08-23 00:03:30.000000000 +0900
+++ b/arch/x86_64/kernel/machine_kexec.c 2007-08-23 00:47:38.000000000 +0900
@@ -10,6 +10,7 @@
#include <linux/kexec.h>
#include <linux/string.h>
#include <linux/reboot.h>
+#include <linux/numa.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
@@ -257,3 +258,11 @@ static int __init setup_crashkernel(char
}
early_param("crashkernel", setup_crashkernel);
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+ SYMBOL(node_data);
+ LENGTH(node_data, MAX_NUMNODES);
+#endif
+}
+
diff -rpuN a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h
--- a/include/asm-ia64/numa.h 2007-08-23 00:03:33.000000000 +0900
+++ b/include/asm-ia64/numa.h 2007-08-23 00:47:38.000000000 +0900
@@ -24,6 +24,7 @@
extern u16 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
extern cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
+extern pg_data_t *pgdat_list[MAX_NUMNODES];
/* Stuff below this line could be architecture independent */
diff -rpuN a/include/linux/kexec.h b/include/linux/kexec.h
--- a/include/linux/kexec.h 2007-08-23 00:03:33.000000000 +0900
+++ b/include/linux/kexec.h 2007-08-23 00:47:38.000000000 +0900
@@ -121,6 +121,23 @@ extern struct page *kimage_alloc_control
extern void crash_kexec(struct pt_regs *);
int kexec_should_crash(struct task_struct *);
void crash_save_cpu(struct pt_regs *regs, int cpu);
+void crash_save_vmcoreinfo(void);
+void arch_crash_save_vmcoreinfo(void);
+void vmcoreinfo_append_str(const char *fmt, ...);
+unsigned long paddr_vmcoreinfo_note(void);
+
+#define SYMBOL(name) \
+ vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #name, (unsigned long)&name)
+#define SIZE(name) \
+ vmcoreinfo_append_str("SIZE(%s)=%d\n", #name, sizeof(struct name))
+#define OFFSET(name, field) \
+ vmcoreinfo_append_str("OFFSET(%s.%s)=%d\n", #name, #field, \
+ &(((struct name *)0)->field))
+#define LENGTH(name, value) \
+ vmcoreinfo_append_str("LENGTH(%s)=%d\n", #name, value)
+#define CONFIG(name) \
+ vmcoreinfo_append_str("CONFIG_%s=y\n", #name)
+
extern struct kimage *kexec_image;
extern struct kimage *kexec_crash_image;
@@ -148,11 +165,20 @@ extern struct kimage *kexec_crash_image;
#define KEXEC_FLAGS (KEXEC_ON_CRASH) /* List of defined/legal kexec flags */
+#define VMCOREINFO_BYTES (4096)
+#define VMCOREINFO_NOTE_NAME "VMCOREINFO"
+#define VMCOREINFO_NOTE_NAME_BYTES ALIGN(sizeof(VMCOREINFO_NOTE_NAME), 4)
+#define VMCOREINFO_NOTE_SIZE (KEXEC_NOTE_HEAD_BYTES*2 + VMCOREINFO_BYTES \
+ + VMCOREINFO_NOTE_NAME_BYTES)
+
/* Location of a reserved region to hold the crash kernel.
*/
extern struct resource crashk_res;
typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];
extern note_buf_t *crash_notes;
+extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+extern unsigned int vmcoreinfo_size;
+extern unsigned int vmcoreinfo_max_size;
#else /* !CONFIG_KEXEC */
diff -rpuN a/kernel/kexec.c b/kernel/kexec.c
--- a/kernel/kexec.c 2007-08-23 00:03:30.000000000 +0900
+++ b/kernel/kexec.c 2007-08-23 00:48:40.000000000 +0900
@@ -22,16 +22,26 @@
#include <linux/hardirq.h>
#include <linux/elf.h>
#include <linux/elfcore.h>
+#include <linux/utsrelease.h>
+#include <linux/utsname.h>
+#include <linux/numa.h>
#include <asm/page.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/semaphore.h>
+#include <asm/sections.h>
/* Per cpu memory for storing cpu states in case of system crash. */
note_buf_t* crash_notes;
+/* vmcoreinfo stuff */
+unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
+u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+unsigned int vmcoreinfo_size = 0;
+unsigned int vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
+
/* Location of the reserved area for the crash kernel */
struct resource crashk_res = {
.name = "Crash kernel",
@@ -1061,6 +1071,7 @@ void crash_kexec(struct pt_regs *regs)
if (kexec_crash_image) {
struct pt_regs fixed_regs;
crash_setup_regs(&fixed_regs, regs);
+ crash_save_vmcoreinfo();
machine_crash_shutdown(&fixed_regs);
machine_kexec(kexec_crash_image);
}
@@ -1135,3 +1146,102 @@ static int __init crash_notes_memory_ini
return 0;
}
module_init(crash_notes_memory_init)
+
+void crash_save_vmcoreinfo(void)
+{
+ u32 *buf;
+
+ if (!vmcoreinfo_size)
+ return;
+
+ vmcoreinfo_append_str("CRASHTIME=%d", xtime.tv_sec);
+
+ buf = (u32 *)vmcoreinfo_note;
+
+ buf = append_elf_note(buf, VMCOREINFO_NOTE_NAME, 0, vmcoreinfo_data,
+ vmcoreinfo_size);
+
+ final_note(buf);
+}
+
+void vmcoreinfo_append_str(const char *fmt, ...)
+{
+ va_list args;
+ char buf[0x50];
+ int r;
+
+ va_start(args, fmt);
+ r = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ if (r + vmcoreinfo_size > vmcoreinfo_max_size)
+ r = vmcoreinfo_max_size - vmcoreinfo_size;
+
+ memcpy(&vmcoreinfo_data[vmcoreinfo_size], buf, r);
+
+ vmcoreinfo_size += r;
+}
+
+/*
+ * provide an empty default implementation here -- architecture
+ * code may override this
+ */
+void __attribute__ ((weak)) arch_crash_save_vmcoreinfo(void)
+{}
+
+unsigned long __attribute__ ((weak)) paddr_vmcoreinfo_note(void)
+{
+ return __pa((unsigned long)(char *)&vmcoreinfo_note);
+}
+
+static int __init crash_save_vmcoreinfo_init(void)
+{
+ vmcoreinfo_append_str("OSRELEASE=%s\n", UTS_RELEASE);
+ vmcoreinfo_append_str("PAGESIZE=%d\n", PAGE_SIZE);
+
+ SYMBOL(init_uts_ns);
+ SYMBOL(node_online_map);
+ SYMBOL(swapper_pg_dir);
+ SYMBOL(_stext);
+
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+ SYMBOL(mem_map);
+ SYMBOL(contig_page_data);
+#endif
+#ifdef CONFIG_SPARSEMEM
+ SYMBOL(mem_section);
+ LENGTH(mem_section, NR_SECTION_ROOTS);
+ SIZE(mem_section);
+ OFFSET(mem_section, section_mem_map);
+#endif
+ SIZE(page);
+ SIZE(pglist_data);
+ SIZE(zone);
+ SIZE(free_area);
+ SIZE(list_head);
+ OFFSET(page, flags);
+ OFFSET(page, _count);
+ OFFSET(page, mapping);
+ OFFSET(page, lru);
+ OFFSET(pglist_data, node_zones);
+ OFFSET(pglist_data, nr_zones);
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
+ OFFSET(pglist_data, node_mem_map);
+#endif
+ OFFSET(pglist_data, node_start_pfn);
+ OFFSET(pglist_data, node_spanned_pages);
+ OFFSET(pglist_data, node_id);
+ OFFSET(zone, free_area);
+ OFFSET(zone, vm_stat);
+ OFFSET(zone, spanned_pages);
+ OFFSET(free_area, free_list);
+ OFFSET(list_head, next);
+ OFFSET(list_head, prev);
+ LENGTH(zone.free_area, MAX_ORDER);
+
+ arch_crash_save_vmcoreinfo();
+
+ return 0;
+}
+
+module_init(crash_save_vmcoreinfo_init)
diff -rpuN a/kernel/ksysfs.c b/kernel/ksysfs.c
--- a/kernel/ksysfs.c 2007-08-23 00:03:30.000000000 +0900
+++ b/kernel/ksysfs.c 2007-08-23 00:47:53.000000000 +0900
@@ -60,6 +60,15 @@ static ssize_t kexec_crash_loaded_show(s
return sprintf(page, "%d\n", !!kexec_crash_image);
}
KERNEL_ATTR_RO(kexec_crash_loaded);
+
+static ssize_t vmcoreinfo_show(struct kset *kset, char *page)
+{
+ return sprintf(page, "%lx %x\n",
+ paddr_vmcoreinfo_note(),
+ vmcoreinfo_max_size);
+}
+KERNEL_ATTR_RO(vmcoreinfo);
+
#endif /* CONFIG_KEXEC */
decl_subsys(kernel, NULL, NULL);
@@ -73,6 +82,7 @@ static struct attribute * kernel_attrs[]
#ifdef CONFIG_KEXEC
&kexec_loaded_attr.attr,
&kexec_crash_loaded_attr.attr,
+ &vmcoreinfo_attr.attr,
#endif
NULL
};
_
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2007-08-22 10:54 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-08-13 7:32 [RFC][PATCH 0/3] Embed vmcoreinfo into kernel file Ken'ichi Ohmichi
2007-08-13 7:36 ` [RFC][PATCH 1/3] " Ken'ichi Ohmichi
2007-08-13 17:38 ` Dan Aloni
2007-08-14 22:00 ` Bernhard Walle
2007-08-16 4:20 ` Vivek Goyal
2007-08-17 6:43 ` Ken'ichi Ohmichi
2007-08-17 9:44 ` Bernhard Walle
2007-08-22 6:40 ` Ken'ichi Ohmichi
2007-08-17 12:28 ` Vivek Goyal
2007-08-22 10:54 ` Ken'ichi Ohmichi
2007-08-13 7:38 ` [RFC][PATCH 2/3] " Ken'ichi Ohmichi
2007-08-13 7:39 ` [RFC][PATCH 3/3] " Ken'ichi Ohmichi
2007-08-14 21:59 ` Bernhard Walle
2007-08-17 7:09 ` Ken'ichi Ohmichi
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.