xref: /openbmc/linux/arch/sh/kernel/relocate_kernel.S (revision 5933f6d2)
15933f6d2SKuninori Morimoto/* SPDX-License-Identifier: GPL-2.0
25933f6d2SKuninori Morimoto *
39d44190eSkogiidena * relocate_kernel.S - put the kernel image in place to boot
49d44190eSkogiidena * 2005.9.17 kogiidena@eggplant.ddo.jp
59d44190eSkogiidena *
69d44190eSkogiidena * LANDISK/sh4 is supported. Maybe, SH archtecture works well.
79d44190eSkogiidena *
8b7cf6ddcSMagnus Damm * 2009-03-18 Magnus Damm - Added Kexec Jump support
99d44190eSkogiidena */
109d44190eSkogiidena#include <linux/linkage.h>
11510c72adSPaul Mundt#include <asm/addrspace.h>
12510c72adSPaul Mundt#include <asm/page.h>
139d44190eSkogiidena
149d44190eSkogiidena		.globl relocate_new_kernel
159d44190eSkogiidenarelocate_new_kernel:
169d44190eSkogiidena	/* r4 = indirection_page   */
179d44190eSkogiidena	/* r5 = reboot_code_buffer */
189d44190eSkogiidena	/* r6 = start_address      */
199d44190eSkogiidena
20b7cf6ddcSMagnus Damm	mov.l	10f, r0		/* PAGE_SIZE */
21b7cf6ddcSMagnus Damm	add	r5, r0		/* setup new stack at end of control page */
229d44190eSkogiidena
23b7cf6ddcSMagnus Damm	/* save r15->r8 to new stack */
24b7cf6ddcSMagnus Damm	mov.l	r15, @-r0
25b7cf6ddcSMagnus Damm	mov	r0, r15
26b7cf6ddcSMagnus Damm	mov.l	r14, @-r15
27b7cf6ddcSMagnus Damm	mov.l	r13, @-r15
28b7cf6ddcSMagnus Damm	mov.l	r12, @-r15
29b7cf6ddcSMagnus Damm	mov.l	r11, @-r15
30b7cf6ddcSMagnus Damm	mov.l	r10, @-r15
31b7cf6ddcSMagnus Damm	mov.l	r9, @-r15
32b7cf6ddcSMagnus Damm	mov.l	r8, @-r15
339d44190eSkogiidena
34b7cf6ddcSMagnus Damm	/* save other random registers */
35b7cf6ddcSMagnus Damm	sts.l	macl, @-r15
36b7cf6ddcSMagnus Damm	sts.l	mach, @-r15
37b7cf6ddcSMagnus Damm	stc.l	gbr, @-r15
38b7cf6ddcSMagnus Damm	stc.l	ssr, @-r15
39b7cf6ddcSMagnus Damm	stc.l	sr, @-r15
40b7cf6ddcSMagnus Damm	sts.l	pr, @-r15
41b7cf6ddcSMagnus Damm	stc.l	spc, @-r15
42b7cf6ddcSMagnus Damm
43b7cf6ddcSMagnus Damm	/* switch to bank1 and save r7->r0 */
44b7cf6ddcSMagnus Damm	mov.l	12f, r9
45b7cf6ddcSMagnus Damm	stc	sr, r8
46b7cf6ddcSMagnus Damm	or	r9, r8
47b7cf6ddcSMagnus Damm	ldc	r8, sr
48b7cf6ddcSMagnus Damm	mov.l	r7, @-r15
49b7cf6ddcSMagnus Damm	mov.l	r6, @-r15
50b7cf6ddcSMagnus Damm	mov.l	r5, @-r15
51b7cf6ddcSMagnus Damm	mov.l	r4, @-r15
52b7cf6ddcSMagnus Damm	mov.l	r3, @-r15
53b7cf6ddcSMagnus Damm	mov.l	r2, @-r15
54b7cf6ddcSMagnus Damm	mov.l	r1, @-r15
55b7cf6ddcSMagnus Damm	mov.l	r0, @-r15
56b7cf6ddcSMagnus Damm
57b7cf6ddcSMagnus Damm	/* switch to bank0 and save r7->r0 */
58b7cf6ddcSMagnus Damm	mov.l	12f, r9
59b7cf6ddcSMagnus Damm	not	r9, r9
60b7cf6ddcSMagnus Damm	stc	sr, r8
61b7cf6ddcSMagnus Damm	and	r9, r8
62b7cf6ddcSMagnus Damm	ldc	r8, sr
63b7cf6ddcSMagnus Damm	mov.l	r7, @-r15
64b7cf6ddcSMagnus Damm	mov.l	r6, @-r15
65b7cf6ddcSMagnus Damm	mov.l	r5, @-r15
66b7cf6ddcSMagnus Damm	mov.l	r4, @-r15
67b7cf6ddcSMagnus Damm	mov.l	r3, @-r15
68b7cf6ddcSMagnus Damm	mov.l	r2, @-r15
69b7cf6ddcSMagnus Damm	mov.l	r1, @-r15
70b7cf6ddcSMagnus Damm	mov.l	r0, @-r15
71b7cf6ddcSMagnus Damm
72b7cf6ddcSMagnus Damm	mov.l	r4, @-r15	/* save indirection page again */
73b7cf6ddcSMagnus Damm
74b7cf6ddcSMagnus Damm	bsr	swap_pages	/* swap pages before jumping to new kernel */
75b7cf6ddcSMagnus Damm	 nop
76b7cf6ddcSMagnus Damm
77b7cf6ddcSMagnus Damm	mova	11f, r0
78b7cf6ddcSMagnus Damm	mov.l	r15, @r0	/* save pointer to stack */
79b7cf6ddcSMagnus Damm
80b7cf6ddcSMagnus Damm	jsr	@r6		/* hand over control to new kernel */
81b7cf6ddcSMagnus Damm	 nop
82b7cf6ddcSMagnus Damm
83b7cf6ddcSMagnus Damm	mov.l	11f, r15	/* get pointer to stack */
84b7cf6ddcSMagnus Damm	mov.l	@r15+, r4	/* restore r4 to get indirection page */
85b7cf6ddcSMagnus Damm
86b7cf6ddcSMagnus Damm	bsr	swap_pages	/* swap pages back to previous state */
87b7cf6ddcSMagnus Damm	 nop
88b7cf6ddcSMagnus Damm
89b7cf6ddcSMagnus Damm	/* make sure bank0 is active and restore r0->r7 */
90b7cf6ddcSMagnus Damm	mov.l	12f, r9
91b7cf6ddcSMagnus Damm	not	r9, r9
92b7cf6ddcSMagnus Damm	stc	sr, r8
93b7cf6ddcSMagnus Damm	and	r9, r8
94b7cf6ddcSMagnus Damm	ldc	r8, sr
95b7cf6ddcSMagnus Damm	mov.l	@r15+, r0
96b7cf6ddcSMagnus Damm	mov.l	@r15+, r1
97b7cf6ddcSMagnus Damm	mov.l	@r15+, r2
98b7cf6ddcSMagnus Damm	mov.l	@r15+, r3
99b7cf6ddcSMagnus Damm	mov.l	@r15+, r4
100b7cf6ddcSMagnus Damm	mov.l	@r15+, r5
101b7cf6ddcSMagnus Damm	mov.l	@r15+, r6
102b7cf6ddcSMagnus Damm	mov.l	@r15+, r7
103b7cf6ddcSMagnus Damm
104b7cf6ddcSMagnus Damm	/* switch to bank1 and restore r0->r7 */
105b7cf6ddcSMagnus Damm	mov.l	12f, r9
106b7cf6ddcSMagnus Damm	stc	sr, r8
107b7cf6ddcSMagnus Damm	or	r9, r8
108b7cf6ddcSMagnus Damm	ldc	r8, sr
109b7cf6ddcSMagnus Damm	mov.l	@r15+, r0
110b7cf6ddcSMagnus Damm	mov.l	@r15+, r1
111b7cf6ddcSMagnus Damm	mov.l	@r15+, r2
112b7cf6ddcSMagnus Damm	mov.l	@r15+, r3
113b7cf6ddcSMagnus Damm	mov.l	@r15+, r4
114b7cf6ddcSMagnus Damm	mov.l	@r15+, r5
115b7cf6ddcSMagnus Damm	mov.l	@r15+, r6
116b7cf6ddcSMagnus Damm	mov.l	@r15+, r7
117b7cf6ddcSMagnus Damm
118b7cf6ddcSMagnus Damm	/* switch back to bank0 */
119b7cf6ddcSMagnus Damm	mov.l	12f, r9
120b7cf6ddcSMagnus Damm	not	r9, r9
121b7cf6ddcSMagnus Damm	stc	sr, r8
122b7cf6ddcSMagnus Damm	and	r9, r8
123b7cf6ddcSMagnus Damm	ldc	r8, sr
124b7cf6ddcSMagnus Damm
125b7cf6ddcSMagnus Damm	/* restore other random registers */
126b7cf6ddcSMagnus Damm	ldc.l	@r15+, spc
127b7cf6ddcSMagnus Damm	lds.l	@r15+, pr
128b7cf6ddcSMagnus Damm	ldc.l	@r15+, sr
129b7cf6ddcSMagnus Damm	ldc.l	@r15+, ssr
130b7cf6ddcSMagnus Damm	ldc.l	@r15+, gbr
131b7cf6ddcSMagnus Damm	lds.l	@r15+, mach
132b7cf6ddcSMagnus Damm	lds.l	@r15+, macl
133b7cf6ddcSMagnus Damm
134b7cf6ddcSMagnus Damm	/* restore r8->r15 */
135b7cf6ddcSMagnus Damm	mov.l	@r15+, r8
136b7cf6ddcSMagnus Damm	mov.l	@r15+, r9
137b7cf6ddcSMagnus Damm	mov.l	@r15+, r10
138b7cf6ddcSMagnus Damm	mov.l	@r15+, r11
139b7cf6ddcSMagnus Damm	mov.l	@r15+, r12
140b7cf6ddcSMagnus Damm	mov.l	@r15+, r13
141b7cf6ddcSMagnus Damm	mov.l	@r15+, r14
142b7cf6ddcSMagnus Damm	mov.l	@r15+, r15
143b7cf6ddcSMagnus Damm	rts
144b7cf6ddcSMagnus Damm	 nop
145b7cf6ddcSMagnus Damm
146b7cf6ddcSMagnus Dammswap_pages:
1479d44190eSkogiidena	bra	1f
1489d44190eSkogiidena	 mov	r4,r0	  /* cmd = indirection_page */
1499d44190eSkogiidena0:
1509d44190eSkogiidena	mov.l	@r4+,r0	  /* cmd = *ind++ */
1519d44190eSkogiidena
152e4e063d0SMagnus Damm1:	/* addr = cmd & 0xfffffff0 */
1539d44190eSkogiidena	mov	r0,r2
1549d44190eSkogiidena	mov	#-16,r1
1559d44190eSkogiidena	and	r1,r2
1569d44190eSkogiidena
1579d44190eSkogiidena	/* if(cmd & IND_DESTINATION) dst = addr  */
1589d44190eSkogiidena	tst	#1,r0
1599d44190eSkogiidena	bt	2f
1609d44190eSkogiidena	bra	0b
1619d44190eSkogiidena	 mov	r2,r5
1629d44190eSkogiidena
1639d44190eSkogiidena2:	/* else if(cmd & IND_INDIRECTION) ind = addr  */
1649d44190eSkogiidena	tst	#2,r0
1659d44190eSkogiidena	bt	3f
1669d44190eSkogiidena	bra	0b
1679d44190eSkogiidena	 mov	r2,r4
1689d44190eSkogiidena
169b7cf6ddcSMagnus Damm3:	/* else if(cmd & IND_DONE) return */
1709d44190eSkogiidena	tst	#4,r0
1719d44190eSkogiidena	bt	4f
172b7cf6ddcSMagnus Damm	rts
1739d44190eSkogiidena	 nop
1749d44190eSkogiidena
1759d44190eSkogiidena4:	/* else if(cmd & IND_SOURCE) memcpy(dst,addr,PAGE_SIZE) */
1769d44190eSkogiidena	tst	#8,r0
1779d44190eSkogiidena	bt	0b
1789d44190eSkogiidena
179b7cf6ddcSMagnus Damm	mov.l	10f,r3	  /* PAGE_SIZE */
1809d44190eSkogiidena	shlr2	r3
1819d44190eSkogiidena	shlr2	r3
1829d44190eSkogiidena5:
1839d44190eSkogiidena	dt	r3
184b7cf6ddcSMagnus Damm
185b7cf6ddcSMagnus Damm	/* regular kexec just overwrites the destination page
186b7cf6ddcSMagnus Damm	 * with the contents of the source page.
187b7cf6ddcSMagnus Damm	 * for the kexec jump case we need to swap the contents
188b7cf6ddcSMagnus Damm	 * of the pages.
189b7cf6ddcSMagnus Damm	 * to keep it simple swap the contents for both cases.
190b7cf6ddcSMagnus Damm	 */
191b7cf6ddcSMagnus Damm	mov.l	@(0, r2), r8
192b7cf6ddcSMagnus Damm	mov.l	@(0, r5), r1
193b7cf6ddcSMagnus Damm	mov.l	r8, @(0, r5)
194b7cf6ddcSMagnus Damm	mov.l	r1, @(0, r2)
195b7cf6ddcSMagnus Damm
196b7cf6ddcSMagnus Damm	mov.l	@(4, r2), r8
197b7cf6ddcSMagnus Damm	mov.l	@(4, r5), r1
198b7cf6ddcSMagnus Damm	mov.l	r8, @(4, r5)
199b7cf6ddcSMagnus Damm	mov.l	r1, @(4, r2)
200b7cf6ddcSMagnus Damm
201b7cf6ddcSMagnus Damm	mov.l	@(8, r2), r8
202b7cf6ddcSMagnus Damm	mov.l	@(8, r5), r1
203b7cf6ddcSMagnus Damm	mov.l	r8, @(8, r5)
204b7cf6ddcSMagnus Damm	mov.l	r1, @(8, r2)
205b7cf6ddcSMagnus Damm
206b7cf6ddcSMagnus Damm	mov.l	@(12, r2), r8
207b7cf6ddcSMagnus Damm	mov.l	@(12, r5), r1
208b7cf6ddcSMagnus Damm	mov.l	r8, @(12, r5)
209b7cf6ddcSMagnus Damm	mov.l	r1, @(12, r2)
210b7cf6ddcSMagnus Damm
211b7cf6ddcSMagnus Damm	add	#16,r5
212b7cf6ddcSMagnus Damm	add	#16,r2
2139d44190eSkogiidena	bf	5b
2149d44190eSkogiidena
2159d44190eSkogiidena	bra	0b
2169d44190eSkogiidena	 nop
2179d44190eSkogiidena
2189d44190eSkogiidena	.align 2
2199d44190eSkogiidena10:
2209d44190eSkogiidena	.long	PAGE_SIZE
221b7cf6ddcSMagnus Damm11:
222b7cf6ddcSMagnus Damm	.long	0
223b7cf6ddcSMagnus Damm12:
224b7cf6ddcSMagnus Damm	.long	0x20000000 ! RB=1
2259d44190eSkogiidena
2269d44190eSkogiidenarelocate_new_kernel_end:
2279d44190eSkogiidena
2289d44190eSkogiidena	.globl relocate_new_kernel_size
2299d44190eSkogiidenarelocate_new_kernel_size:
2309d44190eSkogiidena	.long relocate_new_kernel_end - relocate_new_kernel
231