aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2005-06-25 17:58:11 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-25 19:24:51 -0400
commitcf13f0eaffa31bf6a145c53c589654b11c72ddc7 (patch)
tree55c11d753422398b060ea9571698285b5fdc603b /arch/s390/kernel
parentfce0d5740322b98b863f9e609f5a9bd4c06703af (diff)
[PATCH] kexec: s390 support
Add kexec support for s390 architecture. From: Milton Miller <miltonm@bga.com> - 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. Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/Makefile10
-rw-r--r--arch/s390/kernel/compat_wrapper.S8
-rw-r--r--arch/s390/kernel/crash.c17
-rw-r--r--arch/s390/kernel/machine_kexec.c98
-rw-r--r--arch/s390/kernel/relocate_kernel.S81
-rw-r--r--arch/s390/kernel/relocate_kernel64.S82
-rw-r--r--arch/s390/kernel/syscalls.S2
7 files changed, 297 insertions, 1 deletions
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index b41e0e199a7c..ab1e49d2e518 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -25,6 +25,16 @@ obj-$(CONFIG_ARCH_S390X) += entry64.o reipl64.o
25 25
26obj-$(CONFIG_VIRT_TIMER) += vtime.o 26obj-$(CONFIG_VIRT_TIMER) += vtime.o
27 27
28# Kexec part
29S390_KEXEC_OBJS := machine_kexec.o crash.o
30ifeq ($(CONFIG_ARCH_S390X),y)
31S390_KEXEC_OBJS += relocate_kernel64.o
32else
33S390_KEXEC_OBJS += relocate_kernel.o
34endif
35obj-$(CONFIG_KEXEC) += $(S390_KEXEC_OBJS)
36
37
28# 38#
29# This is just to get the dependencies... 39# This is just to get the dependencies...
30# 40#
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 7a607b1d0380..bf529739c8ab 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1441,3 +1441,11 @@ compat_sys_waitid_wrapper:
1441 lgfr %r5,%r5 # int 1441 lgfr %r5,%r5 # int
1442 llgtr %r6,%r6 # struct rusage_emu31 * 1442 llgtr %r6,%r6 # struct rusage_emu31 *
1443 jg compat_sys_waitid 1443 jg compat_sys_waitid
1444
1445 .globl compat_sys_kexec_load_wrapper
1446compat_sys_kexec_load_wrapper:
1447 llgfr %r2,%r2 # unsigned long
1448 llgfr %r3,%r3 # unsigned long
1449 llgtr %r4,%r4 # struct kexec_segment *
1450 llgfr %r5,%r5 # unsigned long
1451 jg compat_sys_kexec_load
diff --git a/arch/s390/kernel/crash.c b/arch/s390/kernel/crash.c
new file mode 100644
index 000000000000..db38283c1f27
--- /dev/null
+++ b/arch/s390/kernel/crash.c
@@ -0,0 +1,17 @@
1/*
2 * arch/s390/kernel/crash.c
3 *
4 * (C) Copyright IBM Corp. 2005
5 *
6 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
7 *
8 */
9
10#include <linux/threads.h>
11#include <linux/kexec.h>
12
13note_buf_t crash_notes[NR_CPUS];
14
15void machine_crash_shutdown(void)
16{
17}
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
new file mode 100644
index 000000000000..7a94db76df46
--- /dev/null
+++ b/arch/s390/kernel/machine_kexec.c
@@ -0,0 +1,98 @@
1/*
2 * arch/s390/kernel/machine_kexec.c
3 *
4 * (C) Copyright IBM Corp. 2005
5 *
6 * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
7 *
8 */
9
10/*
11 * s390_machine_kexec.c - handle the transition of Linux booting another kernel
12 * on the S390 architecture.
13 */
14
15#include <asm/cio.h>
16#include <asm/setup.h>
17#include <linux/device.h>
18#include <linux/mm.h>
19#include <linux/kexec.h>
20#include <linux/delay.h>
21#include <asm/pgtable.h>
22#include <asm/pgalloc.h>
23#include <asm/system.h>
24
25static void kexec_halt_all_cpus(void *);
26
27typedef void (*relocate_kernel_t) (kimage_entry_t *, unsigned long);
28
29const extern unsigned char relocate_kernel[];
30const extern unsigned long long relocate_kernel_len;
31
32int
33machine_kexec_prepare(struct kimage *image)
34{
35 unsigned long reboot_code_buffer;
36
37 /* We don't support anything but the default image type for now. */
38 if (image->type != KEXEC_TYPE_DEFAULT)
39 return -EINVAL;
40
41 /* Get the destination where the assembler code should be copied to.*/
42 reboot_code_buffer = page_to_pfn(image->control_code_page)<<PAGE_SHIFT;
43
44 /* Then copy it */
45 memcpy((void *) reboot_code_buffer, relocate_kernel,
46 relocate_kernel_len);
47 return 0;
48}
49
50void
51machine_kexec_cleanup(struct kimage *image)
52{
53}
54
55void
56machine_shutdown(void)
57{
58 printk(KERN_INFO "kexec: machine_shutdown called\n");
59}
60
61NORET_TYPE void
62machine_kexec(struct kimage *image)
63{
64 clear_all_subchannels();
65
66 /* Disable lowcore protection */
67 ctl_clear_bit(0,28);
68
69 on_each_cpu(kexec_halt_all_cpus, image, 0, 0);
70 for(;;);
71}
72
73static void
74kexec_halt_all_cpus(void *kernel_image)
75{
76 static atomic_t cpuid = ATOMIC_INIT(-1);
77 int cpu;
78 struct kimage *image;
79 relocate_kernel_t data_mover;
80
81 if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
82 signal_processor(smp_processor_id(), sigp_stop);
83
84 /* Wait for all other cpus to enter stopped state */
85 for_each_online_cpu(cpu) {
86 if (cpu == smp_processor_id())
87 continue;
88 while(!smp_cpu_not_running(cpu))
89 cpu_relax();
90 }
91
92 image = (struct kimage *) kernel_image;
93 data_mover = (relocate_kernel_t)
94 (page_to_pfn(image->control_code_page) << PAGE_SHIFT);
95
96 /* Call the moving routine */
97 (*data_mover) (&image->head, image->start);
98}
diff --git a/arch/s390/kernel/relocate_kernel.S b/arch/s390/kernel/relocate_kernel.S
new file mode 100644
index 000000000000..d5e4a62fbb79
--- /dev/null
+++ b/arch/s390/kernel/relocate_kernel.S
@@ -0,0 +1,81 @@
1/*
2 * arch/s390/kernel/relocate_kernel.S
3 *
4 * (C) Copyright IBM Corp. 2005
5 *
6 * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
7 *
8 */
9
10/*
11 * moves the new kernel to its destination...
12 * %r2 = pointer to first kimage_entry_t
13 * %r3 = start address - where to jump to after the job is done...
14 *
15 * %r5 will be used as temp. storage
16 * %r6 holds the destination address
17 * %r7 = PAGE_SIZE
18 * %r8 holds the source address
19 * %r9 = PAGE_SIZE
20 * %r10 is a page mask
21 */
22
23 .text
24 .globl relocate_kernel
25 relocate_kernel:
26 basr %r13,0 #base address
27 .base:
28 spx zero64-.base(%r13) #absolute addressing mode
29 stnsm sys_msk-.base(%r13),0xf8 #disable DAT and IRQ (external)
30 lhi %r10,-1 #preparing the mask
31 sll %r10,12 #shift it such that it becomes 0xf000
32 .top:
33 lhi %r7,4096 #load PAGE_SIZE in r7
34 lhi %r9,4096 #load PAGE_SIZE in r9
35 l %r5,0(%r2) #read another word for indirection page
36 ahi %r2,4 #increment pointer
37 tml %r5,0x1 #is it a destination page?
38 je .indir_check #NO, goto "indir_check"
39 lr %r6,%r5 #r6 = r5
40 nr %r6,%r10 #mask it out and...
41 j .top #...next iteration
42 .indir_check:
43 tml %r5,0x2 #is it a indirection page?
44 je .done_test #NO, goto "done_test"
45 nr %r5,%r10 #YES, mask out,
46 lr %r2,%r5 #move it into the right register,
47 j .top #and read next...
48 .done_test:
49 tml %r5,0x4 #is it the done indicator?
50 je .source_test #NO! Well, then it should be the source indicator...
51 j .done #ok, lets finish it here...
52 .source_test:
53 tml %r5,0x8 #it should be a source indicator...
54 je .top #NO, ignore it...
55 lr %r8,%r5 #r8 = r5
56 nr %r8,%r10 #masking
57 0: mvcle %r6,%r8,0x0 #copy PAGE_SIZE bytes from r8 to r6 - pad with 0
58 jo 0b
59 j .top
60 .done:
61 sr %r0,%r0 #clear register r0
62 la %r4,load_psw-.base(%r13) #load psw-address into the register
63 o %r3,4(%r4) #or load address into psw
64 st %r3,4(%r4)
65 mvc 0(8,%r0),0(%r4) #copy psw to absolute address 0
66 sr %r1,%r1 #clear %r1
67 sr %r2,%r2 #clear %r2
68 sigp %r1,%r2,0x12 #set cpuid to zero
69 lpsw 0 #hopefully start new kernel...
70
71 .align 8
72 zero64:
73 .quad 0
74 load_psw:
75 .long 0x00080000,0x80000000
76 sys_msk:
77 .quad 0
78 relocate_kernel_end:
79 .globl relocate_kernel_len
80 relocate_kernel_len:
81 .quad relocate_kernel_end - relocate_kernel
diff --git a/arch/s390/kernel/relocate_kernel64.S b/arch/s390/kernel/relocate_kernel64.S
new file mode 100644
index 000000000000..96290cc4eb3c
--- /dev/null
+++ b/arch/s390/kernel/relocate_kernel64.S
@@ -0,0 +1,82 @@
1/*
2 * arch/s390/kernel/relocate_kernel64.S
3 *
4 * (C) Copyright IBM Corp. 2005
5 *
6 * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
7 *
8 */
9
10/*
11 * moves the new kernel to its destination...
12 * %r2 = pointer to first kimage_entry_t
13 * %r3 = start address - where to jump to after the job is done...
14 *
15 * %r5 will be used as temp. storage
16 * %r6 holds the destination address
17 * %r7 = PAGE_SIZE
18 * %r8 holds the source address
19 * %r9 = PAGE_SIZE
20 *
21 * 0xf000 is a page_mask
22 */
23
24 .text
25 .globl relocate_kernel
26 relocate_kernel:
27 basr %r13,0 #base address
28 .base:
29 spx zero64-.base(%r13) #absolute addressing mode
30 stnsm sys_msk-.base(%r13),0xf8 #disable DAT and IRQ (external)
31 .top:
32 lghi %r7,4096 #load PAGE_SIZE in r7
33 lghi %r9,4096 #load PAGE_SIZE in r9
34 lg %r5,0(%r2) #read another word for indirection page
35 aghi %r2,8 #increment pointer
36 tml %r5,0x1 #is it a destination page?
37 je .indir_check #NO, goto "indir_check"
38 lgr %r6,%r5 #r6 = r5
39 nill %r6,0xf000 #mask it out and...
40 j .top #...next iteration
41 .indir_check:
42 tml %r5,0x2 #is it a indirection page?
43 je .done_test #NO, goto "done_test"
44 nill %r5,0xf000 #YES, mask out,
45 lgr %r2,%r5 #move it into the right register,
46 j .top #and read next...
47 .done_test:
48 tml %r5,0x4 #is it the done indicator?
49 je .source_test #NO! Well, then it should be the source indicator...
50 j .done #ok, lets finish it here...
51 .source_test:
52 tml %r5,0x8 #it should be a source indicator...
53 je .top #NO, ignore it...
54 lgr %r8,%r5 #r8 = r5
55 nill %r8,0xf000 #masking
56 0: mvcle %r6,%r8,0x0 #copy PAGE_SIZE bytes from r8 to r6 - pad with 0
57 jo 0b
58 j .top
59 .done:
60 sgr %r0,%r0 #clear register r0
61 la %r4,load_psw-.base(%r13) #load psw-address into the register
62 o %r3,4(%r4) #or load address into psw
63 st %r3,4(%r4)
64 mvc 0(8,%r0),0(%r4) #copy psw to absolute address 0
65 sam31 #31 bit mode
66 sr %r1,%r1 #erase register r1
67 sr %r2,%r2 #erase register r2
68 sigp %r1,%r2,0x12 #set cpuid to zero
69 lpsw 0 #hopefully start new kernel...
70
71 .align 8
72 zero64:
73 .quad 0
74 load_psw:
75 .long 0x00080000,0x80000000
76 sys_msk:
77 .quad 0
78 relocate_kernel_end:
79 .globl relocate_kernel_len
80 relocate_kernel_len:
81 .quad relocate_kernel_end - relocate_kernel
82
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 515938628f82..a8668afb5f87 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -285,7 +285,7 @@ SYSCALL(sys_mq_timedsend,sys_mq_timedsend,compat_sys_mq_timedsend_wrapper)
285SYSCALL(sys_mq_timedreceive,sys_mq_timedreceive,compat_sys_mq_timedreceive_wrapper) 285SYSCALL(sys_mq_timedreceive,sys_mq_timedreceive,compat_sys_mq_timedreceive_wrapper)
286SYSCALL(sys_mq_notify,sys_mq_notify,compat_sys_mq_notify_wrapper) /* 275 */ 286SYSCALL(sys_mq_notify,sys_mq_notify,compat_sys_mq_notify_wrapper) /* 275 */
287SYSCALL(sys_mq_getsetattr,sys_mq_getsetattr,compat_sys_mq_getsetattr_wrapper) 287SYSCALL(sys_mq_getsetattr,sys_mq_getsetattr,compat_sys_mq_getsetattr_wrapper)
288NI_SYSCALL /* reserved for kexec */ 288SYSCALL(sys_kexec_load,sys_kexec_load,compat_sys_kexec_load_wrapper)
289SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key_wrapper) 289SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key_wrapper)
290SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key_wrapper) 290SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key_wrapper)
291SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl) /* 280 */ 291SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl) /* 280 */