drm/rockchip: vop2: Fix the windows switch between different layers
[drm/drm-misc.git] / arch / mips / kernel / relocate_kernel.S
blobde894a0211d7a687bc08872c3a6b318a30b379cb
1 /* 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  */
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>
14 #include <kernel-entry-init.h>
16 LEAF(relocate_new_kernel)
17         PTR_L a0,       arg0
18         PTR_L a1,       arg1
19         PTR_L a2,       arg2
20         PTR_L a3,       arg3
22         PTR_L           s0, kexec_indirection_page
23         PTR_L           s1, kexec_start_address
25 process_entry:
26         PTR_L           s2, (s0)
27         PTR_ADDIU       s0, s0, SZREG
29         /*
30          * In case of a kdump/crash kernel, the indirection page is not
31          * populated as the kernel is directly copied to a reserved location
32          */
33         beqz            s2, done
35         /* destination page */
36         and             s3, s2, 0x1
37         beq             s3, zero, 1f
38         and             s4, s2, ~0x1    /* store destination addr in s4 */
39         b               process_entry
42         /* indirection page, update s0  */
43         and             s3, s2, 0x2
44         beq             s3, zero, 1f
45         and             s0, s2, ~0x2
46         b               process_entry
49         /* done page */
50         and             s3, s2, 0x4
51         beq             s3, zero, 1f
52         b               done
54         /* source page */
55         and             s3, s2, 0x8
56         beq             s3, zero, process_entry
57         and             s2, s2, ~0x8
58         li              s6, (1 << _PAGE_SHIFT) / SZREG
60 copy_word:
61         /* copy page word by word */
62         REG_L           s5, (s2)
63         REG_S           s5, (s4)
64         PTR_ADDIU       s4, s4, SZREG
65         PTR_ADDIU       s2, s2, SZREG
66         LONG_ADDIU      s6, s6, -1
67         beq             s6, zero, process_entry
68         b               copy_word
70 done:
71 #ifdef CONFIG_SMP
72         /* kexec_flag reset is signal to other CPUs what kernel
73            was moved to its location. Note - we need relocated address
74            of kexec_flag.  */
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
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(relocate_new_kernel)
102 #ifdef CONFIG_SMP
104  * Other CPUs should wait until code is relocated and
105  * then start at entry (?) point.
106  */
107 LEAF(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
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          */
119         bal             1f
120 1:      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;
126 1:      LONG_L          s0, (t0)
127         bne             s0, zero,1b
129 #ifdef USE_KEXEC_SMP_WAIT_FINAL
130         kexec_smp_wait_final
131 #else
132         sync
133 #endif
134         j               s1
135         END(kexec_smp_wait)
136 #endif
138 #ifdef __mips64
139        /* all PTR's must be aligned to 8 byte in 64-bit mode */
140        .align  3
141 #endif
143 /* All parameters to new kernel are passed in registers a0-a3.
144  * kexec_args[0..3] are used to prepare register values.
145  */
147 EXPORT(kexec_args)
148 arg0:   PTR_WD          0x0
149 arg1:   PTR_WD          0x0
150 arg2:   PTR_WD          0x0
151 arg3:   PTR_WD          0x0
152         .size   kexec_args,PTRSIZE*4
154 #ifdef CONFIG_SMP
156  * Secondary CPUs may have different kernel parameters in
157  * their registers a0-a3. secondary_kexec_args[0..3] are used
158  * to prepare register values.
159  */
160 EXPORT(secondary_kexec_args)
161 s_arg0: PTR_WD          0x0
162 s_arg1: PTR_WD          0x0
163 s_arg2: PTR_WD          0x0
164 s_arg3: PTR_WD          0x0
165         .size   secondary_kexec_args,PTRSIZE*4
166 kexec_flag:
167         LONG            0x1
169 #endif
171 EXPORT(kexec_start_address)
172         PTR_WD          0x0
173         .size           kexec_start_address, PTRSIZE
175 EXPORT(kexec_indirection_page)
176         PTR_WD          0
177         .size           kexec_indirection_page, PTRSIZE
179 relocate_new_kernel_end:
181 EXPORT(relocate_new_kernel_size)
182         PTR_WD          relocate_new_kernel_end - relocate_new_kernel
183         .size           relocate_new_kernel_size, PTRSIZE