Skip to contentSkip to conversation

kexec (rewrite) for 2.5.52

PATCH In review Eric W. Biederman 5 participants 15 messages Dec 22, 2002 – Feb 7, 2003 3 messages not in the archive kexec

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 kexec (rewrite) for 2.5.52

I have recently taken the time to dig through the internals of kexec to see if I could make my code any simpler and have managed to trim off about 100 lines, and have made the code much more obviously correct.

The key realization was that I had a much simpler test to detect if a page was a destination page. Allowing me to remove the second pass, and put all of the logic to avoid stepping on my own toes in the page allocator.

I have also made the small changes necessary to allow using high memory pages. Since I cannot push the request for memory below 4GB into alloc_pages, I simply keep push the unusable pages on a list, and keep requesting memory. This should be o.k. on a large memory machine but I can also see it as being pathological. The advantage to using high memory is that I should be able to use most of the memory below 4GB for a kernel image, and depending on how the zones are setup this keeps me from artificially limiting myself. I get the feeling what I really want is my own special zone, maybe later...

With all of the strange logic in the kimage_alloc_page the code is much more obviously correct, and in most cases should run in O(N) time, though it can still get pathological and run in O(N^2).

I have also made allocation of the reboot code buffer a little less clever, removing a very small pathological case that was previously present.

Anyway, I would love to know in what entertaining ways this code blows up, or if I get lucky and it doesn't. I probably will not reply back in a timely manner as I am off to visit my parents, for Christmas and New Years.

Eric

 MAINTAINERS                        |    8 
 arch/i386/Kconfig                  |   17 +
 arch/i386/kernel/Makefile          |    1 
 arch/i386/kernel/entry.S           |    1 
 arch/i386/kernel/machine_kexec.c   |  140 +++++++++
 arch/i386/kernel/relocate_kernel.S |  107 +++++++
 include/asm-i386/kexec.h           |   23 +
 include/asm-i386/unistd.h          |    1 
 include/linux/kexec.h              |   54 +++
 include/linux/reboot.h             |    2 
 kernel/Makefile                    |    1 
 kernel/kexec.c                     |  547 +++++++++++++++++++++++++++++++++++++
 kernel/sys.c                       |   23 +
 13 files changed, 925 insertions
MAINTAINERS +8 -0
diff -uNr linux-2.5.52/MAINTAINERS linux-2.5.52.x86kexec-2/MAINTAINERS
@@ -997,6 +997,14 @@
 W:	http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
 S:	Maintained
 
+KEXEC
+P:	Eric Biederman
+M:	[email protected]
+M:	[email protected]
+W:	http://www.xmission.com/~ebiederm/files/kexec/
+L:	[email protected]
+S:	Maintained
+
 LANMEDIA WAN CARD DRIVER
 P:	Andrew Stanley-Jones
 M:	[email protected]
arch/i386/Kconfig +17 -0
diff -uNr linux-2.5.52/arch/i386/Kconfig linux-2.5.52.x86kexec-2/arch/i386/Kconfig
@@ -686,6 +686,23 @@
 	depends on (SMP || PREEMPT) && X86_CMPXCHG
 	default y
 
+config KEXEC
+	bool "kexec system call (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  kexec is a system call that implements the ability to  shutdown your
+	  current kernel, and to start another kernel.  It is like a reboot
+	  but it is indepedent of the system firmware.   And like a reboot
+	  you can start any kernel with it not just Linux.  
+	
+	  The name comes from the similiarity to the exec system call. 
+	
+	  It is on an going process to be certain the hardware in a machine
+	  is properly shutdown, so do not be surprised if this code does not
+	  initially work for you.  It may help to enable device hotplugging
+	  support.  As of this writing the exact hardware interface is
+	  strongly in flux, so no good recommendation can be made.
+
 endmenu
 
 
arch/i386/kernel/Makefile +1 -0
diff -uNr linux-2.5.52/arch/i386/kernel/Makefile linux-2.5.52.x86kexec-2/arch/i386/kernel/Makefile
@@ -24,6 +24,7 @@
 obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
+obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend.o suspend_asm.o
 obj-$(CONFIG_X86_NUMAQ)		+= numaq.o
 obj-$(CONFIG_PROFILING)		+= profile.o
arch/i386/kernel/entry.S +1 -0
diff -uNr linux-2.5.52/arch/i386/kernel/entry.S linux-2.5.52.x86kexec-2/arch/i386/kernel/entry.S
@@ -743,6 +743,7 @@
 	.long sys_epoll_wait
  	.long sys_remap_file_pages
  	.long sys_set_tid_address
+	.long sys_kexec_load
 
 
 	.rept NR_syscalls-(.-sys_call_table)/4
arch/i386/kernel/machine_kexec.c +140 -0

140 lines not on this page · raw message

arch/i386/kernel/relocate_kernel.S +107 -0

107 lines not on this page · raw message

include/asm-i386/kexec.h +23 -0
diff -uNr linux-2.5.52/include/asm-i386/kexec.h linux-2.5.52.x86kexec-2/include/asm-i386/kexec.h
@@ -0,0 +1,23 @@
+#ifndef _I386_KEXEC_H
+#define _I386_KEXEC_H
+
+#include <asm/fixmap.h>
+
+/*
+ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
+ * I.e. Maximum page that is mapped directly into kernel memory,
+ * and kmap is not required.
+ *
+ * Someone correct me if FIXADDR_START - PAGEOFFSET is not the correct
+ * calculation for the amount of memory directly mappable into the
+ * kernel memory space.
+ */
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+
+#define KEXEC_REBOOT_CODE_SIZE	4096
+
+#endif /* _I386_KEXEC_H */
include/asm-i386/unistd.h +1 -0
diff -uNr linux-2.5.52/include/asm-i386/unistd.h linux-2.5.52.x86kexec-2/include/asm-i386/unistd.h
@@ -264,6 +264,7 @@
 #define __NR_epoll_wait		256
 #define __NR_remap_file_pages	257
 #define __NR_set_tid_address	258
+#define __NR_sys_kexec_load	259
 
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
include/linux/kexec.h +54 -0

54 lines not on this page · raw message

include/linux/reboot.h +2 -0
diff -uNr linux-2.5.52/include/linux/reboot.h linux-2.5.52.x86kexec-2/include/linux/reboot.h
@@ -21,6 +21,7 @@
  * POWER_OFF   Stop OS and remove all power from system, if possible.
  * RESTART2    Restart system using given command string.
  * SW_SUSPEND  Suspend system using Software Suspend if compiled in
+ * KEXEC       Restart the system using a different kernel.
  */
 
 #define	LINUX_REBOOT_CMD_RESTART	0x01234567
@@ -30,6 +31,7 @@
 #define	LINUX_REBOOT_CMD_POWER_OFF	0x4321FEDC
 #define	LINUX_REBOOT_CMD_RESTART2	0xA1B2C3D4
 #define	LINUX_REBOOT_CMD_SW_SUSPEND	0xD000FCE2
+#define LINUX_REBOOT_CMD_KEXEC		0x45584543
 
 
 #ifdef __KERNEL__
kernel/Makefile +1 -0
diff -uNr linux-2.5.52/kernel/Makefile linux-2.5.52.x86kexec-2/kernel/Makefile
@@ -21,6 +21,7 @@
 obj-$(CONFIG_CPU_FREQ) += cpufreq.o
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
+obj-$(CONFIG_KEXEC) += kexec.o
 obj-$(CONFIG_COMPAT) += compat.o
 
 ifneq ($(CONFIG_IA64),y)
kernel/kexec.c +547 -0

547 lines not on this page · raw message

kernel/sys.c +23 -0
diff -uNr linux-2.5.52/kernel/sys.c linux-2.5.52.x86kexec-2/kernel/sys.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/highuid.h>
 #include <linux/fs.h>
+#include <linux/kexec.h>
 #include <linux/workqueue.h>
 #include <linux/device.h>
 #include <linux/times.h>
