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