ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[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 #undef SHOW_SYSCALLS
39 #undef SHOW_SYSCALLS_TASK
40
41 #ifdef SHOW_SYSCALLS_TASK
42         .data
43 show_syscalls_task:
44         .long   -1
45 #endif
46
47         .section        ".toc","aw"
48 .SYS_CALL_TABLE:
49         .tc .sys_call_table[TC],.sys_call_table
50
51 .SYS_CALL_TABLE32:
52         .tc .sys_call_table32[TC],.sys_call_table32
53
54         .section        ".text"
55         .align 3
56
57 /*
58  * Handle a system call.
59  */
60 _GLOBAL(DoSyscall)
61         std     r3,ORIG_GPR3(r1)
62         ld      r11,_CCR(r1)    /* Clear SO bit in CR */
63         lis     r10,0x1000
64         andc    r11,r11,r10
65         std     r11,_CCR(r1)
66 #ifdef SHOW_SYSCALLS
67 #ifdef SHOW_SYSCALLS_TASK
68         LOADBASE(r31,show_syscalls_task)
69         ld      r31,show_syscalls_task@l(r31)
70         ld      r10,PACACURRENT(r13)
71         cmp     0,r10,r31
72         bne     1f
73 #endif
74         LOADADDR(r3,7f)
75         ld      r4,GPR0(r1)
76         ld      r5,GPR3(r1)
77         ld      r6,GPR4(r1)
78         ld      r7,GPR5(r1)
79         ld      r8,GPR6(r1)
80         ld      r9,GPR7(r1)
81         bl      .printk
82         LOADADDR(r3,77f)
83         ld      r4,GPR8(r1)
84         ld      r5,GPR9(r1)
85         ld      r6, PACACURRENT(r13)
86         bl      .printk
87         ld      r0,GPR0(r1)
88         ld      r3,GPR3(r1)
89         ld      r4,GPR4(r1)
90         ld      r5,GPR5(r1)
91         ld      r6,GPR6(r1)
92         ld      r7,GPR7(r1)
93         ld      r8,GPR8(r1)
94 1:
95 #endif /* SHOW_SYSCALLS */
96         clrrdi  r10,r1,THREAD_SHIFT
97         ld      r10,TI_FLAGS(r10)
98         andi.   r11,r10,_TIF_SYSCALL_T_OR_A
99         bne-    50f
100         cmpli   0,r0,NR_syscalls
101         bge-    66f
102 /*
103  * Need to vector to 32 Bit or default sys_call_table here,
104  * based on caller's run-mode / personality.
105  */
106         andi.   r11,r10,_TIF_32BIT
107         beq-    15f
108         ld      r10,.SYS_CALL_TABLE32@toc(2)
109 /*
110  * We now zero extend all six arguments (r3 - r8), the compatibility
111  * layer assumes this.
112  */
113         clrldi  r3,r3,32
114         clrldi  r4,r4,32
115         clrldi  r5,r5,32
116         clrldi  r6,r6,32
117         clrldi  r7,r7,32
118         clrldi  r8,r8,32
119         b       17f
120 15:
121         ld      r10,.SYS_CALL_TABLE@toc(2)
122 17:     slwi    r0,r0,3
123         ldx     r10,r10,r0      /* Fetch system call handler [ptr] */
124         mtlr    r10
125         addi    r9,r1,STACK_FRAME_OVERHEAD
126         blrl                    /* Call handler */
127 _GLOBAL(ret_from_syscall_1)
128         std     r3,RESULT(r1)   /* Save result */
129 #ifdef SHOW_SYSCALLS
130 #ifdef SHOW_SYSCALLS_TASK
131         ld      r10, PACACURRENT(13)
132         cmp     0,r10,r31
133         bne     91f
134 #endif
135         mr      r4,r3
136         LOADADDR(r3,79f)
137         bl      .printk
138         ld      r3,RESULT(r1)
139 91:
140 #endif
141         li      r10,-_LAST_ERRNO
142         cmpld   0,r3,r10
143         blt     30f
144         neg     r3,r3
145 22:     ld      r10,_CCR(r1)    /* Set SO bit in CR */
146         oris    r10,r10,0x1000
147         std     r10,_CCR(r1)
148 30:     std     r3,GPR3(r1)     /* Update return value */
149         b       .ret_from_except
150 66:     li      r3,ENOSYS
151         b       22b
152         
153 /* Traced system call support */
154 50:     addi    r3,r1,STACK_FRAME_OVERHEAD
155         bl      .do_syscall_trace_enter
156         ld      r0,GPR0(r1)     /* Restore original registers */
157         ld      r3,GPR3(r1)
158         ld      r4,GPR4(r1)
159         ld      r5,GPR5(r1)
160         ld      r6,GPR6(r1)
161         ld      r7,GPR7(r1)
162         ld      r8,GPR8(r1)
163         /* XXX check this - Anton */
164         ld      r9,GPR9(r1)
165         cmpli   0,r0,NR_syscalls
166         bge-    66f
167 /*
168  * Need to vector to 32 Bit or default sys_call_table here,
169  * based on caller's run-mode / personality.
170  */
171         clrrdi  r10,r1,THREAD_SHIFT
172         ld      r10,TI_FLAGS(r10)
173         andi.   r11,r10,_TIF_32BIT
174         beq-    55f
175         ld      r10,.SYS_CALL_TABLE32@toc(2)
176 /*
177  * We now zero extend all six arguments (r3 - r8), the compatibility
178  * layer assumes this.
179  */
180         clrldi  r3,r3,32
181         clrldi  r4,r4,32
182         clrldi  r5,r5,32
183         clrldi  r6,r6,32
184         clrldi  r7,r7,32
185         clrldi  r8,r8,32
186         b       57f
187 55:
188         ld      r10,.SYS_CALL_TABLE@toc(2)
189 57:
190         slwi    r0,r0,3
191         ldx     r10,r10,r0      /* Fetch system call handler [ptr] */
192         mtlr    r10
193         addi    r9,r1,STACK_FRAME_OVERHEAD
194         blrl                    /* Call handler */
195 _GLOBAL(ret_from_syscall_2)
196         std     r3,RESULT(r1)   /* Save result */       
197         li      r10,-_LAST_ERRNO
198         cmpld   0,r3,r10
199         blt     60f
200         neg     r3,r3
201 57:     ld      r10,_CCR(r1)    /* Set SO bit in CR */
202         oris    r10,r10,0x1000
203         std     r10,_CCR(r1)
204 60:     std     r3,GPR3(r1)     /* Update return value */
205         bl      .do_syscall_trace_leave
206         b       .ret_from_except
207 66:     li      r3,ENOSYS
208         b       57b
209 #ifdef SHOW_SYSCALLS
210 7:      .string "syscall %d(%x, %x, %x, %x, %x, "
211 77:     .string "%x, %x), current=%p\n"
212 79:     .string " -> %x\n"
213         .align  2,0
214 #endif
215
216         
217 _GLOBAL(ppc32_swapcontext)
218         bl      .sys32_swapcontext
219         b       80f
220         
221 _GLOBAL(ppc64_swapcontext)
222         bl      .sys_swapcontext
223         b       80f
224
225 _GLOBAL(ppc32_sigreturn)
226         bl      .sys32_sigreturn
227         b       80f
228
229 _GLOBAL(ppc32_rt_sigreturn)
230         bl      .sys32_rt_sigreturn
231         b       80f
232
233 _GLOBAL(ppc64_rt_sigreturn)
234         bl      .sys_rt_sigreturn
235
236 80:     clrrdi  r4,r1,THREAD_SHIFT
237         ld      r4,TI_FLAGS(r4)
238         andi.   r4,r4,_TIF_SYSCALL_T_OR_A
239         bne-    81f
240         cmpi    0,r3,0
241         bge     .ret_from_except
242         b       .ret_from_syscall_1
243 81:     cmpi    0,r3,0
244         blt     .ret_from_syscall_2
245         bl      .do_syscall_trace_leave
246         b       .ret_from_except
247
248 /*
249  * This routine switches between two different tasks.  The process
250  * state of one is saved on its kernel stack.  Then the state
251  * of the other is restored from its kernel stack.  The memory
252  * management hardware is updated to the second process's state.
253  * Finally, we can return to the second process, via ret_from_except.
254  * On entry, r3 points to the THREAD for the current task, r4
255  * points to the THREAD for the new task.
256  *
257  * Note: there are two ways to get to the "going out" portion
258  * of this code; either by coming in via the entry (_switch)
259  * or via "fork" which must set up an environment equivalent
260  * to the "_switch" path.  If you change this you'll have to change
261  * the fork code also.
262  *
263  * The code which creates the new task context is in 'copy_thread'
264  * in arch/ppc64/kernel/process.c
265  */
266 _GLOBAL(_switch)
267         mflr    r0
268         std     r0,16(r1)
269         stdu    r1,-SWITCH_FRAME_SIZE(r1)
270         /* r3-r13 are caller saved -- Cort */
271         SAVE_8GPRS(14, r1)
272         SAVE_10GPRS(22, r1)
273         mflr    r20             /* Return to switch caller */
274         mfmsr   r22
275         li      r0, MSR_FP
276 #ifdef CONFIG_ALTIVEC
277 BEGIN_FTR_SECTION
278         oris    r0,r0,MSR_VEC@h /* Disable altivec */
279         mfspr   r24,SPRN_VRSAVE /* save vrsave register value */
280         std     r24,THREAD_VRSAVE(r3)
281 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
282 #endif /* CONFIG_ALTIVEC */
283         and.    r0,r0,r22
284         beq+    1f
285         andc    r22,r22,r0
286         mtmsrd  r22
287         isync
288 1:      std     r20,_NIP(r1)
289         mfcr    r23
290         std     r23,_CCR(r1)
291         std     r1,KSP(r3)      /* Set old stack pointer */
292
293 #ifdef CONFIG_SMP
294         /* We need a sync somewhere here to make sure that if the
295          * previous task gets rescheduled on another CPU, it sees all
296          * stores it has performed on this one.
297          */
298         sync
299 #endif /* CONFIG_SMP */
300
301         addi    r6,r4,-THREAD   /* Convert THREAD to 'current' */
302         std     r6,PACACURRENT(r13)     /* Set new 'current' */
303
304         ld      r8,KSP(r4)      /* new stack pointer */
305 BEGIN_FTR_SECTION
306         clrrdi  r6,r8,28        /* get its ESID */
307         clrrdi  r9,r1,28        /* get current sp ESID */
308         clrldi. r0,r6,2         /* is new ESID c00000000? */
309         cmpd    cr1,r6,r9       /* or is new ESID the same as current ESID? */
310         cror    eq,4*cr1+eq,eq
311         beq     2f              /* if yes, don't slbie it */
312         oris    r6,r6,0x0800    /* set C (class) bit */
313         slbie   r6
314         slbie   r6              /* Workaround POWER5 < DD2.1 issue */
315 2:
316 END_FTR_SECTION_IFSET(CPU_FTR_SLB)
317         clrrdi  r7,r8,THREAD_SHIFT      /* base of new stack */
318         addi    r7,r7,THREAD_SIZE-INT_FRAME_SIZE
319
320         mr      r1,r8           /* start using new stack pointer */
321         std     r7,PACAKSAVE(r13)
322
323         ld      r6,_CCR(r1)
324         mtcrf   0xFF,r6
325
326 #ifdef CONFIG_ALTIVEC
327 BEGIN_FTR_SECTION
328         ld      r0,THREAD_VRSAVE(r4)
329         mtspr   SPRN_VRSAVE,r0          /* if G4, restore VRSAVE reg */
330 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
331 #endif /* CONFIG_ALTIVEC */
332
333         /* r3-r13 are destroyed -- Cort */
334         REST_8GPRS(14, r1)
335         REST_10GPRS(22, r1)
336
337 #ifdef CONFIG_PPC_ISERIES
338         clrrdi  r7,r1,THREAD_SHIFT      /* get current_thread_info() */
339         ld      r7,TI_FLAGS(r7)         /* Get run light flag */
340         mfspr   r9,CTRLF
341         srdi    r7,r7,TIF_RUN_LIGHT
342         insrdi  r9,r7,1,63              /* Insert run light into CTRL */
343         mtspr   CTRLT,r9
344 #endif
345
346         /* convert old thread to its task_struct for return value */
347         addi    r3,r3,-THREAD
348         ld      r7,_NIP(r1)     /* Return to _switch caller in new task */
349         mtlr    r7
350         addi    r1,r1,SWITCH_FRAME_SIZE
351         blr
352
353 _GLOBAL(ret_from_fork)
354         bl      .schedule_tail
355         clrrdi  r4,r1,THREAD_SHIFT
356         ld      r4,TI_FLAGS(r4)
357         andi.   r4,r4,_TIF_SYSCALL_T_OR_A
358         beq+    .ret_from_except
359         bl      .do_syscall_trace_leave
360         b       .ret_from_except
361
362 _GLOBAL(ret_from_except)
363         /*
364          * Disable interrupts so that current_thread_info()->flags
365          * can't change between when we test it and when we return
366          * from the interrupt.
367          */
368         mfmsr   r10             /* Get current interrupt state */
369         li      r4,0
370         ori     r4,r4,MSR_EE
371         andc    r9,r10,r4       /* clear MSR_EE */
372         mtmsrd  r9,1            /* Update machine state */
373
374         ld      r3,_MSR(r1)     /* Returning to user mode? */
375         andi.   r3,r3,MSR_PR
376         beq     restore         /* if not, just restore regs and return */
377
378         /* Check current_thread_info()->flags */
379         clrrdi  r3,r1,THREAD_SHIFT
380         ld      r3,TI_FLAGS(r3)
381         andi.   r0,r3,_TIF_USER_WORK_MASK
382         bne     do_work
383
384         addi    r0,r1,INT_FRAME_SIZE    /* size of frame */
385         ld      r4,PACACURRENT(r13)
386         std     r0,THREAD+KSP(r4)       /* save kernel stack pointer */
387
388         /*
389          * r13 is our per cpu area, only restore it if we are returning to
390          * userspace
391          */
392         REST_GPR(13,r1)
393
394 restore:
395 #ifdef CONFIG_PPC_ISERIES
396         ld      r5,SOFTE(r1)
397         mfspr   r4,SPRG3                /* get paca address */
398         cmpdi   0,r5,0
399         beq     4f
400         /* Check for pending interrupts (iSeries) */
401         /* this is CHECKANYINT except that we already have the paca address */
402         ld      r3,PACALPPACA+LPPACAANYINT(r4)
403         cmpdi   r3,0
404         beq+    4f                      /* skip do_IRQ if no interrupts */
405
406         mfspr   r13,SPRG3               /* get paca pointer back */
407         li      r3,0
408         stb     r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */
409         mtmsrd  r10                     /* hard-enable again */
410         addi    r3,r1,STACK_FRAME_OVERHEAD
411         bl      .do_IRQ
412         b       .ret_from_except                /* loop back and handle more */
413
414 4:      stb     r5,PACAPROCENABLED(r4)
415 #endif
416
417         ld      r3,_MSR(r1)
418         andi.   r3,r3,MSR_RI
419         beq-    unrecov_restore
420
421         ld      r3,_CTR(r1)
422         ld      r0,_LINK(r1)
423         mtctr   r3
424         mtlr    r0
425         ld      r3,_XER(r1)
426         mtspr   XER,r3
427
428         REST_8GPRS(5, r1)
429         REST_10GPRS(14, r1)
430         REST_8GPRS(24, r1)
431
432         stdcx.  r0,0,r1         /* to clear the reservation */
433
434         mfmsr   r0
435         li      r2, MSR_RI
436         andc    r0,r0,r2
437         mtmsrd  r0,1
438
439         ld      r0,_MSR(r1)
440         mtspr   SRR1,r0
441
442         ld      r2,_CCR(r1)
443         mtcrf   0xFF,r2
444         ld      r2,_NIP(r1)
445         mtspr   SRR0,r2
446
447         ld      r0,GPR0(r1)
448         ld      r2,GPR2(r1)
449         ld      r3,GPR3(r1)
450         ld      r4,GPR4(r1)
451         ld      r1,GPR1(r1)
452
453         rfid
454
455 /* Note: this must change if we start using the  TIF_NOTIFY_RESUME bit */
456 do_work:
457         /* Enable interrupts */
458         mtmsrd  r10,1
459
460         andi.   r0,r3,_TIF_NEED_RESCHED
461         beq     1f
462         bl      .schedule
463         b       .ret_from_except
464
465 1:      andi.   r0,r3,_TIF_SIGPENDING
466         beq     .ret_from_except
467         li      r3,0
468         addi    r4,r1,STACK_FRAME_OVERHEAD
469         bl      .do_signal
470         b       .ret_from_except
471
472 unrecov_restore:
473         mfspr   r13,SPRG3
474         addi    r3,r1,STACK_FRAME_OVERHEAD
475         bl      .unrecoverable_exception
476         b       unrecov_restore
477
478 #ifdef CONFIG_PPC_PSERIES
479 /*
480  * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
481  * called with the MMU off.
482  *
483  * In addition, we need to be in 32b mode, at least for now.
484  * 
485  * Note: r3 is an input parameter to rtas, so don't trash it...
486  */
487 _GLOBAL(enter_rtas)
488         mflr    r0
489         std     r0,16(r1)
490         stdu    r1,-RTAS_FRAME_SIZE(r1) /* Save SP and create stack space. */
491         
492         /* Because RTAS is running in 32b mode, it clobbers the high order half
493          * of all registers that it saves.  We therefore save those registers
494          * RTAS might touch to the stack.  (r0, r3-r13 are caller saved)
495          */
496         SAVE_GPR(2, r1)                 /* Save the TOC */
497         SAVE_GPR(13, r1)                /* Save paca */
498         SAVE_8GPRS(14, r1)              /* Save the non-volatiles */
499         SAVE_10GPRS(22, r1)             /* ditto */
500
501         mfcr    r4
502         std     r4,_CCR(r1)
503         mfctr   r5
504         std     r5,_CTR(r1)
505         mfspr   r6,XER
506         std     r6,_XER(r1)
507         mfdar   r7
508         std     r7,_DAR(r1)
509         mfdsisr r8
510         std     r8,_DSISR(r1)
511         mfsrr0  r9
512         std     r9,_SRR0(r1)
513         mfsrr1  r10
514         std     r10,_SRR1(r1)
515
516         /* There is no way it is acceptable to get here with interrupts enabled,
517          * check it with the asm equivalent of WARN_ON
518          */
519         mfmsr   r6
520         andi.   r0,r6,MSR_EE
521 1:      tdnei   r0,0
522 .section __bug_table,"a"
523         .llong  1b,__LINE__ + 0x1000000, 1f, 2f
524 .previous
525 .section .rodata,"a"
526 1:      .asciz  __FILE__
527 2:      .asciz "enter_rtas"
528 .previous
529         
530         /* Unfortunately, the stack pointer and the MSR are also clobbered,
531          * so they are saved in the PACA which allows us to restore
532          * our original state after RTAS returns.
533          */
534         std     r1,PACAR1(r13)
535         std     r6,PACASAVEDMSR(r13)
536
537         /* Setup our real return addr */        
538         SET_REG_TO_LABEL(r4,.rtas_return_loc)
539         SET_REG_TO_CONST(r9,KERNELBASE)
540         sub     r4,r4,r9
541         mtlr    r4
542
543         li      r0,0
544         ori     r0,r0,MSR_EE|MSR_SE|MSR_BE|MSR_RI
545         andc    r0,r6,r0
546         
547         li      r9,1
548         rldicr  r9,r9,MSR_SF_LG,(63-MSR_SF_LG)
549         ori     r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP
550         andc    r6,r0,r9
551         ori     r6,r6,MSR_RI
552         sync                            /* disable interrupts so SRR0/1 */
553         mtmsrd  r0                      /* don't get trashed */
554
555         SET_REG_TO_LABEL(r4,rtas)
556         ld      r5,RTASENTRY(r4)        /* get the rtas->entry value */
557         ld      r4,RTASBASE(r4)         /* get the rtas->base value */
558         
559         mtspr   SRR0,r5
560         mtspr   SRR1,r6
561         rfid
562
563 _STATIC(rtas_return_loc)
564         /* relocation is off at this point */
565         mfspr   r4,SPRG3                /* Get PACA */
566         SET_REG_TO_CONST(r5, KERNELBASE)
567         sub     r4,r4,r5                /* RELOC the PACA base pointer */
568
569         mfmsr   r6
570         li      r0,MSR_RI
571         andc    r6,r6,r0
572         sync    
573         mtmsrd  r6
574         
575         ld      r1,PACAR1(r4)           /* Restore our SP */
576         LOADADDR(r3,.rtas_restore_regs)
577         ld      r4,PACASAVEDMSR(r4)     /* Restore our MSR */
578
579         mtspr   SRR0,r3
580         mtspr   SRR1,r4
581         rfid
582
583 _STATIC(rtas_restore_regs)
584         /* relocation is on at this point */
585         REST_GPR(2, r1)                 /* Restore the TOC */
586         REST_GPR(13, r1)                /* Restore paca */
587         REST_8GPRS(14, r1)              /* Restore the non-volatiles */
588         REST_10GPRS(22, r1)             /* ditto */
589
590         mfspr   r13,SPRG3
591
592         ld      r4,_CCR(r1)
593         mtcr    r4
594         ld      r5,_CTR(r1)
595         mtctr   r5
596         ld      r6,_XER(r1)
597         mtspr   XER,r6
598         ld      r7,_DAR(r1)
599         mtdar   r7
600         ld      r8,_DSISR(r1)
601         mtdsisr r8
602         ld      r9,_SRR0(r1)
603         mtsrr0  r9
604         ld      r10,_SRR1(r1)
605         mtsrr1  r10
606
607         addi    r1,r1,RTAS_FRAME_SIZE   /* Unstack our frame */
608         ld      r0,16(r1)               /* get return address */
609
610         mtlr    r0
611         blr                             /* return to caller */
612
613 _GLOBAL(enter_prom)
614         mflr    r0
615         std     r0,16(r1)
616         stdu    r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
617
618         /* Because PROM is running in 32b mode, it clobbers the high order half
619          * of all registers that it saves.  We therefore save those registers
620          * PROM might touch to the stack.  (r0, r3-r13 are caller saved)
621          */
622         SAVE_8GPRS(2, r1)
623         SAVE_GPR(13, r1)
624         SAVE_8GPRS(14, r1)
625         SAVE_10GPRS(22, r1)
626         mfcr    r4
627         std     r4,_CCR(r1)
628         mfctr   r5
629         std     r5,_CTR(r1)
630         mfspr   r6,XER
631         std     r6,_XER(r1)
632         mfdar   r7
633         std     r7,_DAR(r1)
634         mfdsisr r8
635         std     r8,_DSISR(r1)
636         mfsrr0  r9
637         std     r9,_SRR0(r1)
638         mfsrr1  r10
639         std     r10,_SRR1(r1)
640         mfmsr   r11
641         std     r11,_MSR(r1)
642
643         /* Get the PROM entrypoint */
644         bl      .reloc_offset
645         LOADADDR(r12,prom)
646         sub     r12,r12,r3
647         ld      r12,PROMENTRY(r12)
648         mtlr    r12
649
650         /* Switch MSR to 32 bits mode
651          */
652         mfmsr   r11
653         li      r12,1
654         rldicr  r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
655         andc    r11,r11,r12
656         li      r12,1
657         rldicr  r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
658         andc    r11,r11,r12
659         mtmsrd  r11
660         isync
661
662         /* Restore arguments & enter PROM here... */
663         ld      r3,GPR3(r1)
664         blrl
665
666         /* Just make sure that r1 top 32 bits didn't get
667          * corrupt by OF
668          */
669         rldicl  r1,r1,0,32
670
671         /* Restore the MSR (back to 64 bits) */
672         ld      r0,_MSR(r1)
673         mtmsrd  r0
674         isync
675
676         /* Restore other registers */
677         REST_GPR(2, r1)
678         REST_GPR(13, r1)
679         REST_8GPRS(14, r1)
680         REST_10GPRS(22, r1)
681         ld      r4,_CCR(r1)
682         mtcr    r4
683         ld      r5,_CTR(r1)
684         mtctr   r5
685         ld      r6,_XER(r1)
686         mtspr   XER,r6
687         ld      r7,_DAR(r1)
688         mtdar   r7
689         ld      r8,_DSISR(r1)
690         mtdsisr r8
691         ld      r9,_SRR0(r1)
692         mtsrr0  r9
693         ld      r10,_SRR1(r1)
694         mtsrr1  r10
695         
696         addi    r1,r1,PROM_FRAME_SIZE
697         ld      r0,16(r1)
698         mtlr    r0
699         blr
700         
701 #endif  /* defined(CONFIG_PPC_PSERIES) */