@@ -207,6 +208,7 @@
 cond_syscall(sys_lookup_dcookie)
 cond_syscall(sys_swapon)
 cond_syscall(sys_swapoff)
+cond_syscall(sys_kexec_load)
 cond_syscall(sys_init_module)
 cond_syscall(sys_delete_module)
 
@@ -419,6 +421,27 @@
 		machine_restart(buffer);
 		break;
 
+#ifdef CONFIG_KEXEC
+	case LINUX_REBOOT_CMD_KEXEC:
+	{
+		struct kimage *image;
+		if (arg) {
+			unlock_kernel();
+			return -EINVAL;
+		}
+		image = xchg(&kexec_image, 0);
+		if (!image) {
+			unlock_kernel();
+			return -EINVAL;
+		}
+		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
+		system_running = 0;
+		device_shutdown();
+		printk(KERN_EMERG "Starting new kernel\n");
+		machine_kexec(image);
+		break;
+	}
+#endif
 #ifdef CONFIG_SOFTWARE_SUSPEND
 	case LINUX_REBOOT_CMD_SW_SUSPEND:
 		if (!software_suspend_enabled) {
#1 lore raw
Quoted 11 lines · Eric W. Biederman

I have recently taken the time to dig through the internals of kexec to see if I could make my code any simpler and have managed to trim off about 100 lines, and have made the code much more obviously correct.

Anyway, I would love to know in what entertaining ways this code blows up, or if I get lucky and it doesn't. I probably will not reply back in a timely manner as I am off to visit my parents, for Christmas and New Years.

The good news is that it worked for me. Not only that, I have just managed to get lkcd to save a dump in memory and then write it out to disk after a kexec soft boot ! I haven't tried real panic cases yet (which probably won't work rightaway :) ) and have testing and tuning to do. But kexec seems to be looking good.

Have a wonderful new year.

Regards
Suparna

#2 lore raw
Quoted 5 lines · Suparna Bhattacharya

The good news is that it worked for me. Not only that, I have just managed to get lkcd to save a dump in memory and then write it out to disk after a kexec soft boot ! I haven't tried real panic cases yet (which probably won't work rightaway :) ) and have testing and tuning to do. But kexec seems to be looking good.

Nice. Any pointers besides lkcd.sourceforge.net

For the kexec on panic case there is a little code motion yet to be done so that no memory allocations need to happen. The big one is setting up a page table with the reboot code buffer identity mapped.

I am tempted to do the identity mapping of the reboot code buffer in init_mm, but for starters I will look at how complex it will be to have a spare mm just sitting around for that purpose. When I get to dealing with the architectures like the hammer, and the alpha where you always need page tables I will need to develop an architecture specific hook for building the page tables needed by the code residing in the reboot code buffer, (because virtual memory cannot be disabled), but that should be straight forward.

My goal is to have no locks on the kexec part of the panic path. And the current memory allocations are the only really bad part of that.

A dump question. Why doesn't the lkcd stuff use the normal ELF core dump format? allowing ``gdb vmlinux core'' to work?

Eric

#3 lore raw
Quoted 9 lines · Eric W. Biederman
Quoted 5 lines · Suparna Bhattacharya

The good news is that it worked for me. Not only that, I have just managed to get lkcd to save a dump in memory and then write it out to disk after a kexec soft boot ! I haven't tried real panic cases yet (which probably won't work rightaway :) ) and have testing and tuning to do. But kexec seems to be looking good.

Nice. Any pointers besides lkcd.sourceforge.net

I haven't posted this code to lkcd as yet - so far I'd only checked in the preparatory code reshuffle into lkcd cvs. There are still some things to improve and think about, but am planning to upgrade to the latest tree early next week and put things out, and then work on it incrementally.

Quoted 4 lines

For the kexec on panic case there is a little code motion yet to be done so that no memory allocations need to happen. The big one is setting up a page table with the reboot code buffer identity mapped.

I missed noticing that.
Bootimg avoided the allocation at this stage. It did something like this:

+static unsigned long get_identity_mapped_page(void) +{
+ set_pgd(pgd_offset(current->active_mm,
+ virt_to_phys(unity_page)), __pgd((_KERNPG_TABLE
+ _PAGE_PSE + (virt_to_phys(unity_page)&PGDIR_MASK))));
+ return (unsigned long)unity_page;
+}

where unity page is within directly mapped memory (not highmem).

Quoted 9 lines

I am tempted to do the identity mapping of the reboot code buffer in init_mm, but for starters I will look at how complex it will be to have a spare mm just sitting around for that purpose. When I get to dealing with the architectures like the hammer, and the alpha where you always need page tables I will need to develop an architecture specific hook for building the page tables needed by the code residing in the reboot code buffer, (because virtual memory cannot be disabled), but that should be straight forward.

A spare mm may be something which I could use for the crash dump pages mapping possibly simpler than the way it is maintained right now ... but haven't given enough thought to it yet.

Quoted 3 lines

My goal is to have no locks on the kexec part of the panic path. And the current memory allocations are the only really bad part of that.

OK.

Quoted 3 lines

A dump question. Why doesn't the lkcd stuff use the normal ELF core dump format? allowing ``gdb vmlinux core'' to work?

I guess its ultimately a choice of format, how much processing to do at dump time, vs afterwards prior to analysis, and whether it captures all aspects relevant for the kind of analysis intended. The lkcd dump format appears to designed in a way that makes it suitable for crash dumping kind of situations. It takes an approach of simplifying work at dump time (desirable). It enables pages to be dumped right away in any order with a header preceding the page dumped, which makes it easier to support extraction of information from truncated dumps. This also makes it easier to do selective dumping and placement of more critical data earlier in the dump.

Secondly, it retains the notion of pages being dumped by physical address, with interpretation/conversions from virt-to-phys on analysis being taken care of the analyser or convertor. For example there has been work on a post processor that generates a core file from the lkcd dump corresponding to a given task/address space context for analysis via gdb. Similarly there is a capibility in lcrash that lets one generate a (smaller) selected subset of dumped state from an existing dump, which can be mailed out from a remote site for analysis.

The tradeoff is that there is a bit of pre-processing that happens prior to analysis for generation of an index, or conversion depending on what analysis tool gets used. But that time is less crucial than actual dump time.

Am cc'ing lkcd-devel on this one - there are experts who can add to this or answer this question better than I can.

Regards
Suparna

Signature · 3 lines
Suparna Bhattacharya ([email protected])
Linux Technology Center
IBM Software Labs, India
#4 lore raw
Quoted 9 lines · Suparna Bhattacharya
Quoted 8 lines · Eric W. Biederman
Quoted 5 lines · Suparna Bhattacharya

The good news is that it worked for me. Not only that, I have just managed to get lkcd to save a dump in memory and then write it out to disk after a kexec soft boot ! I haven't tried real panic cases yet (which probably won't work rightaway :) ) and have testing and tuning to do. But kexec seems to be looking good.

Quoted 7 lines
Quoted 1 line

Nice. Any pointers besides lkcd.sourceforge.net

I haven't posted this code to lkcd as yet - so far I'd only checked in the preparatory code reshuffle into lkcd cvs. There are still some things to improve and think about, but am planning to upgrade to the latest tree early next week and put things out, and then work on it incrementally.

O.k.

Quoted 16 lines
Quoted 3 lines

For the kexec on panic case there is a little code motion yet to be done so that no memory allocations need to happen. The big one is setting up a page table with the reboot code buffer identity mapped.

I missed noticing that.
Bootimg avoided the allocation at this stage. It did something like this:

(quoted diff) +7 -0
+static unsigned long get_identity_mapped_page(void)
+{
+       set_pgd(pgd_offset(current->active_mm, 
+ 	virt_to_phys(unity_page)), __pgd((_KERNPG_TABLE 
+ 	_PAGE_PSE + (virt_to_phys(unity_page)&PGDIR_MASK))));
+       return (unsigned long)unity_page;
+}
Quoted 1 line

