blob: 0648aa07fbade3be1af6b351c12b4e21b51f1948 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * relocate_kernel.S for kexec
4 * Created by <nschichan@corp.free.fr> on Thu Oct 12 17:49:57 2006
5 */
6
7#include <asm/asm.h>
8#include <asm/asmmacro.h>
9#include <asm/regdef.h>
10#include <asm/mipsregs.h>
11#include <asm/stackframe.h>
12#include <asm/addrspace.h>
13#include "machine_kexec.h"
14
15LEAF(kexec_relocate_new_kernel)
16 PTR_L a0, arg0
17 PTR_L a1, arg1
18 PTR_L a2, arg2
19 PTR_L a3, arg3
20
21 PTR_L s0, kexec_indirection_page
22 PTR_L s1, kexec_start_address
23
24process_entry:
25 PTR_L s2, (s0)
26 PTR_ADDIU s0, s0, SZREG
27
28 /*
29 * In case of a kdump/crash kernel, the indirection page is not
30 * populated as the kernel is directly copied to a reserved location
31 */
32 beqz s2, done
33
34 /* destination page */
35 and s3, s2, 0x1
36 beq s3, zero, 1f
37 and s4, s2, ~0x1 /* store destination addr in s4 */
38 b process_entry
39
401:
41 /* indirection page, update s0 */
42 and s3, s2, 0x2
43 beq s3, zero, 1f
44 and s0, s2, ~0x2
45 b process_entry
46
471:
48 /* done page */
49 and s3, s2, 0x4
50 beq s3, zero, 1f
51 b done
521:
53 /* source page */
54 and s3, s2, 0x8
55 beq s3, zero, process_entry
56 and s2, s2, ~0x8
57 li s6, (1 << _PAGE_SHIFT) / SZREG
58
59copy_word:
60 /* copy page word by word */
61 REG_L s5, (s2)
62 REG_S s5, (s4)
63 PTR_ADDIU s4, s4, SZREG
64 PTR_ADDIU s2, s2, SZREG
65 LONG_ADDIU s6, s6, -1
66 beq s6, zero, process_entry
67 b copy_word
68 b process_entry
69
70done:
71#ifdef CONFIG_SMP
72 /* kexec_flag reset is signal to other CPUs what kernel
73 was moved to it's location. Note - we need relocated address
74 of kexec_flag. */
75
76 bal 1f
77 1: move t1,ra;
78 PTR_LA t2,1b
79 PTR_LA t0,kexec_flag
80 PTR_SUB t0,t0,t2;
81 PTR_ADD t0,t1,t0;
82 LONG_S zero,(t0)
83#endif
84
85#ifdef CONFIG_CPU_CAVIUM_OCTEON
86 /* We need to flush I-cache before jumping to new kernel.
87 * Unfortunately, this code is cpu-specific.
88 */
89 .set push
90 .set noreorder
91 syncw
92 syncw
93 synci 0($0)
94 .set pop
95#else
96 sync
97#endif
98 /* jump to kexec_start_address */
99 j s1
100 END(kexec_relocate_new_kernel)
101
102#ifdef CONFIG_SMP
103/*
104 * Other CPUs should wait until code is relocated and
105 * then start at entry (?) point.
106 */
107LEAF(kexec_smp_wait)
108 PTR_L a0, s_arg0
109 PTR_L a1, s_arg1
110 PTR_L a2, s_arg2
111 PTR_L a3, s_arg3
112 PTR_L s1, kexec_start_address
113
114 /* Non-relocated address works for args and kexec_start_address ( old
115 * kernel is not overwritten). But we need relocated address of
116 * kexec_flag.
117 */
118
119 bal 1f
1201: move t1,ra;
121 PTR_LA t2,1b
122 PTR_LA t0,kexec_flag
123 PTR_SUB t0,t0,t2;
124 PTR_ADD t0,t1,t0;
125
1261: LONG_L s0, (t0)
127 bne s0, zero,1b
128
129#ifdef CONFIG_CPU_CAVIUM_OCTEON
130 .set push
131 .set noreorder
132 synci 0($0)
133 .set pop
134#else
135 sync
136#endif
137 j s1
138 END(kexec_smp_wait)
139#endif
140
141#ifdef __mips64
142 /* all PTR's must be aligned to 8 byte in 64-bit mode */
143 .align 3
144#endif
145
146/* All parameters to new kernel are passed in registers a0-a3.
147 * kexec_args[0..3] are used to prepare register values.
148 */
149
150kexec_args:
151 EXPORT(kexec_args)
152arg0: PTR 0x0
153arg1: PTR 0x0
154arg2: PTR 0x0
155arg3: PTR 0x0
156 .size kexec_args,PTRSIZE*4
157
158#ifdef CONFIG_SMP
159/*
160 * Secondary CPUs may have different kernel parameters in
161 * their registers a0-a3. secondary_kexec_args[0..3] are used
162 * to prepare register values.
163 */
164secondary_kexec_args:
165 EXPORT(secondary_kexec_args)
166s_arg0: PTR 0x0
167s_arg1: PTR 0x0
168s_arg2: PTR 0x0
169s_arg3: PTR 0x0
170 .size secondary_kexec_args,PTRSIZE*4
171kexec_flag:
172 LONG 0x1
173
174#endif
175
176kexec_start_address:
177 EXPORT(kexec_start_address)
178 PTR 0x0
179 .size kexec_start_address, PTRSIZE
180
181kexec_indirection_page:
182 EXPORT(kexec_indirection_page)
183 PTR 0
184 .size kexec_indirection_page, PTRSIZE
185
186kexec_argv_buf:
187 EXPORT(kexec_argv_buf)
188 .skip KEXEC_COMMAND_LINE_SIZE
189 .size kexec_argv_buf, KEXEC_COMMAND_LINE_SIZE
190
191kexec_argv:
192 EXPORT(kexec_argv)
193 .skip KEXEC_ARGV_SIZE
194 .size kexec_argv, KEXEC_ARGV_SIZE
195
196kexec_relocate_new_kernel_end:
197 EXPORT(kexec_relocate_new_kernel_end)