xref: /openbmc/linux/arch/powerpc/kernel/head_44x.S (revision 87c2ce3b)
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-2005 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/ibm4xx.h>
39#include <asm/ibm44x.h>
40#include <asm/cputable.h>
41#include <asm/thread_info.h>
42#include <asm/ppc_asm.h>
43#include <asm/asm-offsets.h>
44#include "head_booke.h"
45
46
47/* As with the other PowerPC ports, it is expected that when code
48 * execution begins here, the following registers contain valid, yet
49 * optional, information:
50 *
51 *   r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
52 *   r4 - Starting address of the init RAM disk
53 *   r5 - Ending address of the init RAM disk
54 *   r6 - Start of kernel command line string (e.g. "mem=128")
55 *   r7 - End of kernel command line string
56 *
57 */
58	.text
59_GLOBAL(_stext)
60_GLOBAL(_start)
61	/*
62	 * Reserve a word at a fixed location to store the address
63	 * of abatron_pteptrs
64	 */
65	nop
66/*
67 * Save parameters we are passed
68 */
69	mr	r31,r3
70	mr	r30,r4
71	mr	r29,r5
72	mr	r28,r6
73	mr	r27,r7
74	li	r24,0		/* CPU number */
75
76/*
77 * Set up the initial MMU state
78 *
79 * We are still executing code at the virtual address
80 * mappings set by the firmware for the base of RAM.
81 *
82 * We first invalidate all TLB entries but the one
83 * we are running from.  We then load the KERNELBASE
84 * mappings so we can begin to use kernel addresses
85 * natively and so the interrupt vector locations are
86 * permanently pinned (necessary since Book E
87 * implementations always have translation enabled).
88 *
89 * TODO: Use the known TLB entry we are running from to
90 *	 determine which physical region we are located
91 *	 in.  This can be used to determine where in RAM
92 *	 (on a shared CPU system) or PCI memory space
93 *	 (on a DRAMless system) we are located.
94 *       For now, we assume a perfect world which means
95 *	 we are located at the base of DRAM (physical 0).
96 */
97
98/*
99 * Search TLB for entry that we are currently using.
100 * Invalidate all entries but the one we are using.
101 */
102	/* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */
103	mfspr	r3,SPRN_PID			/* Get PID */
104	mfmsr	r4				/* Get MSR */
105	andi.	r4,r4,MSR_IS@l			/* TS=1? */
106	beq	wmmucr				/* If not, leave STS=0 */
107	oris	r3,r3,PPC44x_MMUCR_STS@h	/* Set STS=1 */
108wmmucr:	mtspr	SPRN_MMUCR,r3			/* Put MMUCR */
109	sync
110
111	bl	invstr				/* Find our address */
112invstr:	mflr	r5				/* Make it accessible */
113	tlbsx	r23,0,r5			/* Find entry we are in */
114	li	r4,0				/* Start at TLB entry 0 */
115	li	r3,0				/* Set PAGEID inval value */
1161:	cmpw	r23,r4				/* Is this our entry? */
117	beq	skpinv				/* If so, skip the inval */
118	tlbwe	r3,r4,PPC44x_TLB_PAGEID		/* If not, inval the entry */
119skpinv:	addi	r4,r4,1				/* Increment */
120	cmpwi	r4,64				/* Are we done? */
121	bne	1b				/* If not, repeat */
122	isync					/* If so, context change */
123
124/*
125 * Configure and load pinned entry into TLB slot 63.
126 */
127
128	lis	r3,KERNELBASE@h		/* Load the kernel virtual address */
129	ori	r3,r3,KERNELBASE@l
130
131	/* Kernel is at the base of RAM */
132	li r4, 0			/* Load the kernel physical address */
133
134	/* Load the kernel PID = 0 */
135	li	r0,0
136	mtspr	SPRN_PID,r0
137	sync
138
139	/* Initialize MMUCR */
140	li	r5,0
141	mtspr	SPRN_MMUCR,r5
142	sync
143
144 	/* pageid fields */
145	clrrwi	r3,r3,10		/* Mask off the effective page number */
146	ori	r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M
147
148	/* xlat fields */
149	clrrwi	r4,r4,10		/* Mask off the real page number */
150					/* ERPN is 0 for first 4GB page */
151
152	/* attrib fields */
153	/* Added guarded bit to protect against speculative loads/stores */
154	li	r5,0
155	ori	r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
156
157        li      r0,63                    /* TLB slot 63 */
158
159	tlbwe	r3,r0,PPC44x_TLB_PAGEID	/* Load the pageid fields */
160	tlbwe	r4,r0,PPC44x_TLB_XLAT	/* Load the translation fields */
161	tlbwe	r5,r0,PPC44x_TLB_ATTRIB	/* Load the attrib/access fields */
162
163	/* Force context change */
164	mfmsr	r0
165	mtspr	SPRN_SRR1, r0
166	lis	r0,3f@h
167	ori	r0,r0,3f@l
168	mtspr	SPRN_SRR0,r0
169	sync
170	rfi
171
172	/* If necessary, invalidate original entry we used */
1733:	cmpwi	r23,63
174	beq	4f
175	li	r6,0
176	tlbwe   r6,r23,PPC44x_TLB_PAGEID
177	isync
178
1794:
180#ifdef CONFIG_SERIAL_TEXT_DEBUG
181	/*
182	 * Add temporary UART mapping for early debug.
183	 * We can map UART registers wherever we want as long as they don't
184	 * interfere with other system mappings (e.g. with pinned entries).
185	 * For an example of how we handle this - see ocotea.h.       --ebs
186	 */
187 	/* pageid fields */
188	lis	r3,UART0_IO_BASE@h
189	ori	r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_4K
190
191	/* xlat fields */
192	lis	r4,UART0_PHYS_IO_BASE@h		/* RPN depends on SoC */
193#ifndef CONFIG_440EP
194	ori	r4,r4,0x0001		/* ERPN is 1 for second 4GB page */
195#endif
196
197	/* attrib fields */
198	li	r5,0
199	ori	r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G)
200
201        li      r0,0                    /* TLB slot 0 */
202
203	tlbwe	r3,r0,PPC44x_TLB_PAGEID	/* Load the pageid fields */
204	tlbwe	r4,r0,PPC44x_TLB_XLAT	/* Load the translation fields */
205	tlbwe	r5,r0,PPC44x_TLB_ATTRIB	/* Load the attrib/access fields */
206
207	/* Force context change */
208	isync
209#endif /* CONFIG_SERIAL_TEXT_DEBUG */
210
211	/* Establish the interrupt vector offsets */
212	SET_IVOR(0,  CriticalInput);
213	SET_IVOR(1,  MachineCheck);
214	SET_IVOR(2,  DataStorage);
215	SET_IVOR(3,  InstructionStorage);
216	SET_IVOR(4,  ExternalInput);
217	SET_IVOR(5,  Alignment);
218	SET_IVOR(6,  Program);
219	SET_IVOR(7,  FloatingPointUnavailable);
220	SET_IVOR(8,  SystemCall);
221	SET_IVOR(9,  AuxillaryProcessorUnavailable);
222	SET_IVOR(10, Decrementer);
223	SET_IVOR(11, FixedIntervalTimer);
224	SET_IVOR(12, WatchdogTimer);
225	SET_IVOR(13, DataTLBError);
226	SET_IVOR(14, InstructionTLBError);
227	SET_IVOR(15, Debug);
228
229	/* Establish the interrupt vector base */
230	lis	r4,interrupt_base@h	/* IVPR only uses the high 16-bits */
231	mtspr	SPRN_IVPR,r4
232
233#ifdef CONFIG_440EP
234	/* Clear DAPUIB flag in CCR0 (enable APU between CPU and FPU) */
235	mfspr	r2,SPRN_CCR0
236	lis	r3,0xffef
237	ori	r3,r3,0xffff
238	and	r2,r2,r3
239	mtspr	SPRN_CCR0,r2
240	isync
241#endif
242
243	/*
244	 * This is where the main kernel code starts.
245	 */
246
247	/* ptr to current */
248	lis	r2,init_task@h
249	ori	r2,r2,init_task@l
250
251	/* ptr to current thread */
252	addi	r4,r2,THREAD	/* init task's THREAD */
253	mtspr	SPRN_SPRG3,r4
254
255	/* stack */
256	lis	r1,init_thread_union@h
257	ori	r1,r1,init_thread_union@l
258	li	r0,0
259	stwu	r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
260
261	bl	early_init
262
263/*
264 * Decide what sort of machine this is and initialize the MMU.
265 */
266	mr	r3,r31
267	mr	r4,r30
268	mr	r5,r29
269	mr	r6,r28
270	mr	r7,r27
271	bl	machine_init
272	bl	MMU_init
273
274	/* Setup PTE pointers for the Abatron bdiGDB */
275	lis	r6, swapper_pg_dir@h
276	ori	r6, r6, swapper_pg_dir@l
277	lis	r5, abatron_pteptrs@h
278	ori	r5, r5, abatron_pteptrs@l
279	lis	r4, KERNELBASE@h
280	ori	r4, r4, KERNELBASE@l
281	stw	r5, 0(r4)	/* Save abatron_pteptrs at a fixed location */
282	stw	r6, 0(r5)
283
284	/* Let's move on */
285	lis	r4,start_kernel@h
286	ori	r4,r4,start_kernel@l
287	lis	r3,MSR_KERNEL@h
288	ori	r3,r3,MSR_KERNEL@l
289	mtspr	SPRN_SRR0,r4
290	mtspr	SPRN_SRR1,r3
291	rfi			/* change context and jump to start_kernel */
292
293/*
294 * Interrupt vector entry code
295 *
296 * The Book E MMUs are always on so we don't need to handle
297 * interrupts in real mode as with previous PPC processors. In
298 * this case we handle interrupts in the kernel virtual address
299 * space.
300 *
301 * Interrupt vectors are dynamically placed relative to the
302 * interrupt prefix as determined by the address of interrupt_base.
303 * The interrupt vectors offsets are programmed using the labels
304 * for each interrupt vector entry.
305 *
306 * Interrupt vectors must be aligned on a 16 byte boundary.
307 * We align on a 32 byte cache line boundary for good measure.
308 */
309
310interrupt_base:
311	/* Critical Input Interrupt */
312	CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception)
313
314	/* Machine Check Interrupt */
315#ifdef CONFIG_440A
316	MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
317#else
318	CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
319#endif
320
321	/* Data Storage Interrupt */
322	START_EXCEPTION(DataStorage)
323	mtspr	SPRN_SPRG0, r10		/* Save some working registers */
324	mtspr	SPRN_SPRG1, r11
325	mtspr	SPRN_SPRG4W, r12
326	mtspr	SPRN_SPRG5W, r13
327	mfcr	r11
328	mtspr	SPRN_SPRG7W, r11
329
330	/*
331	 * Check if it was a store fault, if not then bail
332	 * because a user tried to access a kernel or
333	 * read-protected page.  Otherwise, get the
334	 * offending address and handle it.
335	 */
336	mfspr	r10, SPRN_ESR
337	andis.	r10, r10, ESR_ST@h
338	beq	2f
339
340	mfspr	r10, SPRN_DEAR		/* Get faulting address */
341
342	/* If we are faulting a kernel address, we have to use the
343	 * kernel page tables.
344	 */
345	lis	r11, TASK_SIZE@h
346	cmplw	r10, r11
347	blt+	3f
348	lis	r11, swapper_pg_dir@h
349	ori	r11, r11, swapper_pg_dir@l
350
351	mfspr   r12,SPRN_MMUCR
352	rlwinm	r12,r12,0,0,23		/* Clear TID */
353
354	b	4f
355
356	/* Get the PGD for the current thread */
3573:
358	mfspr	r11,SPRN_SPRG3
359	lwz	r11,PGDIR(r11)
360
361	/* Load PID into MMUCR TID */
362	mfspr	r12,SPRN_MMUCR		/* Get MMUCR */
363	mfspr   r13,SPRN_PID		/* Get PID */
364	rlwimi	r12,r13,0,24,31		/* Set TID */
365
3664:
367	mtspr   SPRN_MMUCR,r12
368
369	rlwinm  r12, r10, 13, 19, 29    /* Compute pgdir/pmd offset */
370	lwzx    r11, r12, r11           /* Get pgd/pmd entry */
371	rlwinm. r12, r11, 0, 0, 20      /* Extract pt base address */
372	beq     2f                      /* Bail if no table */
373
374	rlwimi  r12, r10, 23, 20, 28    /* Compute pte address */
375	lwz     r11, 4(r12)             /* Get pte entry */
376
377	andi.	r13, r11, _PAGE_RW	/* Is it writeable? */
378	beq	2f			/* Bail if not */
379
380	/* Update 'changed'.
381	*/
382	ori	r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
383	stw	r11, 4(r12)		/* Update Linux page table */
384
385	li	r13, PPC44x_TLB_SR@l	/* Set SR */
386	rlwimi	r13, r11, 29, 29, 29	/* SX = _PAGE_HWEXEC */
387	rlwimi	r13, r11, 0, 30, 30	/* SW = _PAGE_RW */
388	rlwimi	r13, r11, 29, 28, 28	/* UR = _PAGE_USER */
389	rlwimi	r12, r11, 31, 26, 26	/* (_PAGE_USER>>1)->r12 */
390	rlwimi	r12, r11, 29, 30, 30	/* (_PAGE_USER>>3)->r12 */
391	and	r12, r12, r11		/* HWEXEC/RW & USER */
392	rlwimi	r13, r12, 0, 26, 26	/* UX = HWEXEC & USER */
393	rlwimi	r13, r12, 3, 27, 27	/* UW = RW & USER */
394
395	rlwimi	r11,r13,0,26,31		/* Insert static perms */
396
397	rlwinm	r11,r11,0,20,15		/* Clear U0-U3 */
398
399	/* find the TLB index that caused the fault.  It has to be here. */
400	tlbsx	r10, 0, r10
401
402	tlbwe	r11, r10, PPC44x_TLB_ATTRIB	/* Write ATTRIB */
403
404	/* Done...restore registers and get out of here.
405	*/
406	mfspr	r11, SPRN_SPRG7R
407	mtcr	r11
408	mfspr	r13, SPRN_SPRG5R
409	mfspr	r12, SPRN_SPRG4R
410
411	mfspr	r11, SPRN_SPRG1
412	mfspr	r10, SPRN_SPRG0
413	rfi			/* Force context change */
414
4152:
416	/*
417	 * The bailout.  Restore registers to pre-exception conditions
418	 * and call the heavyweights to help us out.
419	 */
420	mfspr	r11, SPRN_SPRG7R
421	mtcr	r11
422	mfspr	r13, SPRN_SPRG5R
423	mfspr	r12, SPRN_SPRG4R
424
425	mfspr	r11, SPRN_SPRG1
426	mfspr	r10, SPRN_SPRG0
427	b	data_access
428
429	/* Instruction Storage Interrupt */
430	INSTRUCTION_STORAGE_EXCEPTION
431
432	/* External Input Interrupt */
433	EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE)
434
435	/* Alignment Interrupt */
436	ALIGNMENT_EXCEPTION
437
438	/* Program Interrupt */
439	PROGRAM_EXCEPTION
440
441	/* Floating Point Unavailable Interrupt */
442#ifdef CONFIG_PPC_FPU
443	FP_UNAVAILABLE_EXCEPTION
444#else
445	EXCEPTION(0x2010, FloatingPointUnavailable, unknown_exception, EXC_XFER_EE)
446#endif
447
448	/* System Call Interrupt */
449	START_EXCEPTION(SystemCall)
450	NORMAL_EXCEPTION_PROLOG
451	EXC_XFER_EE_LITE(0x0c00, DoSyscall)
452
453	/* Auxillary Processor Unavailable Interrupt */
454	EXCEPTION(0x2020, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE)
455
456	/* Decrementer Interrupt */
457	DECREMENTER_EXCEPTION
458
459	/* Fixed Internal Timer Interrupt */
460	/* TODO: Add FIT support */
461	EXCEPTION(0x1010, FixedIntervalTimer, unknown_exception, EXC_XFER_EE)
462
463	/* Watchdog Timer Interrupt */
464	/* TODO: Add watchdog support */
465#ifdef CONFIG_BOOKE_WDT
466	CRITICAL_EXCEPTION(0x1020, WatchdogTimer, WatchdogException)
467#else
468	CRITICAL_EXCEPTION(0x1020, WatchdogTimer, unknown_exception)
469#endif
470
471	/* Data TLB Error Interrupt */
472	START_EXCEPTION(DataTLBError)
473	mtspr	SPRN_SPRG0, r10		/* Save some working registers */
474	mtspr	SPRN_SPRG1, r11
475	mtspr	SPRN_SPRG4W, r12
476	mtspr	SPRN_SPRG5W, r13
477	mfcr	r11
478	mtspr	SPRN_SPRG7W, r11
479	mfspr	r10, SPRN_DEAR		/* Get faulting address */
480
481	/* If we are faulting a kernel address, we have to use the
482	 * kernel page tables.
483	 */
484	lis	r11, TASK_SIZE@h
485	cmplw	r10, r11
486	blt+	3f
487	lis	r11, swapper_pg_dir@h
488	ori	r11, r11, swapper_pg_dir@l
489
490	mfspr	r12,SPRN_MMUCR
491	rlwinm	r12,r12,0,0,23		/* Clear TID */
492
493	b	4f
494
495	/* Get the PGD for the current thread */
4963:
497	mfspr	r11,SPRN_SPRG3
498	lwz	r11,PGDIR(r11)
499
500	/* Load PID into MMUCR TID */
501	mfspr	r12,SPRN_MMUCR
502	mfspr   r13,SPRN_PID		/* Get PID */
503	rlwimi	r12,r13,0,24,31		/* Set TID */
504
5054:
506	mtspr	SPRN_MMUCR,r12
507
508	rlwinm 	r12, r10, 13, 19, 29	/* Compute pgdir/pmd offset */
509	lwzx	r11, r12, r11		/* Get pgd/pmd entry */
510	rlwinm.	r12, r11, 0, 0, 20	/* Extract pt base address */
511	beq	2f			/* Bail if no table */
512
513	rlwimi	r12, r10, 23, 20, 28	/* Compute pte address */
514	lwz	r11, 4(r12)		/* Get pte entry */
515	andi.	r13, r11, _PAGE_PRESENT	/* Is the page present? */
516	beq	2f			/* Bail if not present */
517
518	ori	r11, r11, _PAGE_ACCESSED
519	stw	r11, 4(r12)
520
521	 /* Jump to common tlb load */
522	b	finish_tlb_load
523
5242:
525	/* The bailout.  Restore registers to pre-exception conditions
526	 * and call the heavyweights to help us out.
527	 */
528	mfspr	r11, SPRN_SPRG7R
529	mtcr	r11
530	mfspr	r13, SPRN_SPRG5R
531	mfspr	r12, SPRN_SPRG4R
532	mfspr	r11, SPRN_SPRG1
533	mfspr	r10, SPRN_SPRG0
534	b	data_access
535
536	/* Instruction TLB Error Interrupt */
537	/*
538	 * Nearly the same as above, except we get our
539	 * information from different registers and bailout
540	 * to a different point.
541	 */
542	START_EXCEPTION(InstructionTLBError)
543	mtspr	SPRN_SPRG0, r10		/* Save some working registers */
544	mtspr	SPRN_SPRG1, r11
545	mtspr	SPRN_SPRG4W, r12
546	mtspr	SPRN_SPRG5W, r13
547	mfcr	r11
548	mtspr	SPRN_SPRG7W, r11
549	mfspr	r10, SPRN_SRR0		/* Get faulting address */
550
551	/* If we are faulting a kernel address, we have to use the
552	 * kernel page tables.
553	 */
554	lis	r11, TASK_SIZE@h
555	cmplw	r10, r11
556	blt+	3f
557	lis	r11, swapper_pg_dir@h
558	ori	r11, r11, swapper_pg_dir@l
559
560	mfspr	r12,SPRN_MMUCR
561	rlwinm	r12,r12,0,0,23		/* Clear TID */
562
563	b	4f
564
565	/* Get the PGD for the current thread */
5663:
567	mfspr	r11,SPRN_SPRG3
568	lwz	r11,PGDIR(r11)
569
570	/* Load PID into MMUCR TID */
571	mfspr	r12,SPRN_MMUCR
572	mfspr   r13,SPRN_PID		/* Get PID */
573	rlwimi	r12,r13,0,24,31		/* Set TID */
574
5754:
576	mtspr	SPRN_MMUCR,r12
577
578	rlwinm	r12, r10, 13, 19, 29	/* Compute pgdir/pmd offset */
579	lwzx	r11, r12, r11		/* Get pgd/pmd entry */
580	rlwinm.	r12, r11, 0, 0, 20	/* Extract pt base address */
581	beq	2f			/* Bail if no table */
582
583	rlwimi	r12, r10, 23, 20, 28	/* Compute pte address */
584	lwz	r11, 4(r12)		/* Get pte entry */
585	andi.	r13, r11, _PAGE_PRESENT	/* Is the page present? */
586	beq	2f			/* Bail if not present */
587
588	ori	r11, r11, _PAGE_ACCESSED
589	stw	r11, 4(r12)
590
591	/* Jump to common TLB load point */
592	b	finish_tlb_load
593
5942:
595	/* The bailout.  Restore registers to pre-exception conditions
596	 * and call the heavyweights to help us out.
597	 */
598	mfspr	r11, SPRN_SPRG7R
599	mtcr	r11
600	mfspr	r13, SPRN_SPRG5R
601	mfspr	r12, SPRN_SPRG4R
602	mfspr	r11, SPRN_SPRG1
603	mfspr	r10, SPRN_SPRG0
604	b	InstructionStorage
605
606	/* Debug Interrupt */
607	DEBUG_EXCEPTION
608
609/*
610 * Local functions
611 */
612	/*
613	 * Data TLB exceptions will bail out to this point
614	 * if they can't resolve the lightweight TLB fault.
615	 */
616data_access:
617	NORMAL_EXCEPTION_PROLOG
618	mfspr	r5,SPRN_ESR		/* Grab the ESR, save it, pass arg3 */
619	stw	r5,_ESR(r11)
620	mfspr	r4,SPRN_DEAR		/* Grab the DEAR, save it, pass arg2 */
621	EXC_XFER_EE_LITE(0x0300, handle_page_fault)
622
623/*
624
625 * Both the instruction and data TLB miss get to this
626 * point to load the TLB.
627 * 	r10 - EA of fault
628 * 	r11 - available to use
629 *	r12 - Pointer to the 64-bit PTE
630 *	r13 - available to use
631 *	MMUCR - loaded with proper value when we get here
632 *	Upon exit, we reload everything and RFI.
633 */
634finish_tlb_load:
635	/*
636	 * We set execute, because we don't have the granularity to
637	 * properly set this at the page level (Linux problem).
638	 * If shared is set, we cause a zero PID->TID load.
639	 * Many of these bits are software only.  Bits we don't set
640	 * here we (properly should) assume have the appropriate value.
641	 */
642
643	/* Load the next available TLB index */
644	lis	r13, tlb_44x_index@ha
645	lwz	r13, tlb_44x_index@l(r13)
646	/* Load the TLB high watermark */
647	lis	r11, tlb_44x_hwater@ha
648	lwz	r11, tlb_44x_hwater@l(r11)
649
650	/* Increment, rollover, and store TLB index */
651	addi	r13, r13, 1
652	cmpw	0, r13, r11			/* reserve entries */
653	ble	7f
654	li	r13, 0
6557:
656	/* Store the next available TLB index */
657	lis	r11, tlb_44x_index@ha
658	stw	r13, tlb_44x_index@l(r11)
659
660	lwz	r11, 0(r12)			/* Get MS word of PTE */
661	lwz	r12, 4(r12)			/* Get LS word of PTE */
662	rlwimi	r11, r12, 0, 0 , 19		/* Insert RPN */
663	tlbwe	r11, r13, PPC44x_TLB_XLAT	/* Write XLAT */
664
665	/*
666	 * Create PAGEID. This is the faulting address,
667	 * page size, and valid flag.
668	 */
669	li	r11, PPC44x_TLB_VALID | PPC44x_TLB_4K
670	rlwimi	r10, r11, 0, 20, 31		/* Insert valid and page size */
671	tlbwe	r10, r13, PPC44x_TLB_PAGEID	/* Write PAGEID */
672
673	li	r10, PPC44x_TLB_SR@l		/* Set SR */
674	rlwimi	r10, r12, 0, 30, 30		/* Set SW = _PAGE_RW */
675	rlwimi	r10, r12, 29, 29, 29		/* SX = _PAGE_HWEXEC */
676	rlwimi	r10, r12, 29, 28, 28		/* UR = _PAGE_USER */
677	rlwimi	r11, r12, 31, 26, 26		/* (_PAGE_USER>>1)->r12 */
678	and	r11, r12, r11			/* HWEXEC & USER */
679	rlwimi	r10, r11, 0, 26, 26		/* UX = HWEXEC & USER */
680
681	rlwimi	r12, r10, 0, 26, 31		/* Insert static perms */
682	rlwinm	r12, r12, 0, 20, 15		/* Clear U0-U3 */
683	tlbwe	r12, r13, PPC44x_TLB_ATTRIB	/* Write ATTRIB */
684
685	/* Done...restore registers and get out of here.
686	*/
687	mfspr	r11, SPRN_SPRG7R
688	mtcr	r11
689	mfspr	r13, SPRN_SPRG5R
690	mfspr	r12, SPRN_SPRG4R
691	mfspr	r11, SPRN_SPRG1
692	mfspr	r10, SPRN_SPRG0
693	rfi					/* Force context change */
694
695/*
696 * Global functions
697 */
698
699/*
700 * extern void giveup_altivec(struct task_struct *prev)
701 *
702 * The 44x core does not have an AltiVec unit.
703 */
704_GLOBAL(giveup_altivec)
705	blr
706
707/*
708 * extern void giveup_fpu(struct task_struct *prev)
709 *
710 * The 44x core does not have an FPU.
711 */
712#ifndef CONFIG_PPC_FPU
713_GLOBAL(giveup_fpu)
714	blr
715#endif
716
717/*
718 * extern void abort(void)
719 *
720 * At present, this routine just applies a system reset.
721 */
722_GLOBAL(abort)
723        mfspr   r13,SPRN_DBCR0
724        oris    r13,r13,DBCR0_RST_SYSTEM@h
725        mtspr   SPRN_DBCR0,r13
726
727_GLOBAL(set_context)
728
729#ifdef CONFIG_BDI_SWITCH
730	/* Context switch the PTE pointer for the Abatron BDI2000.
731	 * The PGDIR is the second parameter.
732	 */
733	lis	r5, abatron_pteptrs@h
734	ori	r5, r5, abatron_pteptrs@l
735	stw	r4, 0x4(r5)
736#endif
737	mtspr	SPRN_PID,r3
738	isync			/* Force context change */
739	blr
740
741/*
742 * We put a few things here that have to be page-aligned. This stuff
743 * goes at the beginning of the data segment, which is page-aligned.
744 */
745	.data
746	.align	12
747	.globl	sdata
748sdata:
749	.globl	empty_zero_page
750empty_zero_page:
751	.space	4096
752
753/*
754 * To support >32-bit physical addresses, we use an 8KB pgdir.
755 */
756	.globl	swapper_pg_dir
757swapper_pg_dir:
758	.space	8192
759
760/* Reserved 4k for the critical exception stack & 4k for the machine
761 * check stack per CPU for kernel mode exceptions */
762	.section .bss
763        .align 12
764exception_stack_bottom:
765	.space	BOOKE_EXCEPTION_STACK_SIZE
766	.globl	exception_stack_top
767exception_stack_top:
768
769/*
770 * This space gets a copy of optional info passed to us by the bootstrap
771 * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
772 */
773	.globl	cmd_line
774cmd_line:
775	.space	512
776
777/*
778 * Room for two PTE pointers, usually the kernel and current user pointers
779 * to their respective root page table.
780 */
781abatron_pteptrs:
782	.space	8
783