where unity page is within directly mapped memory (not highmem).

With unity_page being allocated ahead of time...
But there is some other trick it is pulling to make certain the intermediate page table entries are present. Spooky and I don't want to go there.

Quoted 9 lines
Quoted 8 lines

I am tempted to do the identity mapping of the reboot code buffer in init_mm, but for starters I will look at how complex it will be to have a spare mm just sitting around for that purpose. When I get to dealing with the architectures like the hammer, and the alpha where you always need page tables I will need to develop an architecture specific hook for building the page tables needed by the code residing in the reboot code buffer, (because virtual memory cannot be disabled), but that should be straight forward.

Quoted 3 lines

A spare mm may be something which I could use for the crash dump pages mapping possibly simpler than the way it is maintained right now ... but haven't given enough thought to it yet.

Given that it is likely only to be a temporary thing I doubt it will help. A very interesting question along those lines is how do you get at all of the memory you are dumping, especially in PAE mode. I have not seen the code that handles that part at all...

Eric

#5 lore raw
In reply to Suparna Bhattacharya
Quoted 3 lines · Suparna Bhattacharya
Quoted 2 lines · Eric W. Biederman

A dump question. Why doesn't the lkcd stuff use the normal ELF core dump format? allowing ``gdb vmlinux core'' to work?

Digesting.... Of the pieces I have no problem if a valid ELF core dump is written but gdb does not know what to do with it out of the box. The piece that disturbed me most is that the file format seemed to be mutating from release to release.

An ELF core dump consists of:
ELF header
ELF Program header
ELF Note segment
Data Segments...

All of the weird processor specific information can be stored as various ELF note types.

Compression of pages that are zero can be handled by treating them as BSS pages and not putting them in the image.

I do admit it would likely take an extra pass to generate the ELF program header if anything non-trivial like zero removal or
compression was going on. But at the same time that should also
quite dramatically reduce the per page overhead. A pure dump of ram on x86 should take only 2 or 3 segments.

Using physical addresses is no problem in an ELF core dump. The ELF program header has both physical and virtual addresses, and you just fill in the physical addresses.

I keep asking and thinking about ELF images, because they are simple, clean, extensible, and well documented. With an added bonus that using the allows a large degree of code reuse with existing tools.

[snip a good description of the usefulness of the existing core dump format]

Quoted 2 lines

Am cc'ing lkcd-devel on this one - there are experts who can add to this or answer this question better than I can.

Thanks,

Eric

#6 lore raw

PATCH 1/1 kexec for 2.5.54

In reply to Suparna Bhattacharya

O.k. I have switched to using the init_mm and premapping the reboot code buffer. I would have play with a fully private mm, but all of the functions to allocate one are private to kernel/fork.c and so to much of a pain to mess with, right now.

The code in machine_kexec now takes no locks and is drop dead simple, so it should be safe to call from a panic handler.

It is funny in making identity_map_page generic so it should work on all architectures, and using more kernel prebuilt functions the code actually got a little longer...

Linus if you would like to apply it, be my guest.

Suparna this should be a good base to build the kexec on panic code upon. Until I see it a little more in action this is as much as I can do to help.

And if this week goes on schedule I can do an Itanium port...

Eric

 MAINTAINERS                        |    8 
 arch/i386/Kconfig                  |   17 +
 arch/i386/kernel/Makefile          |    1 
 arch/i386/kernel/entry.S           |    1 
 arch/i386/kernel/machine_kexec.c   |  115 ++++++
 arch/i386/kernel/relocate_kernel.S |  107 ++++++
 include/asm-i386/kexec.h           |   23 +
 include/asm-i386/unistd.h          |    1 
 include/linux/kexec.h              |   54 +++
 include/linux/reboot.h             |    2 
 kernel/Makefile                    |    1 
 kernel/kexec.c                     |  629 +++++++++++++++++++++++++++++++++++++
 kernel/sys.c                       |   23 +
 13 files changed, 982 insertions
MAINTAINERS +8 -0
diff -uNr linux-2.5.54/MAINTAINERS linux-2.5.54.x86kexec/MAINTAINERS
@@ -1006,6 +1006,14 @@
 W:	http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
 S:	Maintained
 
+KEXEC
+P:	Eric Biederman
+M:	[email protected]
+M:	[email protected]
+W:	http://www.xmission.com/~ebiederm/files/kexec/
+L:	[email protected]
+S:	Maintained
+
 LANMEDIA WAN CARD DRIVER
 P:	Andrew Stanley-Jones
 M:	[email protected]
arch/i386/Kconfig +17 -0
diff -uNr linux-2.5.54/arch/i386/Kconfig linux-2.5.54.x86kexec/arch/i386/Kconfig
@@ -733,6 +733,23 @@
 	depends on (SMP || PREEMPT) && X86_CMPXCHG
 	default y
 
+config KEXEC
+	bool "kexec system call (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  kexec is a system call that implements the ability to  shutdown your
+	  current kernel, and to start another kernel.  It is like a reboot
+	  but it is indepedent of the system firmware.   And like a reboot
+	  you can start any kernel with it not just Linux.  
+	
+	  The name comes from the similiarity to the exec system call. 
+	
+	  It is on an going process to be certain the hardware in a machine
+	  is properly shutdown, so do not be surprised if this code does not
+	  initially work for you.  It may help to enable device hotplugging
+	  support.  As of this writing the exact hardware interface is
+	  strongly in flux, so no good recommendation can be made.
+
 endmenu
 
 
arch/i386/kernel/Makefile +1 -0
diff -uNr linux-2.5.54/arch/i386/kernel/Makefile linux-2.5.54.x86kexec/arch/i386/kernel/Makefile
@@ -25,6 +25,7 @@
 obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
+obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend.o suspend_asm.o
 obj-$(CONFIG_X86_NUMAQ)		+= numaq.o
 obj-$(CONFIG_PROFILING)		+= profile.o
arch/i386/kernel/entry.S +1 -0
diff -uNr linux-2.5.54/arch/i386/kernel/entry.S linux-2.5.54.x86kexec/arch/i386/kernel/entry.S
@@ -804,6 +804,7 @@
 	.long sys_epoll_wait
  	.long sys_remap_file_pages
  	.long sys_set_tid_address
+	.long sys_kexec_load
 
 
 	.rept NR_syscalls-(.-sys_call_table)/4
arch/i386/kernel/machine_kexec.c +115 -0

115 lines not on this page · raw message

arch/i386/kernel/relocate_kernel.S +107 -0

107 lines not on this page · raw message

include/asm-i386/kexec.h +23 -0
diff -uNr linux-2.5.54/include/asm-i386/kexec.h linux-2.5.54.x86kexec/include/asm-i386/kexec.h
@@ -0,0 +1,23 @@
+#ifndef _I386_KEXEC_H
+#define _I386_KEXEC_H
+
+#include <asm/fixmap.h>
+
+/*
+ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
+ * I.e. Maximum page that is mapped directly into kernel memory,
+ * and kmap is not required.
+ *
+ * Someone correct me if FIXADDR_START - PAGEOFFSET is not the correct
+ * calculation for the amount of memory directly mappable into the
+ * kernel memory space.
+ */
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+
+#define KEXEC_REBOOT_CODE_SIZE	4096
+
+#endif /* _I386_KEXEC_H */
include/asm-i386/unistd.h +1 -0
diff -uNr linux-2.5.54/include/asm-i386/unistd.h linux-2.5.54.x86kexec/include/asm-i386/unistd.h
@@ -262,6 +262,7 @@
 #define __NR_epoll_wait		256
 #define __NR_remap_file_pages	257
 #define __NR_set_tid_address	258
+#define __NR_sys_kexec_load	259
 
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
include/linux/kexec.h +54 -0

54 lines not on this page · raw message

