[PATCH] s390: kexec fixes for -mm

From: Heiko Carstens
Date: Fri Apr 29 2005 - 01:09:13 EST


Hi Andrew,

could you please add the patch below to your mm tree? It fixes some issues
with the current kexec implementation on s390. This one needs to be applied
after kexec-s390-support.patch.

Thanks,
Heiko

From: Heiko Carstens <heiko.carstens@xxxxxxxxxx>

This patch is mostly based on comments which I received from
Milton Miller <miltonm@xxxxxxx>. 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@xxxxxxxxxx>

diffstat:
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 -urN a/arch/s390/Kconfig b/arch/s390/Kconfig
--- a/arch/s390/Kconfig 2005-04-27 13:18:09.000000000 +0200
+++ b/arch/s390/Kconfig 2005-04-27 13:19:11.000000000 +0200
@@ -461,19 +461,7 @@
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 -urN a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
--- a/arch/s390/kernel/machine_kexec.c 2005-04-27 13:18:09.000000000 +0200
+++ b/arch/s390/kernel/machine_kexec.c 2005-04-27 13:19:11.000000000 +0200
@@ -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 @@
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 @@
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 @@
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 -urN a/arch/s390/kernel/relocate_kernel64.S b/arch/s390/kernel/relocate_kernel64.S
--- a/arch/s390/kernel/relocate_kernel64.S 2005-04-27 13:18:09.000000000 +0200
+++ b/arch/s390/kernel/relocate_kernel64.S 2005-04-27 13:20:02.000000000 +0200
@@ -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 -urN a/arch/s390/kernel/relocate_kernel.S b/arch/s390/kernel/relocate_kernel.S
--- a/arch/s390/kernel/relocate_kernel.S 2005-04-27 13:18:09.000000000 +0200
+++ b/arch/s390/kernel/relocate_kernel.S 2005-04-27 13:19:37.000000000 +0200
@@ -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
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/