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