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