include/linux/reboot.h +2 -0
diff -uNr linux-2.5.54/include/linux/reboot.h linux-2.5.54.x86kexec/include/linux/reboot.h
@@ -21,6 +21,7 @@
  * POWER_OFF   Stop OS and remove all power from system, if possible.
  * RESTART2    Restart system using given command string.
  * SW_SUSPEND  Suspend system using Software Suspend if compiled in
+ * KEXEC       Restart the system using a different kernel.
  */
 
 #define	LINUX_REBOOT_CMD_RESTART	0x01234567
@@ -30,6 +31,7 @@
 #define	LINUX_REBOOT_CMD_POWER_OFF	0x4321FEDC
 #define	LINUX_REBOOT_CMD_RESTART2	0xA1B2C3D4
 #define	LINUX_REBOOT_CMD_SW_SUSPEND	0xD000FCE2
+#define LINUX_REBOOT_CMD_KEXEC		0x45584543
 
 
 #ifdef __KERNEL__
kernel/Makefile +1 -0
diff -uNr linux-2.5.54/kernel/Makefile linux-2.5.54.x86kexec/kernel/Makefile
@@ -21,6 +21,7 @@
 obj-$(CONFIG_CPU_FREQ) += cpufreq.o
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
+obj-$(CONFIG_KEXEC) += kexec.o
 obj-$(CONFIG_COMPAT) += compat.o
 
 ifneq ($(CONFIG_IA64),y)
kernel/kexec.c +629 -0

629 lines not on this page · raw message

kernel/sys.c +23 -0
diff -uNr linux-2.5.54/kernel/sys.c linux-2.5.54.x86kexec/kernel/sys.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/highuid.h>
 #include <linux/fs.h>
+#include <linux/kexec.h>
 #include <linux/workqueue.h>
 #include <linux/device.h>
 #include <linux/times.h>
@@ -207,6 +208,7 @@
 cond_syscall(sys_lookup_dcookie)
 cond_syscall(sys_swapon)
 cond_syscall(sys_swapoff)
+cond_syscall(sys_kexec_load)
 cond_syscall(sys_init_module)
 cond_syscall(sys_delete_module)
 
@@ -419,6 +421,27 @@
 		machine_restart(buffer);
 		break;
 
