From: Heiko Carstens <heiko.carstens@de.ibm.com>

This patch is mostly based on comments which I received from Milton Miller
<miltonm@bga.com>.  Changes are:

- Fix passing of first argument to relocate_kernel assembly.
- Fix Kconfig description.
- Remove wrong comment and comments that describe obvious things.
- Allow only KEXEC_TYPE_DEFAULT as image type -> dump not supported.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 arch/s390/Kconfig                    |   14 --------
 arch/s390/kernel/machine_kexec.c     |   61 ++++++++---------------------------
 arch/s390/kernel/relocate_kernel.S   |   14 +++-----
 arch/s390/kernel/relocate_kernel64.S |   14 +++-----
 4 files changed, 27 insertions(+), 76 deletions(-)

diff -puN arch/s390/Kconfig~s390-kexec-fixes arch/s390/Kconfig
--- 25/arch/s390/Kconfig~s390-kexec-fixes	2005-04-28 23:11:21.976403248 -0700
+++ 25-akpm/arch/s390/Kconfig	2005-04-28 23:11:21.984402032 -0700
@@ -461,19 +461,7 @@ config KEXEC
 	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 an ongoing 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.
-
-	  In the GAMECUBE implementation, kexec allows you to load and
-	  run DOL files, including kernel and homebrew DOLs.
+	  but is independent of hardware/microcode support.
 
 endmenu
 
diff -puN arch/s390/kernel/machine_kexec.c~s390-kexec-fixes arch/s390/kernel/machine_kexec.c
--- 25/arch/s390/kernel/machine_kexec.c~s390-kexec-fixes	2005-04-28 23:11:21.977403096 -0700
+++ 25-akpm/arch/s390/kernel/machine_kexec.c	2005-04-28 23:11:21.985401880 -0700
@@ -22,29 +22,22 @@
 #include <asm/pgalloc.h>
 #include <asm/system.h>
 
-int machine_kexec_prepare(struct kimage *);
-void machine_kexec_cleanup(struct kimage *);
-void machine_shutdown(void);
-void machine_kexec(struct kimage *);
 static void kexec_halt_all_cpus(void *);
 
-typedef void (*relocate_kernel_t) (unsigned long indirection_page,
-				   unsigned long reboot_code_buffer,
-				   unsigned long start_address);
+typedef void (*relocate_kernel_t) (kimage_entry_t *, unsigned long);
 
 const extern unsigned char relocate_kernel[];
 const extern unsigned long long relocate_kernel_len;
 
-/*
- * Do whatever setup is needed on image and the reboot code buffer to
- * allow us to aviood allocations later.
- */
-
 int
