1/*
2 * arch/ppc/kernel/head_44x.S
3 *
4 * Kernel execution entry point code.
5 *
6 *    Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
7 *      Initial PowerPC version.
8 *    Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
9 *      Rewritten for PReP
10 *    Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
11 *      Low-level exception handers, MMU support, and rewrite.
12 *    Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
13 *      PowerPC 8xx modifications.
14 *    Copyright (c) 1998-1999 TiVo, Inc.
15 *      PowerPC 403GCX modifications.
16 *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
17 *      PowerPC 403GCX/405GP modifications.
18 *    Copyright 2000 MontaVista Software Inc.
19 *	PPC405 modifications
20 *      PowerPC 403GCX/405GP modifications.
21 * 	Author: MontaVista Software, Inc.
22 *         	frank_rowand@mvista.com or source@mvista.com
23 * 	   	debbie_chu@mvista.com
24 *    Copyright 2002-2004 MontaVista Software, Inc.
25 *      PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org>
26 *
27 * This program is free software; you can redistribute  it and/or modify it
28 * under  the terms of  the GNU General Public License as published by the
29 * Free Software Foundation;  either version 2 of the  License, or (at your
30 * option) any later version.
31 */
32
33#include <linux/config.h>
34#include <asm/processor.h>
35#include <asm/page.h>
36#include <asm/mmu.h>
37#include <asm/pgtable.h>
38#include <asm/ibm44x.h>
39#include <asm/cputable.h>
40#include <asm/ppc_asm.h>
41#include "ppc_defs.h"
42
43/*
44 * Preprocessor Defines
45 */
46
47#define STND_EXC        0
48#define CRIT_EXC        1
49
50#ifdef CONFIG_440A
51#define MCHK_EXC	2
52#define __SPRN_MCSRR0	SPRN_MCSRR0
53#define __SPRN_MCSRR1	SPRN_MCSRR1
54#else
55#define MCHK_EXC	CRIT_EXC
56#define __SPRN_MCSRR0	SPRN_CSRR0
57#define __SPRN_MCSRR1	SPRN_CSRR1
58#endif
59
60/*
61 * Macros
62 */
63
64#define SET_IVOR(vector_number, vector_label)		\
65		li	r26,vector_label@l; 		\
66		mtspr	SPRN_IVOR##vector_number,r26;	\
67		sync
68
69/* As with the other PowerPC ports, it is expected that when code
70 * execution begins here, the following registers contain valid, yet
71 * optional, information:
72 *
73 *   r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
74 *   r4 - Starting address of the init RAM disk
75 *   r5 - Ending address of the init RAM disk
76 *   r6 - Start of kernel command line string (e.g. "mem=128")
77 *   r7 - End of kernel command line string
78 *
79 */
80	.text
81_GLOBAL(_stext)
82_GLOBAL(_start)
83	/*
84	 * Reserve a word at a fixed location to store the address
85	 * of abatron_pteptrs
86	 */
87	nop
88
89/*
90 * Save parameters we are passed
91 */
92	mr	r31,r3
93	mr	r30,r4
94	mr	r29,r5
95	mr	r28,r6
96	mr	r27,r7
97	li	r24,0		/* CPU number */
98
99/*
100 * Set up the initial MMU state
101 *
102 * We are still executing code at the virtual address
103 * mappings set by the firmware for the base of RAM.
104 *
105 * We first invalidate all TLB entries but the one
106 * we are running from.  We then load the KERNELBASE
107 * mappings so we can begin to use kernel addresses
108 * natively and so the interrupt vector locations are
109 * permanently pinned (necessary since Book E
110 * implementations always have translation enabled).
111 *
112 * TODO: Use the known TLB entry we are running from to
113 *	 determine which physical region we are located
114 *	 in.  This can be used to determine where in RAM
115 *	 (on a shared CPU system) or PCI memory space
116 *	 (on a DRAMless system) we are located.
117 *       For now, we assume a perfect world which means
118 *	 we are located at the base of DRAM (physical 0).
119 */
120
121/*
122 * Search TLB for entry that we are currently using.
123 * Invalidate all entries but the one we are using.
124 */
125	/* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */
126 	mfspr	r3,SPRN_MMUCR			/* Get MMUCR */
127	lis	r4,PPC44x_MMUCR_STS@h
128	ori	r4,r4,PPC44x_MMUCR_TID@l	/* Create mask */
129	andc	r3,r3,r4			/* Clear out TID/STS bits */
130	mfspr	r4,SPRN_PID			/* Get PID */
131	or	r3,r3,r4			/* Set TID bits */
132	mfmsr	r5				/* Get MSR */
133	andi.	r5,r5,MSR_IS@l			/* TS=1? */
134	beq	wmmucr				/* If not, leave STS=0 */
135	oris	r3,r3,PPC44x_MMUCR_STS@h	/* Set STS=1 */
136wmmucr:	mtspr	SPRN_MMUCR,r3			/* Put MMUCR */
137	sync
138
139	bl	invstr				/* Find our address */
140invstr:	mflr	r5				/* Make it accessible */
141	tlbsx	r23,0,r5			/* Find entry we are in */
142	li	r4,0				/* Start at TLB entry 0 */
143	li	r3,0				/* Set PAGEID inval value */
1441:	cmpw	r23,r4				/* Is this our entry? */
145	beq	skpinv				/* If so, skip the inval */
146	tlbwe	r3,r4,PPC44x_TLB_PAGEID		/* If not, inval the entry */
147skpinv:	addi	r4,r4,1				/* Increment */
148	cmpwi	r4,64				/* Are we done? */
149	bne	1b				/* If not, repeat */
150	isync					/* If so, context change */
151
152/*
153 * Configure and load pinned entries into TLB slots 62 and 63.
154 */
155
156	lis	r3,KERNELBASE@h		/* Load the kernel virtual address */
157	ori	r3,r3,KERNELBASE@l
158
159	/* Kernel is at the base of RAM */
160	li r4, 0			/* Load the kernel physical address */
161
162	/* Load the kernel PID = 0 */
163	li	r0,0
164	mtspr	SPRN_PID,r0
165	sync
166
167	/* Load the kernel TID  = 0 */
168	mfspr	r5,SPRN_MMUCR
169	lis	r6, PPC44x_MMUCR_TID@h
170	ori	r6,r6,PPC44x_MMUCR_TID@l
171	andc	r5,r5,r6
172	mtspr	SPRN_MMUCR,r5
173	sync
174
175 	/* pageid fields */
176	clrrwi	r3,r3,10		/* Mask off the effective page number */
177	ori	r3,r3,(PPC44x_TLB_VALID | PPC44x_TLB_PAGESZ(PPC44x_PAGESZ_256M))
178
179	/* xlat fields */
180	clrrwi	r4,r4,10		/* Mask off the real page number */
181					/* ERPN is 0 for first 4GB page */
182
183	/* attrib fields */
184	/* Added guarded bit to protect against speculative loads/stores */
185	li	r5,0
186	ori	r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
187
188        li      r0,62                    /* TLB slot 62 */
189
190	tlbwe	r3,r0,PPC44x_TLB_PAGEID	/* Load the pageid fields */
191	tlbwe	r4,r0,PPC44x_TLB_XLAT	/* Load the translation fields */
192	tlbwe	r5,r0,PPC44x_TLB_ATTRIB	/* Load the attrib/access fields */
193
194	/* Force context change */
195	mfmsr	r0
196	mtspr	SRR1, r0
197	lis	r0,3f@h
198	ori	r0,r0,3f@l
199	mtspr	SRR0,r0
200	sync
201	rfi
202
203	/* If necessary, invalidate original entry we used */
2043:	cmpwi	r23,62
205	beq	4f
206	li	r6,0
207	tlbwe   r6,r23,PPC44x_TLB_PAGEID
208	sync
209
2104:	ori	r3,r3,PPC44x_TLB_TS	/* TS = 1 */
211
212        li      r0,63                   /* TLB slot 63 */
213
214	tlbwe	r3,r0,PPC44x_TLB_PAGEID	/* Load the pageid fields */
215	tlbwe	r4,r0,PPC44x_TLB_XLAT	/* Load the translation fields */
216	tlbwe	r5,r0,PPC44x_TLB_ATTRIB	/* Load the attrib/access fields */
217
218#ifdef CONFIG_SERIAL_TEXT_DEBUG
219	/*
220	 * Add temporary UART mapping for early debug.  This
221	 * mapping must be identical to that used by the early
222	 * bootloader code since the same asm/serial.h parameters
223	 * are used for polled operation.
224	 */
225 	/* pageid fields */
226	lis	r3,0xe000
227	ori	r3,r3,(PPC44x_TLB_VALID | PPC44x_TLB_PAGESZ(PPC44x_PAGESZ_256M))
228
229	/* xlat fields */
230	lis	r4,0x4000		/* RPN is 0x40000000 */
231	ori	r4,r4,0x0001		/* ERPN is 1 for second 4GB page */
232
233	/* attrib fields */
234	li	r5,0
235	ori	r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G)
236
237        li      r0,60                    /* TLB slot 60 */
238
239	tlbwe	r3,r0,PPC44x_TLB_PAGEID	/* Load the pageid fields */
240	tlbwe	r4,r0,PPC44x_TLB_XLAT	/* Load the translation fields */
241	tlbwe	r5,r0,PPC44x_TLB_ATTRIB	/* Load the attrib/access fields */
242
243	ori	r3,r3,PPC44x_TLB_TS	/* Translation state 1 */
244
245        li      r0,61			/* TLB slot 61 */
246
247	tlbwe	r3,r0,PPC44x_TLB_PAGEID	/* Load the pageid fields */
248	tlbwe	r4,r0,PPC44x_TLB_XLAT	/* Load the translation fields */
249	tlbwe	r5,r0,PPC44x_TLB_ATTRIB	/* Load the attrib/access fields */
250#endif /* CONFIG_SERIAL_TEXT_DEBUG */
251
252	/* Force context change */
253	isync
254
255	/* Establish the interrupt vector offsets */
256	SET_IVOR(0,  CriticalInput);
257	SET_IVOR(1,  MachineCheck);
258	SET_IVOR(2,  DataStorage);
259	SET_IVOR(3,  InstructionStorage);
260	SET_IVOR(4,  ExternalInput);
261	SET_IVOR(5,  Alignment);
262	SET_IVOR(6,  Program);
263	SET_IVOR(7,  FloatingPointUnavailable);
264	SET_IVOR(8,  SystemCall);
265	SET_IVOR(9,  AuxillaryProcessorUnavailable);
266	SET_IVOR(10, Decrementer);
267	SET_IVOR(11, FixedIntervalTimer);
268	SET_IVOR(12, WatchdogTimer);
269	SET_IVOR(13, DataTLBError);
270	SET_IVOR(14, InstructionTLBError);
271	SET_IVOR(15, Debug);
272
273	/* Establish the interrupt vector base */
274	lis	r4,interrupt_base@h	/* IVPR only uses the high 16-bits */
275	mtspr	SPRN_IVPR,r4
276
277	/*
278	 * This is where the main kernel code starts.
279	 */
280
281	/* ptr to current */
282	lis	r2,init_task_union@h
283	ori	r2,r2,init_task_union@l
284
285	/* ptr to current thread */
286	addi	r4,r2,THREAD	/* init task's THREAD */
287	mtspr	SPRG3,r4
288	li	r3,0
289	mtspr	SPRG2,r3	/* 0 => r1 has kernel sp */
290
291	/* stack */
292	addi	r1,r2,TASK_UNION_SIZE
293	li	r0,0
294	stwu	r0,-STACK_FRAME_OVERHEAD(r1)
295
296	bl	early_init
297
298/*
299 * Decide what sort of machine this is and initialize the MMU.
300 */
301	mr	r3,r31
302	mr	r4,r30
303	mr	r5,r29
304	mr	r6,r28
305	mr	r7,r27
306	bl	machine_init
307	bl	MMU_init
308
309	/* Setup PTE pointers for the Abatron bdiGDB */
310	lis	r6, swapper_pg_dir@h
311	ori	r6, r6, swapper_pg_dir@l
312	lis	r5, abatron_pteptrs@h
313	ori	r5, r5, abatron_pteptrs@l
314	lis	r4, KERNELBASE@h
315	ori	r4, r4, KERNELBASE@l
316	stw	r5, 0(r4)	/* Save abatron_pteptrs at a fixed location */
317	stw	r6, 0(r5)
318
319	/* Let's move on */
320	lis	r4,start_kernel@h
321	ori	r4,r4,start_kernel@l
322	lis	r3,MSR_KERNEL@h
323	ori	r3,r3,MSR_KERNEL@l
324	mtspr	SRR0,r4
325	mtspr	SRR1,r3
326	rfi			/* change context and jump to start_kernel */
327
328/*
329 * Interrupt vector entry code
330 *
331 * The Book E MMUs are always on so we don't need to handle
332 * interrupts in real mode as with previous PPC processors. In
333 * this case we handle interrupts in the kernel virtual address
334 * space.
335 *
336 * Interrupt vectors are dynamically placed relative to the
337 * interrupt prefix as determined by the address of interrupt_base.
338 * The interrupt vectors offsets are programmed using the labels
339 * for each interrupt vector entry.
340 *
341 * Interrupt vectors must be aligned on a 16 byte boundary.
342 * We align on a 32 byte cache line boundary for good measure.
343 */
344
345#define COMMON_PROLOG                                                        \
3460:	mtspr	SPRN_SPRG0,r20;         /* We need r20, move it to SPRG0   */\
347	mtspr	SPRN_SPRG1,r21;         /* We need r21, move it to SPRG1   */\
348	mfcr	r20;                    /* We need the CR, move it to r20  */\
349	mfspr	r21,SPRN_SPRG2;         /* Exception stack to use          */\
350	cmpwi	cr0,r21,0;              /* From user mode or RTAS?         */\
351	bne	1f;                     /* Not RTAS, branch                */\
352	mr	r21, r1;                /* Move vka in r1 to r21           */\
353	subi	r21,r21,INT_FRAME_SIZE; /* Allocate an exception frame     */\
3541:	stw	r20,_CCR(r21);          /* Save CR on the stack            */\
355	stw	r22,GPR22(r21);         /* Save r22 on the stack           */\
356	stw	r23,GPR23(r21);         /* r23 Save on the stack           */\
357	mfspr	r20,SPRN_SPRG0;         /* Get r20 back out of SPRG0       */\
358	stw	r20,GPR20(r21);         /* Save r20 on the stack           */\
359	mfspr	r22,SPRN_SPRG1;         /* Get r21 back out of SPRG0       */\
360	stw	r22,GPR21(r21);         /* Save r21 on the stack           */\
361	mflr	r20;                                                         \
362	stw	r20,_LINK(r21);         /* Save LR on the stack            */\
363	mfctr	r22;                                                         \
364	stw	r22,_CTR(r21);          /* Save CTR on the stack           */\
365	mfspr	r20,XER;                                                     \
366	stw	r20,_XER(r21);          /* Save XER on the stack           */
367
368#define	COMMON_EPILOG							     \
369	stw	r0,GPR0(r21);		/* Save r0 on the stack		   */\
370	stw	r1,GPR1(r21);		/* Save r1 on the stack		   */\
371	stw	r2,GPR2(r21);		/* Save r2 on the stack		   */\
372	stw	r1,0(r21);						     \
373	mr	r1,r21;			/* Set-up new kernel stack pointer */\
374	SAVE_4GPRS(3, r21);		/* Save r3 through r6 on the stack */\
375	SAVE_GPR(7, r21);		/* Save r7 on the stack		   */
376
377#define	STND_EXCEPTION_PROLOG						     \
378	COMMON_PROLOG;							     \
379	mfspr	r22,SPRN_SRR0;		/* Faulting instruction address	   */\
380	lis	r20,MSR_WE@h;						     \
381	mfspr	r23,SPRN_SRR1;		/* MSR at the time of fault	   */\
382	andc	r23,r23,r20;		/* disable processor wait state    */\
383	COMMON_EPILOG;
384
385#define CRIT_EXCEPTION_PROLOG	                                             \
386	COMMON_PROLOG;	                                                     \
387	mfspr   r22,SPRN_CSRR0;         /* Faulting instruction address    */\
388	lis     r20,MSR_WE@h;                                                \
389	mfspr   r23,SPRN_CSRR1;         /* MSR at the time of fault        */\
390	andc    r23,r23,r20;            /* disable processor wait state    */\
391	COMMON_EPILOG;
392
393#define START_EXCEPTION(label) \
394        .align 5;              \
395label:
396
397#define FINISH_EXCEPTION(n, func)					     \
398	bl	transfer_to_handler;					     \
399	.long	func;							     \
400	.long	ret_from_except;					     \
401	.long	n
402
403#define STND_EXCEPTION(n, label, func)					     \
404	START_EXCEPTION(label)						     \
405	STND_EXCEPTION_PROLOG;						     \
406	addi	r3,r1,STACK_FRAME_OVERHEAD;				     \
407	li	r7,STND_EXC;						     \
408	li	r20,MSR_KERNEL;						     \
409	FINISH_EXCEPTION(n, func)
410
411#define	CRIT_EXCEPTION(n, label, func)					     \
412	START_EXCEPTION(label)						     \
413	CRIT_EXCEPTION_PROLOG;						     \
414	addi	r3,r1,STACK_FRAME_OVERHEAD;				     \
415	li	r7,CRIT_EXC;						     \
416	li	r20,MSR_KERNEL;						     \
417	FINISH_EXCEPTION(n, func)
418
419interrupt_base:
420
421	/* Critical Input Interrupt */
422	CRIT_EXCEPTION(0x100, CriticalInput,UnknownException);
423
424	/* Machine Check Interrupt */
425	/* TODO: provide bus error register status */
426	START_EXCEPTION(MachineCheck)
427	COMMON_PROLOG;
428	mfspr   r22,__SPRN_MCSRR0       /* Faulting instruction address    */
429	lis     r20,MSR_WE@h
430	mfspr   r23,__SPRN_MCSRR1       /* MSR at the time of fault        */
431	andc    r23,r23,r20             /* disable processor wait state    */
432	COMMON_EPILOG;
433#ifdef CONFIG_440A
434	lis	r20,MCSR_MCS@h
435	mfspr	r4,SPRN_MCSR		/* We may want to access original
436					   MCSR as arg2 in the future. --ebs */
437	mtspr	SPRN_MCSR,r20		/* Clear Machine Check Summary field */
438#endif
439	mfspr	r5,SPRN_ESR		/* Grab the ESR, save it */
440	stw	r5,_ESR(r21)
441	addi	r3,r1,STACK_FRAME_OVERHEAD
442	li	r7,MCHK_EXC
443	li	r20,MSR_KERNEL
444	FINISH_EXCEPTION(0x200, MachineCheckException)
445
446	/* Data Storage Interrupt */
447	START_EXCEPTION(DataStorage)
448	mtspr	SPRG0, r20		/* Save some working registers */
449	mtspr	SPRG1, r21
450	mtspr	SPRG4W, r22
451	mtspr	SPRG5W, r23
452	mtspr	SPRG6W, r24
453	mfcr	r21
454	mtspr	SPRG7W, r21
455
456	/*
457	 * Check if it was a store fault, if not then bail
458	 * because a user tried to access a kernel or
459	 * read-protected page.  Otherwise, get the
460	 * offending address and handle it.
461	 */
462	mfspr	r20, SPRN_ESR
463	andis.	r20, r20, ESR_DST@h
464	beq	2f
465
466	mfspr	r20, SPRN_DEAR		/* Get faulting address */
467
468	/* If we are faulting a kernel address, we have to use the
469	 * kernel page tables.
470	 */
471	andis.	r21, r20, 0x8000
472	beq	3f
473	lis	r21, swapper_pg_dir@h
474	ori	r21, r21, swapper_pg_dir@l
475
476	mfspr   r22,SPRN_MMUCR          /* Set TID to 0 */
477	li      r23,PPC44x_MMUCR_TID@l
478	andc    r22,r22,r23
479	mtspr   SPRN_MMUCR,r22
480
481	b	4f
482
483	/* Get the PGD for the current thread */
4843:
485	mfspr	r21,SPRG3
486	lwz	r21,PGDIR(r21)
487
488	/* Load MMUCR with our PID and STS=<current TS> */
489	mfspr	r22,SPRN_MMUCR			/* Get MMUCR */
490	lis     r23,PPC44x_MMUCR_STS@h
491	ori     r23,r23,PPC44x_MMUCR_TID@l      /* Create mask */
492	andc    r22,r22,r23                     /* Clear out TID/STS bits */
493	mfspr   r23,SPRN_PID                    /* Get PID */
494	or      r22,r22,r23			/* Set TID bits */
495	mfspr	r24,SPRN_SRR1			/* Get SRR1 */
496	andi.	r24,r24,MSR_IS@l		/* TS=1? */
497	beq	4f				/* If not, leave STS=0 */
498	oris	r22,r22,PPC44x_MMUCR_STS@h	/* Set STS=1 */
499	mtspr   SPRN_MMUCR,r22
5004:
501	rlwinm  r22, r20, 13, 19, 29    /* Compute pgdir/pmd offset */
502	lwzx    r21, r22, r21           /* Get pgd/pmd entry */
503	rlwinm. r22, r21, 0, 0, 20      /* Extract pt base address */
504	beq     2f                      /* Bail if no table */
505
506	rlwimi  r22, r20, 23, 20, 28    /* Compute pte address */
507	lwz     r21, 4(r22)             /* Get pte entry */
508
509	andi.	r23, r21, _PAGE_RW	/* Is it writeable? */
510	beq	2f			/* Bail if not */
511
512	/* Update 'changed'.
513	*/
514	ori	r21, r21, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
515	stw	r21, 4(r22)		/* Update Linux page table */
516
517	/* FIXME: Staticly setting some permissions */
518	li	r23, 0x003f		/* Set UX,UW,UR,SX,SW,SR */
519	andi.	r21,r21,0xffff		/* Clear MS 16 bits */
520	/* FIXME: Force attributes */
521	ori	r21,r21, 0x0100		/* Set G */
522	/* FIXME: Already set in PTE */
523	rlwimi	r21,r23,0,26,31		/* Insert static perms */
524
525	lis	r23,0xffff
526	ori	r23,r23,0x0fff			/* Set U0-U3 mask */
527	and	r21,r21,r23			/* Clear U0-U3 */
528
529	/* find the TLB index that caused the fault.  It has to be here. */
530	tlbsx	r24, 0, r20
531
532	tlbwe	r21, r24, PPC44x_TLB_ATTRIB		/* Write ATTRIB */
533
534	/* Done...restore registers and get out of here.
535	*/
536	mfspr	r21, SPRG7R
537	mtcr	r21
538	mfspr	r24, SPRG6R
539	mfspr	r23, SPRG5R
540	mfspr	r22, SPRG4R
541
542	mfspr	r21, SPRG1
543	mfspr	r20, SPRG0
544	rfi			/* Force context change */
545
5462:
547	/*
548	 * The bailout.  Restore registers to pre-exception conditions
549	 * and call the heavyweights to help us out.
550	 */
551	mfspr	r21, SPRG7R
552	mtcr	r21
553	mfspr	r24, SPRG6R
554	mfspr	r23, SPRG5R
555	mfspr	r22, SPRG4R
556
557	mfspr	r21, SPRG1
558	mfspr	r20, SPRG0
559	b	data_access
560
561	/* Instruction Storage Interrupt */
562	START_EXCEPTION(InstructionStorage)
563	STND_EXCEPTION_PROLOG
564	mfspr	r5,SPRN_ESR		/* Grab the ESR, save it */
565	stw	r5,_ESR(r21)
566	mr      r4,r22                  /* Pass SRR0 as arg2 */
567	li      r5,0                    /* Pass zero as arg3 */
568	addi    r3,r1,STACK_FRAME_OVERHEAD
569	li      r7,STND_EXC
570	li      r20,MSR_KERNEL
571	rlwimi  r20,r23,0,16,16         /* Copy EE bit from the saved MSR */
572	FINISH_EXCEPTION(0x400, do_page_fault)/* do_page_fault(regs, SRR0, SRR1) */
573
574	/* External Input Interrupt */
575	START_EXCEPTION(ExternalInput)
576	STND_EXCEPTION_PROLOG
577	addi    r3,r1,STACK_FRAME_OVERHEAD
578	li      r7,STND_EXC
579	li      r20,MSR_KERNEL
580	li      r4,0
581	bl      transfer_to_handler
582_GLOBAL(do_IRQ_intercept)
583	.long   do_IRQ
584	.long   ret_from_intercept
585	.long	0x500
586
587	/* Alignment Interrupt */
588	START_EXCEPTION(Alignment)
589	STND_EXCEPTION_PROLOG
590	mfspr   r4,SPRN_DEAR            /* Grab the DEAR and save it */
591	stw     r4,_DEAR(r21)
592	addi    r3,r1,STACK_FRAME_OVERHEAD
593	li      r7,STND_EXC
594	li      r20,MSR_KERNEL
595	rlwimi  r20,r23,0,16,16         /* Copy EE bit from the saved MSR */
596	FINISH_EXCEPTION(0x600, AlignmentException)
597
598	/* Program Interrupt */
599	START_EXCEPTION(Program)
600	STND_EXCEPTION_PROLOG
601	mfspr	r4,SPRN_ESR		/* Grab the ESR, save it */
602	stw	r4,_ESR(r21)
603	addi    r3,r1,STACK_FRAME_OVERHEAD
604	li      r7,STND_EXC
605	li      r20,MSR_KERNEL
606	rlwimi  r20,r23,0,16,16         /* Copy EE bit from the saved MSR */
607	FINISH_EXCEPTION(0x700, ProgramCheckException)
608
609	/* Floating Point Unavailable Interrupt */
610	STND_EXCEPTION(0x2010, FloatingPointUnavailable,UnknownException);
611
612	/* System Call Interrupt */
613	START_EXCEPTION(SystemCall)
614	STND_EXCEPTION_PROLOG
615	stw	r3,ORIG_GPR3(r21)
616	li	r7,STND_EXC
617	li	r20,MSR_KERNEL
618	rlwimi	r20,r23,0,16,16		/* Copy EE bit from the saved MSR */
619	FINISH_EXCEPTION(0xc00, DoSyscall)
620
621	/* Auxillary Processor Unavailable */
622	STND_EXCEPTION(0x2020, AuxillaryProcessorUnavailable,UnknownException);
623
624	/* Decrementer Interrupt */
625	START_EXCEPTION(Decrementer)
626	STND_EXCEPTION_PROLOG
627	lis     r0,TSR_DIS@h            /* Setup the DEC interrupt mask */
628	mtspr   SPRN_TSR,r0            /* Clear the DEC interrupt */
629	addi    r3,r1,STACK_FRAME_OVERHEAD
630	li      r7,STND_EXC
631	li      r20,MSR_KERNEL
632	bl      transfer_to_handler
633_GLOBAL(timer_interrupt_intercept)
634	.long   timer_interrupt
635	.long   ret_from_intercept
636	.long	0x1000
637
638	/* Fixed Internal Timer Interrupt */
639	/* TODO: Add FIT support */
640	STND_EXCEPTION(0x1010, FixedIntervalTimer,UnknownException);
641
642	/* Watchdog Timer Interrupt */
643	/* TODO: Add watchdog support */
644	CRIT_EXCEPTION(0x1020, WatchdogTimer,UnknownException);
645
646	/* Data TLB Error Interrupt */
647	START_EXCEPTION(DataTLBError)
648	mtspr	SPRG0, r20		/* Save some working registers */
649	mtspr	SPRG1, r21
650	mtspr	SPRG4W, r22
651	mtspr	SPRG5W, r23
652	mtspr	SPRG6W, r24
653	mfcr	r21
654	mtspr	SPRG7W, r21
655	mfspr	r20, SPRN_DEAR		/* Get faulting address */
656
657	/* If we are faulting a kernel address, we have to use the
658	 * kernel page tables.
659	 */
660	andis.	r21, r20, 0x8000
661	beq	3f
662	lis	r21, swapper_pg_dir@h
663	ori	r21, r21, swapper_pg_dir@l
664
665	mfspr	r22,SPRN_MMUCR		/* Set TID to 0 */
666	li	r23,PPC44x_MMUCR_TID@l
667	andc	r22,r22,r23
668	mtspr	SPRN_MMUCR,r22
669
670	b	4f
671
672	/* Get the PGD for the current thread */
6733:
674	mfspr	r21,SPRG3
675	lwz	r21,PGDIR(r21)
676
677	/* Load PID into MMUCR TID */
678	li      r23,PPC44x_MMUCR_TID@l       	 /* Create mask */
679	andc    r22,r22,r23                      /* Clear out TID/STS bits */
680	mfspr   r23,SPRN_PID                     /* Get PID */
681	or      r22,r22,r23
682	mtspr	SPRN_MMUCR,r22
6834:
684	rlwinm 	r22, r20, 13, 19, 29	/* Compute pgdir/pmd offset */
685	lwzx	r21, r22, r21		/* Get pgd/pmd entry */
686	rlwinm.	r22, r21, 0, 0, 20	/* Extract pt base address */
687	beq	2f			/* Bail if no table */
688
689	rlwimi	r22, r20, 23, 20, 28	/* Compute pte address */
690	lwz	r21, 4(r22)		/* Get pte entry */
691	andi.	r23, r21, _PAGE_PRESENT	/* Is the page present? */
692	beq	2f			/* Bail if not present */
693
694	ori	r21, r21, _PAGE_ACCESSED
695	stw	r21, 4(r22)
696
697	 /* Jump to common tlb load */
698	b	finish_tlb_load
699
7002:
701	/* The bailout.  Restore registers to pre-exception conditions
702	 * and call the heavyweights to help us out.
703	 */
704	mfspr	r21, SPRG7R
705	mtcr	r21
706	mfspr	r24, SPRG6R
707	mfspr	r23, SPRG5R
708	mfspr	r22, SPRG4R
709	mfspr	r21, SPRG1
710	mfspr	r20, SPRG0
711	b	data_access
712
713	/* Instruction TLB Error Interrupt */
714	/*
715	 * Nearly the same as above, except we get our
716	 * information from different registers and bailout
717	 * to a different point.
718	 */
719	START_EXCEPTION(InstructionTLBError)
720	mtspr	SPRG0, r20		/* Save some working registers */
721	mtspr	SPRG1, r21
722	mtspr	SPRG4W, r22
723	mtspr	SPRG5W, r23
724	mtspr	SPRG6W, r24
725	mfcr	r21
726	mtspr	SPRG7W, r21
727	mfspr	r20, SRR0		/* Get faulting address */
728
729	/* If we are faulting a kernel address, we have to use the
730	 * kernel page tables.
731	 */
732	andis.	r21, r20, 0x8000
733	beq	3f
734	lis	r21, swapper_pg_dir@h
735	ori	r21, r21, swapper_pg_dir@l
736
737	mfspr	r22,SPRN_MMUCR		/* Set TID to 0 */
738	li	r23,PPC44x_MMUCR_TID@l
739	andc	r22,r22,r23
740	mtspr	SPRN_MMUCR,r22
741
742	b	4f
743
744	/* Get the PGD for the current thread */
7453:
746	mfspr	r21,SPRG3
747	lwz	r21,PGDIR(r21)
748
749	/* Load PID into MMUCR TID */
750	li      r23,PPC44x_MMUCR_TID@l       	 /* Create mask */
751	andc    r22,r23,r23                      /* Clear out TID/STS bits */
752	mfspr   r23,SPRN_PID                     /* Get PID */
753	or      r22,r22,r23
754	mtspr	SPRN_MMUCR,r22
755
7564:
757	rlwinm	r22, r20, 13, 19, 29	/* Compute pgdir/pmd offset */
758	lwzx	r21, r22, r21		/* Get pgd/pmd entry */
759	rlwinm.	r22, r21, 0, 0, 20	/* Extract pt base address */
760	beq	2f			/* Bail if no table */
761
762	rlwimi	r22, r20, 23, 20, 28	/* Compute pte address */
763	lwz	r21, 4(r22)		/* Get pte entry */
764	andi.	r23, r21, _PAGE_PRESENT	/* Is the page present? */
765	beq	2f			/* Bail if not present */
766
767	ori	r21, r21, _PAGE_ACCESSED
768	stw	r21, 4(r22)
769
770	/* Jump to common TLB load point */
771	b	finish_tlb_load
772
7732:
774	/* The bailout.  Restore registers to pre-exception conditions
775	 * and call the heavyweights to help us out.
776	 */
777	mfspr	r21, SPRG7R
778	mtcr	r21
779	mfspr	r24, SPRG6R
780	mfspr	r23, SPRG5R
781	mfspr	r22, SPRG4R
782	mfspr	r21, SPRG1
783	mfspr	r20, SPRG0
784	b	InstructionStorage
785
786/* Check for a single step debug exception while in an exception
787 * handler before state has been saved.  This is to catch the case
788 * where an instruction that we are trying to single step causes
789 * an exception (eg ITLB/DTLB miss) and thus the first instruction of
790 * the exception handler generates a single step debug exception.
791 *
792 * If we get a debug trap on the first instruction of an exception handler,
793 * we reset the MSR_DE in the _exception handlers_ MSR (the debug trap is
794 * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
795 * The exception handler was handling a non-critical interrupt, so it will
796 * save (and later restore) the MSR via SPRN_SRR1, which will still have
797 * the MSR_DE bit set.
798 */
799	/* Debug Interrupt */
800	START_EXCEPTION(Debug)
801	/* This first instruction was already executed by the exception
802	 * handler and must be the first instruction of every exception
803	 * handler.
804	 */
805	mtspr	SPRN_SPRG0,r20		/* Save some working registers... */
806	mtspr	SPRN_SPRG1,r21
807	mtspr	SPRN_SPRG4W,r22
808	mfcr	r20			/* ..and the cr because we change it */
809
810	mfspr   r21,SPRN_CSRR1		/* MSR at the time of fault */
811	andi.   r21,r21,MSR_PR
812	bne+    2f			/* trapped from problem state */
813
814	mfspr   r21,SPRN_CSRR0		/* Faulting instruction address */
815	lis	r22, KERNELBASE@h
816	ori	r22, r22, KERNELBASE@l
817	cmplw   r21,r22
818	blt+    2f			/* addr below exception vectors */
819
820	lis	r22, Debug@h
821	ori	r22, r22, Debug@l
822	cmplw   r21,r22
823	bgt+    2f			/* addr above TLB exception vectors */
824
825	lis     r21,DBSR_IC@h           /* Remove the trap status */
826	mtspr   SPRN_DBSR,r21
827
828	mfspr	r21,SPRN_CSRR1
829	rlwinm	r21,r21,0,23,21		/* clear MSR_DE */
830	mtspr	SPRN_CSRR1, r21		/* restore MSR at rcfi without DE */
831
832	mtcrf   0xff,r20                /* restore registers */
833	mfspr	r22,SPRN_SPRG4R
834	mfspr   r21,SPRN_SPRG1
835	mfspr   r20,SPRN_SPRG0
836
837	sync
838	rfci                            /* return to the exception handler  */
839	b	.			/* prevent prefetch past rfci */
840
8412:
842	mtcrf   0xff,r20                /* restore registers */
843	mfspr	r22,SPRN_SPRG4R
844	mfspr   r21,SPRN_SPRG1
845	mfspr   r20,SPRN_SPRG0
846
847	CRIT_EXCEPTION_PROLOG
848	addi	r3,r1,STACK_FRAME_OVERHEAD
849	li	r7,CRIT_EXC;
850        li      r20,MSR_KERNEL
851	FINISH_EXCEPTION(0x2000, DebugException)
852
853/*
854 * Local functions
855 */
856
857	/*
858	 * Data TLB exceptions will bail out to this point
859	 * if they can't resolve the lightweight TLB fault.
860	 */
861data_access:
862	STND_EXCEPTION_PROLOG
863	mfspr	r5,SPRN_ESR		/* Grab the ESR, save it, pass arg3 */
864	stw	r5,_ESR(r21)
865	mfspr	r4,SPRN_DEAR		/* Grab the DEAR, save it, pass arg2 */
866	stw	r4,_DEAR(r21)
867	addi	r3,r1,STACK_FRAME_OVERHEAD
868	li	r7,STND_EXC
869	li	r20,MSR_KERNEL
870	rlwimi	r20,r23,0,16,16		/* Copy EE bit from the saved MSR */
871	FINISH_EXCEPTION(0x800, do_page_fault) /* do_page_fault(regs, ESR, DEAR) */
872
873/*
874 * Both the instruction and data TLB miss get to this
875 * point to load the TLB.
876 * 	r20 - EA of fault
877 * 	r21 - available to use
878 *	r22 - Pointer to the 64-bit PTE
879 *	r23 - available to use
880 *	r24 - available to use
881 *	MMUCR - loaded with proper value when we get here
882 *	Upon exit, we reload everything and RFI.
883 */
884finish_tlb_load:
885	/*
886	 * We set execute, because we don't have the granularity to
887	 * properly set this at the page level (Linux problem).
888	 * If shared is set, we cause a zero PID->TID load.
889	 * Many of these bits are software only.  Bits we don't set
890	 * here we (properly should) assume have the appropriate value.
891	 */
892
893	/* Load the next available TLB index */
894	lis	r23, tlb_44x_index@h
895	ori	r23, r23, tlb_44x_index@l
896	lwz	r24, 0(r23)
897	/* Load the TLB high watermark */
898	lis	r23, tlb_44x_hwater@h
899	ori	r23, r23, tlb_44x_hwater@l
900	lwz	r21, 0(r23)
901
902
903	/* Increment, rollover, and store TLB index */
904	addi	r24, r24, 1
905	cmpw	0, r24, r21		/* reserve entries 62-63 for kernel */
906	ble	7f
907	li	r24, 0
9087:
909	/* Load the next available TLB index */
910	lis     r23, tlb_44x_index@h
911	ori     r23, r23, tlb_44x_index@l
912	stw	r24, 0(r23)
913
9146:
915	lwz	r23, 0(r22)			/* Get MS word of PTE */
916	lwz	r21, 4(r22)			/* Get LS word of PTE */
917	rlwimi	r23, r21, 0, 0 , 19		/* Insert RPN */
918	tlbwe	r23, r24, PPC44x_TLB_XLAT	/* Write XLAT */
919
920	/*
921	 * Create PAGEID. This is the faulting address plus
922	 * a set of static bits. The static bits are page
923	 * size and valid. Bits 20  and 21 should be zero
924	 * for a page size of 4KB.
925	 */
926	li	r22, 0x0210			/* Set size and valid */
927	mfspr	r23, SPRN_SRR1			/* Get SRR1 */
928	andi.	r23, r23, MSR_IS@l
929	beq	7f
930	ori	r22, r22, PPC44x_TLB_TS@l	/* Set TS=1 */
9317:	rlwimi	r20, r22, 0, 20, 31		/* Insert statics */
932	tlbwe	r20, r24, PPC44x_TLB_PAGEID	/* Write PAGEID */
933
934	/* FIXME: Staticly setting some permissions */
935	li	r23, 0x002d			/* Set UX,UR,SX,SR */
936	andi.	r21, r21, 0xffff		/* Clear MS 16 bits */
937	andi.	r22, r21, 0x0002		/* _PAGE_HWWRITE? */
938	beq	8f
939	ori	r23, r23, 0x0002		/* Set SW */
940	/* FIXME: Force attributes */
9418:	ori	r21, r21, 0x0100		/* Set G */
942	/* FIXME: Already set in PTE */
943	rlwimi	r21, r23, 0, 26, 31		/* Insert static perms */
944
945	lis	r23,0xffff
946	ori	r23,r23,0x0fff			/* Set U0-U3 mask */
947	and	r21,r21,r23			/* Clear U0-U3 */
948	tlbwe	r21, r24, PPC44x_TLB_ATTRIB	/* Write ATTRIB */
949
950	/* Done...restore registers and get out of here.
951	*/
952	mfspr	r21, SPRG7R
953	mtcr	r21
954	mfspr	r24, SPRG6R
955	mfspr	r23, SPRG5R
956	mfspr	r22, SPRG4R
957	mfspr	r21, SPRG1
958	mfspr	r20, SPRG0
959	rfi					/* Force context change */
960
961/*
962 * Global functions
963 */
964
965/*
966 * extern void giveup_altivec(struct task_struct *prev)
967 *
968 * The 44x core does not have an AltiVec unit.
969 */
970_GLOBAL(giveup_altivec)
971	blr
972
973/*
974 * extern void giveup_fpu(struct task_struct *prev)
975 *
976 * The 44x core does not have an FPU.
977 */
978_GLOBAL(giveup_fpu)
979	blr
980
981/*
982 * extern void abort(void)
983 *
984 * At present, this routine just applies a system reset.
985 */
986_GLOBAL(abort)
987        mfspr   r13,SPRN_DBCR0
988        oris    r13,r13,DBCR_RST(DBCR_RST_SYSTEM)@h
989        mtspr   SPRN_DBCR0,r13
990
991_GLOBAL(set_context)
992
993#ifdef CONFIG_BDI_SWITCH
994	/* Context switch the PTE pointer for the Abatron BDI2000.
995	 * The PGDIR is the second parameter.
996	 */
997	lis	r5, abatron_pteptrs@h
998	ori	r5, r5, abatron_pteptrs@l
999	stw	r4, 0x4(r5)
1000#endif
1001	mtspr	SPRN_PID,r3
1002	isync			/* Force context change */
1003	blr
1004
1005/*
1006 * This code finishes saving the registers to the exception frame
1007 * and jumps to the appropriate handler for the exception, turning
1008 * on address translation.
1009 */
1010_GLOBAL(transfer_to_handler)
1011	stw	r22,_NIP(r21)		/* Save the faulting IP on the stack */
1012	stw	r23,_MSR(r21)		/* Save the exception MSR on stack */
1013	SAVE_4GPRS(8, r21)		/* Save r8 through r11 on the stack */
1014	SAVE_8GPRS(12, r21)		/* Save r12 through r19 on the stack */
1015	SAVE_8GPRS(24, r21)		/* Save r24 through r31 on the stack */
1016	andi.	r23,r23,MSR_PR		/* Is this from user space? */
1017	mfspr	r23,SPRN_SPRG3		/* If from user, fix up THREAD.regs */
1018	beq	2f			/* No, it is from the kernel; branch. */
1019	mfspr   r24,SPRN_DBCR0
1020	stw     r24,THREAD_DBCR0(r23)	/* Save Debug Control in thread_struct */
1021	addi	r24,r1,STACK_FRAME_OVERHEAD
1022	stw	r24,PT_REGS(r23)
10232:	addi	r2,r23,-THREAD		/* Set r2 to current thread */
1024	mflr	r23
1025	lwz	r24,8(r23)		/* Emulate classic PPC vectors */
1026	stw	r24,TRAP(r21)
1027	li	r22,RESULT
1028	/* No need to put an erratum #77 workaround here
1029		because interrupts are currently disabled */
1030	stwcx.	r22,r22,r21		/* Clear the reservation */
1031	li	r22,0
1032	stw	r22,RESULT(r21)
1033	mtspr	SPRN_SPRG2,r22		/* r1 is now the kernel stack pointer */
1034	addi	r24,r2,TASK_STRUCT_SIZE	/* Check for kernel stack overflow */
1035	cmplw	cr0,r1,r2
1036	cmplw	cr1,r1,r24
1037	crand	cr1,cr1,cr4
1038	bgt-	stack_ovf		/* If r2 < r1 < r2 + TASK_STRUCT_SIZE */
1039	lwz	r24,0(r23)		/* Virtual address of the handler */
1040	lwz	r23,4(r23)		/* Handler return pointer */
1041	cmpwi	cr0,r7,STND_EXC		/* What type of exception is this? */
1042	bne	3f			/* It is a critical/machine check exception... */
1043
1044	/* Standard exception jump path
1045	*/
1046
1047	/* We have to recover r7 from the register save stack.
1048	 * It was used to indicate standard/critical exception.  In
1049	 * the case of a standard exception that is the system call
1050	 * trap, it may have originally contained one of the syscall
1051	 * parameters and we have to get it back now.
1052	 */
1053	lwz	r7,GPR7(r21)
1054	mtspr	SPRN_SRR0,r24		/* Set up the instruction pointer */
1055	mtspr	SPRN_SRR1,r20		/* Set up the machine state register */
1056	mtlr	r23			/* Set up the return pointer */
1057	SYNC
1058	rfi
1059
1060	/* Critical/Machine check exception jump path
1061	*/
10623:	cmpwi	r7,CRIT_EXC		/* Critical or machine check ? */
1063	mtlr	r23			/* Set up the return pointer */
1064	bne	4f
1065	mtspr	SPRN_CSRR0,r24		/* Set up the instruction pointer */
1066	mtspr	SPRN_CSRR1,r20		/* Set up the machine state register */
1067	SYNC
1068	rfci
1069
10704:	mtspr	SPRN_MCSRR0,r24		/* Set up the instruction pointer */
1071	mtspr	SPRN_MCSRR1,r20		/* Set up the machine state register */
1072	SYNC
1073	RFMCI
1074
1075/* On kernel stack overlow, load up an initial stack pointer and call
1076 * StackOverflow(regs), which should NOT return.
1077 */
1078
1079stack_ovf:
1080	addi	r3,r1,STACK_FRAME_OVERHEAD
1081	lis	r1,init_task_union@ha
1082	addi	r1,r1,init_task_union@l
1083	addi	r1,r1,TASK_UNION_SIZE - STACK_FRAME_OVERHEAD
1084	lis	r24,StackOverflow@ha
1085	addi	r24,r24,StackOverflow@l
1086	li	r20,MSR_KERNEL
1087	mtspr	SPRN_SRR0,r24
1088	mtspr	SPRN_SRR1,r20
1089	SYNC
1090	rfi
1091
1092/*
1093 * We put a few things here that have to be page-aligned. This stuff
1094 * goes at the beginning of the data segment, which is page-aligned.
1095 */
1096	.data
1097_GLOBAL(sdata)
1098_GLOBAL(empty_zero_page)
1099	.space	4096
1100
1101/*
1102 * To support >32-bit physical addresses, we use an 8KB pgdir.
1103 */
1104_GLOBAL(swapper_pg_dir)
1105	.space	8192
1106
1107/*
1108 * This space gets a copy of optional info passed to us by the bootstrap
1109 * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
1110 */
1111_GLOBAL(cmd_line)
1112	.space	512
1113
1114/*
1115 * Room for two PTE pointers, usually the kernel and current user pointers
1116 * to their respective root page table.
1117 */
1118abatron_pteptrs:
1119	.space	8
1120