Skip to contentSkip to conversation

kexec for 2.5.42

PATCH Eric W. Biederman 2 participants 2 messages Oct 17, 2002 – Oct 18, 2002 3 messages not in the archive kexec

lore
Share & tools
lore

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]

#3 lore raw

O.k. My first pass at getting up to date with the current kernel is available at:
http://www.xmission.com/~ebiederm/files/kexec/linux-2.5.42.kexec.x86.diff
http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.0.tar.gz

The big changes are:
1) I have rebundled my tools so it is a little easier to get at:
2) I have included a test case kexec_test that tests the stranger cases, so when the kernel doesn't boot, we can rule out the kexec code.
3) I have added a call to device_shutdown so device drivers get a chance to shut up.
4) I have moved kexec into its one system call instead of treating sys_reboot like an ioctl. The big reason is that while there is a lot of generic code some very architecture specific code must be written for each architecture, and having to register a system call means the code won't become active by accident.

I will probably split this up before sending to Linus but anyway, here is the patch so you can pick it apart and tell me what you don't like.

Eric

 MAINTAINERS                        |    7 
 arch/i386/Config.help              |   14 
 arch/i386/config.in                |    3 
 arch/i386/kernel/Makefile          |    1 
 arch/i386/kernel/apic.c            |   71 ++++
 arch/i386/kernel/dmi_scan.c        |   27 -
 arch/i386/kernel/entry.S           |    3 
 arch/i386/kernel/io_apic.c         |    2 
 arch/i386/kernel/machine_kexec.c   |  141 ++++++++
 arch/i386/kernel/reboot.c          |   32 -
 arch/i386/kernel/relocate_kernel.S |   84 ++++
 arch/i386/kernel/smp.c             |   24 +
 include/asm-i386/apicdef.h         |    1 
 include/asm-i386/kexec.h           |   25 +
 include/linux/kexec.h              |   49 ++
 kernel/Makefile                    |    3 
 kernel/kexec.c                     |  630 +++++++++++++++++++++++++++++++++++++
 kernel/sys.c                       |   59 +++
 18 files changed, 1116 insertions, 60 deletions
MAINTAINERS +7 -0
diff -uNrX linux-ignore-files linux-2.5.42.eb1/MAINTAINERS linux-2.5.42.kexec.x86/MAINTAINERS
@@ -934,6 +934,13 @@
 W:	http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
 S:	Maintained
 
+KEXEC
+P:	Eric Biederman
+M:	[email protected]
+M:	[email protected]
+L:	[email protected]
+S:	Maintained
+
 LANMEDIA WAN CARD DRIVER
 P:	Andrew Stanley-Jones
 M:	[email protected]
arch/i386/Config.help +14 -0
diff -uNrX linux-ignore-files linux-2.5.42.eb1/arch/i386/Config.help linux-2.5.42.kexec.x86/arch/i386/Config.help
@@ -411,6 +411,20 @@
   you have use for it; the module is called binfmt_misc.o. If you
   don't know what to answer at this point, say Y.
 
+CONFIG_KEXEC
+  kexec is a system call that implements kernel level exec support.
+  Or the ability to boot linux from linux.  The kexec system call
+  allows you to replace your current kernel with another kernel, 
+  not necessarily linux.
+
+  A known caveat is that for this to be fully useful all of the
+  devices must be shutdown.  One way to impelment this is to build
+  all devices as modules and remove them before rebooting.
+
+  You will probably want to dig up the elfboottools package as this
+  has the first implementation of a user client that uses this kernel
+  interface.
+
 CONFIG_M386
   This is the processor type of your CPU. This information is used for
   optimizing purposes. In order to compile a kernel that can run on
arch/i386/config.in +3 -0
diff -uNrX linux-ignore-files linux-2.5.42.eb1/arch/i386/config.in linux-2.5.42.kexec.x86/arch/i386/config.in
@@ -242,6 +242,9 @@
    fi
 fi
 
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   bool 'Kernel execing kernel support' CONFIG_KEXEC
+fi
 endmenu
 
 mainmenu_option next_comment
arch/i386/kernel/Makefile +1 -0
diff -uNrX linux-ignore-files linux-2.5.42.eb1/arch/i386/kernel/Makefile linux-2.5.42.kexec.x86/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
 obj-$(CONFIG_X86_NUMAQ)		+= numaq.o
 
arch/i386/kernel/apic.c +71 -0

107 lines not on this page · raw message

