Merge branch 'topic/slab/earlyboot' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6] / arch / sh / kernel / relocate_kernel.S
1 /*
2  * relocate_kernel.S - put the kernel image in place to boot
3  * 2005.9.17 kogiidena@eggplant.ddo.jp
4  *
5  * LANDISK/sh4 is supported. Maybe, SH archtecture works well.
6  *
7  * 2009-03-18 Magnus Damm - Added Kexec Jump support
8  *
9  * This source code is licensed under the GNU General Public License,
10  * Version 2.  See the file COPYING for more details.
11  */
12 #include <linux/linkage.h>
13 #include <asm/addrspace.h>
14 #include <asm/page.h>
15
16                 .globl relocate_new_kernel
17 relocate_new_kernel:
18         /* r4 = indirection_page   */
19         /* r5 = reboot_code_buffer */
20         /* r6 = start_address      */
21
22         mov.l   10f, r0         /* PAGE_SIZE */
23         add     r5, r0          /* setup new stack at end of control page */
24
25         /* save r15->r8 to new stack */
26         mov.l   r15, @-r0
27         mov     r0, r15
28         mov.l   r14, @-r15
29         mov.l   r13, @-r15
30         mov.l   r12, @-r15
31         mov.l   r11, @-r15
32         mov.l   r10, @-r15
33         mov.l   r9, @-r15
34         mov.l   r8, @-r15
35
36         /* save other random registers */
37         sts.l   macl, @-r15
38         sts.l   mach, @-r15
39         stc.l   gbr, @-r15
40         stc.l   ssr, @-r15
41         stc.l   sr, @-r15
42         sts.l   pr, @-r15
43         stc.l   spc, @-r15
44
45         /* switch to bank1 and save r7->r0 */
46         mov.l   12f, r9
47         stc     sr, r8
48         or      r9, r8
49         ldc     r8, sr
50         mov.l   r7, @-r15
51         mov.l   r6, @-r15
52         mov.l   r5, @-r15
53         mov.l   r4, @-r15
54         mov.l   r3, @-r15
55         mov.l   r2, @-r15
56         mov.l   r1, @-r15
57         mov.l   r0, @-r15
58
59         /* switch to bank0 and save r7->r0 */
60         mov.l   12f, r9
61         not     r9, r9
62         stc     sr, r8
63         and     r9, r8
64         ldc     r8, sr
65         mov.l   r7, @-r15
66         mov.l   r6, @-r15
67         mov.l   r5, @-r15
68         mov.l   r4, @-r15
69         mov.l   r3, @-r15
70         mov.l   r2, @-r15
71         mov.l   r1, @-r15
72         mov.l   r0, @-r15
73
74         mov.l   r4, @-r15       /* save indirection page again */
75
76         bsr     swap_pages      /* swap pages before jumping to new kernel */
77          nop
78
79         mova    11f, r0
80         mov.l   r15, @r0        /* save pointer to stack */
81
82         jsr     @r6             /* hand over control to new kernel */
83          nop
84
85         mov.l   11f, r15        /* get pointer to stack */
86         mov.l   @r15+, r4       /* restore r4 to get indirection page */
87
88         bsr     swap_pages      /* swap pages back to previous state */
89          nop
90
91         /* make sure bank0 is active and restore r0->r7 */
92         mov.l   12f, r9
93         not     r9, r9
94         stc     sr, r8
95         and     r9, r8
96         ldc     r8, sr
97         mov.l   @r15+, r0
98         mov.l   @r15+, r1
99         mov.l   @r15+, r2
100         mov.l   @r15+, r3
101         mov.l   @r15+, r4
102         mov.l   @r15+, r5
103         mov.l   @r15+, r6
104         mov.l   @r15+, r7
105
106         /* switch to bank1 and restore r0->r7 */
107         mov.l   12f, r9
108         stc     sr, r8
109         or      r9, r8
110         ldc     r8, sr
111         mov.l   @r15+, r0
112         mov.l   @r15+, r1
113         mov.l   @r15+, r2
114         mov.l   @r15+, r3
115         mov.l   @r15+, r4
116         mov.l   @r15+, r5
117         mov.l   @r15+, r6
118         mov.l   @r15+, r7
119
120         /* switch back to bank0 */
121         mov.l   12f, r9
122         not     r9, r9
123         stc     sr, r8
124         and     r9, r8
125         ldc     r8, sr
126
127         /* restore other random registers */
128         ldc.l   @r15+, spc
129         lds.l   @r15+, pr
130         ldc.l   @r15+, sr
131         ldc.l   @r15+, ssr
132         ldc.l   @r15+, gbr
133         lds.l   @r15+, mach
134         lds.l   @r15+, macl
135
136         /* restore r8->r15 */
137         mov.l   @r15+, r8
138         mov.l   @r15+, r9
139         mov.l   @r15+, r10
140         mov.l   @r15+, r11
141         mov.l   @r15+, r12
142         mov.l   @r15+, r13
143         mov.l   @r15+, r14
144         mov.l   @r15+, r15
145         rts
146          nop
147
148 swap_pages:
149         bra     1f
150          mov    r4,r0     /* cmd = indirection_page */
151 0:
152         mov.l   @r4+,r0   /* cmd = *ind++ */
153
154 1:      /* addr = cmd & 0xfffffff0 */
155         mov     r0,r2
156         mov     #-16,r1
157         and     r1,r2
158
159         /* if(cmd & IND_DESTINATION) dst = addr  */
160         tst     #1,r0
161         bt      2f
162         bra     0b
163          mov    r2,r5
164
165 2:      /* else if(cmd & IND_INDIRECTION) ind = addr  */
166         tst     #2,r0
167         bt      3f
168         bra     0b
169          mov    r2,r4
170
171 3:      /* else if(cmd & IND_DONE) return */
172         tst     #4,r0
173         bt      4f
174         rts
175          nop
176
177 4:      /* else if(cmd & IND_SOURCE) memcpy(dst,addr,PAGE_SIZE) */
178         tst     #8,r0
179         bt      0b
180
181         mov.l   10f,r3    /* PAGE_SIZE */
182         shlr2   r3
183         shlr2   r3
184 5:
185         dt      r3
186
187         /* regular kexec just overwrites the destination page
188          * with the contents of the source page.
189          * for the kexec jump case we need to swap the contents
190          * of the pages.
191          * to keep it simple swap the contents for both cases.
192          */
193         mov.l   @(0, r2), r8
194         mov.l   @(0, r5), r1
195         mov.l   r8, @(0, r5)
196         mov.l   r1, @(0, r2)
197
198         mov.l   @(4, r2), r8
199         mov.l   @(4, r5), r1
200         mov.l   r8, @(4, r5)
201         mov.l   r1, @(4, r2)
202
203         mov.l   @(8, r2), r8
204         mov.l   @(8, r5), r1
205         mov.l   r8, @(8, r5)
206         mov.l   r1, @(8, r2)
207
208         mov.l   @(12, r2), r8
209         mov.l   @(12, r5), r1
210         mov.l   r8, @(12, r5)
211         mov.l   r1, @(12, r2)
212
213         add     #16,r5
214         add     #16,r2
215         bf      5b
216
217         bra     0b
218          nop
219
220         .align 2
221 10:
222         .long   PAGE_SIZE
223 11:
224         .long   0
225 12:
226         .long   0x20000000 ! RB=1
227
228 relocate_new_kernel_end:
229
230         .globl relocate_new_kernel_size
231 relocate_new_kernel_size:
232         .long relocate_new_kernel_end - relocate_new_kernel