Linux 3.11-rc3
[cris-mirror.git] / arch / mips / kernel / relocate_kernel.S
blob43d2d78d3287dfbfa52ad7fb1a52f6571d9deaa3
1 /*
2  * relocate_kernel.S for kexec
3  * Created by <nschichan@corp.free.fr> on Thu Oct 12 17:49:57 2006
4  *
5  * This source code is licensed under the GNU General Public License,
6  * Version 2.  See the file COPYING for more details.
7  */
9 #include <asm/asm.h>
10 #include <asm/asmmacro.h>
11 #include <asm/regdef.h>
12 #include <asm/mipsregs.h>
13 #include <asm/stackframe.h>
14 #include <asm/addrspace.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_ADD         s0, s0, SZREG
29         /* destination page */
30         and             s3, s2, 0x1
31         beq             s3, zero, 1f
32         and             s4, s2, ~0x1    /* store destination addr in s4 */
33         b               process_entry
36         /* indirection page, update s0  */
37         and             s3, s2, 0x2
38         beq             s3, zero, 1f
39         and             s0, s2, ~0x2
40         b               process_entry
43         /* done page */
44         and             s3, s2, 0x4
45         beq             s3, zero, 1f
46         b               done
48         /* source page */
49         and             s3, s2, 0x8
50         beq             s3, zero, process_entry
51         and             s2, s2, ~0x8
52         li              s6, (1 << _PAGE_SHIFT) / SZREG
54 copy_word:
55         /* copy page word by word */
56         REG_L           s5, (s2)
57         REG_S           s5, (s4)
58         PTR_ADD         s4, s4, SZREG
59         PTR_ADD         s2, s2, SZREG
60         LONG_SUB        s6, s6, 1
61         beq             s6, zero, process_entry
62         b               copy_word
63         b               process_entry
65 done:
66 #ifdef CONFIG_SMP
67         /* kexec_flag reset is signal to other CPUs what kernel
68            was moved to it's location. Note - we need relocated address
69            of kexec_flag.  */
71         bal             1f
72  1:     move            t1,ra;
73         PTR_LA          t2,1b
74         PTR_LA          t0,kexec_flag
75         PTR_SUB         t0,t0,t2;
76         PTR_ADD         t0,t1,t0;
77         LONG_S          zero,(t0)
78 #endif
80 #ifdef CONFIG_CPU_CAVIUM_OCTEON
81         /* We need to flush I-cache before jumping to new kernel.
82          * Unfortunatelly, this code is cpu-specific.
83          */
84         .set push
85         .set noreorder
86         syncw
87         syncw
88         synci           0($0)
89         .set pop
90 #else
91         sync
92 #endif
93         /* jump to kexec_start_address */
94         j               s1
95         END(relocate_new_kernel)
97 #ifdef CONFIG_SMP
99  * Other CPUs should wait until code is relocated and
100  * then start at entry (?) point.
101  */
102 LEAF(kexec_smp_wait)
103         PTR_L           a0, s_arg0
104         PTR_L           a1, s_arg1
105         PTR_L           a2, s_arg2
106         PTR_L           a3, s_arg3
107         PTR_L           s1, kexec_start_address
109         /* Non-relocated address works for args and kexec_start_address ( old
110          * kernel is not overwritten). But we need relocated address of
111          * kexec_flag.
112          */
114         bal             1f
115 1:      move            t1,ra;
116         PTR_LA          t2,1b
117         PTR_LA          t0,kexec_flag
118         PTR_SUB         t0,t0,t2;
119         PTR_ADD         t0,t1,t0;
121 1:      LONG_L          s0, (t0)
122         bne             s0, zero,1b
124 #ifdef CONFIG_CPU_CAVIUM_OCTEON
125         .set push
126         .set noreorder
127         synci           0($0)
128         .set pop
129 #else
130         sync
131 #endif
132         j               s1
133         END(kexec_smp_wait)
134 #endif
136 #ifdef __mips64
137        /* all PTR's must be aligned to 8 byte in 64-bit mode */
138        .align  3
139 #endif
141 /* All parameters to new kernel are passed in registers a0-a3.
142  * kexec_args[0..3] are uses to prepare register values.
143  */
145 kexec_args:
146         EXPORT(kexec_args)
147 arg0:   PTR             0x0
148 arg1:   PTR             0x0
149 arg2:   PTR             0x0
150 arg3:   PTR             0x0
151         .size   kexec_args,PTRSIZE*4
153 #ifdef CONFIG_SMP
155  * Secondary CPUs may have different kernel parameters in
156  * their registers a0-a3. secondary_kexec_args[0..3] are used
157  * to prepare register values.
158  */
159 secondary_kexec_args:
160         EXPORT(secondary_kexec_args)
161 s_arg0: PTR             0x0
162 s_arg1: PTR             0x0
163 s_arg2: PTR             0x0
164 s_arg3: PTR             0x0
165         .size   secondary_kexec_args,PTRSIZE*4
166 kexec_flag:
167         LONG            0x1
169 #endif
171 kexec_start_address:
172         EXPORT(kexec_start_address)
173         PTR             0x0
174         .size           kexec_start_address, PTRSIZE
176 kexec_indirection_page:
177         EXPORT(kexec_indirection_page)
178         PTR             0
179         .size           kexec_indirection_page, PTRSIZE
181 relocate_new_kernel_end:
183 relocate_new_kernel_size:
184         EXPORT(relocate_new_kernel_size)
185         PTR             relocate_new_kernel_end - relocate_new_kernel
186         .size           relocate_new_kernel_size, PTRSIZE