+#ifdef CONFIG_KEXEC
+	case LINUX_REBOOT_CMD_KEXEC:
+	{
+		struct kimage *image;
+		if (arg) {
+			unlock_kernel();
+			return -EINVAL;
+		}
+		image = xchg(&kexec_image, 0);
+		if (!image) {
+			unlock_kernel();
+			return -EINVAL;
+		}
+		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
+		system_running = 0;
+		device_shutdown();
+		printk(KERN_EMERG "Starting new kernel\n");
+		machine_kexec(image);
+		break;
+	}
+#endif
 #ifdef CONFIG_SOFTWARE_SUSPEND
 	case LINUX_REBOOT_CMD_SW_SUSPEND:
 		if (!software_suspend_enabled) {
#7 lore raw

Re: [PATCH] kexec for 2.5.54

Quoted 3 lines · Eric W. Biederman

O.k. I have switched to using the init_mm and premapping the reboot code buffer.

<snip>

Quoted 2 lines

The code in machine_kexec now takes no locks and is drop dead simple, so it should be safe to call from a panic handler.

Eric,

The patch applies cleanly to 2.5.54 for me. Current behavior matches the version of kexec for 2.5.48 that I carried forward into 2.5.52 and 2.5.54 (and kexec_tools 1.8):

- the kexec-ed kernel starts rebooting and finds all of my system's memory, so the generic kexec machinery is working as expected.

- the kexec-ed kernel hangs while calibrating the delay loop. The list of kernels I attempted to reboot includes permutations of 2.5.48 +/- kexec, 2.5.52 +/- kexec(from 2.5.48), 2.5.54, 2.5.54 + kexec(from 2.5.48), and 2.5.54 + kexec (recent patch from you).

- Whatever it is that SuSE supplies in 8.0 (2.4.x +) panics near/during frame buffer initialization when rebooted via kexec for 2.5.54:

	.
	.
	.
	Initializing CPU#0
	Detected 799.665 MHz Processor
	Console: colour VGA+ 80x25
	invalid operand: 0000
	CPU: 0
	EIP: 0010[<00000007>] Not tainted
	EFLAGS 00010002
	.
	.
	.

Something has definitely changed in the 2.5.5x series, and the symptoms indicate that at least the clock interrupt is not being received.

kexec for 2.5.48 worked for me (with some limits), so I should be able to walk the tree forwards and poke at it some more.

For those that have had success w/ recent vintage kernels and kexec (> 2.5.48), could I get a roll-call of your machine's hardware? Uniproc, SMP, AGP, chipset, BIOS version, that kind of thing. lspci -v, /cat/proc/cpuinfo, and maybe the boot-up messages would all be appreciated.

Regards,
Andy

#8 lore raw

Re: [PATCH] kexec for 2.5.54

... taking poor Linus off the cc list

Quoted 5 lines · Andy Pfiffer

For those that have had success w/ recent vintage kernels and kexec (> 2.5.48), could I get a roll-call of your machine's hardware? Uniproc, SMP, AGP, chipset, BIOS version, that kind of thing. lspci -v, /cat/proc/cpuinfo, and maybe the boot-up messages would all be appreciated.

I've had it work on 2 IBM x86 boxes.
4/8-way SMP
1/4/16 GB RAM
no AGP
Intel Profusion Chipset and some funky IBM one

It failed on the NUMA-Q's I tried it on. I haven't investigated any more thoroughly.

If you want more details, let me know. But, I've never seen your "Calibrating delay loop..." problem. The last time I saw problems there was when I broke the interrupt stack patches. But, since those aren't in mainline, you shouldn't be seeing it.

Signature · 2 lines
Dave Hansen
[email protected]
#9 lore raw

Re: [PATCH] kexec for 2.5.54

Quoted 14 lines

... taking poor Linus off the cc list

Quoted 5 lines · Andy Pfiffer

For those that have had success w/ recent vintage kernels and kexec (> 2.5.48), could I get a roll-call of your machine's hardware? Uniproc, SMP, AGP, chipset, BIOS version, that kind of thing. lspci -v, /cat/proc/cpuinfo, and maybe the boot-up messages would all be appreciated.

I've had it work on 2 IBM x86 boxes.
4/8-way SMP
1/4/16 GB RAM
no AGP
Intel Profusion Chipset and some funky IBM one

Quoted 3 lines

It failed on the NUMA-Q's I tried it on. I haven't investigated any more thoroughly.

If you want more details, let me know. But, I've never seen your "Calibrating delay loop..." problem. The last time I saw problems there was when I broke the interrupt stack patches. But, since those aren't in mainline, you shouldn't be seeing it.

Last time I saw calibrating delay loop problems, it just mean the other CPUs weren't getting / acting upon IPIs. I might expect that on NUMA-Q, but the INIT, INIT, STARTUP sequence on normal machines should kick the remote proc pretty damned hard and reset it. You might want to add more APIC resetting things (I think there are some in there that only NUMA-Q does right now .. try turning those on).

M.

#10 lore raw

[2.5.58][KEXEC] Success! (using 2.5.54 version + kexec tools 1.8)

In reply to Eric W. Biederman

Eric,

Success!

I've been carrying your kexec for 2.5.54 patch (and the hwfixes patch) forward through subsequent kernels, and have had good luck (kexec works fine for me) with them in 2.5.58 on my troublesome system (UP, P3-800, 640MB, Adaptec AIC7XXX SCSI).

I haven't had to change a thing with kexec. For reference, the code I'm currently using is downloadable from OSDL's patch-manager:

The "kexec-hwfixes" for to 2.5.58:
http://www.osdl.org/cgi-bin/plm?module=patch_info&patch_id=1432

kexec patch for 2.5.58 (from the 2.5.54 version):
http://www.osdl.org/cgi-bin/plm?module=patch_info&patch_id=1424

Regards,
Andy

#11 lore raw

2.5.54: Re: [PATCH][CFT] kexec (rewrite) for 2.5.52

In reply to Suparna Bhattacharya
Quoted 7 lines · Suparna Bhattacharya
Quoted 6 lines · Eric W. Biederman

I have recently taken the time to dig through the internals of kexec to see if I could make my code any simpler and have managed to trim off about 100 lines, and have made the code much more obviously correct.

Quoted 5 lines
Quoted 5 lines

Anyway, I would love to know in what entertaining ways this code blows up, or if I get lucky and it doesn't. I probably will not reply back in a timely manner as I am off to visit my parents, for Christmas and New Years.

Eric,

The patch applied cleanly to 2.5.54 for me.

The kexec portion works just fine and the reboot discovers all of the memory on my system using kexec_tools 1.8.

However, something has recently changed in the 2.5.5x series that causes the reboot to hang while calibrating the delay loop after a kexec reboot:

setup16_end: 00091b2f
Synchronizing SCSI caches:
Shutting down devices
Starting new kernel
Linux version 2.5.54 (andyp@joe) (gcc version 2.95.3 20010315 (SuSE)) #2 SMP Fri Jan 3 21:36:51 PST 2003
Video mode to be used for restore is ffff
BIOS-provided physical RAM map:
BIOS-e820: 0000000000000000 - 000000000009dc00 (usable)
BIOS-e820: 000000000009dc00 - 00000000000a0000 (reserved)
BIOS-e820: 0000000000100000 - 0000000027fed140 (usable)
BIOS-e820: 0000000027fed140 - 0000000027ff0000 (ACPI data)
BIOS-e820: 0000000027ff0000 - 0000000028000000 (reserved)
BIOS-e820: 00000000fec00000 - 0000000100000000 (reserved)
639MB LOWMEM available.
found SMP MP-table at 0009ddd0
hm, page 0009d000 reserved twice.
hm, page 0009e000 reserved twice.
hm, page 0009d000 reserved twice.
hm, page 0009e000 reserved twice.
WARNING: MP table in the EBDA can be UNSAFE, contact [email protected] if you experience SMP problems!
On node 0 totalpages: 163821
DMA zone: 4096 pages, LIFO batch:1
Normal zone: 159725 pages, LIFO batch:16
HighMem zone: 0 pages, LIFO batch:1
Intel MultiProcessor Specification v1.4
Virtual Wire compatibility mode.
OEM ID: IBM ENSW Product ID: xSeries 220 APIC at: 0xFEE00000 Processor #0 6:8 APIC version 17
I/O APIC #14 Version 17 at 0xFEC00000.
I/O APIC #13 Version 17 at 0xFEC01000.
Enabling APIC mode: Flat. Using 2 I/O APICs
Processors: 1
IBM machine detected. Enabling interrupts during APM calls. IBM machine detected. Disabling SMBus accesses.
Building zonelist for node : 0
Kernel command line: auto BOOT_IMAGE=linux-2.5 ro root=805 console=ttyS0,9600n8
Initializing
CPU#0
Detected 799.578 MHz processor.
Console: colour VGA+ 80x25
Calibrating delay loop...

<wedged>

This happens with -and- without the separate "hwfixes" chunk of code (that patch carries forward and continues to apply cleanly).

It would appear that clock interrupts are no long arriving (ticks always equals jiffies).

You can download the kexec patches for 2.5.54 from OSDL's PLM service:
(apologies in advance for the long URL):
https://www.osdl.org/cgi-bin/plm?module=search&search_patch=kexec-rewrite&search_created=Anytime&search_format=detailed&action=run_patch_search&sort_field=idDESC

If the URL is mangled, go here:
https://www.osdl.org/cgi-bin/plm?module=search
and then put "kexec-rewrite" into the "Patch Name or ID" box, and then press "Submit Query".

Key:
kexec-rewrite-2.5.54-1-of-3-1 == your rewrite from 2002-12-22 kexec-rewrite-2.5.54-2-of-3-1 == your "hwfixes" from 2.5.48ish kexec-rewrite-2.5.54-3-of-3-1 == ignore it (changes CONFIG_KEXEC=y for PLM)

Regards,
Andy

#12 lore raw

Re: 2.5.54: Re: [PATCH][CFT] kexec (rewrite) for 2.5.52

Quoted 10 lines · Andy Pfiffer

Eric,

The patch applied cleanly to 2.5.54 for me.

The kexec portion works just fine and the reboot discovers all of the memory on my system using kexec_tools 1.8.

However, something has recently changed in the 2.5.5x series that causes the reboot to hang while calibrating the delay loop after a kexec reboot:

Thanks I will take a look. It looks like something is definitely having interrupt problems...

BTW, Have you tried booting an older kernel?
That would help indicate where the problem is. I am pretty certain it is from somewhere in the kernels initialization path.

Eric

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

#16 lore raw

PATCH 1/1 Using kexec for crash dumps in LKCD

This is an extension to LKCD to make use of Eric Biederman's kexec implementation to delay the actual writeout of a crashdump to disk to happen after a memory preserving reboot of a new kernel.

The real thanks for this goes to Dave Winchell and the rest of the Mission Critical Linux folks for first implementing such an approach in mcore using Werner Alamesberger's bootimg, and letting us learn and borrow ideas from it.

There is a subtle but crucial difference in the design of the scheme we use to get spare pages to save the dump which potentially enables us to save a complete memory snapshot (not just kernel pages) if we can get a good compression efficiency (i.e. theoretically limited only by the degree of compressability of the memory state and working memory space that must be left for the dump and kernel bootup code).

This code is still somewhat raw and there's a list of todo's and improvements in my mind, and loopholes to fix, but I decided it was high time to put this out for a start, so anyone who is interested could start taking a look and playing with it, and maybe help out if they like.

I plan to fold it into lkcd cvs tomorrow if possible unless anyone notices a major regression of existing lkcd functionality (i.e. without CONFIG_CRASHDUMP_MEMDEV and CRASH_DUMP_SOFT_BOOT). I have tried out Alt+Sysrq+d and a simple panic from a module as a sanity check.

(I haven't tried it out for a true panic yet - going there bit by bit :))

In any case, I'll tag the cvs tree before checking in.

Merging and testing has been rather time consuming, so would appreciate if anyone planning to check in any changes before I do would let me know ahead of time.

I'm considering also checkin in a TODO file at the top of the 2.5 directory in CVS to keep track of what needs to be done. Would that be a good idea ? I'll probably also post the TODOs on the mailing list.

OK, going ahead:

Steps to use:
--------------

A. Patching the kernel:
1) Patch vanilla 2.5.59 kernel with the kexec patches for 2.5.59.
I picked the ones from the OSDL site which Andy Pfiffer had mentioned in an earlier post
kexec for 2.5.59 (based upon the version for 2.5.54)

	http://www.osdl.org/cgi-bin/plm?module=patch_info&patch_id=1442

	hwfixes that makes it work for me (same as for 2.5.58):
	http://www.osdl.org/cgi-bin/plm?module=patch_info&patch_id=1444

2) Apply the latest dump patches from lkcd cvs
i.e. apply the kernel patches under 2.5/patches
(expect to see one reject in the 2nd hunk for reboot.c
when applying notify_die.patch - you could ignore it for now)
and copy the dump driver files at the appropriate places

3) Apply the attached patch (kexecdump.patch)

B. Kernel Build Configuration settings
You'll need CRASH_DUMP to be built into the kernel (not as a module) to be able to dump across a kexec boot CRASH_DUMP_BLOCKDEV, CRASH_DUMP_COMPRESS_GZIP are needed as we use them today
New options you'll need CRASH_DUMP_MEMDEV (memory dump driver) and CRASH_DUMP_SOFTBOOT (kexec based dumping)

