Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/riscv/kernel/kexec_relocate.S
26424 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
/*
3
* Copyright (C) 2019 FORTH-ICS/CARV
4
* Nick Kossifidis <[email protected]>
5
*/
6
7
#include <asm/asm.h> /* For RISCV_* and REG_* macros */
8
#include <asm/csr.h> /* For CSR_* macros */
9
#include <asm/page.h> /* For PAGE_SIZE */
10
#include <linux/linkage.h> /* For SYM_* macros */
11
12
.section ".rodata"
13
SYM_CODE_START(riscv_kexec_relocate)
14
15
/*
16
* s0: Pointer to the current entry
17
* s1: (const) Phys address to jump to after relocation
18
* s2: (const) Phys address of the FDT image
19
* s3: (const) The hartid of the current hart
20
* s4: (const) kernel_map.va_pa_offset, used when switching MMU off
21
* s5: Pointer to the destination address for the relocation
22
* s6: (const) Physical address of the main loop
23
*/
24
mv s0, a0
25
mv s1, a1
26
mv s2, a2
27
mv s3, a3
28
mv s4, a4
29
mv s5, zero
30
mv s6, zero
31
32
/* Disable / cleanup interrupts */
33
csrw CSR_SIE, zero
34
csrw CSR_SIP, zero
35
36
/*
37
* When we switch SATP.MODE to "Bare" we'll only
38
* play with physical addresses. However the first time
39
* we try to jump somewhere, the offset on the jump
40
* will be relative to pc which will still be on VA. To
41
* deal with this we set stvec to the physical address at
42
* the start of the loop below so that we jump there in
43
* any case.
44
*/
45
la s6, 1f
46
sub s6, s6, s4
47
csrw CSR_STVEC, s6
48
49
/*
50
* With C-extension, here we get 42 Bytes and the next
51
* .align directive would pad zeros here up to 44 Bytes.
52
* So manually put a nop here to avoid zeros padding.
53
*/
54
nop
55
56
/* Process entries in a loop */
57
.align 2
58
1:
59
REG_L t0, 0(s0) /* t0 = *image->entry */
60
addi s0, s0, RISCV_SZPTR /* image->entry++ */
61
62
/* IND_DESTINATION entry ? -> save destination address */
63
andi t1, t0, 0x1
64
beqz t1, 2f
65
andi s5, t0, ~0x1
66
j 1b
67
68
2:
69
/* IND_INDIRECTION entry ? -> update next entry ptr (PA) */
70
andi t1, t0, 0x2
71
beqz t1, 2f
72
andi s0, t0, ~0x2
73
csrw CSR_SATP, zero
74
jr s6
75
76
2:
77
/* IND_DONE entry ? -> jump to done label */
78
andi t1, t0, 0x4
79
beqz t1, 2f
80
j 4f
81
82
2:
83
/*
84
* IND_SOURCE entry ? -> copy page word by word to the
85
* destination address we got from IND_DESTINATION
86
*/
87
andi t1, t0, 0x8
88
beqz t1, 1b /* Unknown entry type, ignore it */
89
andi t0, t0, ~0x8
90
li t3, (PAGE_SIZE / RISCV_SZPTR) /* i = num words per page */
91
3: /* copy loop */
92
REG_L t1, (t0) /* t1 = *src_ptr */
93
REG_S t1, (s5) /* *dst_ptr = *src_ptr */
94
addi t0, t0, RISCV_SZPTR /* stc_ptr++ */
95
addi s5, s5, RISCV_SZPTR /* dst_ptr++ */
96
addi t3, t3, -0x1 /* i-- */
97
beqz t3, 1b /* copy done ? */
98
j 3b
99
100
4:
101
/* Pass the arguments to the next kernel / Cleanup*/
102
mv a0, s3
103
mv a1, s2
104
mv a2, s1
105
106
/* Cleanup */
107
mv a3, zero
108
mv a4, zero
109
mv a5, zero
110
mv a6, zero
111
mv a7, zero
112
113
mv s0, zero
114
mv s1, zero
115
mv s2, zero
116
mv s3, zero
117
mv s4, zero
118
mv s5, zero
119
mv s6, zero
120
mv s7, zero
121
mv s8, zero
122
mv s9, zero
123
mv s10, zero
124
mv s11, zero
125
126
mv t0, zero
127
mv t1, zero
128
mv t2, zero
129
mv t3, zero
130
mv t4, zero
131
mv t5, zero
132
mv t6, zero
133
csrw CSR_SEPC, zero
134
csrw CSR_SCAUSE, zero
135
csrw CSR_SSCRATCH, zero
136
137
/*
138
* Make sure the relocated code is visible
139
* and jump to the new kernel
140
*/
141
fence.i
142
143
jr a2
144
145
SYM_CODE_END(riscv_kexec_relocate)
146
riscv_kexec_relocate_end:
147
148
149
/* Used for jumping to crashkernel */
150
.section ".text"
151
SYM_CODE_START(riscv_kexec_norelocate)
152
/*
153
* s0: (const) Phys address to jump to
154
* s1: (const) Phys address of the FDT image
155
* s2: (const) The hartid of the current hart
156
*/
157
mv s0, a1
158
mv s1, a2
159
mv s2, a3
160
161
/* Disable / cleanup interrupts */
162
csrw CSR_SIE, zero
163
csrw CSR_SIP, zero
164
165
/* Pass the arguments to the next kernel / Cleanup*/
166
mv a0, s2
167
mv a1, s1
168
mv a2, s0
169
170
/* Cleanup */
171
mv a3, zero
172
mv a4, zero
173
mv a5, zero
174
mv a6, zero
175
mv a7, zero
176
177
mv s0, zero
178
mv s1, zero
179
mv s2, zero
180
mv s3, zero
181
mv s4, zero
182
mv s5, zero
183
mv s6, zero
184
mv s7, zero
185
mv s8, zero
186
mv s9, zero
187
mv s10, zero
188
mv s11, zero
189
190
mv t0, zero
191
mv t1, zero
192
mv t2, zero
193
mv t3, zero
194
mv t4, zero
195
mv t5, zero
196
mv t6, zero
197
csrw CSR_SEPC, zero
198
csrw CSR_SCAUSE, zero
199
csrw CSR_SSCRATCH, zero
200
201
/*
202
* Switch to physical addressing
203
* This will also trigger a jump to CSR_STVEC
204
* which in this case is the address of the new
205
* kernel.
206
*/
207
csrw CSR_STVEC, a2
208
csrw CSR_SATP, zero
209
210
SYM_CODE_END(riscv_kexec_norelocate)
211
212
.section ".rodata"
213
SYM_DATA(riscv_kexec_relocate_size,
214
.long riscv_kexec_relocate_end - riscv_kexec_relocate)
215
216
217