xref: /openbmc/linux/arch/powerpc/kernel/entry_32.S (revision 96de0e252cedffad61b3cb5e05662c591898e69a)
1/*
2 *  PowerPC version
3 *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
4 *  Rewritten by Cort Dougan (cort@fsmlabs.com) for PReP
5 *    Copyright (C) 1996 Cort Dougan <cort@fsmlabs.com>
6 *  Adapted for Power Macintosh by Paul Mackerras.
7 *  Low-level exception handlers and MMU support
8 *  rewritten by Paul Mackerras.
9 *    Copyright (C) 1996 Paul Mackerras.
10 *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
11 *
12 *  This file contains the system call entry code, context switch
13 *  code, and exception/interrupt return code for PowerPC.
14 *
15 *  This program is free software; you can redistribute it and/or
16 *  modify it under the terms of the GNU General Public License
17 *  as published by the Free Software Foundation; either version
18 *  2 of the License, or (at your option) any later version.
19 *
20 */
21
22#include <linux/errno.h>
23#include <linux/sys.h>
24#include <linux/threads.h>
25#include <asm/reg.h>
26#include <asm/page.h>
27#include <asm/mmu.h>
28#include <asm/cputable.h>
29#include <asm/thread_info.h>
30#include <asm/ppc_asm.h>
31#include <asm/asm-offsets.h>
32#include <asm/unistd.h>
33
34#undef SHOW_SYSCALLS
35#undef SHOW_SYSCALLS_TASK
36
37/*
38 * MSR_KERNEL is > 0x10000 on 4xx/Book-E since it include MSR_CE.
39 */
40#if MSR_KERNEL >= 0x10000
41#define LOAD_MSR_KERNEL(r, x)	lis r,(x)@h; ori r,r,(x)@l
42#else
43#define LOAD_MSR_KERNEL(r, x)	li r,(x)
44#endif
45
46#ifdef CONFIG_BOOKE
47#include "head_booke.h"
48#define TRANSFER_TO_HANDLER_EXC_LEVEL(exc_level)	\
49	mtspr	exc_level##_SPRG,r8;			\
50	BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);		\
51	lwz	r0,GPR10-INT_FRAME_SIZE(r8);		\
52	stw	r0,GPR10(r11);				\
53	lwz	r0,GPR11-INT_FRAME_SIZE(r8);		\
54	stw	r0,GPR11(r11);				\
55	mfspr	r8,exc_level##_SPRG
56
57	.globl	mcheck_transfer_to_handler
58mcheck_transfer_to_handler:
59	TRANSFER_TO_HANDLER_EXC_LEVEL(MCHECK)
60	b	transfer_to_handler_full
61
62	.globl	debug_transfer_to_handler
63debug_transfer_to_handler:
64	TRANSFER_TO_HANDLER_EXC_LEVEL(DEBUG)
65	b	transfer_to_handler_full
66
67	.globl	crit_transfer_to_handler
68crit_transfer_to_handler:
69	TRANSFER_TO_HANDLER_EXC_LEVEL(CRIT)
70	/* fall through */
71#endif
72
73#ifdef CONFIG_40x
74	.globl	crit_transfer_to_handler
75crit_transfer_to_handler:
76	lwz	r0,crit_r10@l(0)
77	stw	r0,GPR10(r11)
78	lwz	r0,crit_r11@l(0)
79	stw	r0,GPR11(r11)
80	/* fall through */
81#endif
82
83/*
84 * This code finishes saving the registers to the exception frame
85 * and jumps to the appropriate handler for the exception, turning
86 * on address translation.
87 * Note that we rely on the caller having set cr0.eq iff the exception
88 * occurred in kernel mode (i.e. MSR:PR = 0).
89 */
90	.globl	transfer_to_handler_full
91transfer_to_handler_full:
92	SAVE_NVGPRS(r11)
93	/* fall through */
94
95	.globl	transfer_to_handler
96transfer_to_handler:
97	stw	r2,GPR2(r11)
98	stw	r12,_NIP(r11)
99	stw	r9,_MSR(r11)
100	andi.	r2,r9,MSR_PR
101	mfctr	r12
102	mfspr	r2,SPRN_XER
103	stw	r12,_CTR(r11)
104	stw	r2,_XER(r11)
105	mfspr	r12,SPRN_SPRG3
106	addi	r2,r12,-THREAD
107	tovirt(r2,r2)			/* set r2 to current */
108	beq	2f			/* if from user, fix up THREAD.regs */
109	addi	r11,r1,STACK_FRAME_OVERHEAD
110	stw	r11,PT_REGS(r12)
111#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
112	/* Check to see if the dbcr0 register is set up to debug.  Use the
113	   single-step bit to do this. */
114	lwz	r12,THREAD_DBCR0(r12)
115	andis.	r12,r12,DBCR0_IC@h
116	beq+	3f
117	/* From user and task is ptraced - load up global dbcr0 */
118	li	r12,-1			/* clear all pending debug events */
119	mtspr	SPRN_DBSR,r12
120	lis	r11,global_dbcr0@ha
121	tophys(r11,r11)
122	addi	r11,r11,global_dbcr0@l
123	lwz	r12,0(r11)
124	mtspr	SPRN_DBCR0,r12
125	lwz	r12,4(r11)
126	addi	r12,r12,-1
127	stw	r12,4(r11)
128#endif
129	b	3f
130
1312:	/* if from kernel, check interrupted DOZE/NAP mode and
132         * check for stack overflow
133         */
134	lwz	r9,THREAD_INFO-THREAD(r12)
135	cmplw	r1,r9			/* if r1 <= current->thread_info */
136	ble-	stack_ovf		/* then the kernel stack overflowed */
1375:
138#ifdef CONFIG_6xx
139	tophys(r9,r9)			/* check local flags */
140	lwz	r12,TI_LOCAL_FLAGS(r9)
141	mtcrf	0x01,r12
142	bt-	31-TLF_NAPPING,4f
143#endif /* CONFIG_6xx */
144	.globl transfer_to_handler_cont
145transfer_to_handler_cont:
1463:
147	mflr	r9
148	lwz	r11,0(r9)		/* virtual address of handler */
149	lwz	r9,4(r9)		/* where to go when done */
150	mtspr	SPRN_SRR0,r11
151	mtspr	SPRN_SRR1,r10
152	mtlr	r9
153	SYNC
154	RFI				/* jump to handler, enable MMU */
155
156#ifdef CONFIG_6xx
1574:	rlwinm	r12,r12,0,~_TLF_NAPPING
158	stw	r12,TI_LOCAL_FLAGS(r9)
159	b	power_save_6xx_restore
160#endif
161
162/*
163 * On kernel stack overflow, load up an initial stack pointer
164 * and call StackOverflow(regs), which should not return.
165 */
166stack_ovf:
167	/* sometimes we use a statically-allocated stack, which is OK. */
168	lis	r12,_end@h
169	ori	r12,r12,_end@l
170	cmplw	r1,r12
171	ble	5b			/* r1 <= &_end is OK */
172	SAVE_NVGPRS(r11)
173	addi	r3,r1,STACK_FRAME_OVERHEAD
174	lis	r1,init_thread_union@ha
175	addi	r1,r1,init_thread_union@l
176	addi	r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
177	lis	r9,StackOverflow@ha
178	addi	r9,r9,StackOverflow@l
179	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
180	FIX_SRR1(r10,r12)
181	mtspr	SPRN_SRR0,r9
182	mtspr	SPRN_SRR1,r10
183	SYNC
184	RFI
185
186/*
187 * Handle a system call.
188 */
189	.stabs	"arch/powerpc/kernel/",N_SO,0,0,0f
190	.stabs	"entry_32.S",N_SO,0,0,0f
1910:
192
193_GLOBAL(DoSyscall)
194	stw	r3,ORIG_GPR3(r1)
195	li	r12,0
196	stw	r12,RESULT(r1)
197	lwz	r11,_CCR(r1)	/* Clear SO bit in CR */
198	rlwinm	r11,r11,0,4,2
199	stw	r11,_CCR(r1)
200#ifdef SHOW_SYSCALLS
201	bl	do_show_syscall
202#endif /* SHOW_SYSCALLS */
203	rlwinm	r10,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
204	lwz	r11,TI_FLAGS(r10)
205	andi.	r11,r11,_TIF_SYSCALL_T_OR_A
206	bne-	syscall_dotrace
207syscall_dotrace_cont:
208	cmplwi	0,r0,NR_syscalls
209	lis	r10,sys_call_table@h
210	ori	r10,r10,sys_call_table@l
211	slwi	r0,r0,2
212	bge-	66f
213	lwzx	r10,r10,r0	/* Fetch system call handler [ptr] */
214	mtlr	r10
215	addi	r9,r1,STACK_FRAME_OVERHEAD
216	PPC440EP_ERR42
217	blrl			/* Call handler */
218	.globl	ret_from_syscall
219ret_from_syscall:
220#ifdef SHOW_SYSCALLS
221	bl	do_show_syscall_exit
222#endif
223	mr	r6,r3
224	rlwinm	r12,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
225	/* disable interrupts so current_thread_info()->flags can't change */
226	LOAD_MSR_KERNEL(r10,MSR_KERNEL)	/* doesn't include MSR_EE */
227	SYNC
228	MTMSRD(r10)
229	lwz	r9,TI_FLAGS(r12)
230	li	r8,-_LAST_ERRNO
231	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)
232	bne-	syscall_exit_work
233	cmplw	0,r3,r8
234	blt+	syscall_exit_cont
235	lwz	r11,_CCR(r1)			/* Load CR */
236	neg	r3,r3
237	oris	r11,r11,0x1000	/* Set SO bit in CR */
238	stw	r11,_CCR(r1)
239syscall_exit_cont:
240#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
241	/* If the process has its own DBCR0 value, load it up.  The single
242	   step bit tells us that dbcr0 should be loaded. */
243	lwz	r0,THREAD+THREAD_DBCR0(r2)
244	andis.	r10,r0,DBCR0_IC@h
245	bnel-	load_dbcr0
246#endif
247	stwcx.	r0,0,r1			/* to clear the reservation */
248	lwz	r4,_LINK(r1)
249	lwz	r5,_CCR(r1)
250	mtlr	r4
251	mtcr	r5
252	lwz	r7,_NIP(r1)
253	lwz	r8,_MSR(r1)
254	FIX_SRR1(r8, r0)
255	lwz	r2,GPR2(r1)
256	lwz	r1,GPR1(r1)
257	mtspr	SPRN_SRR0,r7
258	mtspr	SPRN_SRR1,r8
259	SYNC
260	RFI
261
26266:	li	r3,-ENOSYS
263	b	ret_from_syscall
264
265	.globl	ret_from_fork
266ret_from_fork:
267	REST_NVGPRS(r1)
268	bl	schedule_tail
269	li	r3,0
270	b	ret_from_syscall
271
272/* Traced system call support */
273syscall_dotrace:
274	SAVE_NVGPRS(r1)
275	li	r0,0xc00
276	stw	r0,_TRAP(r1)
277	addi	r3,r1,STACK_FRAME_OVERHEAD
278	bl	do_syscall_trace_enter
279	lwz	r0,GPR0(r1)	/* Restore original registers */
280	lwz	r3,GPR3(r1)
281	lwz	r4,GPR4(r1)
282	lwz	r5,GPR5(r1)
283	lwz	r6,GPR6(r1)
284	lwz	r7,GPR7(r1)
285	lwz	r8,GPR8(r1)
286	REST_NVGPRS(r1)
287	b	syscall_dotrace_cont
288
289syscall_exit_work:
290	andi.	r0,r9,_TIF_RESTOREALL
291	beq+	0f
292	REST_NVGPRS(r1)
293	b	2f
2940:	cmplw	0,r3,r8
295	blt+	1f
296	andi.	r0,r9,_TIF_NOERROR
297	bne-	1f
298	lwz	r11,_CCR(r1)			/* Load CR */
299	neg	r3,r3
300	oris	r11,r11,0x1000	/* Set SO bit in CR */
301	stw	r11,_CCR(r1)
302
3031:	stw	r6,RESULT(r1)	/* Save result */
304	stw	r3,GPR3(r1)	/* Update return value */
3052:	andi.	r0,r9,(_TIF_PERSYSCALL_MASK)
306	beq	4f
307
308	/* Clear per-syscall TIF flags if any are set.  */
309
310	li	r11,_TIF_PERSYSCALL_MASK
311	addi	r12,r12,TI_FLAGS
3123:	lwarx	r8,0,r12
313	andc	r8,r8,r11
314#ifdef CONFIG_IBM405_ERR77
315	dcbt	0,r12
316#endif
317	stwcx.	r8,0,r12
318	bne-	3b
319	subi	r12,r12,TI_FLAGS
320
3214:	/* Anything which requires enabling interrupts? */
322	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
323	beq	ret_from_except
324
325	/* Re-enable interrupts */
326	ori	r10,r10,MSR_EE
327	SYNC
328	MTMSRD(r10)
329
330	/* Save NVGPRS if they're not saved already */
331	lwz	r4,_TRAP(r1)
332	andi.	r4,r4,1
333	beq	5f
334	SAVE_NVGPRS(r1)
335	li	r4,0xc00
336	stw	r4,_TRAP(r1)
3375:
338	addi	r3,r1,STACK_FRAME_OVERHEAD
339	bl	do_syscall_trace_leave
340	b	ret_from_except_full
341
342#ifdef SHOW_SYSCALLS
343do_show_syscall:
344#ifdef SHOW_SYSCALLS_TASK
345	lis	r11,show_syscalls_task@ha
346	lwz	r11,show_syscalls_task@l(r11)
347	cmp	0,r2,r11
348	bnelr
349#endif
350	stw	r31,GPR31(r1)
351	mflr	r31
352	lis	r3,7f@ha
353	addi	r3,r3,7f@l
354	lwz	r4,GPR0(r1)
355	lwz	r5,GPR3(r1)
356	lwz	r6,GPR4(r1)
357	lwz	r7,GPR5(r1)
358	lwz	r8,GPR6(r1)
359	lwz	r9,GPR7(r1)
360	bl	printk
361	lis	r3,77f@ha
362	addi	r3,r3,77f@l
363	lwz	r4,GPR8(r1)
364	mr	r5,r2
365	bl	printk
366	lwz	r0,GPR0(r1)
367	lwz	r3,GPR3(r1)
368	lwz	r4,GPR4(r1)
369	lwz	r5,GPR5(r1)
370	lwz	r6,GPR6(r1)
371	lwz	r7,GPR7(r1)
372	lwz	r8,GPR8(r1)
373	mtlr	r31
374	lwz	r31,GPR31(r1)
375	blr
376
377do_show_syscall_exit:
378#ifdef SHOW_SYSCALLS_TASK
379	lis	r11,show_syscalls_task@ha
380	lwz	r11,show_syscalls_task@l(r11)
381	cmp	0,r2,r11
382	bnelr
383#endif
384	stw	r31,GPR31(r1)
385	mflr	r31
386	stw	r3,RESULT(r1)	/* Save result */
387	mr	r4,r3
388	lis	r3,79f@ha
389	addi	r3,r3,79f@l
390	bl	printk
391	lwz	r3,RESULT(r1)
392	mtlr	r31
393	lwz	r31,GPR31(r1)
394	blr
395
3967:	.string	"syscall %d(%x, %x, %x, %x, %x, "
39777:	.string	"%x), current=%p\n"
39879:	.string	" -> %x\n"
399	.align	2,0
400
401#ifdef SHOW_SYSCALLS_TASK
402	.data
403	.globl	show_syscalls_task
404show_syscalls_task:
405	.long	-1
406	.text
407#endif
408#endif /* SHOW_SYSCALLS */
409
410/*
411 * The fork/clone functions need to copy the full register set into
412 * the child process. Therefore we need to save all the nonvolatile
413 * registers (r13 - r31) before calling the C code.
414 */
415	.globl	ppc_fork
416ppc_fork:
417	SAVE_NVGPRS(r1)
418	lwz	r0,_TRAP(r1)
419	rlwinm	r0,r0,0,0,30		/* clear LSB to indicate full */
420	stw	r0,_TRAP(r1)		/* register set saved */
421	b	sys_fork
422
423	.globl	ppc_vfork
424ppc_vfork:
425	SAVE_NVGPRS(r1)
426	lwz	r0,_TRAP(r1)
427	rlwinm	r0,r0,0,0,30		/* clear LSB to indicate full */
428	stw	r0,_TRAP(r1)		/* register set saved */
429	b	sys_vfork
430
431	.globl	ppc_clone
432ppc_clone:
433	SAVE_NVGPRS(r1)
434	lwz	r0,_TRAP(r1)
435	rlwinm	r0,r0,0,0,30		/* clear LSB to indicate full */
436	stw	r0,_TRAP(r1)		/* register set saved */
437	b	sys_clone
438
439	.globl	ppc_swapcontext
440ppc_swapcontext:
441	SAVE_NVGPRS(r1)
442	lwz	r0,_TRAP(r1)
443	rlwinm	r0,r0,0,0,30		/* clear LSB to indicate full */
444	stw	r0,_TRAP(r1)		/* register set saved */
445	b	sys_swapcontext
446
447/*
448 * Top-level page fault handling.
449 * This is in assembler because if do_page_fault tells us that
450 * it is a bad kernel page fault, we want to save the non-volatile
451 * registers before calling bad_page_fault.
452 */
453	.globl	handle_page_fault
454handle_page_fault:
455	stw	r4,_DAR(r1)
456	addi	r3,r1,STACK_FRAME_OVERHEAD
457	bl	do_page_fault
458	cmpwi	r3,0
459	beq+	ret_from_except
460	SAVE_NVGPRS(r1)
461	lwz	r0,_TRAP(r1)
462	clrrwi	r0,r0,1
463	stw	r0,_TRAP(r1)
464	mr	r5,r3
465	addi	r3,r1,STACK_FRAME_OVERHEAD
466	lwz	r4,_DAR(r1)
467	bl	bad_page_fault
468	b	ret_from_except_full
469
470/*
471 * This routine switches between two different tasks.  The process
472 * state of one is saved on its kernel stack.  Then the state
473 * of the other is restored from its kernel stack.  The memory
474 * management hardware is updated to the second process's state.
475 * Finally, we can return to the second process.
476 * On entry, r3 points to the THREAD for the current task, r4
477 * points to the THREAD for the new task.
478 *
479 * This routine is always called with interrupts disabled.
480 *
481 * Note: there are two ways to get to the "going out" portion
482 * of this code; either by coming in via the entry (_switch)
483 * or via "fork" which must set up an environment equivalent
484 * to the "_switch" path.  If you change this , you'll have to
485 * change the fork code also.
486 *
487 * The code which creates the new task context is in 'copy_thread'
488 * in arch/ppc/kernel/process.c
489 */
490_GLOBAL(_switch)
491	stwu	r1,-INT_FRAME_SIZE(r1)
492	mflr	r0
493	stw	r0,INT_FRAME_SIZE+4(r1)
494	/* r3-r12 are caller saved -- Cort */
495	SAVE_NVGPRS(r1)
496	stw	r0,_NIP(r1)	/* Return to switch caller */
497	mfmsr	r11
498	li	r0,MSR_FP	/* Disable floating-point */
499#ifdef CONFIG_ALTIVEC
500BEGIN_FTR_SECTION
501	oris	r0,r0,MSR_VEC@h	/* Disable altivec */
502	mfspr	r12,SPRN_VRSAVE	/* save vrsave register value */
503	stw	r12,THREAD+THREAD_VRSAVE(r2)
504END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
505#endif /* CONFIG_ALTIVEC */
506#ifdef CONFIG_SPE
507BEGIN_FTR_SECTION
508	oris	r0,r0,MSR_SPE@h	 /* Disable SPE */
509	mfspr	r12,SPRN_SPEFSCR /* save spefscr register value */
510	stw	r12,THREAD+THREAD_SPEFSCR(r2)
511END_FTR_SECTION_IFSET(CPU_FTR_SPE)
512#endif /* CONFIG_SPE */
513	and.	r0,r0,r11	/* FP or altivec or SPE enabled? */
514	beq+	1f
515	andc	r11,r11,r0
516	MTMSRD(r11)
517	isync
5181:	stw	r11,_MSR(r1)
519	mfcr	r10
520	stw	r10,_CCR(r1)
521	stw	r1,KSP(r3)	/* Set old stack pointer */
522
523#ifdef CONFIG_SMP
524	/* We need a sync somewhere here to make sure that if the
525	 * previous task gets rescheduled on another CPU, it sees all
526	 * stores it has performed on this one.
527	 */
528	sync
529#endif /* CONFIG_SMP */
530
531	tophys(r0,r4)
532	CLR_TOP32(r0)
533	mtspr	SPRN_SPRG3,r0	/* Update current THREAD phys addr */
534	lwz	r1,KSP(r4)	/* Load new stack pointer */
535
536	/* save the old current 'last' for return value */
537	mr	r3,r2
538	addi	r2,r4,-THREAD	/* Update current */
539
540#ifdef CONFIG_ALTIVEC
541BEGIN_FTR_SECTION
542	lwz	r0,THREAD+THREAD_VRSAVE(r2)
543	mtspr	SPRN_VRSAVE,r0		/* if G4, restore VRSAVE reg */
544END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
545#endif /* CONFIG_ALTIVEC */
546#ifdef CONFIG_SPE
547BEGIN_FTR_SECTION
548	lwz	r0,THREAD+THREAD_SPEFSCR(r2)
549	mtspr	SPRN_SPEFSCR,r0		/* restore SPEFSCR reg */
550END_FTR_SECTION_IFSET(CPU_FTR_SPE)
551#endif /* CONFIG_SPE */
552
553	lwz	r0,_CCR(r1)
554	mtcrf	0xFF,r0
555	/* r3-r12 are destroyed -- Cort */
556	REST_NVGPRS(r1)
557
558	lwz	r4,_NIP(r1)	/* Return to _switch caller in new task */
559	mtlr	r4
560	addi	r1,r1,INT_FRAME_SIZE
561	blr
562
563	.globl	fast_exception_return
564fast_exception_return:
565#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
566	andi.	r10,r9,MSR_RI		/* check for recoverable interrupt */
567	beq	1f			/* if not, we've got problems */
568#endif
569
5702:	REST_4GPRS(3, r11)
571	lwz	r10,_CCR(r11)
572	REST_GPR(1, r11)
573	mtcr	r10
574	lwz	r10,_LINK(r11)
575	mtlr	r10
576	REST_GPR(10, r11)
577	mtspr	SPRN_SRR1,r9
578	mtspr	SPRN_SRR0,r12
579	REST_GPR(9, r11)
580	REST_GPR(12, r11)
581	lwz	r11,GPR11(r11)
582	SYNC
583	RFI
584
585#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
586/* check if the exception happened in a restartable section */
5871:	lis	r3,exc_exit_restart_end@ha
588	addi	r3,r3,exc_exit_restart_end@l
589	cmplw	r12,r3
590	bge	3f
591	lis	r4,exc_exit_restart@ha
592	addi	r4,r4,exc_exit_restart@l
593	cmplw	r12,r4
594	blt	3f
595	lis	r3,fee_restarts@ha
596	tophys(r3,r3)
597	lwz	r5,fee_restarts@l(r3)
598	addi	r5,r5,1
599	stw	r5,fee_restarts@l(r3)
600	mr	r12,r4		/* restart at exc_exit_restart */
601	b	2b
602
603	.section .bss
604	.align	2
605fee_restarts:
606	.space	4
607	.previous
608
609/* aargh, a nonrecoverable interrupt, panic */
610/* aargh, we don't know which trap this is */
611/* but the 601 doesn't implement the RI bit, so assume it's OK */
6123:
613BEGIN_FTR_SECTION
614	b	2b
615END_FTR_SECTION_IFSET(CPU_FTR_601)
616	li	r10,-1
617	stw	r10,_TRAP(r11)
618	addi	r3,r1,STACK_FRAME_OVERHEAD
619	lis	r10,MSR_KERNEL@h
620	ori	r10,r10,MSR_KERNEL@l
621	bl	transfer_to_handler_full
622	.long	nonrecoverable_exception
623	.long	ret_from_except
624#endif
625
626	.globl	ret_from_except_full
627ret_from_except_full:
628	REST_NVGPRS(r1)
629	/* fall through */
630
631	.globl	ret_from_except
632ret_from_except:
633	/* Hard-disable interrupts so that current_thread_info()->flags
634	 * can't change between when we test it and when we return
635	 * from the interrupt. */
636	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
637	SYNC			/* Some chip revs have problems here... */
638	MTMSRD(r10)		/* disable interrupts */
639
640	lwz	r3,_MSR(r1)	/* Returning to user mode? */
641	andi.	r0,r3,MSR_PR
642	beq	resume_kernel
643
644user_exc_return:		/* r10 contains MSR_KERNEL here */
645	/* Check current_thread_info()->flags */
646	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT)
647	lwz	r9,TI_FLAGS(r9)
648	andi.	r0,r9,(_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NEED_RESCHED)
649	bne	do_work
650
651restore_user:
652#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
653	/* Check whether this process has its own DBCR0 value.  The single
654	   step bit tells us that dbcr0 should be loaded. */
655	lwz	r0,THREAD+THREAD_DBCR0(r2)
656	andis.	r10,r0,DBCR0_IC@h
657	bnel-	load_dbcr0
658#endif
659
660#ifdef CONFIG_PREEMPT
661	b	restore
662
663/* N.B. the only way to get here is from the beq following ret_from_except. */
664resume_kernel:
665	/* check current_thread_info->preempt_count */
666	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT)
667	lwz	r0,TI_PREEMPT(r9)
668	cmpwi	0,r0,0		/* if non-zero, just restore regs and return */
669	bne	restore
670	lwz	r0,TI_FLAGS(r9)
671	andi.	r0,r0,_TIF_NEED_RESCHED
672	beq+	restore
673	andi.	r0,r3,MSR_EE	/* interrupts off? */
674	beq	restore		/* don't schedule if so */
6751:	bl	preempt_schedule_irq
676	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT)
677	lwz	r3,TI_FLAGS(r9)
678	andi.	r0,r3,_TIF_NEED_RESCHED
679	bne-	1b
680#else
681resume_kernel:
682#endif /* CONFIG_PREEMPT */
683
684	/* interrupts are hard-disabled at this point */
685restore:
686	lwz	r0,GPR0(r1)
687	lwz	r2,GPR2(r1)
688	REST_4GPRS(3, r1)
689	REST_2GPRS(7, r1)
690
691	lwz	r10,_XER(r1)
692	lwz	r11,_CTR(r1)
693	mtspr	SPRN_XER,r10
694	mtctr	r11
695
696	PPC405_ERR77(0,r1)
697	stwcx.	r0,0,r1			/* to clear the reservation */
698
699#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
700	lwz	r9,_MSR(r1)
701	andi.	r10,r9,MSR_RI		/* check if this exception occurred */
702	beql	nonrecoverable		/* at a bad place (MSR:RI = 0) */
703
704	lwz	r10,_CCR(r1)
705	lwz	r11,_LINK(r1)
706	mtcrf	0xFF,r10
707	mtlr	r11
708
709	/*
710	 * Once we put values in SRR0 and SRR1, we are in a state
711	 * where exceptions are not recoverable, since taking an
712	 * exception will trash SRR0 and SRR1.  Therefore we clear the
713	 * MSR:RI bit to indicate this.  If we do take an exception,
714	 * we can't return to the point of the exception but we
715	 * can restart the exception exit path at the label
716	 * exc_exit_restart below.  -- paulus
717	 */
718	LOAD_MSR_KERNEL(r10,MSR_KERNEL & ~MSR_RI)
719	SYNC
720	MTMSRD(r10)		/* clear the RI bit */
721	.globl exc_exit_restart
722exc_exit_restart:
723	lwz	r9,_MSR(r1)
724	lwz	r12,_NIP(r1)
725	FIX_SRR1(r9,r10)
726	mtspr	SPRN_SRR0,r12
727	mtspr	SPRN_SRR1,r9
728	REST_4GPRS(9, r1)
729	lwz	r1,GPR1(r1)
730	.globl exc_exit_restart_end
731exc_exit_restart_end:
732	SYNC
733	RFI
734
735#else /* !(CONFIG_4xx || CONFIG_BOOKE) */
736	/*
737	 * This is a bit different on 4xx/Book-E because it doesn't have
738	 * the RI bit in the MSR.
739	 * The TLB miss handler checks if we have interrupted
740	 * the exception exit path and restarts it if so
741	 * (well maybe one day it will... :).
742	 */
743	lwz	r11,_LINK(r1)
744	mtlr	r11
745	lwz	r10,_CCR(r1)
746	mtcrf	0xff,r10
747	REST_2GPRS(9, r1)
748	.globl exc_exit_restart
749exc_exit_restart:
750	lwz	r11,_NIP(r1)
751	lwz	r12,_MSR(r1)
752exc_exit_start:
753	mtspr	SPRN_SRR0,r11
754	mtspr	SPRN_SRR1,r12
755	REST_2GPRS(11, r1)
756	lwz	r1,GPR1(r1)
757	.globl exc_exit_restart_end
758exc_exit_restart_end:
759	PPC405_ERR77_SYNC
760	rfi
761	b	.			/* prevent prefetch past rfi */
762
763/*
764 * Returning from a critical interrupt in user mode doesn't need
765 * to be any different from a normal exception.  For a critical
766 * interrupt in the kernel, we just return (without checking for
767 * preemption) since the interrupt may have happened at some crucial
768 * place (e.g. inside the TLB miss handler), and because we will be
769 * running with r1 pointing into critical_stack, not the current
770 * process's kernel stack (and therefore current_thread_info() will
771 * give the wrong answer).
772 * We have to restore various SPRs that may have been in use at the
773 * time of the critical interrupt.
774 *
775 */
776#ifdef CONFIG_40x
777#define PPC_40x_TURN_OFF_MSR_DR						    \
778	/* avoid any possible TLB misses here by turning off MSR.DR, we	    \
779	 * assume the instructions here are mapped by a pinned TLB entry */ \
780	li	r10,MSR_IR;						    \
781	mtmsr	r10;							    \
782	isync;								    \
783	tophys(r1, r1);
784#else
785#define PPC_40x_TURN_OFF_MSR_DR
786#endif
787
788#define RET_FROM_EXC_LEVEL(exc_lvl_srr0, exc_lvl_srr1, exc_lvl_rfi)	\
789	REST_NVGPRS(r1);						\
790	lwz	r3,_MSR(r1);						\
791	andi.	r3,r3,MSR_PR;						\
792	LOAD_MSR_KERNEL(r10,MSR_KERNEL);				\
793	bne	user_exc_return;					\
794	lwz	r0,GPR0(r1);						\
795	lwz	r2,GPR2(r1);						\
796	REST_4GPRS(3, r1);						\
797	REST_2GPRS(7, r1);						\
798	lwz	r10,_XER(r1);						\
799	lwz	r11,_CTR(r1);						\
800	mtspr	SPRN_XER,r10;						\
801	mtctr	r11;							\
802	PPC405_ERR77(0,r1);						\
803	stwcx.	r0,0,r1;		/* to clear the reservation */	\
804	lwz	r11,_LINK(r1);						\
805	mtlr	r11;							\
806	lwz	r10,_CCR(r1);						\
807	mtcrf	0xff,r10;						\
808	PPC_40x_TURN_OFF_MSR_DR;					\
809	lwz	r9,_DEAR(r1);						\
810	lwz	r10,_ESR(r1);						\
811	mtspr	SPRN_DEAR,r9;						\
812	mtspr	SPRN_ESR,r10;						\
813	lwz	r11,_NIP(r1);						\
814	lwz	r12,_MSR(r1);						\
815	mtspr	exc_lvl_srr0,r11;					\
816	mtspr	exc_lvl_srr1,r12;					\
817	lwz	r9,GPR9(r1);						\
818	lwz	r12,GPR12(r1);						\
819	lwz	r10,GPR10(r1);						\
820	lwz	r11,GPR11(r1);						\
821	lwz	r1,GPR1(r1);						\
822	PPC405_ERR77_SYNC;						\
823	exc_lvl_rfi;							\
824	b	.;		/* prevent prefetch past exc_lvl_rfi */
825
826	.globl	ret_from_crit_exc
827ret_from_crit_exc:
828	RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
829
830#ifdef CONFIG_BOOKE
831	.globl	ret_from_debug_exc
832ret_from_debug_exc:
833	RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, RFDI)
834
835	.globl	ret_from_mcheck_exc
836ret_from_mcheck_exc:
837	RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI)
838#endif /* CONFIG_BOOKE */
839
840/*
841 * Load the DBCR0 value for a task that is being ptraced,
842 * having first saved away the global DBCR0.  Note that r0
843 * has the dbcr0 value to set upon entry to this.
844 */
845load_dbcr0:
846	mfmsr	r10		/* first disable debug exceptions */
847	rlwinm	r10,r10,0,~MSR_DE
848	mtmsr	r10
849	isync
850	mfspr	r10,SPRN_DBCR0
851	lis	r11,global_dbcr0@ha
852	addi	r11,r11,global_dbcr0@l
853	stw	r10,0(r11)
854	mtspr	SPRN_DBCR0,r0
855	lwz	r10,4(r11)
856	addi	r10,r10,1
857	stw	r10,4(r11)
858	li	r11,-1
859	mtspr	SPRN_DBSR,r11	/* clear all pending debug events */
860	blr
861
862	.section .bss
863	.align	4
864global_dbcr0:
865	.space	8
866	.previous
867#endif /* !(CONFIG_4xx || CONFIG_BOOKE) */
868
869do_work:			/* r10 contains MSR_KERNEL here */
870	andi.	r0,r9,_TIF_NEED_RESCHED
871	beq	do_user_signal
872
873do_resched:			/* r10 contains MSR_KERNEL here */
874	ori	r10,r10,MSR_EE
875	SYNC
876	MTMSRD(r10)		/* hard-enable interrupts */
877	bl	schedule
878recheck:
879	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
880	SYNC
881	MTMSRD(r10)		/* disable interrupts */
882	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT)
883	lwz	r9,TI_FLAGS(r9)
884	andi.	r0,r9,_TIF_NEED_RESCHED
885	bne-	do_resched
886	andi.	r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
887	beq	restore_user
888do_user_signal:			/* r10 contains MSR_KERNEL here */
889	ori	r10,r10,MSR_EE
890	SYNC
891	MTMSRD(r10)		/* hard-enable interrupts */
892	/* save r13-r31 in the exception frame, if not already done */
893	lwz	r3,_TRAP(r1)
894	andi.	r0,r3,1
895	beq	2f
896	SAVE_NVGPRS(r1)
897	rlwinm	r3,r3,0,0,30
898	stw	r3,_TRAP(r1)
8992:	li	r3,0
900	addi	r4,r1,STACK_FRAME_OVERHEAD
901	bl	do_signal
902	REST_NVGPRS(r1)
903	b	recheck
904
905/*
906 * We come here when we are at the end of handling an exception
907 * that occurred at a place where taking an exception will lose
908 * state information, such as the contents of SRR0 and SRR1.
909 */
910nonrecoverable:
911	lis	r10,exc_exit_restart_end@ha
912	addi	r10,r10,exc_exit_restart_end@l
913	cmplw	r12,r10
914	bge	3f
915	lis	r11,exc_exit_restart@ha
916	addi	r11,r11,exc_exit_restart@l
917	cmplw	r12,r11
918	blt	3f
919	lis	r10,ee_restarts@ha
920	lwz	r12,ee_restarts@l(r10)
921	addi	r12,r12,1
922	stw	r12,ee_restarts@l(r10)
923	mr	r12,r11		/* restart at exc_exit_restart */
924	blr
9253:	/* OK, we can't recover, kill this process */
926	/* but the 601 doesn't implement the RI bit, so assume it's OK */
927BEGIN_FTR_SECTION
928	blr
929END_FTR_SECTION_IFSET(CPU_FTR_601)
930	lwz	r3,_TRAP(r1)
931	andi.	r0,r3,1
932	beq	4f
933	SAVE_NVGPRS(r1)
934	rlwinm	r3,r3,0,0,30
935	stw	r3,_TRAP(r1)
9364:	addi	r3,r1,STACK_FRAME_OVERHEAD
937	bl	nonrecoverable_exception
938	/* shouldn't return */
939	b	4b
940
941	.section .bss
942	.align	2
943ee_restarts:
944	.space	4
945	.previous
946
947/*
948 * PROM code for specific machines follows.  Put it
949 * here so it's easy to add arch-specific sections later.
950 * -- Cort
951 */
952#ifdef CONFIG_PPC_RTAS
953/*
954 * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
955 * called with the MMU off.
956 */
957_GLOBAL(enter_rtas)
958	stwu	r1,-INT_FRAME_SIZE(r1)
959	mflr	r0
960	stw	r0,INT_FRAME_SIZE+4(r1)
961	LOAD_REG_ADDR(r4, rtas)
962	lis	r6,1f@ha	/* physical return address for rtas */
963	addi	r6,r6,1f@l
964	tophys(r6,r6)
965	tophys(r7,r1)
966	lwz	r8,RTASENTRY(r4)
967	lwz	r4,RTASBASE(r4)
968	mfmsr	r9
969	stw	r9,8(r1)
970	LOAD_MSR_KERNEL(r0,MSR_KERNEL)
971	SYNC			/* disable interrupts so SRR0/1 */
972	MTMSRD(r0)		/* don't get trashed */
973	li	r9,MSR_KERNEL & ~(MSR_IR|MSR_DR)
974	mtlr	r6
975	mtspr	SPRN_SPRG2,r7
976	mtspr	SPRN_SRR0,r8
977	mtspr	SPRN_SRR1,r9
978	RFI
9791:	tophys(r9,r1)
980	lwz	r8,INT_FRAME_SIZE+4(r9)	/* get return address */
981	lwz	r9,8(r9)	/* original msr value */
982	FIX_SRR1(r9,r0)
983	addi	r1,r1,INT_FRAME_SIZE
984	li	r0,0
985	mtspr	SPRN_SPRG2,r0
986	mtspr	SPRN_SRR0,r8
987	mtspr	SPRN_SRR1,r9
988	RFI			/* return to caller */
989
990	.globl	machine_check_in_rtas
991machine_check_in_rtas:
992	twi	31,0,0
993	/* XXX load up BATs and panic */
994
995#endif /* CONFIG_PPC_RTAS */
996