Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/sh/kernel/relocate_kernel.S
10817 views
1
/*
2
* relocate_kernel.S - put the kernel image in place to boot
3
* 2005.9.17 [email protected]
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
233
234