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>
13
14		.globl relocate_new_kernel
15relocate_new_kernel:
16	/* r4 = indirection_page   */
17	/* r5 = reboot_code_buffer */
18	/* r6 = start_address      */
19
20	mov.l	10f, r0		/* PAGE_SIZE */
21	add	r5, r0		/* setup new stack at end of control page */
22
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
33
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
42
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
56
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
71
72	mov.l	r4, @-r15	/* save indirection page again */
73
74	bsr	swap_pages	/* swap pages before jumping to new kernel */
75	 nop
76
77	mova	11f, r0
78	mov.l	r15, @r0	/* save pointer to stack */
79
80	jsr	@r6		/* hand over control to new kernel */
81	 nop
82
83	mov.l	11f, r15	/* get pointer to stack */
84	mov.l	@r15+, r4	/* restore r4 to get indirection page */
85
86	bsr	swap_pages	/* swap pages back to previous state */
87	 nop
88
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
103
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
117
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
124
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
133
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
145
146swap_pages:
147	bra	1f
148	 mov	r4,r0	  /* cmd = indirection_page */
1490:
150	mov.l	@r4+,r0	  /* cmd = *ind++ */
151
1521:	/* addr = cmd & 0xfffffff0 */
153	mov	r0,r2
154	mov	#-16,r1
155	and	r1,r2
156
157	/* if(cmd & IND_DESTINATION) dst = addr  */
158	tst	#1,r0
159	bt	2f
160	bra	0b
161	 mov	r2,r5
162
1632:	/* else if(cmd & IND_INDIRECTION) ind = addr  */
164	tst	#2,r0
165	bt	3f
166	bra	0b
167	 mov	r2,r4
168
1693:	/* else if(cmd & IND_DONE) return */
170	tst	#4,r0
171	bt	4f
172	rts
173	 nop
174
1754:	/* else if(cmd & IND_SOURCE) memcpy(dst,addr,PAGE_SIZE) */
176	tst	#8,r0
177	bt	0b
178
179	mov.l	10f,r3	  /* PAGE_SIZE */
180	shlr2	r3
181	shlr2	r3
1825:
183	dt	r3
184
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)
195
196	mov.l	@(4, r2), r8
197	mov.l	@(4, r5), r1
198	mov.l	r8, @(4, r5)
199	mov.l	r1, @(4, r2)
200
201	mov.l	@(8, r2), r8
202	mov.l	@(8, r5), r1
203	mov.l	r8, @(8, r5)
204	mov.l	r1, @(8, r2)
205
206	mov.l	@(12, r2), r8
207	mov.l	@(12, r5), r1
208	mov.l	r8, @(12, r5)
209	mov.l	r1, @(12, r2)
210
211	add	#16,r5
212	add	#16,r2
213	bf	5b
214
215	bra	0b
216	 nop
217
218	.align 2
21910:
220	.long	PAGE_SIZE
22111:
222	.long	0
22312:
224	.long	0x20000000 ! RB=1
225
226relocate_new_kernel_end:
227
228	.globl relocate_new_kernel_size
229relocate_new_kernel_size:
230	.long relocate_new_kernel_end - relocate_new_kernel
231