upgrade to linux 2.6.10-1.12_FC2
[linux-2.6.git] / arch / ppc64 / kernel / entry.S
1 /*
2  *  arch/ppc64/kernel/entry.S
3  *
4  *  PowerPC version 
5  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6  *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
7  *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
8  *  Adapted for Power Macintosh by Paul Mackerras.
9  *  Low-level exception handlers and MMU support
10  *  rewritten by Paul Mackerras.
11  *    Copyright (C) 1996 Paul Mackerras.
12  *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
13  *
14  *  This file contains the system call entry code, context switch
15  *  code, and exception/interrupt return code for PowerPC.
16  *
17  *  This program is free software; you can redistribute it and/or
18  *  modify it under the terms of the GNU General Public License
19  *  as published by the Free Software Foundation; either version
20  *  2 of the License, or (at your option) any later version.
21  */
22
23 #include <linux/config.h>
24 #include <linux/errno.h>
25 #include <asm/unistd.h>
26 #include <asm/processor.h>
27 #include <asm/page.h>
28 #include <asm/mmu.h>
29 #include <asm/thread_info.h>
30 #include <asm/ppc_asm.h>
31 #include <asm/offsets.h>
32 #include <asm/cputable.h>
33
34 #ifdef CONFIG_PPC_ISERIES
35 #define DO_SOFT_DISABLE
36 #endif
37
38 /*
39  * System calls.
40  */
41         .section        ".toc","aw"
42 .SYS_CALL_TABLE:
43         .tc .sys_call_table[TC],.sys_call_table
44
45 .SYS_CALL_TABLE32:
46         .tc .sys_call_table32[TC],.sys_call_table32
47
48 /* This value is used to mark exception frames on the stack. */
49 exception_marker:
50         .tc     ID_72656773_68657265[TC],0x7265677368657265
51
52         .section        ".text"
53         .align 7
54
55 #undef SHOW_SYSCALLS
56
57         .globl SystemCall_common
58 SystemCall_common:
59         andi.   r10,r12,MSR_PR
60         mr      r10,r1
61         addi    r1,r1,-INT_FRAME_SIZE
62         beq-    1f
63         ld      r1,PACAKSAVE(r13)
64 1:      std     r10,0(r1)
65         std     r11,_NIP(r1)
66         std     r12,_MSR(r1)
67         std     r0,GPR0(r1)
68         std     r10,GPR1(r1)
69         std     r2,GPR2(r1)
70         std     r3,GPR3(r1)
71         std     r4,GPR4(r1)
72         std     r5,GPR5(r1)
73         std     r6,GPR6(r1)
74         std     r7,GPR7(r1)
75         std     r8,GPR8(r1)
76         li      r11,0
77         std     r11,GPR9(r1)
78         std     r11,GPR10(r1)
79         std     r11,GPR11(r1)
80         std     r11,GPR12(r1)
81         std     r9,GPR13(r1)
82         crclr   so
83         mfcr    r9
84         mflr    r10
85         li      r11,0xc01
86         std     r9,_CCR(r1)
87         std     r10,_LINK(r1)
88         std     r11,_TRAP(r1)
89         mfxer   r9
90         mfctr   r10
91         std     r9,_XER(r1)
92         std     r10,_CTR(r1)
93         std     r3,ORIG_GPR3(r1)
94         ld      r2,PACATOC(r13)
95         addi    r9,r1,STACK_FRAME_OVERHEAD
96         ld      r11,exception_marker@toc(r2)
97         std     r11,-16(r9)             /* "regshere" marker */
98 #ifdef CONFIG_PPC_ISERIES
99         /* Hack for handling interrupts when soft-enabling on iSeries */
100         cmpdi   cr1,r0,0x5555           /* syscall 0x5555 */
101         andi.   r10,r12,MSR_PR          /* from kernel */
102         crand   4*cr0+eq,4*cr1+eq,4*cr0+eq
103         beq     HardwareInterrupt_entry
104         lbz     r10,PACAPROCENABLED(r13)
105         std     r10,SOFTE(r1)
106 #endif
107         mfmsr   r11
108         ori     r11,r11,MSR_EE
109         mtmsrd  r11,1
110
111 #ifdef SHOW_SYSCALLS
112         bl      .do_show_syscall
113         REST_GPR(0,r1)
114         REST_4GPRS(3,r1)
115         REST_2GPRS(7,r1)
116         addi    r9,r1,STACK_FRAME_OVERHEAD
117 #endif
118         clrrdi  r11,r1,THREAD_SHIFT
119         li      r12,0
120         ld      r10,TI_FLAGS(r11)
121         stb     r12,TI_SC_NOERR(r11)
122         andi.   r11,r10,_TIF_SYSCALL_T_OR_A
123         bne-    syscall_dotrace
124 syscall_dotrace_cont:
125         cmpldi  0,r0,NR_syscalls
126         bge-    syscall_enosys
127
128 system_call:                    /* label this so stack traces look sane */
129 /*
130  * Need to vector to 32 Bit or default sys_call_table here,
131  * based on caller's run-mode / personality.
132  */
133         ld      r11,.SYS_CALL_TABLE@toc(2)
134         andi.   r10,r10,_TIF_32BIT
135         beq     15f
136         ld      r11,.SYS_CALL_TABLE32@toc(2)
137         clrldi  r3,r3,32
138         clrldi  r4,r4,32
139         clrldi  r5,r5,32
140         clrldi  r6,r6,32
141         clrldi  r7,r7,32
142         clrldi  r8,r8,32
143 15:
144         slwi    r0,r0,3
145         ldx     r10,r11,r0      /* Fetch system call handler [ptr] */
146         mtctr   r10
147         bctrl                   /* Call handler */
148
149 syscall_exit:
150 #ifdef SHOW_SYSCALLS
151         std     r3,GPR3(r1)
152         bl      .do_show_syscall_exit
153         ld      r3,GPR3(r1)
154 #endif
155         std     r3,RESULT(r1)
156         ld      r5,_CCR(r1)
157         li      r10,-_LAST_ERRNO
158         cmpld   r3,r10
159         clrrdi  r12,r1,THREAD_SHIFT
160         bge-    syscall_error
161 syscall_error_cont:
162
163         /* check for syscall tracing or audit */
164         ld      r9,TI_FLAGS(r12)
165         andi.   r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
166         bne-    syscall_exit_trace
167 syscall_exit_trace_cont:
168
169         /* disable interrupts so current_thread_info()->flags can't change,
170            and so that we don't get interrupted after loading SRR0/1. */
171         ld      r8,_MSR(r1)
172         andi.   r10,r8,MSR_RI
173         beq-    unrecov_restore
174         mfmsr   r10
175         rldicl  r10,r10,48,1
176         rotldi  r10,r10,16
177         mtmsrd  r10,1
178         ld      r9,TI_FLAGS(r12)
179         andi.   r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
180         bne-    syscall_exit_work
181         ld      r7,_NIP(r1)
182         stdcx.  r0,0,r1                 /* to clear the reservation */
183         andi.   r6,r8,MSR_PR
184         ld      r4,_LINK(r1)
185         beq-    1f                      /* only restore r13 if */
186         ld      r13,GPR13(r1)           /* returning to usermode */
187 1:      ld      r2,GPR2(r1)
188         ld      r1,GPR1(r1)
189         li      r12,MSR_RI
190         andc    r10,r10,r12
191         mtmsrd  r10,1                   /* clear MSR.RI */
192         mtlr    r4
193         mtcr    r5
194         mtspr   SRR0,r7
195         mtspr   SRR1,r8
196         rfid
197         b       .       /* prevent speculative execution */
198
199 syscall_enosys:
200         li      r3,-ENOSYS
201         std     r3,RESULT(r1)
202         clrrdi  r12,r1,THREAD_SHIFT
203         ld      r5,_CCR(r1)
204
205 syscall_error:
206         lbz     r11,TI_SC_NOERR(r12)
207         cmpwi   0,r11,0
208         bne-    syscall_error_cont
209         neg     r3,r3
210         oris    r5,r5,0x1000    /* Set SO bit in CR */
211         std     r5,_CCR(r1)
212         b       syscall_error_cont
213         
214 /* Traced system call support */
215 syscall_dotrace:
216         bl      .save_nvgprs
217         addi    r3,r1,STACK_FRAME_OVERHEAD
218         bl      .do_syscall_trace_enter
219         ld      r0,GPR0(r1)     /* Restore original registers */
220         ld      r3,GPR3(r1)
221         ld      r4,GPR4(r1)
222         ld      r5,GPR5(r1)
223         ld      r6,GPR6(r1)
224         ld      r7,GPR7(r1)
225         ld      r8,GPR8(r1)
226         addi    r9,r1,STACK_FRAME_OVERHEAD
227         clrrdi  r10,r1,THREAD_SHIFT
228         ld      r10,TI_FLAGS(r10)
229         b       syscall_dotrace_cont
230
231 syscall_exit_trace:
232         std     r3,GPR3(r1)
233         bl      .save_nvgprs
234         bl      .do_syscall_trace_leave
235         REST_NVGPRS(r1)
236         ld      r3,GPR3(r1)
237         ld      r5,_CCR(r1)
238         clrrdi  r12,r1,THREAD_SHIFT
239         b       syscall_exit_trace_cont
240
241 /* Stuff to do on exit from a system call. */
242 syscall_exit_work:
243         std     r3,GPR3(r1)
244         std     r5,_CCR(r1)
245         b       .ret_from_except_lite
246
247 /* Save non-volatile GPRs, if not already saved. */
248 _GLOBAL(save_nvgprs)
249         ld      r11,_TRAP(r1)
250         andi.   r0,r11,1
251         beqlr-
252         SAVE_NVGPRS(r1)
253         clrrdi  r0,r11,1
254         std     r0,_TRAP(r1)
255         blr
256
257 /*
258  * The sigsuspend and rt_sigsuspend system calls can call do_signal
259  * and thus put the process into the stopped state where we might
260  * want to examine its user state with ptrace.  Therefore we need
261  * to save all the nonvolatile registers (r14 - r31) before calling
262  * the C code.  Similarly, fork, vfork and clone need the full
263  * register state on the stack so that it can be copied to the child.
264  */
265 _GLOBAL(ppc32_sigsuspend)
266         bl      .save_nvgprs
267         bl      .sys32_sigsuspend
268         b       70f
269
270 _GLOBAL(ppc64_rt_sigsuspend)
271         bl      .save_nvgprs
272         bl      .sys_rt_sigsuspend
273         b       70f
274
275 _GLOBAL(ppc32_rt_sigsuspend)
276         bl      .save_nvgprs
277         bl      .sys32_rt_sigsuspend
278         /* If sigsuspend() returns zero, we are going into a signal handler */
279 70:     cmpdi   0,r3,0
280         beq     .ret_from_except
281         /* If it returned -EINTR, we need to return via syscall_exit to set
282            the SO bit in cr0 and potentially stop for ptrace. */
283         b       syscall_exit
284
285 _GLOBAL(ppc_fork)
286         bl      .save_nvgprs
287         bl      .sys_fork
288         b       syscall_exit
289
290 _GLOBAL(ppc_vfork)
291         bl      .save_nvgprs
292         bl      .sys_vfork
293         b       syscall_exit
294
295 _GLOBAL(ppc_clone)
296         bl      .save_nvgprs
297         bl      .sys_clone
298         b       syscall_exit
299
300 _GLOBAL(ppc32_swapcontext)
301         bl      .save_nvgprs
302         bl      .sys32_swapcontext
303         b       80f
304         
305 _GLOBAL(ppc64_swapcontext)
306         bl      .save_nvgprs
307         bl      .sys_swapcontext
308         b       80f
309
310 _GLOBAL(ppc32_sigreturn)
311         bl      .sys32_sigreturn
312         b       80f
313
314 _GLOBAL(ppc32_rt_sigreturn)
315         bl      .sys32_rt_sigreturn
316         b       80f
317
318 _GLOBAL(ppc64_rt_sigreturn)
319         bl      .sys_rt_sigreturn
320
321 80:     cmpdi   0,r3,0
322         blt     syscall_exit
323         clrrdi  r4,r1,THREAD_SHIFT
324         ld      r4,TI_FLAGS(r4)
325         andi.   r4,r4,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
326         beq+    81f
327         bl      .do_syscall_trace_leave
328 81:     b       .ret_from_except
329
330 _GLOBAL(ret_from_fork)
331         bl      .schedule_tail
332         REST_NVGPRS(r1)
333         li      r3,0
334         b       syscall_exit
335
336 /*
337  * This routine switches between two different tasks.  The process
338  * state of one is saved on its kernel stack.  Then the state
339  * of the other is restored from its kernel stack.  The memory
340  * management hardware is updated to the second process's state.
341  * Finally, we can return to the second process, via ret_from_except.
342  * On entry, r3 points to the THREAD for the current task, r4
343  * points to the THREAD for the new task.
344  *
345  * Note: there are two ways to get to the "going out" portion
346  * of this code; either by coming in via the entry (_switch)
347  * or via "fork" which must set up an environment equivalent
348  * to the "_switch" path.  If you change this you'll have to change
349  * the fork code also.
350  *
351  * The code which creates the new task context is in 'copy_thread'
352  * in arch/ppc64/kernel/process.c
353  */
354         .align  7
355 _GLOBAL(_switch)
356         mflr    r0
357         std     r0,16(r1)
358         stdu    r1,-SWITCH_FRAME_SIZE(r1)
359         /* r3-r13 are caller saved -- Cort */
360         SAVE_8GPRS(14, r1)
361         SAVE_10GPRS(22, r1)
362         mflr    r20             /* Return to switch caller */
363         mfmsr   r22
364         li      r0, MSR_FP
365 #ifdef CONFIG_ALTIVEC
366 BEGIN_FTR_SECTION
367         oris    r0,r0,MSR_VEC@h /* Disable altivec */
368         mfspr   r24,SPRN_VRSAVE /* save vrsave register value */
369         std     r24,THREAD_VRSAVE(r3)
370 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
371 #endif /* CONFIG_ALTIVEC */
372         and.    r0,r0,r22
373         beq+    1f
374         andc    r22,r22,r0
375         mtmsrd  r22
376         isync
377 1:      std     r20,_NIP(r1)
378         mfcr    r23
379         std     r23,_CCR(r1)
380         std     r1,KSP(r3)      /* Set old stack pointer */
381
382 #ifdef CONFIG_SMP
383         /* We need a sync somewhere here to make sure that if the
384          * previous task gets rescheduled on another CPU, it sees all
385          * stores it has performed on this one.
386          */
387         sync
388 #endif /* CONFIG_SMP */
389
390         addi    r6,r4,-THREAD   /* Convert THREAD to 'current' */
391         std     r6,PACACURRENT(r13)     /* Set new 'current' */
392
393         ld      r8,KSP(r4)      /* new stack pointer */
394 BEGIN_FTR_SECTION
395         clrrdi  r6,r8,28        /* get its ESID */
396         clrrdi  r9,r1,28        /* get current sp ESID */
397         clrldi. r0,r6,2         /* is new ESID c00000000? */
398         cmpd    cr1,r6,r9       /* or is new ESID the same as current ESID? */
399         cror    eq,4*cr1+eq,eq
400         beq     2f              /* if yes, don't slbie it */
401         oris    r0,r6,0x0800    /* set C (class) bit */
402
403         /* Bolt in the new stack SLB entry */
404         ld      r7,KSP_VSID(r4) /* Get new stack's VSID */
405         oris    r6,r6,(SLB_ESID_V)@h
406         ori     r6,r6,(SLB_NUM_BOLTED-1)@l
407         slbie   r0
408         slbie   r0              /* Workaround POWER5 < DD2.1 issue */
409         slbmte  r7,r6
410         isync
411
412 2:
413 END_FTR_SECTION_IFSET(CPU_FTR_SLB)
414         clrrdi  r7,r8,THREAD_SHIFT      /* base of new stack */
415         /* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE
416            because we don't need to leave the 288-byte ABI gap at the
417            top of the kernel stack. */
418         addi    r7,r7,THREAD_SIZE-SWITCH_FRAME_SIZE
419
420         mr      r1,r8           /* start using new stack pointer */
421         std     r7,PACAKSAVE(r13)
422
423         ld      r6,_CCR(r1)
424         mtcrf   0xFF,r6
425
426 #ifdef CONFIG_ALTIVEC
427 BEGIN_FTR_SECTION
428         ld      r0,THREAD_VRSAVE(r4)
429         mtspr   SPRN_VRSAVE,r0          /* if G4, restore VRSAVE reg */
430 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
431 #endif /* CONFIG_ALTIVEC */
432
433         /* r3-r13 are destroyed -- Cort */
434         REST_8GPRS(14, r1)
435         REST_10GPRS(22, r1)
436
437 #ifdef CONFIG_PPC_ISERIES
438         clrrdi  r7,r1,THREAD_SHIFT      /* get current_thread_info() */
439         ld      r7,TI_FLAGS(r7)         /* Get run light flag */
440         mfspr   r9,CTRLF
441         srdi    r7,r7,TIF_RUN_LIGHT
442         insrdi  r9,r7,1,63              /* Insert run light into CTRL */
443         mtspr   CTRLT,r9
444 #endif
445
446         /* convert old thread to its task_struct for return value */
447         addi    r3,r3,-THREAD
448         ld      r7,_NIP(r1)     /* Return to _switch caller in new task */
449         mtlr    r7
450         addi    r1,r1,SWITCH_FRAME_SIZE
451         blr
452
453         .align  7
454 _GLOBAL(ret_from_except)
455         ld      r11,_TRAP(r1)
456         andi.   r0,r11,1
457         bne     .ret_from_except_lite
458         REST_NVGPRS(r1)
459
460 _GLOBAL(ret_from_except_lite)
461         /*
462          * Disable interrupts so that current_thread_info()->flags
463          * can't change between when we test it and when we return
464          * from the interrupt.
465          */
466         mfmsr   r10             /* Get current interrupt state */
467         rldicl  r9,r10,48,1     /* clear MSR_EE */
468         rotldi  r9,r9,16
469         mtmsrd  r9,1            /* Update machine state */
470
471 #ifdef CONFIG_PREEMPT
472         clrrdi  r9,r1,THREAD_SHIFT      /* current_thread_info() */
473         li      r0,_TIF_NEED_RESCHED    /* bits to check */
474         ld      r3,_MSR(r1)
475         ld      r4,TI_FLAGS(r9)
476         /* Move MSR_PR bit in r3 to _TIF_SIGPENDING position in r0 */
477         rlwimi  r0,r3,32+TIF_SIGPENDING-MSR_PR_LG,_TIF_SIGPENDING
478         and.    r0,r4,r0        /* check NEED_RESCHED and maybe SIGPENDING */
479         bne     do_work
480
481 #else /* !CONFIG_PREEMPT */
482         ld      r3,_MSR(r1)     /* Returning to user mode? */
483         andi.   r3,r3,MSR_PR
484         beq     restore         /* if not, just restore regs and return */
485
486         /* Check current_thread_info()->flags */
487         clrrdi  r9,r1,THREAD_SHIFT
488         ld      r4,TI_FLAGS(r9)
489         andi.   r0,r4,_TIF_USER_WORK_MASK
490         bne     do_work
491 #endif
492
493 restore:
494 #ifdef CONFIG_PPC_ISERIES
495         ld      r5,SOFTE(r1)
496         cmpdi   0,r5,0
497         beq     4f
498         /* Check for pending interrupts (iSeries) */
499         ld      r3,PACALPPACA+LPPACAANYINT(r13)
500         cmpdi   r3,0
501         beq+    4f                      /* skip do_IRQ if no interrupts */
502
503         li      r3,0
504         stb     r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */
505         ori     r10,r10,MSR_EE
506         mtmsrd  r10                     /* hard-enable again */
507         addi    r3,r1,STACK_FRAME_OVERHEAD
508         bl      .do_IRQ
509         b       .ret_from_except_lite           /* loop back and handle more */
510
511 4:      stb     r5,PACAPROCENABLED(r13)
512 #endif
513
514         ld      r3,_MSR(r1)
515         andi.   r0,r3,MSR_RI
516         beq-    unrecov_restore
517
518         andi.   r0,r3,MSR_PR
519
520         /*
521          * r13 is our per cpu area, only restore it if we are returning to
522          * userspace
523          */
524         beq     1f
525         REST_GPR(13, r1)
526 1:
527         ld      r3,_CTR(r1)
528         ld      r0,_LINK(r1)
529         mtctr   r3
530         mtlr    r0
531         ld      r3,_XER(r1)
532         mtspr   XER,r3
533
534         REST_8GPRS(5, r1)
535
536         stdcx.  r0,0,r1         /* to clear the reservation */
537
538         mfmsr   r0
539         li      r2, MSR_RI
540         andc    r0,r0,r2
541         mtmsrd  r0,1
542
543         ld      r0,_MSR(r1)
544         mtspr   SRR1,r0
545
546         ld      r2,_CCR(r1)
547         mtcrf   0xFF,r2
548         ld      r2,_NIP(r1)
549         mtspr   SRR0,r2
550
551         ld      r0,GPR0(r1)
552         ld      r2,GPR2(r1)
553         ld      r3,GPR3(r1)
554         ld      r4,GPR4(r1)
555         ld      r1,GPR1(r1)
556
557         rfid
558         b       .       /* prevent speculative execution */
559
560 /* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */
561 do_work:
562 #ifdef CONFIG_PREEMPT
563         andi.   r0,r3,MSR_PR    /* Returning to user mode? */
564         bne     user_work
565         /* Check that preempt_count() == 0 and interrupts are enabled */
566         lwz     r8,TI_PREEMPT(r9)
567         cmpwi   cr1,r8,0
568 #ifdef CONFIG_PPC_ISERIES
569         ld      r0,SOFTE(r1)
570         cmpdi   r0,0
571 #else
572         andi.   r0,r3,MSR_EE
573 #endif
574         crandc  eq,cr1*4+eq,eq
575         bne     restore
576         /* here we are preempting the current task */
577 1:      lis     r0,PREEMPT_ACTIVE@h
578         stw     r0,TI_PREEMPT(r9)
579 #ifdef CONFIG_PPC_ISERIES
580         li      r0,1
581         stb     r0,PACAPROCENABLED(r13)
582 #endif
583         ori     r10,r10,MSR_EE
584         mtmsrd  r10,1           /* reenable interrupts */
585         bl      .schedule
586         mfmsr   r10
587         clrrdi  r9,r1,THREAD_SHIFT
588         rldicl  r10,r10,48,1    /* disable interrupts again */
589         li      r0,0
590         rotldi  r10,r10,16
591         mtmsrd  r10,1
592         ld      r4,TI_FLAGS(r9)
593         andi.   r0,r4,_TIF_NEED_RESCHED
594         bne     1b
595         stw     r0,TI_PREEMPT(r9)
596         b       restore
597
598 user_work:
599 #endif
600         /* Enable interrupts */
601         ori     r10,r10,MSR_EE
602         mtmsrd  r10,1
603
604         andi.   r0,r4,_TIF_NEED_RESCHED
605         beq     1f
606         bl      .schedule
607         b       .ret_from_except_lite
608
609 1:      bl      .save_nvgprs
610         li      r3,0
611         addi    r4,r1,STACK_FRAME_OVERHEAD
612         bl      .do_signal
613         b       .ret_from_except
614
615 unrecov_restore:
616         addi    r3,r1,STACK_FRAME_OVERHEAD
617         bl      .unrecoverable_exception
618         b       unrecov_restore
619
620 #ifdef CONFIG_PPC_PSERIES
621 /*
622  * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
623  * called with the MMU off.
624  *
625  * In addition, we need to be in 32b mode, at least for now.
626  * 
627  * Note: r3 is an input parameter to rtas, so don't trash it...
628  */
629 _GLOBAL(enter_rtas)
630         mflr    r0
631         std     r0,16(r1)
632         stdu    r1,-RTAS_FRAME_SIZE(r1) /* Save SP and create stack space. */
633
634         /* Because RTAS is running in 32b mode, it clobbers the high order half
635          * of all registers that it saves.  We therefore save those registers
636          * RTAS might touch to the stack.  (r0, r3-r13 are caller saved)
637          */
638         SAVE_GPR(2, r1)                 /* Save the TOC */
639         SAVE_GPR(13, r1)                /* Save paca */
640         SAVE_8GPRS(14, r1)              /* Save the non-volatiles */
641         SAVE_10GPRS(22, r1)             /* ditto */
642
643         mfcr    r4
644         std     r4,_CCR(r1)
645         mfctr   r5
646         std     r5,_CTR(r1)
647         mfspr   r6,XER
648         std     r6,_XER(r1)
649         mfdar   r7
650         std     r7,_DAR(r1)
651         mfdsisr r8
652         std     r8,_DSISR(r1)
653         mfsrr0  r9
654         std     r9,_SRR0(r1)
655         mfsrr1  r10
656         std     r10,_SRR1(r1)
657
658         /* There is no way it is acceptable to get here with interrupts enabled,
659          * check it with the asm equivalent of WARN_ON
660          */
661         mfmsr   r6
662         andi.   r0,r6,MSR_EE
663 1:      tdnei   r0,0
664 .section __bug_table,"a"
665         .llong  1b,__LINE__ + 0x1000000, 1f, 2f
666 .previous
667 .section .rodata,"a"
668 1:      .asciz  __FILE__
669 2:      .asciz "enter_rtas"
670 .previous
671         
672         /* Unfortunately, the stack pointer and the MSR are also clobbered,
673          * so they are saved in the PACA which allows us to restore
674          * our original state after RTAS returns.
675          */
676         std     r1,PACAR1(r13)
677         std     r6,PACASAVEDMSR(r13)
678
679         /* Setup our real return addr */        
680         SET_REG_TO_LABEL(r4,.rtas_return_loc)
681         SET_REG_TO_CONST(r9,KERNELBASE)
682         sub     r4,r4,r9
683         mtlr    r4
684
685         li      r0,0
686         ori     r0,r0,MSR_EE|MSR_SE|MSR_BE|MSR_RI
687         andc    r0,r6,r0
688         
689         li      r9,1
690         rldicr  r9,r9,MSR_SF_LG,(63-MSR_SF_LG)
691         ori     r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP
692         andc    r6,r0,r9
693         ori     r6,r6,MSR_RI
694         sync                            /* disable interrupts so SRR0/1 */
695         mtmsrd  r0                      /* don't get trashed */
696
697         SET_REG_TO_LABEL(r4,rtas)
698         ld      r5,RTASENTRY(r4)        /* get the rtas->entry value */
699         ld      r4,RTASBASE(r4)         /* get the rtas->base value */
700         
701         mtspr   SRR0,r5
702         mtspr   SRR1,r6
703         rfid
704         b       .       /* prevent speculative execution */
705
706 _STATIC(rtas_return_loc)
707         /* relocation is off at this point */
708         mfspr   r4,SPRG3                /* Get PACA */
709         SET_REG_TO_CONST(r5, KERNELBASE)
710         sub     r4,r4,r5                /* RELOC the PACA base pointer */
711
712         mfmsr   r6
713         li      r0,MSR_RI
714         andc    r6,r6,r0
715         sync    
716         mtmsrd  r6
717         
718         ld      r1,PACAR1(r4)           /* Restore our SP */
719         LOADADDR(r3,.rtas_restore_regs)
720         ld      r4,PACASAVEDMSR(r4)     /* Restore our MSR */
721
722         mtspr   SRR0,r3
723         mtspr   SRR1,r4
724         rfid
725         b       .       /* prevent speculative execution */
726
727 _STATIC(rtas_restore_regs)
728         /* relocation is on at this point */
729         REST_GPR(2, r1)                 /* Restore the TOC */
730         REST_GPR(13, r1)                /* Restore paca */
731         REST_8GPRS(14, r1)              /* Restore the non-volatiles */
732         REST_10GPRS(22, r1)             /* ditto */
733
734         mfspr   r13,SPRG3
735
736         ld      r4,_CCR(r1)
737         mtcr    r4
738         ld      r5,_CTR(r1)
739         mtctr   r5
740         ld      r6,_XER(r1)
741         mtspr   XER,r6
742         ld      r7,_DAR(r1)
743         mtdar   r7
744         ld      r8,_DSISR(r1)
745         mtdsisr r8
746         ld      r9,_SRR0(r1)
747         mtsrr0  r9
748         ld      r10,_SRR1(r1)
749         mtsrr1  r10
750
751         addi    r1,r1,RTAS_FRAME_SIZE   /* Unstack our frame */
752         ld      r0,16(r1)               /* get return address */
753
754         mtlr    r0
755         blr                             /* return to caller */
756
757 #endif /* CONFIG_PPC_PSERIES */
758
759 #ifdef CONFIG_PPC_MULTIPLATFORM
760
761 _GLOBAL(enter_prom)
762         mflr    r0
763         std     r0,16(r1)
764         stdu    r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
765
766         /* Because PROM is running in 32b mode, it clobbers the high order half
767          * of all registers that it saves.  We therefore save those registers
768          * PROM might touch to the stack.  (r0, r3-r13 are caller saved)
769          */
770         SAVE_8GPRS(2, r1)
771         SAVE_GPR(13, r1)
772         SAVE_8GPRS(14, r1)
773         SAVE_10GPRS(22, r1)
774         mfcr    r4
775         std     r4,_CCR(r1)
776         mfctr   r5
777         std     r5,_CTR(r1)
778         mfspr   r6,XER
779         std     r6,_XER(r1)
780         mfdar   r7
781         std     r7,_DAR(r1)
782         mfdsisr r8
783         std     r8,_DSISR(r1)
784         mfsrr0  r9
785         std     r9,_SRR0(r1)
786         mfsrr1  r10
787         std     r10,_SRR1(r1)
788         mfmsr   r11
789         std     r11,_MSR(r1)
790
791         /* Get the PROM entrypoint */
792         ld      r0,GPR4(r1)
793         mtlr    r0
794
795         /* Switch MSR to 32 bits mode
796          */
797         mfmsr   r11
798         li      r12,1
799         rldicr  r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
800         andc    r11,r11,r12
801         li      r12,1
802         rldicr  r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
803         andc    r11,r11,r12
804         mtmsrd  r11
805         isync
806
807         /* Restore arguments & enter PROM here... */
808         ld      r3,GPR3(r1)
809         blrl
810
811         /* Just make sure that r1 top 32 bits didn't get
812          * corrupt by OF
813          */
814         rldicl  r1,r1,0,32
815
816         /* Restore the MSR (back to 64 bits) */
817         ld      r0,_MSR(r1)
818         mtmsrd  r0
819         isync
820
821         /* Restore other registers */
822         REST_GPR(2, r1)
823         REST_GPR(13, r1)
824         REST_8GPRS(14, r1)
825         REST_10GPRS(22, r1)
826         ld      r4,_CCR(r1)
827         mtcr    r4
828         ld      r5,_CTR(r1)
829         mtctr   r5
830         ld      r6,_XER(r1)
831         mtspr   XER,r6
832         ld      r7,_DAR(r1)
833         mtdar   r7
834         ld      r8,_DSISR(r1)
835         mtdsisr r8
836         ld      r9,_SRR0(r1)
837         mtsrr0  r9
838         ld      r10,_SRR1(r1)
839         mtsrr1  r10
840         
841         addi    r1,r1,PROM_FRAME_SIZE
842         ld      r0,16(r1)
843         mtlr    r0
844         blr
845         
846 #endif  /* CONFIG_PPC_MULTIPLATFORM */