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        */
21GLOBAL_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	;;
571:
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
802:
81        cmp.ltu p6,p7=r24,r19
82(p7)    br.cond.dpnt.few 4f
83        mov ar.lc=r20
843:
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
944:
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;;
1661:
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
185memory_stack:
186	.fill           8192, 1, 0
187memory_stack_end:
188register_stack:
189	.fill           8192, 1, 0
190register_stack_end:
191relocate_new_kernel_end:
192END(relocate_new_kernel)
193
194.global relocate_new_kernel_size
195relocate_new_kernel_size:
196	data8	relocate_new_kernel_end - relocate_new_kernel
197
198GLOBAL_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
332END(ia64_dump_cpu_regs)
333
334
335