C. Run-time setup
A new dump flag for memory-save-and-dump-after-boot DUMP_FLAGS_SOFTBOOT has been introduced (0x2), which would need to be turned on in the dump flags.

After running lkcd config as usual, there is one extra step needed to load the kernel to be kexec'ed This involves executing "kexec -l" with the regular command line options (derived from you /proc/cmdline) and one extra boot parameter, obtained as follows:
crashdump=cat /proc/sys/kernel/dump/addr (This tells the new kernel where to find a saved in-memory crash dump from previous boot)

   e.g.
   kexec -l --command-line="root=806 console=tty0 console=
   ttyS0,38400 crashdump=`cat /proc/sys/kernel/dump/addr`"	
   <kernel bzImage>

D. On panic, the dump is saved in memory and then kexec is
used to boot up a new kernel (instead of a regular reboot) If Alt+Sysrq+d is pressed then the dump is just saved in memory without rebooting

[Note: The first few times you try it, it might be a good idea to drop into "init 1" and unmount most filesystems or remount them as read-only , before you force the panic
- thanks to Andy Pfiffer for the tip ]

E. After running "lkcd config" triggers a writeout
to the dump disk of the previously saved dump in memory.

F. From here on, one can run "lkcd save" as usual to generate
the /var/log/dump/* files for analysis.

Regards
Suparna

Signature · 3 lines
Suparna Bhattacharya ([email protected])
Linux Technology Center
IBM Software Labs, India
arch/i386/Kconfig +17 -0
diff -urN -X ../dontdiff linux-2.5.59/arch/i386/Kconfig linux-2.5.59-kexecdump/arch/i386/Kconfig
@@ -1577,6 +1577,23 @@
 	help
 	  Say Y to allow saving crash dumps over a network device.
 
+config CRASH_DUMP_MEMDEV
+	bool "Crash dump staged memory driver"
+	depends on CRASH_DUMP
+	help
+	  Say Y to allow intermediate saving crash dumps in spare 
+	  memory pages which would then be written out to disk
+	  later.
+
+config CRASH_DUMP_SOFTBOOT
+	bool "Save crash dump across a soft reboot"
+	depends on CRASH_DUMP_MEMDEV
+	help
+	  Say Y to allow a crash dump to be preserved in memory
+	  pages across a soft reboot and written out to disk
+	  thereafter. For this to work, CRASH_DUMP must be 
+	  configured as part of the kernel (not as a module).
+
 config CRASH_DUMP_COMPRESS_RLE
 	tristate "Crash dump RLE compression"
 	depends on CRASH_DUMP
arch/i386/kernel/setup.c +10 -0
diff -urN -X ../dontdiff linux-2.5.59/arch/i386/kernel/setup.c linux-2.5.59-kexecdump/arch/i386/kernel/setup.c
@@ -503,6 +503,7 @@
 	print_memory_map(who);
 } /* setup_memory_region */
 
+unsigned long crashdump_addr = 0xdeadbeef;
 
 static void __init parse_cmdline_early (char ** cmdline_p)
 {
@@ -565,6 +566,9 @@
 		if (c == ' ' && !memcmp(from, "highmem=", 8))
 			highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT;
 	
+		if (c == ' ' && !memcmp(from, "crashdump=", 10))
+			crashdump_addr = memparse(from+10, &from); 
+			
 		c = *(from++);
 		if (!c)
 			break;
@@ -839,6 +843,8 @@
 		pci_mem_start = low_mem_size;
 }
 
+extern void crashdump_reserve(void);
+
 void __init setup_arch(char **cmdline_p)
 {
 	unsigned long max_low_pfn;
@@ -895,6 +901,10 @@
 	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
 #endif
 	paging_init();
+
+#ifdef CONFIG_CRASH_DUMP_SOFTBOOT
+	crashdump_reserve(); /* Preserve crash dump state from prev boot */
+#endif
 #ifdef CONFIG_ACPI_BOOT
 	/*
 	 * Parse the ACPI tables for possible boot-time SMP configuration.
drivers/dump/Makefile +1 -0
diff -urN -X ../dontdiff linux-2.5.59/drivers/dump/Makefile linux-2.5.59-kexecdump/drivers/dump/Makefile
@@ -5,6 +5,7 @@
 
 dump-y					:= dump_setup.o dump_fmt.o dump_filters.o dump_scheme.o dump_execute.o
 dump-$(CONFIG_X86)			+= dump_i386.o
+dump-$(CONFIG_CRASH_DUMP_MEMDEV)	+= dump_memdev.o dump_overlay.o
 dump-objs				+= $(dump-y)
 
 obj-$(CONFIG_CRASH_DUMP)		+= dump.o
drivers/dump/dump_blockdev.c +6 -1
diff -urN -X ../dontdiff linux-2.5.59/drivers/dump/dump_blockdev.c linux-2.5.59-kexecdump/drivers/dump/dump_blockdev.c
@@ -61,14 +61,19 @@
 	int len) 
 {
 	struct bio *bio = dev->bio;
+	unsigned long bsize = 0;
 
 	if (!bio->bi_vcnt)
 		return 0; /* first time, not mapped */
 
 
-	if ((bio_page(bio) != page) || (len != bio->bi_vcnt << PAGE_SHIFT)) 
+	if ((bio_page(bio) != page) || (len > bio->bi_vcnt << PAGE_SHIFT))
 		return 0; /* buffer not mapped */
 
+	bsize = bdev_hardsect_size(bio->bi_bdev);
+	if ((len & (PAGE_SIZE - 1)) || (len & bsize))
+		return 0; /* alignment checks needed */
+
 	/* quick check to decide if we need to redo bio_add_page */
 	if (bdev_get_queue(bio->bi_bdev)->merge_bvec_fn)
 		return 0; /* device may have other restrictions */
drivers/dump/dump_execute.c +8 -6
diff -urN -X ../dontdiff linux-2.5.59/drivers/dump/dump_execute.c linux-2.5.59-kexecdump/drivers/dump/dump_execute.c
@@ -22,8 +22,6 @@
 #include <linux/dump.h>
 #include "dump_methods.h"
 
-extern int dump_device;
-
 struct notifier_block *dump_notifier_list; /* dump started/ended callback */
 
 /* Dump progress indicator */
@@ -84,7 +82,7 @@
 /* Saves all dump data */
 int dump_execute_savedump(void)
 {
-	int ret = 0;
+	int ret = 0, err = 0;
 
 	if ((ret = dump_begin()))  {
 		return ret;
@@ -93,7 +91,9 @@
 	if (dump_config.level != DUMP_LEVEL_HEADER) { 
 		ret = dump_sequencer();
 	}
-	dump_complete();
+	if ((err = dump_complete())) {
+		printk("Dump complete failed. Error %d\n", err);
+	}
 
 	return ret;
 }
@@ -109,7 +109,8 @@
 	}
 
 	/* tell interested parties that a dump is about to start */
-	notifier_call_chain(&dump_notifier_list, DUMP_BEGIN, &dump_device);
+	notifier_call_chain(&dump_notifier_list, DUMP_BEGIN, 
+		&dump_config.dump_device);
 
 	if (dump_config.level != DUMP_LEVEL_NONE)
 		ret = dump_execute_savedump();
@@ -118,7 +119,8 @@
 		dump_config.dumper->count, DUMP_BUFFER_SIZE);
 	
 	/* tell interested parties that a dump has completed */
-	notifier_call_chain(&dump_notifier_list, DUMP_END, &dump_device);
+	notifier_call_chain(&dump_notifier_list, DUMP_END, 
+		&dump_config.dump_device);
 
 	return ret;
 }
