Skip to contentSkip to conversation

Embed vmcoreinfo into kernel file

RFC PATCH In review Ken'ichi Ohmichi 4 participants 14 messages Aug 13, 2007 – Aug 22, 2007

Subsystems (8)
Arm (32-bit) PowerPC MIPS s390 +4 more subsystems
lore
Share & tools
lore
#0 lore raw

cover Embed vmcoreinfo into kernel file

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
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#1 lore raw

RFC PATCH 1/3 Embed vmcoreinfo into kernel file

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.

---

---

arch/ia64/mm/discontig.c +1 -1
diff -rpuN linux-2.6.22.org/arch/ia64/mm/discontig.c linux-2.6.22/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
include/linux/kexec.h +10 -0
diff -rpuN linux-2.6.22.org/include/linux/kexec.h linux-2.6.22/include/linux/kexec.h
@@ -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 */
kernel/kexec.c +140 -0

155 lines not on this page · raw message

kernel/ksysfs.c +10 -0
diff -rpuN linux-2.6.22.org/kernel/ksysfs.c linux-2.6.22/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
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#2 lore raw
Quoted 11 lines · Ken'ichi Ohmichi

[..]
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.

Signature · 8 lines
Dan Aloni
XIV LTD, http://www.xivstorage.com
da-x (at) monatomic.org, dan (at) xiv.co.il

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#3 lore raw
Quoted 13 lines · Dan Aloni
Quoted 11 lines · Ken'ichi Ohmichi

[..]
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.

Quoted 5 lines

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
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#4 lore raw
In reply to Ken'ichi Ohmichi
Quoted 12 lines · Ken'ichi Ohmichi

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.

kernel/kexec.c static int __init crash_notes_memory_ini · line 1195

Quoted 12 lines
kernel/kexec.c +12 -0
+#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?

kernel/kexec.c static int __init crash_notes_memory_ini · line 1199

Quoted 4 lines
kernel/kexec.c +4 -0
+#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.

Quoted 24 lines
kernel/kexec.c +24 -0
+#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);

kernel/kexec.c static int __init crash_notes_memory_ini · line 1233

Quoted 10 lines
kernel/kexec.c +10 -0
+	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().

Quoted 26 lines
kernel/kexec.c +26 -0
+#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);

kernel/kexec.c static int __init crash_notes_memory_ini · line 1269

Quoted 10 lines
kernel/kexec.c +10 -0
+	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
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#5 lore raw

Hi Dan Aloni, Vivek, and Bernhard,

Thank you for good comments.
I updated the patch for applying your comments.

Quoted 16 lines · Vivek Goyal

Review

Quoted 12 lines
(quoted diff) +12 -0
+#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.

Quoted 2 lines

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.

Quoted 7 lines

Review

Quoted 4 lines
(quoted diff) +4 -0
+#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.

Quoted 12 lines
Quoted 12 lines
(quoted diff) +12 -0
+#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);
Quoted 8 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+	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.

Quoted 8 lines

- 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

---

arch/arm/kernel/machine_kexec.c +5 -0
diff -rpuN linux-2.6.22.org/arch/arm/kernel/machine_kexec.c linux-2.6.22/arch/arm/kernel/machine_kexec.c
@@ -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)
+{
+}
+
arch/i386/kernel/machine_kexec.c +13 -0
diff -rpuN linux-2.6.22.org/arch/i386/kernel/machine_kexec.c linux-2.6.22/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
+}
+
arch/ia64/kernel/machine_kexec.c +22 -0
diff -rpuN linux-2.6.22.org/arch/ia64/kernel/machine_kexec.c linux-2.6.22/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
+}
+
arch/ia64/mm/discontig.c +1 -1
diff -rpuN linux-2.6.22.org/arch/ia64/mm/discontig.c linux-2.6.22/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
arch/mips/kernel/machine_kexec.c +5 -0
diff -rpuN linux-2.6.22.org/arch/mips/kernel/machine_kexec.c linux-2.6.22/arch/mips/kernel/machine_kexec.c
@@ -83,3 +83,8 @@ machine_kexec(struct kimage *image)
 	flush_cache_all();
 	((void (*)(void))reboot_code_buffer)();
 }
