Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/shaggy...
[linux-2.6] / arch / ia64 / kernel / relocate_kernel.S
1 /*
2  * arch/ia64/kernel/relocate_kernel.S
3  *
4  * Relocate kexec'able kernel and start it
5  *
6  * Copyright (C) 2005 Hewlett-Packard Development Company, L.P.
7  * Copyright (C) 2005 Khalid Aziz  <khalid.aziz@hp.com>
8  * Copyright (C) 2005 Intel Corp,  Zou Nan hai <nanhai.zou@intel.com>
9  *
10  * This source code is licensed under the GNU General Public License,
11  * Version 2.  See the file COPYING for more details.
12  */
13 #include <asm/asmmacro.h>
14 #include <asm/kregs.h>
15 #include <asm/page.h>
16 #include <asm/pgtable.h>
17 #include <asm/mca_asm.h>
18
19        /* Must be relocatable PIC code callable as a C function
20         */
21 GLOBAL_ENTRY(relocate_new_kernel)
22         .prologue
23         alloc r31=ar.pfs,4,0,0,0
24         .body
25 .reloc_entry:
26 {
27         rsm psr.i| psr.ic
28         mov r2=ip
29 }
30         ;;
31 {
32         flushrs                         // must be first insn in group
33         srlz.i
34 }
35         ;;
36         dep r2=0,r2,61,3                //to physical address
37         ;;
38         //first switch to physical mode
39         add r3=1f-.reloc_entry, r2
40         movl r16 = IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_IC
41         mov ar.rsc=0                    // put RSE in enforced lazy mode
42         ;;
43         add sp=(memory_stack_end - 16 - .reloc_entry),r2
44         add r8=(register_stack - .reloc_entry),r2
45         ;;
46         mov r18=ar.rnat
47         mov ar.bspstore=r8
48         ;;
49         mov cr.ipsr=r16
50         mov cr.iip=r3
51         mov cr.ifs=r0
52         srlz.i
53         ;;
54         mov ar.rnat=r18
55         rfi
56         ;;
57 1:
58         //physical mode code begin
59         mov b6=in1
60         dep r28=0,in2,61,3      //to physical address
61
62         // purge all TC entries
63 #define O(member)       IA64_CPUINFO_##member##_OFFSET
64         GET_THIS_PADDR(r2, cpu_info)    // load phys addr of cpu_info into r2
65         ;;
66         addl r17=O(PTCE_STRIDE),r2
67         addl r2=O(PTCE_BASE),r2
68         ;;
69         ld8 r18=[r2],(O(PTCE_COUNT)-O(PTCE_BASE));;     // r18=ptce_base
70         ld4 r19=[r2],4                                  // r19=ptce_count[0]
71         ld4 r21=[r17],4                                 // r21=ptce_stride[0]
72         ;;
73         ld4 r20=[r2]                                    // r20=ptce_count[1]
74         ld4 r22=[r17]                                   // r22=ptce_stride[1]
75         mov r24=r0
76         ;;
77         adds r20=-1,r20
78         ;;
79 #undef O
80 2:
81         cmp.ltu p6,p7=r24,r19
82 (p7)    br.cond.dpnt.few 4f
83         mov ar.lc=r20
84 3:
85         ptc.e r18
86         ;;
87         add r18=r22,r18
88         br.cloop.sptk.few 3b
89         ;;
90         add r18=r21,r18
91         add r24=1,r24
92         ;;
93         br.sptk.few 2b
94 4:
95         srlz.i
96         ;;
97         //purge TR entry for kernel text and data
98         movl r16=KERNEL_START
99         mov r18=KERNEL_TR_PAGE_SHIFT<<2
100         ;;
101         ptr.i r16, r18
102         ptr.d r16, r18
103         ;;
104         srlz.i
105         ;;
106
107         // purge TR entry for percpu data
108         movl r16=PERCPU_ADDR
109         mov r18=PERCPU_PAGE_SHIFT<<2
110         ;;
111         ptr.d r16,r18
112         ;;
113         srlz.d
114         ;;
115
116         // purge TR entry for pal code
117         mov r16=in3
118         mov r18=IA64_GRANULE_SHIFT<<2
119         ;;
120         ptr.i r16,r18
121         ;;
122         srlz.i
123         ;;
124
125         // purge TR entry for stack
126         mov r16=IA64_KR(CURRENT_STACK)
127         ;;
128         shl r16=r16,IA64_GRANULE_SHIFT
129         movl r19=PAGE_OFFSET
130         ;;
131         add r16=r19,r16
132         mov r18=IA64_GRANULE_SHIFT<<2
133         ;;
134         ptr.d r16,r18
135         ;;
136         srlz.i
137         ;;
138
139         //copy segments
140         movl r16=PAGE_MASK
141         mov  r30=in0                    // in0 is page_list
142         br.sptk.few .dest_page
143         ;;
144 .loop:
145         ld8  r30=[in0], 8;;
146 .dest_page:
147         tbit.z p0, p6=r30, 0;;          // 0x1 dest page
148 (p6)    and r17=r30, r16
149 (p6)    br.cond.sptk.few .loop;;
150
151         tbit.z p0, p6=r30, 1;;          // 0x2 indirect page
152 (p6)    and in0=r30, r16
153 (p6)    br.cond.sptk.few .loop;;
154
155         tbit.z p0, p6=r30, 2;;          // 0x4 end flag
156 (p6)    br.cond.sptk.few .end_loop;;
157
158         tbit.z p6, p0=r30, 3;;          // 0x8 source page
159 (p6)    br.cond.sptk.few .loop
160
161         and r18=r30, r16
162
163         // simple copy page, may optimize later
164         movl r14=PAGE_SIZE/8 - 1;;
165         mov ar.lc=r14;;
166 1:
167         ld8 r14=[r18], 8;;
168         st8 [r17]=r14;;
169         fc.i r17
170         add r17=8, r17
171         br.ctop.sptk.few 1b
172         br.sptk.few .loop
173         ;;
174
175 .end_loop:
176         sync.i                  // for fc.i
177         ;;
178         srlz.i
179         ;;
180         srlz.d
181         ;;
182         br.call.sptk.many b0=b6;;
183
184 .align  32
185 memory_stack:
186         .fill           8192, 1, 0
187 memory_stack_end:
188 register_stack:
189         .fill           8192, 1, 0
190 register_stack_end:
191 relocate_new_kernel_end:
192 END(relocate_new_kernel)
193
194 .global relocate_new_kernel_size
195 relocate_new_kernel_size:
196         data8   relocate_new_kernel_end - relocate_new_kernel
197
198 GLOBAL_ENTRY(ia64_dump_cpu_regs)
199         .prologue
200         alloc loc0=ar.pfs,1,2,0,0
201         .body
202         mov     ar.rsc=0                // put RSE in enforced lazy mode
203         add     loc1=4*8, in0           // save r4 and r5 first
204         ;;
205 {
206         flushrs                         // flush dirty regs to backing store
207         srlz.i
208 }
209         st8 [loc1]=r4, 8
210         ;;
211         st8 [loc1]=r5, 8
212         ;;
213         add loc1=32*8, in0
214         mov r4=ar.rnat
215         ;;
216         st8 [in0]=r0, 8                 // r0
217         st8 [loc1]=r4, 8                // rnat
218         mov r5=pr
219         ;;
220         st8 [in0]=r1, 8                 // r1
221         st8 [loc1]=r5, 8                // pr
222         mov r4=b0
223         ;;
224         st8 [in0]=r2, 8                 // r2
225         st8 [loc1]=r4, 8                // b0
226         mov r5=b1;
227         ;;
228         st8 [in0]=r3, 24                // r3
229         st8 [loc1]=r5, 8                // b1
230         mov r4=b2
231         ;;
232         st8 [in0]=r6, 8                 // r6
233         st8 [loc1]=r4, 8                // b2
234         mov r5=b3
235         ;;
236         st8 [in0]=r7, 8                 // r7
237         st8 [loc1]=r5, 8                // b3
238         mov r4=b4
239         ;;
240         st8 [in0]=r8, 8                 // r8
241         st8 [loc1]=r4, 8                // b4
242         mov r5=b5
243         ;;
244         st8 [in0]=r9, 8                 // r9
245         st8 [loc1]=r5, 8                // b5
246         mov r4=b6
247         ;;
248         st8 [in0]=r10, 8                // r10
249         st8 [loc1]=r5, 8                // b6
250         mov r5=b7
251         ;;
252         st8 [in0]=r11, 8                // r11
253         st8 [loc1]=r5, 8                // b7
254         mov r4=b0
255         ;;
256         st8 [in0]=r12, 8                // r12
257         st8 [loc1]=r4, 8                // ip
258         mov r5=loc0
259         ;;
260         st8 [in0]=r13, 8                // r13
261         extr.u r5=r5, 0, 38             // ar.pfs.pfm
262         mov r4=r0                       // user mask
263         ;;
264         st8 [in0]=r14, 8                // r14
265         st8 [loc1]=r5, 8                // cfm
266         ;;
267         st8 [in0]=r15, 8                // r15
268         st8 [loc1]=r4, 8                // user mask
269         mov r5=ar.rsc
270         ;;
271         st8 [in0]=r16, 8                // r16
272         st8 [loc1]=r5, 8                // ar.rsc
273         mov r4=ar.bsp
274         ;;
275         st8 [in0]=r17, 8                // r17
276         st8 [loc1]=r4, 8                // ar.bsp
277         mov r5=ar.bspstore
278         ;;
279         st8 [in0]=r18, 8                // r18
280         st8 [loc1]=r5, 8                // ar.bspstore
281         mov r4=ar.rnat
282         ;;
283         st8 [in0]=r19, 8                // r19
284         st8 [loc1]=r4, 8                // ar.rnat
285         mov r5=ar.ccv
286         ;;
287         st8 [in0]=r20, 8                // r20
288         st8 [loc1]=r5, 8                // ar.ccv
289         mov r4=ar.unat
290         ;;
291         st8 [in0]=r21, 8                // r21
292         st8 [loc1]=r4, 8                // ar.unat
293         mov r5 = ar.fpsr
294         ;;
295         st8 [in0]=r22, 8                // r22
296         st8 [loc1]=r5, 8                // ar.fpsr
297         mov r4 = ar.unat
298         ;;
299         st8 [in0]=r23, 8                // r23
300         st8 [loc1]=r4, 8                // unat
301         mov r5 = ar.fpsr
302         ;;
303         st8 [in0]=r24, 8                // r24
304         st8 [loc1]=r5, 8                // fpsr
305         mov r4 = ar.pfs
306         ;;
307         st8 [in0]=r25, 8                // r25
308         st8 [loc1]=r4, 8                // ar.pfs
309         mov r5 = ar.lc
310         ;;
311         st8 [in0]=r26, 8                // r26
312         st8 [loc1]=r5, 8                // ar.lc
313         mov r4 = ar.ec
314         ;;
315         st8 [in0]=r27, 8                // r27
316         st8 [loc1]=r4, 8                // ar.ec
317         mov r5 = ar.csd
318         ;;
319         st8 [in0]=r28, 8                // r28
320         st8 [loc1]=r5, 8                // ar.csd
321         mov r4 = ar.ssd
322         ;;
323         st8 [in0]=r29, 8                // r29
324         st8 [loc1]=r4, 8                // ar.ssd
325         ;;
326         st8 [in0]=r30, 8                // r30
327         ;;
328         st8 [in0]=r31, 8                // r31
329         mov ar.pfs=loc0
330         ;;
331         br.ret.sptk.many rp
332 END(ia64_dump_cpu_regs)
333
334