drivers/dump/dump_fmt.c +6 -6
diff -urN -X ../dontdiff linux-2.5.59/drivers/dump/dump_fmt.c linux-2.5.59-kexecdump/drivers/dump/dump_fmt.c
@@ -88,6 +88,7 @@
 /*
  *  Set up common header fields (mainly the arch indep section) 
  *  Per-cpu state is handled by lcrash_save_context
+ *  Returns the size of the header in bytes.
  */
 static int lcrash_init_dump_header(const char *panic_str)
 {
@@ -154,7 +155,7 @@
 
 	dump_header_asm.dha_dumping_cpu = smp_processor_id();
 	
-	return 0;
+	return sizeof(dump_header) + sizeof(dump_header_asm);
 }
 
 
@@ -163,8 +164,7 @@
 {
 	int retval = 0;
 
-	if ((retval = lcrash_init_dump_header(panic_str))) 
-		return retval;
+	dump_config.dumper->header_len = lcrash_init_dump_header(panic_str);
 
 	/* capture register states for all processors */
 	dump_save_this_cpu(regs);
@@ -212,10 +212,10 @@
 	size = sizeof(dump_header);
 	memcpy(buf + size, (void *)&dump_header_asm, sizeof(dump_header_asm));
 	size += sizeof(dump_header_asm);
-	/* assuming header is dump buffer size always ? */
-	retval = dump_ll_write(buf , DUMP_BUFFER_SIZE);
+	size = PAGE_ALIGN(size);
+	retval = dump_ll_write(buf , size);
 
-	if (retval < DUMP_BUFFER_SIZE) 
+	if (retval < size) 
 		return (retval >= 0) ? ENOSPC : retval;
 
 	return 0;
drivers/dump/dump_memdev.c +640 -0

640 lines not on this page · raw message

drivers/dump/dump_methods.h +34 -0
diff -urN -X ../dontdiff linux-2.5.59/drivers/dump/dump_methods.h linux-2.5.59-kexecdump/drivers/dump/dump_methods.h
@@ -139,6 +139,7 @@
 	void *curr_buf; /* current position in the dump buffer */
 	void *dump_buf; /* starting addr of dump buffer */
 	int header_dirty; /* whether the header needs to be written out */
+	int header_len; 
 	struct list_head dumper_list; /* links to other dumpers */
 };	
 
@@ -147,11 +148,32 @@
 	ulong level;
 	ulong flags;
 	struct dumper *dumper;
+	unsigned long dump_device;
+	unsigned long dump_addr; /* relevant only for in-memory dumps */
 	struct list_head dump_dev_list;
 };	
 
 extern struct dump_config dump_config;
 
+/* Used to save the dump config across a reboot for 2-stage dumps: 
+ * 
+ * Note: The scheme, format, compression and device type should be 
+ * registered at bootup, for this config to be sharable across soft-boot. 
+ * The function addresses could have changed and become invalid, and
+ * need to be set up again.
+ */
+struct dump_config_block {
+	u64 magic; /* for a quick sanity check after reboot */
+	struct dump_memdev memdev; /* handle to dump stored in memory */
+	struct dump_config config;
+	struct dumper dumper;
+	struct dump_scheme scheme;
+	struct dump_fmt fmt;
+	struct __dump_compress compress;
+	struct dump_data_filter filter_table[MAX_PASSES];
+	struct dump_anydev dev[MAX_DEVS]; /* target dump device */
+};
+
 
 /* Wrappers that invoke the methods for the current (active) dumper */
 
@@ -275,6 +297,8 @@
 
 /* Some pre-defined dumpers */
 extern struct dumper dumper_singlestage;
+extern struct dumper dumper_stage1;
+extern struct dumper dumper_stage2;
 
 /* These are temporary */
 #define DUMP_MASK_HEADER	DUMP_LEVEL_HEADER
@@ -287,6 +311,7 @@
 
 int dump_generic_execute(const char *panic_str, const struct pt_regs *regs);
 extern int dump_ll_write(void *buf, unsigned long len); 
+int dump_check_and_free_page(struct dump_memdev *dev, struct page *page);
 
 static inline void dumper_reset(void)
 {
@@ -308,7 +333,16 @@
 
 static inline void dump_free_mem(void *buf)
 {
+	struct page *page;
+
+	/* ignore reserved pages (e.g. post soft boot stage) */
+	if (buf && (page = virt_to_page(buf))) {
+		if (PageReserved(page))
+			return;
+	}
+
 	kfree(buf);
 }
 
+
 #endif /*  _LINUX_DUMP_METHODS_H */
drivers/dump/dump_overlay.c +848 -0

848 lines not on this page · raw message

drivers/dump/dump_scheme.c +15 -4
diff -urN -X ../dontdiff linux-2.5.59/drivers/dump/dump_scheme.c linux-2.5.59-kexecdump/drivers/dump/dump_scheme.c
@@ -151,7 +151,7 @@
 
 		if (!(dump_config.dumper->count & 0x3f)) {
 			/* Update the header every one in a while */
-			/* memset((void *)dump_buf, 'b', DUMP_BUFFER_SIZE);*/
+			memset((void *)dump_buf, 'b', DUMP_BUFFER_SIZE);
 			if ((ret = dump_update_header()) < 0) {
 				/* issue warning */
 				return ret;
@@ -167,6 +167,12 @@
 
 		/* --- Done with periodic chores -- */
 
+		/* 
+		 * extra bit of copying to simplify verification  
+		 * in the second kernel boot based scheme
+		 */
+		memcpy(dump_buf - DUMP_PAGE_SIZE, dump_buf + 
+			DUMP_BUFFER_SIZE - DUMP_PAGE_SIZE, DUMP_PAGE_SIZE);
 
 		/* now adjust the leftover bits back to the top of the page */
 		/* this case would not arise during stage 2 (passthru) */
@@ -267,7 +273,7 @@
 
 	/* Allocate the dump buffer and initialize dumper state */
 	/* Assume that we get aligned addresses */
-	if (!(buf = dump_alloc_mem(DUMP_BUFFER_SIZE + 2 * DUMP_PAGE_SIZE)))
+	if (!(buf = dump_alloc_mem(DUMP_BUFFER_SIZE + 3 * DUMP_PAGE_SIZE)))
 		return -ENOMEM;
 
 	if ((unsigned long)buf & (PAGE_SIZE - 1)) {
@@ -277,7 +283,7 @@
 	}
 
 	/* Initialize the rest of the fields */
-	dump_config.dumper->dump_buf = buf;
+	dump_config.dumper->dump_buf = buf + DUMP_PAGE_SIZE;
 	dumper_reset();
 
 	/* Open the dump device */
@@ -305,14 +311,19 @@
 	void *buf = dump_config.dumper->dump_buf;
 	int ret = 0;
 
+	pr_debug("Generic unconfigure\n");
 	/* Close the dump device */
 	if (dev && (ret = dev->ops->release(dev)))
 		return ret;
+
+	printk("Closed dump device\n");
 	
 	if (buf)
-		dump_free_mem(buf);
+		dump_free_mem((buf - DUMP_PAGE_SIZE));
 
 	dump_config.dumper->curr_buf = dump_config.dumper->dump_buf = NULL;
+	pr_debug("Released dump buffer\n");
+
 	return 0;
 }
 
drivers/dump/dump_setup.c +62 -9

145 lines not on this page · raw message

include/linux/dump.h +4 -1
diff -urN -X ../dontdiff linux-2.5.59/include/linux/dump.h linux-2.5.59-kexecdump/include/linux/dump.h
@@ -87,6 +87,7 @@
 
 /* dump flags - any dump-type specific flags -- add as necessary */
 #define DUMP_FLAGS_NONE		0x0	/* no flags are set for this dump   */
+#define DUMP_FLAGS_SOFTBOOT	0x2	/* 2 stage soft-boot based dump	    */
 
 #define DUMP_FLAGS_TARGETMASK	0xf0000000 /* handle special case targets   */
 #define DUMP_FLAGS_DISKDUMP	0x80000000 /* dump to local disk 	    */
@@ -107,6 +108,7 @@
 #define DUMP_COMPRESS_NAME	"compress"
 #define DUMP_LEVEL_NAME		"level"
 #define DUMP_FLAGS_NAME		"flags"
+#define DUMP_ADDR_NAME		"addr"
 
 #define DUMP_SYSRQ_KEY		'd'	/* key to use for MAGIC_SYSRQ key   */
 
@@ -117,7 +119,8 @@
 	CTL_DUMP_COMPRESS=3,
 	CTL_DUMP_LEVEL=3,
 	CTL_DUMP_FLAGS=4,
-	CTL_DUMP_TEST=5,
+	CTL_DUMP_ADDR=5,
+	CTL_DUMP_TEST=6,
 };
 
 
include/linux/dumpdev.h +38 -0
diff -urN -X ../dontdiff linux-2.5.59/include/linux/dumpdev.h linux-2.5.59-kexecdump/include/linux/dumpdev.h
@@ -70,6 +70,44 @@
 	return container_of(dev, struct dump_blockdev, ddev);
 }
 