+
+void arch_crash_save_vmcoreinfo(void)
+{
+}
+
arch/powerpc/kernel/machine_kexec.c +5 -0
diff -rpuN linux-2.6.22.org/arch/powerpc/kernel/machine_kexec.c linux-2.6.22/arch/powerpc/kernel/machine_kexec.c
@@ -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)
+{
+}
+
arch/ppc/kernel/machine_kexec.c +4 -0
diff -rpuN linux-2.6.22.org/arch/ppc/kernel/machine_kexec.c linux-2.6.22/arch/ppc/kernel/machine_kexec.c
@@ -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)
+{
+}
+
arch/s390/kernel/machine_kexec.c +5 -0
diff -rpuN linux-2.6.22.org/arch/s390/kernel/machine_kexec.c linux-2.6.22/arch/s390/kernel/machine_kexec.c
@@ -69,3 +69,8 @@ void machine_kexec(struct kimage *image)
 	(*data_mover)(&image->head, image->start);
 	for (;;);
 }
+
+void arch_crash_save_vmcoreinfo(void)
+{
+}
+
arch/x86_64/kernel/machine_kexec.c +9 -0
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
@@ -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
+}
+
include/asm-ia64/numa.h +1 -0
diff -rpuN linux-2.6.22.org/include/asm-ia64/numa.h linux-2.6.22/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 */
 
include/linux/kexec.h +23 -0
diff -rpuN linux-2.6.22.org/include/linux/kexec.h linux-2.6.22/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 */
kernel/kexec.c +96 -0

115 lines not on this page · raw message

kernel/ksysfs.c +10 -0
diff -rpuN linux-2.6.22.org/kernel/ksysfs.c linux-2.6.22/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
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#6 lore raw

Hi,

Quoted 3 lines · Ken'ichi Ohmichi

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:

---
 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(-)
arch/i386/kernel/machine_kexec.c +13 -0
@@ -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
+}
+
arch/ia64/kernel/machine_kexec.c +22 -0
@@ -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
+}
+
arch/ia64/mm/discontig.c +1 -1
@@ -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
arch/x86_64/kernel/machine_kexec.c +9 -0
@@ -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
+}
+
include/asm-ia64/numa.h +1 -0
@@ -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 */
 
include/linux/kexec.h +23 -0
@@ -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 */
kernel/kexec.c +103 -0

122 lines not on this page · raw message

kernel/ksysfs.c +10 -0
@@ -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
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#7 lore raw

Hi Bernhard,

Quoted 11 lines · Bernhard Walle

Hi,

Quoted 3 lines · Ken'ichi Ohmichi

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
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#8 lore raw
In reply to Ken'ichi Ohmichi

On Fri, Aug 17, 2007 at 03:43:31PM +0900, Ken'ichi Ohmichi wrote:
[..]

Quoted 24 lines
Quoted 8 lines

- 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
Quoted 10 lines
     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.

[..]

include/linux/kexec.h extern struct page *kimage_alloc_control · line 138

Quoted 11 lines
include/linux/kexec.h +11 -0
+#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
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#9 lore raw

Hi Vivek,

Quoted 37 lines · Vivek Goyal

On Fri, Aug 17, 2007 at 03:43:31PM +0900, Ken'ichi Ohmichi wrote:
[..]

Quoted 24 lines
Quoted 8 lines

- 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
Quoted 10 lines
     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)
Quoted 8 lines

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.

Quoted 6 lines
Quoted 6 lines
(quoted diff) +6 -0
+#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))
Quoted 8 lines

Review

Quoted 5 lines
(quoted diff) +5 -0
+#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

