[PATCH] ppc64: SMU based macs cpufreq support
[linux-2.6/mini2440.git] / arch / powerpc / kernel / misc_64.S
blobae1433da09b27ea4cd76f0013616a35d38560855
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  */
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>
31         .text
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  */
38 _GLOBAL(reloc_offset)
39         mflr    r0
40         bl      1f
41 1:      mflr    r3
42         LOADADDR(r4,1b)
43         subf    r3,r4,r3
44         mtlr    r0
45         blr
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         LOADADDR(r4,1b)
55         subf    r5,r4,r5
56         add     r3,r3,r5
57         mtlr    r0
58         blr
60 _GLOBAL(get_msr)
61         mfmsr   r3
62         blr
64 _GLOBAL(get_dar)
65         mfdar   r3
66         blr
68 _GLOBAL(get_srr0)
69         mfsrr0  r3
70         blr
72 _GLOBAL(get_srr1)
73         mfsrr1  r3
74         blr
75         
76 _GLOBAL(get_sp)
77         mr      r3,r1
78         blr
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
92 _GLOBAL(call_handle_IRQ_event)
93         mflr    r0
94         std     r0,16(r1)
95         stdu    r1,THREAD_SIZE-112(r6)
96         mr      r1,r6
97         bl      .handle_IRQ_event
98         ld      r1,0(r1)
99         ld      r0,16(r1)
100         mtlr    r0
101         blr
102 #endif /* CONFIG_IRQSTACKS */
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
112  * prototype is void *call_with_mmu_off(void *func, void *data);
114  * the called function is expected to be of the form
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 */
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
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
146         .section        ".toc","aw"
147 PPC64_CACHES:
148         .tc             ppc64_caches[TC],ppc64_caches
149         .section        ".text"
152  * Write any modified data cache blocks out to memory
153  * and invalidate the corresponding instruction cache blocks.
155  * flush_icache_range(unsigned long start, unsigned long stop)
157  *   flush all bytes from start through stop-1 inclusive
158  */
160 _KPROBE(__flush_icache_range)
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
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
202  * Like above, but only do the D-cache.
204  * flush_dcache_range(unsigned long start, unsigned long stop)
206  *    flush all bytes from start to stop-1 inclusive
207  */
208 _GLOBAL(flush_dcache_range)
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
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 
237  * flush_dcache_phys_range(unsigned long start, unsigned long stop)
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
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
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.
295  *      void __flush_dcache_icache(void *page)
296  */
297 _GLOBAL(__flush_dcache_icache)
299  * Flush the data cache to memory 
300  * 
301  * Different systems have different cache line sizes
302  */
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
316 /* Now invalidate the icache */ 
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         
328  * I/O string operations
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)
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
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     
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
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     
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
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     
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
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     
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
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     
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
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
482         sub     r0,r3,r5
483         std     r0,0(r4)
484         ld      r4,CPU_SPEC_SETUP(r3)
485         add     r4,r4,r5
486         ld      r4,0(r4)
487         add     r4,r4,r5
488         mtctr   r4
489         /* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */
490         mr      r4,r3
491         mr      r3,r5
492         bctr
495  * do_cpu_ftr_fixups - goes through the list of CPU feature fixups
496  * and writes nop's over sections of code that don't apply for this cpu.
497  * r3 = data offset (not changed)
498  */
499 _GLOBAL(do_cpu_ftr_fixups)
500         /* Get CPU 0 features */
501         LOADADDR(r6,cur_cpu_spec)
502         sub     r6,r6,r3
503         ld      r4,0(r6)
504         sub     r4,r4,r3
505         ld      r4,CPU_SPEC_FEATURES(r4)
506         /* Get the fixup table */
507         LOADADDR(r6,__start___ftr_fixup)
508         sub     r6,r6,r3
509         LOADADDR(r7,__stop___ftr_fixup)
510         sub     r7,r7,r3
511         /* Do the fixup */
512 1:      cmpld   r6,r7
513         bgelr
514         addi    r6,r6,32
515         ld      r8,-32(r6)      /* mask */
516         and     r8,r8,r4
517         ld      r9,-24(r6)      /* value */
518         cmpld   r8,r9
519         beq     1b
520         ld      r8,-16(r6)      /* section begin */
521         ld      r9,-8(r6)       /* section end */
522         subf.   r9,r8,r9
523         beq     1b
524         /* write nops over the section of code */
525         /* todo: if large section, add a branch at the start of it */
526         srwi    r9,r9,2
527         mtctr   r9
528         sub     r8,r8,r3
529         lis     r0,0x60000000@h /* nop */
530 3:      stw     r0,0(r8)
531         andi.   r10,r4,CPU_FTR_SPLIT_ID_CACHE@l
532         beq     2f
533         dcbst   0,r8            /* suboptimal, but simpler */
534         sync
535         icbi    0,r8
536 2:      addi    r8,r8,4
537         bdnz    3b
538         sync                    /* additional sync needed on g4 */
539         isync
540         b       1b
542 #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
544  * Do an IO access in real mode
545  */
546 _GLOBAL(real_readb)
547         mfmsr   r7
548         ori     r0,r7,MSR_DR
549         xori    r0,r0,MSR_DR
550         sync
551         mtmsrd  r0
552         sync
553         isync
554         mfspr   r6,SPRN_HID4
555         rldicl  r5,r6,32,0
556         ori     r5,r5,0x100
557         rldicl  r5,r5,32,0
558         sync
559         mtspr   SPRN_HID4,r5
560         isync
561         slbia
562         isync
563         lbz     r3,0(r3)
564         sync
565         mtspr   SPRN_HID4,r6
566         isync
567         slbia
568         isync
569         mtmsrd  r7
570         sync
571         isync
572         blr
574         /*
575  * Do an IO access in real mode
576  */
577 _GLOBAL(real_writeb)
578         mfmsr   r7
579         ori     r0,r7,MSR_DR
580         xori    r0,r0,MSR_DR
581         sync
582         mtmsrd  r0
583         sync
584         isync
585         mfspr   r6,SPRN_HID4
586         rldicl  r5,r6,32,0
587         ori     r5,r5,0x100
588         rldicl  r5,r5,32,0
589         sync
590         mtspr   SPRN_HID4,r5
591         isync
592         slbia
593         isync
594         stb     r3,0(r4)
595         sync
596         mtspr   SPRN_HID4,r6
597         isync
598         slbia
599         isync
600         mtmsrd  r7
601         sync
602         isync
603         blr
604 #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */
607  * SCOM access functions for 970 (FX only for now)
609  * unsigned long scom970_read(unsigned int address);
610  * void scom970_write(unsigned int address, unsigned long value);
612  * The address passed in is the 24 bits register address. This code
613  * is 970 specific and will not check the status bits, so you should
614  * know what you are doing.
615  */
616 _GLOBAL(scom970_read)
617         /* interrupts off */
618         mfmsr   r4
619         ori     r0,r4,MSR_EE
620         xori    r0,r0,MSR_EE
621         mtmsrd  r0,1
623         /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits
624          * (including parity). On current CPUs they must be 0'd,
625          * and finally or in RW bit
626          */
627         rlwinm  r3,r3,8,0,15
628         ori     r3,r3,0x8000
630         /* do the actual scom read */
631         sync
632         mtspr   SPRN_SCOMC,r3
633         isync
634         mfspr   r3,SPRN_SCOMD
635         isync
636         mfspr   r0,SPRN_SCOMC
637         isync
639         /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah
640          * that's the best we can do). Not implemented yet as we don't use
641          * the scom on any of the bogus CPUs yet, but may have to be done
642          * ultimately
643          */
645         /* restore interrupts */
646         mtmsrd  r4,1
647         blr
650 _GLOBAL(scom970_write)
651         /* interrupts off */
652         mfmsr   r5
653         ori     r0,r5,MSR_EE
654         xori    r0,r0,MSR_EE
655         mtmsrd  r0,1
657         /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits
658          * (including parity). On current CPUs they must be 0'd.
659          */
661         rlwinm  r3,r3,8,0,15
663         sync
664         mtspr   SPRN_SCOMD,r4      /* write data */
665         isync
666         mtspr   SPRN_SCOMC,r3      /* write command */
667         isync
668         mfspr   3,SPRN_SCOMC
669         isync
671         /* restore interrupts */
672         mtmsrd  r5,1
673         blr
677  * Create a kernel thread
678  *   kernel_thread(fn, arg, flags)
679  */
680 _GLOBAL(kernel_thread)
681         std     r29,-24(r1)
682         std     r30,-16(r1)
683         stdu    r1,-STACK_FRAME_OVERHEAD(r1)
684         mr      r29,r3
685         mr      r30,r4
686         ori     r3,r5,CLONE_VM  /* flags */
687         oris    r3,r3,(CLONE_UNTRACED>>16)
688         li      r4,0            /* new sp (unused) */
689         li      r0,__NR_clone
690         sc
691         cmpdi   0,r3,0          /* parent or child? */
692         bne     1f              /* return if parent */
693         li      r0,0
694         stdu    r0,-STACK_FRAME_OVERHEAD(r1)
695         ld      r2,8(r29)
696         ld      r29,0(r29)
697         mtlr    r29              /* fn addr in lr */
698         mr      r3,r30          /* load arg and call fn */
699         blrl
700         li      r0,__NR_exit    /* exit after child exits */
701         li      r3,0
702         sc
703 1:      addi    r1,r1,STACK_FRAME_OVERHEAD      
704         ld      r29,-24(r1)
705         ld      r30,-16(r1)
706         blr
709  * disable_kernel_fp()
710  * Disable the FPU.
711  */
712 _GLOBAL(disable_kernel_fp)
713         mfmsr   r3
714         rldicl  r0,r3,(63-MSR_FP_LG),1
715         rldicl  r3,r0,(MSR_FP_LG+1),0
716         mtmsrd  r3                      /* disable use of fpu now */
717         isync
718         blr
720 #ifdef CONFIG_ALTIVEC
722 #if 0 /* this has no callers for now */
724  * disable_kernel_altivec()
725  * Disable the VMX.
726  */
727 _GLOBAL(disable_kernel_altivec)
728         mfmsr   r3
729         rldicl  r0,r3,(63-MSR_VEC_LG),1
730         rldicl  r3,r0,(MSR_VEC_LG+1),0
731         mtmsrd  r3                      /* disable use of VMX now */
732         isync
733         blr
734 #endif /* 0 */
737  * giveup_altivec(tsk)
738  * Disable VMX for the task given as the argument,
739  * and save the vector registers in its thread_struct.
740  * Enables the VMX for use in the kernel on return.
741  */
742 _GLOBAL(giveup_altivec)
743         mfmsr   r5
744         oris    r5,r5,MSR_VEC@h
745         mtmsrd  r5                      /* enable use of VMX now */
746         isync
747         cmpdi   0,r3,0
748         beqlr-                          /* if no previous owner, done */
749         addi    r3,r3,THREAD            /* want THREAD of task */
750         ld      r5,PT_REGS(r3)
751         cmpdi   0,r5,0
752         SAVE_32VRS(0,r4,r3)
753         mfvscr  vr0
754         li      r4,THREAD_VSCR
755         stvx    vr0,r4,r3
756         beq     1f
757         ld      r4,_MSR-STACK_FRAME_OVERHEAD(r5)
758         lis     r3,MSR_VEC@h
759         andc    r4,r4,r3                /* disable FP for previous task */
760         std     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
762 #ifndef CONFIG_SMP
763         li      r5,0
764         ld      r4,last_task_used_altivec@got(r2)
765         std     r5,0(r4)
766 #endif /* CONFIG_SMP */
767         blr
769 #endif /* CONFIG_ALTIVEC */
771 _GLOBAL(__setup_cpu_power3)
772         blr
774 _GLOBAL(execve)
775         li      r0,__NR_execve
776         sc
777         bnslr
778         neg     r3,r3
779         blr
781 /* kexec_wait(phys_cpu)
783  * wait for the flag to change, indicating this kernel is going away but
784  * the slave code for the next one is at addresses 0 to 100.
786  * This is used by all slaves.
788  * Physical (hardware) cpu id should be in r3.
789  */
790 _GLOBAL(kexec_wait)
791         bl      1f
792 1:      mflr    r5
793         addi    r5,r5,kexec_flag-1b
795 99:     HMT_LOW
796 #ifdef CONFIG_KEXEC             /* use no memory without kexec */
797         lwz     r4,0(r5)
798         cmpwi   0,r4,0
799         bnea    0x60
800 #endif
801         b       99b
803 /* this can be in text because we won't change it until we are
804  * running in real anyways
805  */
806 kexec_flag:
807         .long   0
810 #ifdef CONFIG_KEXEC
812 /* kexec_smp_wait(void)
814  * call with interrupts off
815  * note: this is a terminal routine, it does not save lr
817  * get phys id from paca
818  * set paca id to -1 to say we got here
819  * switch to real mode
820  * join other cpus in kexec_wait(phys_id)
821  */
822 _GLOBAL(kexec_smp_wait)
823         lhz     r3,PACAHWCPUID(r13)
824         li      r4,-1
825         sth     r4,PACAHWCPUID(r13)     /* let others know we left */
826         bl      real_mode
827         b       .kexec_wait
830  * switch to real mode (turn mmu off)
831  * we use the early kernel trick that the hardware ignores bits
832  * 0 and 1 (big endian) of the effective address in real mode
834  * don't overwrite r3 here, it is live for kexec_wait above.
835  */
836 real_mode:      /* assume normal blr return */
837 1:      li      r9,MSR_RI
838         li      r10,MSR_DR|MSR_IR
839         mflr    r11             /* return address to SRR0 */
840         mfmsr   r12
841         andc    r9,r12,r9
842         andc    r10,r12,r10
844         mtmsrd  r9,1
845         mtspr   SPRN_SRR1,r10
846         mtspr   SPRN_SRR0,r11
847         rfid
851  * kexec_sequence(newstack, start, image, control, clear_all())
853  * does the grungy work with stack switching and real mode switches
854  * also does simple calls to other code
855  */
857 _GLOBAL(kexec_sequence)
858         mflr    r0
859         std     r0,16(r1)
861         /* switch stacks to newstack -- &kexec_stack.stack */
862         stdu    r1,THREAD_SIZE-112(r3)
863         mr      r1,r3
865         li      r0,0
866         std     r0,16(r1)
868         /* save regs for local vars on new stack.
869          * yes, we won't go back, but ...
870          */
871         std     r31,-8(r1)
872         std     r30,-16(r1)
873         std     r29,-24(r1)
874         std     r28,-32(r1)
875         std     r27,-40(r1)
876         std     r26,-48(r1)
877         std     r25,-56(r1)
879         stdu    r1,-112-64(r1)
881         /* save args into preserved regs */
882         mr      r31,r3                  /* newstack (both) */
883         mr      r30,r4                  /* start (real) */
884         mr      r29,r5                  /* image (virt) */
885         mr      r28,r6                  /* control, unused */
886         mr      r27,r7                  /* clear_all() fn desc */
887         mr      r26,r8                  /* spare */
888         lhz     r25,PACAHWCPUID(r13)    /* get our phys cpu from paca */
890         /* disable interrupts, we are overwriting kernel data next */
891         mfmsr   r3
892         rlwinm  r3,r3,0,17,15
893         mtmsrd  r3,1
895         /* copy dest pages, flush whole dest image */
896         mr      r3,r29
897         bl      .kexec_copy_flush       /* (image) */
899         /* turn off mmu */
900         bl      real_mode
902         /* clear out hardware hash page table and tlb */
903         ld      r5,0(r27)               /* deref function descriptor */
904         mtctr   r5
905         bctrl                           /* ppc_md.hash_clear_all(void); */
908  *   kexec image calling is:
909  *      the first 0x100 bytes of the entry point are copied to 0
911  *      all slaves branch to slave = 0x60 (absolute)
912  *              slave(phys_cpu_id);
914  *      master goes to start = entry point
915  *              start(phys_cpu_id, start, 0);
918  *   a wrapper is needed to call existing kernels, here is an approximate
919  *   description of one method:
921  * v2: (2.6.10)
922  *   start will be near the boot_block (maybe 0x100 bytes before it?)
923  *   it will have a 0x60, which will b to boot_block, where it will wait
924  *   and 0 will store phys into struct boot-block and load r3 from there,
925  *   copy kernel 0-0x100 and tell slaves to back down to 0x60 again
927  * v1: (2.6.9)
928  *    boot block will have all cpus scanning device tree to see if they
929  *    are the boot cpu ?????
930  *    other device tree differences (prop sizes, va vs pa, etc)...
931  */
933         /* copy  0x100 bytes starting at start to 0 */
934         li      r3,0
935         mr      r4,r30
936         li      r5,0x100
937         li      r6,0
938         bl      .copy_and_flush /* (dest, src, copy limit, start offset) */
939 1:      /* assume normal blr return */
941         /* release other cpus to the new kernel secondary start at 0x60 */
942         mflr    r5
943         li      r6,1
944         stw     r6,kexec_flag-1b(5)
945         mr      r3,r25  # my phys cpu
946         mr      r4,r30  # start, aka phys mem offset
947         mtlr    4
948         li      r5,0
949         blr     /* image->start(physid, image->start, 0); */
950 #endif /* CONFIG_KEXEC */