[POWERPC] 64bit FPSCR support
[linux-2.6] / arch / powerpc / kernel / misc_64.S
1 /*
2  *  arch/powerpc/kernel/misc64.S
3  *
4  * This file contains miscellaneous low-level functions.
5  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6  *
7  * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
8  * and Paul Mackerras.
9  * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
10  * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) 
11  * 
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version
15  * 2 of the License, or (at your option) any later version.
16  *
17  */
18
19 #include <linux/config.h>
20 #include <linux/sys.h>
21 #include <asm/unistd.h>
22 #include <asm/errno.h>
23 #include <asm/processor.h>
24 #include <asm/page.h>
25 #include <asm/cache.h>
26 #include <asm/ppc_asm.h>
27 #include <asm/asm-offsets.h>
28 #include <asm/cputable.h>
29 #include <asm/thread_info.h>
30
31         .text
32
33 /*
34  * Returns (address we are running at) - (address we were linked at)
35  * for use before the text and data are mapped to KERNELBASE.
36  */
37
38 _GLOBAL(reloc_offset)
39         mflr    r0
40         bl      1f
41 1:      mflr    r3
42         LOAD_REG_IMMEDIATE(r4,1b)
43         subf    r3,r4,r3
44         mtlr    r0
45         blr
46
47 /*
48  * add_reloc_offset(x) returns x + reloc_offset().
49  */
50 _GLOBAL(add_reloc_offset)
51         mflr    r0
52         bl      1f
53 1:      mflr    r5
54         LOAD_REG_IMMEDIATE(r4,1b)
55         subf    r5,r4,r5
56         add     r3,r3,r5
57         mtlr    r0
58         blr
59
60 _GLOBAL(get_msr)
61         mfmsr   r3
62         blr
63
64 _GLOBAL(get_dar)
65         mfdar   r3
66         blr
67
68 _GLOBAL(get_srr0)
69         mfsrr0  r3
70         blr
71
72 _GLOBAL(get_srr1)
73         mfsrr1  r3
74         blr
75         
76 _GLOBAL(get_sp)
77         mr      r3,r1
78         blr
79
80 #ifdef CONFIG_IRQSTACKS
81 _GLOBAL(call_do_softirq)
82         mflr    r0
83         std     r0,16(r1)
84         stdu    r1,THREAD_SIZE-112(r3)
85         mr      r1,r3
86         bl      .__do_softirq
87         ld      r1,0(r1)
88         ld      r0,16(r1)
89         mtlr    r0
90         blr
91
92 _GLOBAL(call___do_IRQ)
93         mflr    r0
94         std     r0,16(r1)
95         stdu    r1,THREAD_SIZE-112(r5)
96         mr      r1,r5
97         bl      .__do_IRQ
98         ld      r1,0(r1)
99         ld      r0,16(r1)
100         mtlr    r0
101         blr
102 #endif /* CONFIG_IRQSTACKS */
103
104         /*
105  * To be called by C code which needs to do some operations with MMU
106  * disabled. Note that interrupts have to be disabled by the caller
107  * prior to calling us. The code called _MUST_ be in the RMO of course
108  * and part of the linear mapping as we don't attempt to translate the
109  * stack pointer at all. The function is called with the stack switched
110  * to this CPU emergency stack
111  *
112  * prototype is void *call_with_mmu_off(void *func, void *data);
113  *
114  * the called function is expected to be of the form
115  *
116  * void *called(void *data); 
117  */
118 _GLOBAL(call_with_mmu_off)
119         mflr    r0                      /* get link, save it on stackframe */
120         std     r0,16(r1)
121         mr      r1,r5                   /* save old stack ptr */
122         ld      r1,PACAEMERGSP(r13)     /* get emerg. stack */
123         subi    r1,r1,STACK_FRAME_OVERHEAD
124         std     r0,16(r1)               /* save link on emerg. stack */
125         std     r5,0(r1)                /* save old stack ptr in backchain */
126         ld      r3,0(r3)                /* get to real function ptr (assume same TOC) */
127         bl      2f                      /* we need LR to return, continue at label 2 */
128
129         ld      r0,16(r1)               /* we return here from the call, get LR and */
130         ld      r1,0(r1)                /* .. old stack ptr */
131         mtspr   SPRN_SRR0,r0            /* and get back to virtual mode with these */
132         mfmsr   r4
133         ori     r4,r4,MSR_IR|MSR_DR
134         mtspr   SPRN_SRR1,r4
135         rfid
136
137 2:      mtspr   SPRN_SRR0,r3            /* coming from above, enter real mode */
138         mr      r3,r4                   /* get parameter */
139         mfmsr   r0
140         ori     r0,r0,MSR_IR|MSR_DR
141         xori    r0,r0,MSR_IR|MSR_DR
142         mtspr   SPRN_SRR1,r0
143         rfid
144
145
146         .section        ".toc","aw"
147 PPC64_CACHES:
148         .tc             ppc64_caches[TC],ppc64_caches
149         .section        ".text"
150
151 /*
152  * Write any modified data cache blocks out to memory
153  * and invalidate the corresponding instruction cache blocks.
154  *
155  * flush_icache_range(unsigned long start, unsigned long stop)
156  *
157  *   flush all bytes from start through stop-1 inclusive
158  */
159
160 _KPROBE(__flush_icache_range)
161
162 /*
163  * Flush the data cache to memory 
164  * 
165  * Different systems have different cache line sizes
166  * and in some cases i-cache and d-cache line sizes differ from
167  * each other.
168  */
169         ld      r10,PPC64_CACHES@toc(r2)
170         lwz     r7,DCACHEL1LINESIZE(r10)/* Get cache line size */
171         addi    r5,r7,-1
172         andc    r6,r3,r5                /* round low to line bdy */
173         subf    r8,r6,r4                /* compute length */
174         add     r8,r8,r5                /* ensure we get enough */
175         lwz     r9,DCACHEL1LOGLINESIZE(r10)     /* Get log-2 of cache line size */
176         srw.    r8,r8,r9                /* compute line count */
177         beqlr                           /* nothing to do? */
178         mtctr   r8
179 1:      dcbst   0,r6
180         add     r6,r6,r7
181         bdnz    1b
182         sync
183
184 /* Now invalidate the instruction cache */
185         
186         lwz     r7,ICACHEL1LINESIZE(r10)        /* Get Icache line size */
187         addi    r5,r7,-1
188         andc    r6,r3,r5                /* round low to line bdy */
189         subf    r8,r6,r4                /* compute length */
190         add     r8,r8,r5
191         lwz     r9,ICACHEL1LOGLINESIZE(r10)     /* Get log-2 of Icache line size */
192         srw.    r8,r8,r9                /* compute line count */
193         beqlr                           /* nothing to do? */
194         mtctr   r8
195 2:      icbi    0,r6
196         add     r6,r6,r7
197         bdnz    2b
198         isync
199         blr
200         .previous .text
201 /*
202  * Like above, but only do the D-cache.
203  *
204  * flush_dcache_range(unsigned long start, unsigned long stop)
205  *
206  *    flush all bytes from start to stop-1 inclusive
207  */
208 _GLOBAL(flush_dcache_range)
209
210 /*
211  * Flush the data cache to memory 
212  * 
213  * Different systems have different cache line sizes
214  */
215         ld      r10,PPC64_CACHES@toc(r2)
216         lwz     r7,DCACHEL1LINESIZE(r10)        /* Get dcache line size */
217         addi    r5,r7,-1
218         andc    r6,r3,r5                /* round low to line bdy */
219         subf    r8,r6,r4                /* compute length */
220         add     r8,r8,r5                /* ensure we get enough */
221         lwz     r9,DCACHEL1LOGLINESIZE(r10)     /* Get log-2 of dcache line size */
222         srw.    r8,r8,r9                /* compute line count */
223         beqlr                           /* nothing to do? */
224         mtctr   r8
225 0:      dcbst   0,r6
226         add     r6,r6,r7
227         bdnz    0b
228         sync
229         blr
230
231 /*
232  * Like above, but works on non-mapped physical addresses.
233  * Use only for non-LPAR setups ! It also assumes real mode
234  * is cacheable. Used for flushing out the DART before using
235  * it as uncacheable memory 
236  *
237  * flush_dcache_phys_range(unsigned long start, unsigned long stop)
238  *
239  *    flush all bytes from start to stop-1 inclusive
240  */
241 _GLOBAL(flush_dcache_phys_range)
242         ld      r10,PPC64_CACHES@toc(r2)
243         lwz     r7,DCACHEL1LINESIZE(r10)        /* Get dcache line size */
244         addi    r5,r7,-1
245         andc    r6,r3,r5                /* round low to line bdy */
246         subf    r8,r6,r4                /* compute length */
247         add     r8,r8,r5                /* ensure we get enough */
248         lwz     r9,DCACHEL1LOGLINESIZE(r10)     /* Get log-2 of dcache line size */
249         srw.    r8,r8,r9                /* compute line count */
250         beqlr                           /* nothing to do? */
251         mfmsr   r5                      /* Disable MMU Data Relocation */
252         ori     r0,r5,MSR_DR
253         xori    r0,r0,MSR_DR
254         sync
255         mtmsr   r0
256         sync
257         isync
258         mtctr   r8
259 0:      dcbst   0,r6
260         add     r6,r6,r7
261         bdnz    0b
262         sync
263         isync
264         mtmsr   r5                      /* Re-enable MMU Data Relocation */
265         sync
266         isync
267         blr
268
269 _GLOBAL(flush_inval_dcache_range)
270         ld      r10,PPC64_CACHES@toc(r2)
271         lwz     r7,DCACHEL1LINESIZE(r10)        /* Get dcache line size */
272         addi    r5,r7,-1
273         andc    r6,r3,r5                /* round low to line bdy */
274         subf    r8,r6,r4                /* compute length */
275         add     r8,r8,r5                /* ensure we get enough */
276         lwz     r9,DCACHEL1LOGLINESIZE(r10)/* Get log-2 of dcache line size */
277         srw.    r8,r8,r9                /* compute line count */
278         beqlr                           /* nothing to do? */
279         sync
280         isync
281         mtctr   r8
282 0:      dcbf    0,r6
283         add     r6,r6,r7
284         bdnz    0b
285         sync
286         isync
287         blr
288
289
290 /*
291  * Flush a particular page from the data cache to RAM.
292  * Note: this is necessary because the instruction cache does *not*
293  * snoop from the data cache.
294  *
295  *      void __flush_dcache_icache(void *page)
296  */
297 _GLOBAL(__flush_dcache_icache)
298 /*
299  * Flush the data cache to memory 
300  * 
301  * Different systems have different cache line sizes
302  */
303
304 /* Flush the dcache */
305         ld      r7,PPC64_CACHES@toc(r2)
306         clrrdi  r3,r3,PAGE_SHIFT                    /* Page align */
307         lwz     r4,DCACHEL1LINESPERPAGE(r7)     /* Get # dcache lines per page */
308         lwz     r5,DCACHEL1LINESIZE(r7)         /* Get dcache line size */
309         mr      r6,r3
310         mtctr   r4
311 0:      dcbst   0,r6
312         add     r6,r6,r5
313         bdnz    0b
314         sync
315
316 /* Now invalidate the icache */ 
317
318         lwz     r4,ICACHEL1LINESPERPAGE(r7)     /* Get # icache lines per page */
319         lwz     r5,ICACHEL1LINESIZE(r7)         /* Get icache line size */
320         mtctr   r4
321 1:      icbi    0,r3
322         add     r3,r3,r5
323         bdnz    1b
324         isync
325         blr
326         
327 /*
328  * I/O string operations
329  *
330  * insb(port, buf, len)
331  * outsb(port, buf, len)
332  * insw(port, buf, len)
333  * outsw(port, buf, len)
334  * insl(port, buf, len)
335  * outsl(port, buf, len)
336  * insw_ns(port, buf, len)
337  * outsw_ns(port, buf, len)
338  * insl_ns(port, buf, len)
339  * outsl_ns(port, buf, len)
340  *
341  * The *_ns versions don't do byte-swapping.
342  */
343 _GLOBAL(_insb)
344         cmpwi   0,r5,0
345         mtctr   r5
346         subi    r4,r4,1
347         blelr-
348 00:     lbz     r5,0(r3)
349         eieio
350         stbu    r5,1(r4)
351         bdnz    00b
352         twi     0,r5,0
353         isync
354         blr
355
356 _GLOBAL(_outsb)
357         cmpwi   0,r5,0
358         mtctr   r5
359         subi    r4,r4,1
360         blelr-
361 00:     lbzu    r5,1(r4)
362         stb     r5,0(r3)
363         bdnz    00b
364         sync
365         blr     
366
367 _GLOBAL(_insw)
368         cmpwi   0,r5,0
369         mtctr   r5
370         subi    r4,r4,2
371         blelr-
372 00:     lhbrx   r5,0,r3
373         eieio
374         sthu    r5,2(r4)
375         bdnz    00b
376         twi     0,r5,0
377         isync
378         blr
379
380 _GLOBAL(_outsw)
381         cmpwi   0,r5,0
382         mtctr   r5
383         subi    r4,r4,2
384         blelr-
385 00:     lhzu    r5,2(r4)
386         sthbrx  r5,0,r3 
387         bdnz    00b
388         sync
389         blr     
390
391 _GLOBAL(_insl)
392         cmpwi   0,r5,0
393         mtctr   r5
394         subi    r4,r4,4
395         blelr-
396 00:     lwbrx   r5,0,r3
397         eieio
398         stwu    r5,4(r4)
399         bdnz    00b
400         twi     0,r5,0
401         isync
402         blr
403
404 _GLOBAL(_outsl)
405         cmpwi   0,r5,0
406         mtctr   r5
407         subi    r4,r4,4
408         blelr-
409 00:     lwzu    r5,4(r4)
410         stwbrx  r5,0,r3
411         bdnz    00b
412         sync
413         blr     
414
415 /* _GLOBAL(ide_insw) now in drivers/ide/ide-iops.c */
416 _GLOBAL(_insw_ns)
417         cmpwi   0,r5,0
418         mtctr   r5
419         subi    r4,r4,2
420         blelr-
421 00:     lhz     r5,0(r3)
422         eieio
423         sthu    r5,2(r4)
424         bdnz    00b
425         twi     0,r5,0
426         isync
427         blr
428
429 /* _GLOBAL(ide_outsw) now in drivers/ide/ide-iops.c */
430 _GLOBAL(_outsw_ns)
431         cmpwi   0,r5,0
432         mtctr   r5
433         subi    r4,r4,2
434         blelr-
435 00:     lhzu    r5,2(r4)
436         sth     r5,0(r3)
437         bdnz    00b
438         sync
439         blr     
440
441 _GLOBAL(_insl_ns)
442         cmpwi   0,r5,0
443         mtctr   r5
444         subi    r4,r4,4
445         blelr-
446 00:     lwz     r5,0(r3)
447         eieio
448         stwu    r5,4(r4)
449         bdnz    00b
450         twi     0,r5,0
451         isync
452         blr
453
454 _GLOBAL(_outsl_ns)
455         cmpwi   0,r5,0
456         mtctr   r5
457         subi    r4,r4,4
458         blelr-
459 00:     lwzu    r5,4(r4)
460         stw     r5,0(r3)
461         bdnz    00b
462         sync
463         blr     
464
465 /*
466  * identify_cpu and calls setup_cpu
467  * In:  r3 = base of the cpu_specs array
468  *      r4 = address of cur_cpu_spec
469  *      r5 = relocation offset
470  */
471 _GLOBAL(identify_cpu)
472         mfpvr   r7
473 1:
474         lwz     r8,CPU_SPEC_PVR_MASK(r3)
475         and     r8,r8,r7
476         lwz     r9,CPU_SPEC_PVR_VALUE(r3)
477         cmplw   0,r9,r8
478         beq     1f
479         addi    r3,r3,CPU_SPEC_ENTRY_SIZE
480         b       1b
481 1:
482         sub     r0,r3,r5
483         std     r0,0(r4)
484         ld      r4,CPU_SPEC_SETUP(r3)
485         cmpdi   0,r4,0
486         add     r4,r4,r5
487         beqlr
488         ld      r4,0(r4)
489         add     r4,r4,r5
490         mtctr   r4
491         /* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */
492         mr      r4,r3
493         mr      r3,r5
494         bctr
495
496 /*
497  * do_cpu_ftr_fixups - goes through the list of CPU feature fixups
498  * and writes nop's over sections of code that don't apply for this cpu.
499  * r3 = data offset (not changed)
500  */
501 _GLOBAL(do_cpu_ftr_fixups)
502         /* Get CPU 0 features */
503         LOAD_REG_IMMEDIATE(r6,cur_cpu_spec)
504         sub     r6,r6,r3
505         ld      r4,0(r6)
506         sub     r4,r4,r3
507         ld      r4,CPU_SPEC_FEATURES(r4)
508         /* Get the fixup table */
509         LOAD_REG_IMMEDIATE(r6,__start___ftr_fixup)
510         sub     r6,r6,r3
511         LOAD_REG_IMMEDIATE(r7,__stop___ftr_fixup)
512         sub     r7,r7,r3
513         /* Do the fixup */
514 1:      cmpld   r6,r7
515         bgelr
516         addi    r6,r6,32
517         ld      r8,-32(r6)      /* mask */
518         and     r8,r8,r4
519         ld      r9,-24(r6)      /* value */
520         cmpld   r8,r9
521         beq     1b
522         ld      r8,-16(r6)      /* section begin */
523         ld      r9,-8(r6)       /* section end */
524         subf.   r9,r8,r9
525         beq     1b
526         /* write nops over the section of code */
527         /* todo: if large section, add a branch at the start of it */
528         srwi    r9,r9,2
529         mtctr   r9
530         sub     r8,r8,r3
531         lis     r0,0x60000000@h /* nop */
532 3:      stw     r0,0(r8)
533         andi.   r10,r4,CPU_FTR_SPLIT_ID_CACHE@l
534         beq     2f
535         dcbst   0,r8            /* suboptimal, but simpler */
536         sync
537         icbi    0,r8
538 2:      addi    r8,r8,4
539         bdnz    3b
540         sync                    /* additional sync needed on g4 */
541         isync
542         b       1b
543
544 #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
545 /*
546  * Do an IO access in real mode
547  */
548 _GLOBAL(real_readb)
549         mfmsr   r7
550         ori     r0,r7,MSR_DR
551         xori    r0,r0,MSR_DR
552         sync
553         mtmsrd  r0
554         sync
555         isync
556         mfspr   r6,SPRN_HID4
557         rldicl  r5,r6,32,0
558         ori     r5,r5,0x100
559         rldicl  r5,r5,32,0
560         sync
561         mtspr   SPRN_HID4,r5
562         isync
563         slbia
564         isync
565         lbz     r3,0(r3)
566         sync
567         mtspr   SPRN_HID4,r6
568         isync
569         slbia
570         isync
571         mtmsrd  r7
572         sync
573         isync
574         blr
575
576         /*
577  * Do an IO access in real mode
578  */
579 _GLOBAL(real_writeb)
580         mfmsr   r7
581         ori     r0,r7,MSR_DR
582         xori    r0,r0,MSR_DR
583         sync
584         mtmsrd  r0
585         sync
586         isync
587         mfspr   r6,SPRN_HID4
588         rldicl  r5,r6,32,0
589         ori     r5,r5,0x100
590         rldicl  r5,r5,32,0
591         sync
592         mtspr   SPRN_HID4,r5
593         isync
594         slbia
595         isync
596         stb     r3,0(r4)
597         sync
598         mtspr   SPRN_HID4,r6
599         isync
600         slbia
601         isync
602         mtmsrd  r7
603         sync
604         isync
605         blr
606 #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */
607
608 /*
609  * SCOM access functions for 970 (FX only for now)
610  *
611  * unsigned long scom970_read(unsigned int address);
612  * void scom970_write(unsigned int address, unsigned long value);
613  *
614  * The address passed in is the 24 bits register address. This code
615  * is 970 specific and will not check the status bits, so you should
616  * know what you are doing.
617  */
618 _GLOBAL(scom970_read)
619         /* interrupts off */
620         mfmsr   r4
621         ori     r0,r4,MSR_EE
622         xori    r0,r0,MSR_EE
623         mtmsrd  r0,1
624
625         /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits
626          * (including parity). On current CPUs they must be 0'd,
627          * and finally or in RW bit
628          */
629         rlwinm  r3,r3,8,0,15
630         ori     r3,r3,0x8000
631
632         /* do the actual scom read */
633         sync
634         mtspr   SPRN_SCOMC,r3
635         isync
636         mfspr   r3,SPRN_SCOMD
637         isync
638         mfspr   r0,SPRN_SCOMC
639         isync
640
641         /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah
642          * that's the best we can do). Not implemented yet as we don't use
643          * the scom on any of the bogus CPUs yet, but may have to be done
644          * ultimately
645          */
646
647         /* restore interrupts */
648         mtmsrd  r4,1
649         blr
650
651
652 _GLOBAL(scom970_write)
653         /* interrupts off */
654         mfmsr   r5
655         ori     r0,r5,MSR_EE
656         xori    r0,r0,MSR_EE
657         mtmsrd  r0,1
658
659         /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits
660          * (including parity). On current CPUs they must be 0'd.
661          */
662
663         rlwinm  r3,r3,8,0,15
664
665         sync
666         mtspr   SPRN_SCOMD,r4      /* write data */
667         isync
668         mtspr   SPRN_SCOMC,r3      /* write command */
669         isync
670         mfspr   3,SPRN_SCOMC
671         isync
672
673         /* restore interrupts */
674         mtmsrd  r5,1
675         blr
676
677
678 /*
679  * Create a kernel thread
680  *   kernel_thread(fn, arg, flags)
681  */
682 _GLOBAL(kernel_thread)
683         std     r29,-24(r1)
684         std     r30,-16(r1)
685         stdu    r1,-STACK_FRAME_OVERHEAD(r1)
686         mr      r29,r3
687         mr      r30,r4
688         ori     r3,r5,CLONE_VM  /* flags */
689         oris    r3,r3,(CLONE_UNTRACED>>16)
690         li      r4,0            /* new sp (unused) */
691         li      r0,__NR_clone
692         sc
693         cmpdi   0,r3,0          /* parent or child? */
694         bne     1f              /* return if parent */
695         li      r0,0
696         stdu    r0,-STACK_FRAME_OVERHEAD(r1)
697         ld      r2,8(r29)
698         ld      r29,0(r29)
699         mtlr    r29              /* fn addr in lr */
700         mr      r3,r30          /* load arg and call fn */
701         blrl
702         li      r0,__NR_exit    /* exit after child exits */
703         li      r3,0
704         sc
705 1:      addi    r1,r1,STACK_FRAME_OVERHEAD      
706         ld      r29,-24(r1)
707         ld      r30,-16(r1)
708         blr
709
710 /*
711  * disable_kernel_fp()
712  * Disable the FPU.
713  */
714 _GLOBAL(disable_kernel_fp)
715         mfmsr   r3
716         rldicl  r0,r3,(63-MSR_FP_LG),1
717         rldicl  r3,r0,(MSR_FP_LG+1),0
718         mtmsrd  r3                      /* disable use of fpu now */
719         isync
720         blr
721
722 #ifdef CONFIG_ALTIVEC
723
724 #if 0 /* this has no callers for now */
725 /*
726  * disable_kernel_altivec()
727  * Disable the VMX.
728  */
729 _GLOBAL(disable_kernel_altivec)
730         mfmsr   r3
731         rldicl  r0,r3,(63-MSR_VEC_LG),1
732         rldicl  r3,r0,(MSR_VEC_LG+1),0
733         mtmsrd  r3                      /* disable use of VMX now */
734         isync
735         blr
736 #endif /* 0 */
737
738 /*
739  * giveup_altivec(tsk)
740  * Disable VMX for the task given as the argument,
741  * and save the vector registers in its thread_struct.
742  * Enables the VMX for use in the kernel on return.
743  */
744 _GLOBAL(giveup_altivec)
745         mfmsr   r5
746         oris    r5,r5,MSR_VEC@h
747         mtmsrd  r5                      /* enable use of VMX now */
748         isync
749         cmpdi   0,r3,0
750         beqlr-                          /* if no previous owner, done */
751         addi    r3,r3,THREAD            /* want THREAD of task */
752         ld      r5,PT_REGS(r3)
753         cmpdi   0,r5,0
754         SAVE_32VRS(0,r4,r3)
755         mfvscr  vr0
756         li      r4,THREAD_VSCR
757         stvx    vr0,r4,r3
758         beq     1f
759         ld      r4,_MSR-STACK_FRAME_OVERHEAD(r5)
760         lis     r3,MSR_VEC@h
761         andc    r4,r4,r3                /* disable FP for previous task */
762         std     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
763 1:
764 #ifndef CONFIG_SMP
765         li      r5,0
766         ld      r4,last_task_used_altivec@got(r2)
767         std     r5,0(r4)
768 #endif /* CONFIG_SMP */
769         blr
770
771 #endif /* CONFIG_ALTIVEC */
772
773 _GLOBAL(execve)
774         li      r0,__NR_execve
775         sc
776         bnslr
777         neg     r3,r3
778         blr
779
780 /* kexec_wait(phys_cpu)
781  *
782  * wait for the flag to change, indicating this kernel is going away but
783  * the slave code for the next one is at addresses 0 to 100.
784  *
785  * This is used by all slaves.
786  *
787  * Physical (hardware) cpu id should be in r3.
788  */
789 _GLOBAL(kexec_wait)
790         bl      1f
791 1:      mflr    r5
792         addi    r5,r5,kexec_flag-1b
793
794 99:     HMT_LOW
795 #ifdef CONFIG_KEXEC             /* use no memory without kexec */
796         lwz     r4,0(r5)
797         cmpwi   0,r4,0
798         bnea    0x60
799 #endif
800         b       99b
801
802 /* this can be in text because we won't change it until we are
803  * running in real anyways
804  */
805 kexec_flag:
806         .long   0
807
808
809 #ifdef CONFIG_KEXEC
810
811 /* kexec_smp_wait(void)
812  *
813  * call with interrupts off
814  * note: this is a terminal routine, it does not save lr
815  *
816  * get phys id from paca
817  * set paca id to -1 to say we got here
818  * switch to real mode
819  * join other cpus in kexec_wait(phys_id)
820  */
821 _GLOBAL(kexec_smp_wait)
822         lhz     r3,PACAHWCPUID(r13)
823         li      r4,-1
824         sth     r4,PACAHWCPUID(r13)     /* let others know we left */
825         bl      real_mode
826         b       .kexec_wait
827
828 /*
829  * switch to real mode (turn mmu off)
830  * we use the early kernel trick that the hardware ignores bits
831  * 0 and 1 (big endian) of the effective address in real mode
832  *
833  * don't overwrite r3 here, it is live for kexec_wait above.
834  */
835 real_mode:      /* assume normal blr return */
836 1:      li      r9,MSR_RI
837         li      r10,MSR_DR|MSR_IR
838         mflr    r11             /* return address to SRR0 */
839         mfmsr   r12
840         andc    r9,r12,r9
841         andc    r10,r12,r10
842
843         mtmsrd  r9,1
844         mtspr   SPRN_SRR1,r10
845         mtspr   SPRN_SRR0,r11
846         rfid
847
848
849 /*
850  * kexec_sequence(newstack, start, image, control, clear_all())
851  *
852  * does the grungy work with stack switching and real mode switches
853  * also does simple calls to other code
854  */
855
856 _GLOBAL(kexec_sequence)
857         mflr    r0
858         std     r0,16(r1)
859
860         /* switch stacks to newstack -- &kexec_stack.stack */
861         stdu    r1,THREAD_SIZE-112(r3)
862         mr      r1,r3
863
864         li      r0,0
865         std     r0,16(r1)
866
867         /* save regs for local vars on new stack.
868          * yes, we won't go back, but ...
869          */
870         std     r31,-8(r1)
871         std     r30,-16(r1)
872         std     r29,-24(r1)
873         std     r28,-32(r1)
874         std     r27,-40(r1)
875         std     r26,-48(r1)
876         std     r25,-56(r1)
877
878         stdu    r1,-112-64(r1)
879
880         /* save args into preserved regs */
881         mr      r31,r3                  /* newstack (both) */
882         mr      r30,r4                  /* start (real) */
883         mr      r29,r5                  /* image (virt) */
884         mr      r28,r6                  /* control, unused */
885         mr      r27,r7                  /* clear_all() fn desc */
886         mr      r26,r8                  /* spare */
887         lhz     r25,PACAHWCPUID(r13)    /* get our phys cpu from paca */
888
889         /* disable interrupts, we are overwriting kernel data next */
890         mfmsr   r3
891         rlwinm  r3,r3,0,17,15
892         mtmsrd  r3,1
893
894         /* copy dest pages, flush whole dest image */
895         mr      r3,r29
896         bl      .kexec_copy_flush       /* (image) */
897
898         /* turn off mmu */
899         bl      real_mode
900
901         /* clear out hardware hash page table and tlb */
902         ld      r5,0(r27)               /* deref function descriptor */
903         mtctr   r5
904         bctrl                           /* ppc_md.hash_clear_all(void); */
905
906 /*
907  *   kexec image calling is:
908  *      the first 0x100 bytes of the entry point are copied to 0
909  *
910  *      all slaves branch to slave = 0x60 (absolute)
911  *              slave(phys_cpu_id);
912  *
913  *      master goes to start = entry point
914  *              start(phys_cpu_id, start, 0);
915  *
916  *
917  *   a wrapper is needed to call existing kernels, here is an approximate
918  *   description of one method:
919  *
920  * v2: (2.6.10)
921  *   start will be near the boot_block (maybe 0x100 bytes before it?)
922  *   it will have a 0x60, which will b to boot_block, where it will wait
923  *   and 0 will store phys into struct boot-block and load r3 from there,
924  *   copy kernel 0-0x100 and tell slaves to back down to 0x60 again
925  *
926  * v1: (2.6.9)
927  *    boot block will have all cpus scanning device tree to see if they
928  *    are the boot cpu ?????
929  *    other device tree differences (prop sizes, va vs pa, etc)...
930  */
931
932         /* copy  0x100 bytes starting at start to 0 */
933         li      r3,0
934         mr      r4,r30
935         li      r5,0x100
936         li      r6,0
937         bl      .copy_and_flush /* (dest, src, copy limit, start offset) */
938 1:      /* assume normal blr return */
939
940         /* release other cpus to the new kernel secondary start at 0x60 */
941         mflr    r5
942         li      r6,1
943         stw     r6,kexec_flag-1b(5)
944         mr      r3,r25  # my phys cpu
945         mr      r4,r30  # start, aka phys mem offset
946         mtlr    4
947         li      r5,0
948         blr     /* image->start(physid, image->start, 0); */
949 #endif /* CONFIG_KEXEC */