arch/i386/kernel/dmi_scan.c +1 -26
diff -uNrX linux-ignore-files linux-2.5.42.eb1/arch/i386/kernel/dmi_scan.c linux-2.5.42.kexec.x86/arch/i386/kernel/dmi_scan.c
@@ -204,31 +204,6 @@
 	return 0;
 }
 
-/*
- * Some machines require the "reboot=s"  commandline option, this quirk makes that automatic.
- */
-static __init int set_smp_reboot(struct dmi_blacklist *d)
-{
-#ifdef CONFIG_SMP
-	extern int reboot_smp;
-	if (reboot_smp == 0)
-	{
-		reboot_smp = 1;
-		printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.\n", d->ident);
-	}
-#endif
-	return 0;
-}
-
-/*
- * Some machines require the "reboot=b,s"  commandline option, this quirk makes that automatic.
- */
-static __init int set_smp_bios_reboot(struct dmi_blacklist *d)
-{
-	set_smp_reboot(d);
-	set_bios_reboot(d);
-	return 0;
-}
 
 /*
  * Some bioses have a broken protected mode poweroff and need to use realmode
@@ -519,7 +494,7 @@
 			MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
 			MATCH(DMI_BIOS_DATE, "134526184"), NO_MATCH
 			} },
-	{ set_smp_bios_reboot, "Dell PowerEdge 1300", {	/* Handle problems with rebooting on Dell 1300's */
+	{ set_bios_reboot, "Dell PowerEdge 1300", {	/* Handle problems with rebooting on Dell 1300's */
 			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
 			MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
 			NO_MATCH, NO_MATCH
arch/i386/kernel/entry.S +2 -1
diff -uNrX linux-ignore-files linux-2.5.42.eb1/arch/i386/kernel/entry.S linux-2.5.42.kexec.x86/arch/i386/kernel/entry.S
@@ -736,7 +736,8 @@
 	.long sys_alloc_hugepages /* 250 */
 	.long sys_free_hugepages
 	.long sys_exit_group
-
+	.long sys_kexec
+	
 	.rept NR_syscalls-(.-sys_call_table)/4
 		.long sys_ni_syscall
 	.endr
arch/i386/kernel/io_apic.c +0 -2
diff -uNrX linux-ignore-files linux-2.5.42.eb1/arch/i386/kernel/io_apic.c linux-2.5.42.kexec.x86/arch/i386/kernel/io_apic.c
@@ -1112,8 +1112,6 @@
 	 * Clear the IO-APIC before rebooting:
 	 */
 	clear_IO_APIC();
-
-	disconnect_bsp_APIC();
 }
 
 /*
arch/i386/kernel/machine_kexec.c +141 -0

141 lines not on this page · raw message

arch/i386/kernel/reboot.c +1 -31
diff -uNrX linux-ignore-files linux-2.5.42.eb1/arch/i386/kernel/reboot.c linux-2.5.42.kexec.x86/arch/i386/kernel/reboot.c
@@ -19,8 +19,7 @@
 int reboot_thru_bios;
 
 #ifdef CONFIG_SMP
-int reboot_smp = 0;
-static int reboot_cpu = -1;
+int reboot_cpu = -1;	  /* specifies the internal linux cpu id, not the apicid */
 /* shamelessly grabbed from lib/vsprintf.c for readability */
 #define is_digit(c)	((c) >= '0' && (c) <= '9')
 #endif
@@ -42,7 +41,6 @@
 			break;
 #ifdef CONFIG_SMP
 		case 's': /* "smp" reboot by executing reset on BSP or other CPU*/
-			reboot_smp = 1;
 			if (is_digit(*(str+1))) {
 				reboot_cpu = (int) (*(str+1) - '0');
 				if (is_digit(*(str+2))) 
@@ -224,34 +222,6 @@
 void machine_restart(char * __unused)
 {
 #if CONFIG_SMP
-	int cpuid;
-	
-	cpuid = GET_APIC_ID(apic_read(APIC_ID));
-
-	if (reboot_smp) {
-
-		/* check to see if reboot_cpu is valid 
-		   if its not, default to the BSP */
-		if ((reboot_cpu == -1) ||  
-		      (reboot_cpu > (NR_CPUS -1))  || 
-		      !(phys_cpu_present_map & (1<<cpuid))) 
-			reboot_cpu = boot_cpu_physical_apicid;
-
-		reboot_smp = 0;  /* use this as a flag to only go through this once*/
-		/* re-run this function on the other CPUs
-		   it will fall though this section since we have 
-		   cleared reboot_smp, and do the reboot if it is the
-		   correct CPU, otherwise it halts. */
-		if (reboot_cpu != cpuid)
-			smp_call_function((void *)machine_restart , NULL, 1, 0);
-	}
-
-	/* if reboot_cpu is still -1, then we want a tradional reboot, 
-	   and if we are not running on the reboot_cpu,, halt */
-	if ((reboot_cpu != -1) && (cpuid != reboot_cpu)) {
-		for (;;)
-		__asm__ __volatile__ ("hlt");
-	}
 	/*
 	 * Stop all CPUs and turn off local APICs and the IO-APIC, so
 	 * other OSs see a clean IRQ state.
arch/i386/kernel/relocate_kernel.S +84 -0

84 lines not on this page · raw message

arch/i386/kernel/smp.c +24 -0
diff -uNrX linux-ignore-files linux-2.5.42.eb1/arch/i386/kernel/smp.c linux-2.5.42.kexec.x86/arch/i386/kernel/smp.c
@@ -611,6 +611,30 @@
 
 void smp_send_stop(void)
 {
+	extern int reboot_cpu;
+	int reboot_cpu_id;
+
+ 	/* The boot cpu is always logical cpu 0 */
+	reboot_cpu_id = 0;
+
+	/* See if there has been give a command line override .
+	 */
+	if ((reboot_cpu != -1) && !(reboot_cpu >= NR_CPUS) && 
+		test_bit(reboot_cpu, &cpu_online_map)) {
+		reboot_cpu_id = reboot_cpu;
+	}
+	 
+	/* Make certain the the cpu I'm rebooting on is online */
+	if (!test_bit(reboot_cpu_id, &cpu_online_map)) {
+		reboot_cpu_id = smp_processor_id();
+	}
+
+	/* Make certain I only run on the appropriate processor */
+	set_cpus_allowed(current, 1 << reboot_cpu_id);
+
+	/* O.k. Now that I'm on the appropriate processor stop
+	 * all of the others.
+	 */
 	smp_call_function(stop_this_cpu, NULL, 1, 0);
 
 	local_irq_disable();
include/asm-i386/apicdef.h +1 -0
diff -uNrX linux-ignore-files linux-2.5.42.eb1/include/asm-i386/apicdef.h linux-2.5.42.kexec.x86/include/asm-i386/apicdef.h
@@ -86,6 +86,7 @@
 #define			APIC_LVT_REMOTE_IRR		(1<<14)
 #define			APIC_INPUT_POLARITY		(1<<13)
 #define			APIC_SEND_PENDING		(1<<12)
+#define			APIC_MODE_MASK			0x700
 #define			GET_APIC_DELIVERY_MODE(x)	(((x)>>8)&0x7)
 #define			SET_APIC_DELIVERY_MODE(x,y)	(((x)&~0x700)|((y)<<8))
 #define				APIC_MODE_FIXED		0x0
include/asm-i386/kexec.h +25 -0
diff -uNrX linux-ignore-files linux-2.5.42.eb1/include/asm-i386/kexec.h linux-2.5.42.kexec.x86/include/asm-i386/kexec.h
@@ -0,0 +1,25 @@
+#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 (FIXADDR_START - PAGE_OFFSET) 
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+
+#define KEXEC_REBOOT_CODE_SIZE	4096
+#define KEXEC_REBOOT_CODE_ALIGN 0
+
+
+#endif /* _I386_KEXEC_H */
include/linux/kexec.h +49 -0

49 lines not on this page · raw message

kernel/Makefile +3 -0
diff -uNrX linux-ignore-files linux-2.5.42.eb1/kernel/Makefile linux-2.5.42.kexec.x86/kernel/Makefile
@@ -19,6 +19,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
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
@@ -28,5 +29,7 @@
 # to get a correct value for the wait-channel (WCHAN in ps). --davidm
 CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer
 endif
+
+obj-$(CONFIG_KEXEC)             += kexec.o
 
 include $(TOPDIR)/Rules.make
kernel/kexec.c +630 -0

630 lines not on this page · raw message

kernel/sys.c +59 -0

71 lines not on this page · raw message

#4 lore raw
Quoted 2 lines · Eric W. Biederman

O.k. My first pass at getting up to date with the current kernel is available at:

Yipee! I was already having nightmares that we'd have to live without it for another major kernel release cycle.

I had a quick glance at it, and it looks quite lovely. You want to get rid of the load_elf_kernel prototype in include/linux/kexec.h, though :-)

Thanks,
- Werner

Signature · 3 lines
  _________________________________________________________________________
 / Werner Almesberger, Buenos Aires, Argentina         [email protected] /
/_http://www.almesberger.net/____________________________________________/