-machine_kexec_prepare(struct kimage * image)
+machine_kexec_prepare(struct kimage *image)
 {
 	unsigned long reboot_code_buffer;
 
+	/* We don't support anything but the default image type for now. */
+	if (image->type != KEXEC_TYPE_DEFAULT)
+		return -EINVAL;
+
 	/* Get the destination where the assembler code should be copied to.*/
 	reboot_code_buffer = page_to_pfn(image->control_code_page)<<PAGE_SHIFT;
 
@@ -54,45 +47,20 @@ machine_kexec_prepare(struct kimage * im
 	return 0;
 }
 
-
-/*
- * We don't have to do anything here, because we didn't have to prepare
- * (i.e. allocate or the like) anything in 'machine_kexec_prepare'.
- */
 void
 machine_kexec_cleanup(struct kimage *image)
 {
 }
 
-/*
- * Just print a message in the kernel log.
- */
 void
 machine_shutdown(void)
 {
 	printk(KERN_INFO "kexec: machine_shutdown called\n");
 }
 
-/*
- * The addresses for the reboot_code_buffer, the indirection page and the
- * data_mover can already be assigned here.
- * Also, we can here clear all subchannels.
- * In any case we have to disable the lowcore protection, because we will
- * write a new PSW to address 0.
- * Then we call the function 'kexec_halt_all_cpus'.
- */
-
-static unsigned long indirection_page;
-static unsigned long reboot_code_buffer;
-static relocate_kernel_t data_mover;
-
 NORET_TYPE void
 machine_kexec(struct kimage *image)
 {
-	reboot_code_buffer = page_to_pfn(image->control_code_page)<<PAGE_SHIFT;
-	indirection_page = image->head & PAGE_MASK;
-	data_mover = (relocate_kernel_t) reboot_code_buffer;
-
 	clear_all_subchannels();
 
 	/* Disable lowcore protection */
@@ -102,20 +70,15 @@ machine_kexec(struct kimage *image)
 	for(;;);
 }
 
-/*
- * Make sure that all except one CPU are stopped. The first CPU
- * that enters this function is going to halt all the others and then, if it is
- * the only one left, the 'data_mover' function will be called.
- */
 static void
 kexec_halt_all_cpus(void *kernel_image)
 {
 	static atomic_t cpuid = ATOMIC_INIT(-1);
 	int cpu;
+	struct kimage *image;
+	relocate_kernel_t data_mover;
 
-	struct kimage *image = (struct kimage *) kernel_image;
-
-	if(atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
+	if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
 		signal_processor(smp_processor_id(), sigp_stop);
 
 	/* Wait for all other cpus to enter stopped state */
@@ -126,6 +89,10 @@ kexec_halt_all_cpus(void *kernel_image)
 			cpu_relax();
 	}
 
+	image = (struct kimage *) kernel_image;
+	data_mover = (relocate_kernel_t)
+		(page_to_pfn(image->control_code_page) << PAGE_SHIFT);
+
 	/* Call the moving routine */
-	(*data_mover) (indirection_page, reboot_code_buffer, image->start);
+	(*data_mover) (&image->head, image->start);
 }
diff -puN arch/s390/kernel/relocate_kernel64.S~s390-kexec-fixes arch/s390/kernel/relocate_kernel64.S
--- 25/arch/s390/kernel/relocate_kernel64.S~s390-kexec-fixes	2005-04-28 23:11:21.978402944 -0700
+++ 25-akpm/arch/s390/kernel/relocate_kernel64.S	2005-04-28 23:11:21.986401728 -0700
@@ -9,9 +9,8 @@
 
 /*
  * moves the new kernel to its destination...
- * %r2 = indirection page
- * %r3 = reboot_code_buffer
- * %r4 = start address - where to jump to after the job is done...
+ * %r2 = pointer to first kimage_entry_t
+ * %r3 = start address - where to jump to after the job is done...
  *
  * %r5 will be used as temp. storage
  * %r6 holds the destination address
@@ -59,11 +58,10 @@
 		j       .top
 	.done:
 		sgr     %r0,%r0		#clear register r0
-		la      %r3,load_psw-.base(%r13)	#load psw-address into the register
-		mvc     0(4,%r0),0(%r3)	#copy the first part of it
-		l	%r1,4(0,%r3)	#copy the second part of load_psw in %r1
-		or	%r1,%r4		#OR it with the given psw --> %r1 = (%r1 | %r4)
-		st	%r1,4(0,%r0)	#store it at addr 0+4B, i.e. second part of psw
+		la      %r4,load_psw-.base(%r13)	#load psw-address into the register
+		o	%r3,4(%r4)	#or load address into psw
+		st	%r3,4(%r4)
+		mvc     0(8,%r0),0(%r4)	#copy psw to absolute address 0
 		sam31			#31 bit mode
 		sr      %r1,%r1		#erase register r1
 		sr      %r2,%r2		#erase register r2
diff -puN arch/s390/kernel/relocate_kernel.S~s390-kexec-fixes arch/s390/kernel/relocate_kernel.S
--- 25/arch/s390/kernel/relocate_kernel.S~s390-kexec-fixes	2005-04-28 23:11:21.980402640 -0700
+++ 25-akpm/arch/s390/kernel/relocate_kernel.S	2005-04-28 23:11:21.986401728 -0700
@@ -9,9 +9,8 @@
 
 /*
  * moves the new kernel to its destination...
- * %r2 = indirection page
- * %r3 = reboot_code_buffer
- * %r4 = start address - where to jump to after the job is done...
+ * %r2 = pointer to first kimage_entry_t
+ * %r3 = start address - where to jump to after the job is done...
  *
  * %r5 will be used as temp. storage
  * %r6 holds the destination address
@@ -60,11 +59,10 @@
 		j	.top
 	.done:
 		sr	%r0,%r0		#clear register r0
-		la	%r3,load_psw-.base(%r13)	#load psw-address into the register
-		mvc	0(4,%r0),0(%r3)	#copy the first part of psw
-		l	%r1,4(0,%r3)	#get the second part of psw in %r1
-		or	%r1,%r4		#OR the load address with the 2nd part of psw
-		st	%r1,4(0,%r0)	#store it at add 0+4B
+		la	%r4,load_psw-.base(%r13)	#load psw-address into the register
+		o	%r3,4(%r4)	#or load address into psw
+		st	%r3,4(%r4)
+		mvc	0(8,%r0),0(%r4)	#copy psw to absolute address 0
 		sr	%r1,%r1		#clear %r1
 		sr	%r2,%r2		#clear %r2
 		sigp	%r1,%r2,0x12	#set cpuid to zero
_