+
+/* mem  - for internal use by soft-boot based dumper */
+struct dump_memdev {
+	struct dump_dev ddev;
+	unsigned long indirect_map_root;
+	unsigned long nr_free;
+	struct page *curr_page;
+	unsigned long *curr_map;
+	unsigned long curr_map_offset;
+	unsigned long last_offset;
+	unsigned long last_used_offset;
+	unsigned long last_bs_offset;
+};	
+
+static inline struct dump_memdev *DUMP_MDEV(struct dump_dev *dev)
+{
+	return container_of(dev, struct dump_memdev, ddev);
+}
+
+/* Todo/future - meant for raw dedicated interfaces e.g. mini-ide driver */
+struct dump_rdev {
+	struct dump_dev ddev;
+	char name[32];
+	int (*reset)(struct dump_rdev *, unsigned int, 
+		unsigned long);
+	/* ... to do ... */
+};
+
+/* just to get the size right when saving config across a soft-reboot */
+struct dump_anydev {
+	union {
+		struct dump_blockdev bddev;
+		/* .. add other types here .. */
+	};
+};
+
+
+
 /* Dump device / target operation wrappers */
 /* These assume that dump_dev is initiatized to dump_config.dumper->dev */
 
kernel/panic.c +11 -1
diff -urN -X ../dontdiff linux-2.5.59/kernel/panic.c linux-2.5.59-kexecdump/kernel/panic.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/sysrq.h>
 #include <linux/interrupt.h>
+#include <linux/kexec.h>
 
 asmlinkage void sys_sync(void);	/* it's really int */
 
@@ -74,13 +75,22 @@
 	 	 * Delay timeout seconds before rebooting the machine. 
 		 * We can't use the "normal" timers since we just panicked..
 	 	 */
+		struct kimage *image;
 		printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout);
-		mdelay(panic_timeout*1000);
 		/*
 		 *	Should we run the reboot notifier. For the moment Im
 		 *	choosing not too. It might crash, be corrupt or do
 		 *	more harm than good for other reasons.
 		 */
+#ifdef CONFIG_KEXEC
+		image = xchg(&kexec_image, 0);
+		if (image) {
+			printk(KERN_EMERG "by starting a new kernel ..\n");
+			mdelay(panic_timeout*1000);
+			machine_kexec(image);
+		}
+#endif
+		mdelay(panic_timeout*1000);
 		machine_restart(NULL);
 	}
 #ifdef __sparc__
#17 lore raw

Re: [PATCH][WIP] Using kexec for crash dumps in LKCD

I just checked in the changes for kexec based dumping into lkcd cvs after tagging the earlier code as "linux2559".

Brief Description/Recap from CVS log:
------------------------------------
Initial release of code to implement an option to save dump in memory and write it out later (CONFIG_CRASH_DUMP_MEMDEV).

In case of a panic dump, if CONFIG_CRASH_DUMP_SOFTBOOT is enabled and CONFIG_KEXEC is on, this would use Eric Biederman's kexec implementation to delay the actual writeout of the dump to disk to happen after a memory preserving reboot of a new kernel (along the lines of Mission Critical Linux's mcore implementation).
-------------------------------------

The first call to lkcd config after a boot would trigger the actual writeout to the dump disk/partition. And then lkcd save works as usual to copy the dump into /var/log/dump/<n>/

This is still in a somewhat raw/experimental form, made available for anyone who'd like to play with it early. To use it you'd need to apply the kexec patches along with lkcd. I'll try to put out a TODO list soon for some things that need to be done to stabilize, complete and simplify this.

The following patches to sbin.lkcd script and the sysconfig.dump file should be used with this. (kexec preloading gets automatically handled once you specify the image and kernel command line to use).

I've held back on checking in these particular changes for now as I wanted to be sure not to break anything for 2.4 lkcd users.

(BTW, is that also why the lkcd script still uses 227 as the dump device number rather than 221 ?)

Any suggestions on how to handle this best would be appreciated.

Regards
Suparna

Signature · 83 lines
Suparna Bhattacharya ([email protected])
Linux Technology Center
IBM Software Labs, India


--- sbin.lkcd	Mon Dec 16 15:52:51 2002
+++ /home/suparna/suparna/ras/dump/sbin.lkcd	Fri Feb  7 19:28:16 2003
@@ -14,6 +14,7 @@
 KERNTYPES=/boot/Kerntypes
 DUMPCONFIG=/sbin/lkcd_config
 DUMPSYSDEVICE=/dev/dump
+KEXEC=/sbin/kexec
 
 ###########################################################################
 # Functions
@@ -65,8 +66,37 @@
 
 	if [ $? -ne 0 ] ; then
 		echo "$DUMPCONFIG failed!" >&2
+		exit 1
+	fi
+
+	# Set things up for kexec based dumping if applicable
+
+	if [ ! -e /proc/sys/kernel/dump/addr ] ; then
+		return
+	fi
+
+	DUMP_ADDR=`cat /proc/sys/kernel/dump/addr`
+
+	if [ $DUMP_ADDR != 0 ] ; then
+		echo "Preloading kernel for kexec based dumping"
+	else
+		return
 	fi
 
+	if [ ! -e "$KEXEC_IMAGE" ] ; then
+		echo "KEXECIMAGE does not exist!" >&2
+		exit 1
+	fi
+
+	# Preload the kernel image to switch to on panic
+	echo $KEXEC -l \
+	--command-line="$KEXEC_CMDLINE crashdump=$DUMP_ADDR" \
+	$KEXEC_IMAGE
+
+	$KEXEC -l \
+	--command-line="$KEXEC_CMDLINE crashdump=$DUMP_ADDR" \
+	$KEXEC_IMAGE
+
 	return
 }
 
@@ -256,7 +286,7 @@
 
 # make sure system dump device exists -- otherwise, make it
 if [ ! -e $DUMPSYSDEVICE ] ; then
-	mknod $DUMPSYSDEVICE c 227 0
+	mknod $DUMPSYSDEVICE c 221 0
 	chmod 644 $DUMPSYSDEVICE
 fi
 
--- sysconfig.dump	Wed Dec  4 15:20:45 2002
+++ /home/suparna/suparna/ras/dump/sysconfig.dump	Fri Feb  7 20:32:39 2003
@@ -117,11 +117,15 @@
 DUMPDEV=/dev/vmdump
 DUMPDIR=/var/log/dump
 DUMP_SAVE=1
-DUMP_LEVEL=8
-DUMP_FLAGS=0x80000000 # disruptive disk dump is default
-DUMP_COMPRESS=0
+DUMP_LEVEL=2
+DUMP_FLAGS=0x80000002 # disruptive disk dump is default
+DUMP_COMPRESS=2
 PANIC_TIMEOUT=5
 
+# Only relevant for dumping via kexec
+KEXEC_IMAGE=/boot/kexec	
+KEXEC_CMDLINE="root=806 console=tty0 console=ttyS0,38400"
+
 # Network dump configuration parameters
 TARGET_HOST=hostname # set this to vaild hostname/IP
 TARGET_PORT=6666