---

---

arch/i386/kernel/machine_kexec.c +13 -0
diff -rpuN 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
+}
+
arch/ia64/kernel/machine_kexec.c +30 -0
diff -rpuN a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c
@@ -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;
+}
+
arch/ia64/mm/discontig.c +1 -1
diff -rpuN 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
arch/x86_64/kernel/machine_kexec.c +9 -0
diff -rpuN 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
+}
+
include/asm-ia64/numa.h +1 -0
diff -rpuN 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 */
 
include/linux/kexec.h +26 -0
diff -rpuN a/include/linux/kexec.h b/include/linux/kexec.h
@@ -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 */
kernel/kexec.c +110 -0

135 lines not on this page · raw message

kernel/ksysfs.c +10 -0
diff -rpuN 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",
+		       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
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#10 lore raw

RFC PATCH 2/3 Embed vmcoreinfo into kernel file

In reply to Ken'ichi Ohmichi

Patches:
- [2/3] patch for kexec-tools-testing-20070330.
Changelog:
* Rename "mkdfinfo" to "vmcoreinfo".

---

---

kexec/crashdump-elf.c renamed from kexec-tools-testing-20070330/kexec/crashdump-elf.c +22 -1
diff -rpuN backup/kexec-tools-testing-20070330/kexec/crashdump-elf.c kexec-tools/kexec/crashdump-elf.c
@@ -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.
 	 */
kexec/crashdump.c renamed from kexec-tools-testing-20070330/kexec/crashdump.c +32 -0
diff -rpuN backup/kexec-tools-testing-20070330/kexec/crashdump.c kexec-tools/kexec/crashdump.c
@@ -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;
+}
kexec/crashdump.h renamed from kexec-tools-testing-20070330/kexec/crashdump.h +1 -0
diff -rpuN backup/kexec-tools-testing-20070330/kexec/crashdump.h kexec-tools/kexec/crashdump.h
@@ -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
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#11 lore raw

RFC PATCH 3/3 Embed vmcoreinfo into kernel file

In reply to Ken'ichi Ohmichi

Patches:
- [3/3] patch for makedumpfile-v1.1.6.

---

---

ia64.c renamed from v1.1.6/ia64.c +4 -0
diff -puN backup/v1.1.6/ia64.c makedumpfile/ia64.c
@@ -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).
 	 */
makedumpfile.c renamed from v1.1.6/makedumpfile.c +228 -13

283 lines not on this page · raw message

makedumpfile.h renamed from v1.1.6/makedumpfile.h +25 -7
diff -puN backup/v1.1.6/makedumpfile.h makedumpfile/makedumpfile.h
@@ -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 */
x86.c renamed from v1.1.6/x86.c +5 -4
diff -puN backup/v1.1.6/x86.c makedumpfile/x86.c
@@ -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
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#12 lore raw

Hello,

Quoted 1 line · Ken'ichi Ohmichi

+#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
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#13 lore raw

Hi Bernhard,

Thank you for the review and a good comment.

Quoted 5 lines · Bernhard Walle

Hello,

Quoted 1 line · Ken'ichi Ohmichi

+#define FILENAME_VMCOREINFO "/tmp/vmcoreinfo.tmp"

Quoted 8 lines

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

---

ia64.c renamed from v1.1.6/ia64.c +4 -0
diff -puN backup/v1.1.6/ia64.c makedumpfile/ia64.c
@@ -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).
 	 */
makedumpfile.c renamed from v1.1.6/makedumpfile.c +227 -13

282 lines not on this page · raw message

makedumpfile.h renamed from v1.1.6/makedumpfile.h +25 -7
diff -puN backup/v1.1.6/makedumpfile.h makedumpfile/makedumpfile.h
@@ -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 */
x86.c renamed from v1.1.6/x86.c +5 -4
diff -puN backup/v1.1.6/x86.c makedumpfile/x86.c
@@ -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
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec