1176771Sraj/*-
2192532Sraj * Copyright (C) 2006-2009 Semihalf, Rafal Jaworowski <raj@semihalf.com>
3176771Sraj * Copyright (C) 2006 Semihalf, Marian Balakowicz <m8@semihalf.com>
4176771Sraj * Copyright (C) 2006 Juniper Networks, Inc.
5176771Sraj * All rights reserved.
6176771Sraj *
7176771Sraj * Redistribution and use in source and binary forms, with or without
8176771Sraj * modification, are permitted provided that the following conditions
9176771Sraj * are met:
10176771Sraj * 1. Redistributions of source code must retain the above copyright
11176771Sraj *    notice, this list of conditions and the following disclaimer.
12176771Sraj * 2. Redistributions in binary form must reproduce the above copyright
13176771Sraj *    notice, this list of conditions and the following disclaimer in the
14176771Sraj *    documentation and/or other materials provided with the distribution.
15176771Sraj * 3. The name of the author may not be used to endorse or promote products
16176771Sraj *    derived from this software without specific prior written permission.
17176771Sraj *
18176771Sraj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19176771Sraj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20176771Sraj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
21176771Sraj * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22176771Sraj * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23176771Sraj * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24176771Sraj * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25176771Sraj * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26176771Sraj * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27176771Sraj * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28176771Sraj *
29176771Sraj * $FreeBSD: releng/10.3/sys/powerpc/booke/trap_subr.S 266001 2014-05-14 03:09:37Z ian $
30176771Sraj */
31176771Sraj/*-
32176771Sraj * Copyright (C) 1995, 1996 Wolfgang Solfrank.
33176771Sraj * Copyright (C) 1995, 1996 TooLs GmbH.
34176771Sraj * All rights reserved.
35176771Sraj *
36176771Sraj * Redistribution and use in source and binary forms, with or without
37176771Sraj * modification, are permitted provided that the following conditions
38176771Sraj * are met:
39176771Sraj * 1. Redistributions of source code must retain the above copyright
40176771Sraj *    notice, this list of conditions and the following disclaimer.
41176771Sraj * 2. Redistributions in binary form must reproduce the above copyright
42176771Sraj *    notice, this list of conditions and the following disclaimer in the
43176771Sraj *    documentation and/or other materials provided with the distribution.
44176771Sraj * 3. All advertising materials mentioning features or use of this software
45176771Sraj *    must display the following acknowledgement:
46176771Sraj *	This product includes software developed by TooLs GmbH.
47176771Sraj * 4. The name of TooLs GmbH may not be used to endorse or promote products
48176771Sraj *    derived from this software without specific prior written permission.
49176771Sraj *
50176771Sraj * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
51176771Sraj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
52176771Sraj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
53176771Sraj * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54176771Sraj * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
55176771Sraj * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
56176771Sraj * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
57176771Sraj * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
58176771Sraj * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
59176771Sraj * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60176771Sraj *
61176771Sraj *	from: $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $
62176771Sraj */
63176771Sraj
64176771Sraj/*
65176771Sraj * NOTICE: This is not a standalone file.  to use it, #include it in
66176771Sraj * your port's locore.S, like so:
67176771Sraj *
68176771Sraj *	#include <powerpc/booke/trap_subr.S>
69176771Sraj */
70176771Sraj
71176771Sraj/*
72176771Sraj * SPRG usage notes
73176771Sraj *
74176771Sraj * SPRG0 - pcpu pointer
75176771Sraj * SPRG1 - all interrupts except TLB miss, critical, machine check
76176771Sraj * SPRG2 - critical
77176771Sraj * SPRG3 - machine check
78192532Sraj * SPRG4-6 - scratch
79176771Sraj *
80176771Sraj */
81176771Sraj
82176771Sraj/* Get the per-CPU data structure */
83176771Sraj#define GET_CPUINFO(r) mfsprg0 r
84176771Sraj
85192532Sraj#define RES_GRANULE	32
86192532Sraj#define RES_LOCK	0	/* offset to the 'lock' word */
87192532Sraj#define RES_RECURSE	4	/* offset to the 'recurse' word */
88192532Sraj
89176771Sraj/*
90176771Sraj * Standard interrupt prolog
91176771Sraj *
92176771Sraj * sprg_sp - SPRG{1-3} reg used to temporarily store the SP
93176771Sraj * savearea - temp save area (pc_{tempsave, disisave, critsave, mchksave})
94176771Sraj * isrr0-1 - save restore registers with CPU state at interrupt time (may be
95176771Sraj *           SRR0-1, CSRR0-1, MCSRR0-1
96176771Sraj *
97176771Sraj * 1. saves in the given savearea:
98176771Sraj *   - R30-31
99176771Sraj *   - DEAR, ESR
100176771Sraj *   - xSRR0-1
101176771Sraj *
102176771Sraj * 2. saves CR -> R30
103176771Sraj *
104176771Sraj * 3. switches to kstack if needed
105176771Sraj *
106176771Sraj * 4. notes:
107176771Sraj *   - R31 can be used as scratch register until a new frame is layed on
108176771Sraj *     the stack with FRAME_SETUP
109176771Sraj *
110176771Sraj *   - potential TLB miss: NO. Saveareas are always acessible via TLB1
111176771Sraj *     permanent entries, and within this prolog we do not dereference any
112176771Sraj *     locations potentially not in the TLB
113176771Sraj */
114176771Sraj#define STANDARD_PROLOG(sprg_sp, savearea, isrr0, isrr1)		\
115176771Sraj	mtspr	sprg_sp, %r1;		/* Save SP */			\
116176771Sraj	GET_CPUINFO(%r1);		/* Per-cpu structure */		\
117176771Sraj	stw	%r30, (savearea+CPUSAVE_R30)(%r1);			\
118176771Sraj	stw	%r31, (savearea+CPUSAVE_R31)(%r1); 			\
119176771Sraj	mfdear	%r30;		 					\
120176771Sraj	mfesr	%r31;							\
121176771Sraj	stw	%r30, (savearea+CPUSAVE_BOOKE_DEAR)(%r1); 		\
122176771Sraj	stw	%r31, (savearea+CPUSAVE_BOOKE_ESR)(%r1); 		\
123176771Sraj	mfspr	%r30, isrr0;						\
124176771Sraj	mfspr	%r31, isrr1;	 	/* MSR at interrupt time */	\
125176771Sraj	stw	%r30, (savearea+CPUSAVE_SRR0)(%r1);			\
126176771Sraj	stw	%r31, (savearea+CPUSAVE_SRR1)(%r1);			\
127176771Sraj	isync;			 					\
128176771Sraj	mfspr	%r1, sprg_sp;	 	/* Restore SP */		\
129176771Sraj	mfcr	%r30;		 	/* Save CR */			\
130176771Sraj	/* switch to per-thread kstack if intr taken in user mode */	\
131176771Sraj	mtcr	%r31;			/* MSR at interrupt time  */	\
132176771Sraj	bf	17, 1f;							\
133176771Sraj	GET_CPUINFO(%r1);		/* Per-cpu structure */		\
134176771Sraj	lwz	%r1, PC_CURPCB(%r1); 	/* Per-thread kernel stack */	\
135187153Sraj1:
136176771Sraj
137176771Sraj#define	STANDARD_CRIT_PROLOG(sprg_sp, savearea, isrr0, isrr1)		\
138176771Sraj	mtspr	sprg_sp, %r1;		/* Save SP */			\
139176771Sraj	GET_CPUINFO(%r1);		/* Per-cpu structure */		\
140176771Sraj	stw	%r30, (savearea+CPUSAVE_R30)(%r1);			\
141176771Sraj	stw	%r31, (savearea+CPUSAVE_R31)(%r1);			\
142176771Sraj	mfdear	%r30;							\
143176771Sraj	mfesr	%r31;							\
144176771Sraj	stw	%r30, (savearea+CPUSAVE_BOOKE_DEAR)(%r1);		\
145176771Sraj	stw	%r31, (savearea+CPUSAVE_BOOKE_ESR)(%r1);		\
146176771Sraj	mfspr	%r30, isrr0;						\
147176771Sraj	mfspr	%r31, isrr1;		/* MSR at interrupt time */	\
148176771Sraj	stw	%r30, (savearea+CPUSAVE_SRR0)(%r1);			\
149176771Sraj	stw	%r31, (savearea+CPUSAVE_SRR1)(%r1);			\
150176771Sraj	mfspr	%r30, SPR_SRR0;						\
151176771Sraj	mfspr	%r31, SPR_SRR1;		/* MSR at interrupt time */	\
152176771Sraj	stw	%r30, (savearea+CPUSAVE_SRR0+8)(%r1);			\
153176771Sraj	stw	%r31, (savearea+CPUSAVE_SRR1+8)(%r1);			\
154176771Sraj	isync;								\
155176771Sraj	mfspr	%r1, sprg_sp;		/* Restore SP */		\
156176771Sraj	mfcr	%r30;			/* Save CR */			\
157176771Sraj	/* switch to per-thread kstack if intr taken in user mode */	\
158176771Sraj	mtcr	%r31;			/* MSR at interrupt time  */	\
159176771Sraj	bf	17, 1f;							\
160176771Sraj	GET_CPUINFO(%r1);		/* Per-cpu structure */		\
161176771Sraj	lwz	%r1, PC_CURPCB(%r1);	/* Per-thread kernel stack */	\
162176771Sraj1:
163176771Sraj
164176771Sraj/*
165176771Sraj * FRAME_SETUP assumes:
166176771Sraj *	SPRG{1-3}	SP at the time interrupt occured
167176771Sraj *	savearea	r30-r31, DEAR, ESR, xSRR0-1
168176771Sraj *	r30		CR
169176771Sraj *	r31		scratch
170176771Sraj *	r1		kernel stack
171176771Sraj *
172176771Sraj * sprg_sp - SPRG reg containing SP at the time interrupt occured
173176771Sraj * savearea - temp save
174176771Sraj * exc - exception number (EXC_xxx)
175176771Sraj *
176176771Sraj * 1. sets a new frame
177176771Sraj * 2. saves in the frame:
178176771Sraj *   - R0, R1 (SP at the time of interrupt), R2, LR, CR
179176771Sraj *   - R3-31 (R30-31 first restored from savearea)
180176771Sraj *   - XER, CTR, DEAR, ESR (from savearea), xSRR0-1
181176771Sraj *
182176771Sraj * Notes:
183176771Sraj * - potential TLB miss: YES, since we make dereferences to kstack, which
184176771Sraj *   can happen not covered (we can have up to two DTLB misses if fortunate
185176771Sraj *   enough i.e. when kstack crosses page boundary and both pages are
186176771Sraj *   untranslated)
187176771Sraj */
188176771Sraj#define	FRAME_SETUP(sprg_sp, savearea, exc)				\
189176771Sraj	mfspr	%r31, sprg_sp;		/* get saved SP */		\
190176771Sraj	/* establish a new stack frame and put everything on it */	\
191176771Sraj	stwu	%r31, -FRAMELEN(%r1);					\
192176771Sraj	stw	%r0, FRAME_0+8(%r1);	/* save r0 in the trapframe */	\
193176771Sraj	stw	%r31, FRAME_1+8(%r1);	/* save SP   "      "       */	\
194176771Sraj	stw	%r2, FRAME_2+8(%r1);	/* save r2   "      "       */	\
195176771Sraj	mflr	%r31;		 					\
196176771Sraj	stw	%r31, FRAME_LR+8(%r1);	/* save LR   "      "       */	\
197176771Sraj	stw	%r30, FRAME_CR+8(%r1);	/* save CR   "      "       */	\
198176771Sraj	GET_CPUINFO(%r2);						\
199176771Sraj	lwz	%r30, (savearea+CPUSAVE_R30)(%r2); /* get saved r30 */	\
200176771Sraj	lwz	%r31, (savearea+CPUSAVE_R31)(%r2); /* get saved r31 */	\
201176771Sraj	/* save R3-31 */						\
202176771Sraj	stmw	%r3,  FRAME_3+8(%r1) ;					\
203176771Sraj	/* save DEAR, ESR */						\
204176771Sraj	lwz	%r28, (savearea+CPUSAVE_BOOKE_DEAR)(%r2);		\
205176771Sraj	lwz	%r29, (savearea+CPUSAVE_BOOKE_ESR)(%r2);		\
206189101Sraj	stw	%r28, FRAME_BOOKE_DEAR+8(%r1);				\
207189101Sraj	stw	%r29, FRAME_BOOKE_ESR+8(%r1);				\
208176771Sraj	/* save XER, CTR, exc number */					\
209176771Sraj	mfxer	%r3;							\
210176771Sraj	mfctr	%r4;							\
211189101Sraj	stw	%r3, FRAME_XER+8(%r1);					\
212189101Sraj	stw	%r4, FRAME_CTR+8(%r1);					\
213176771Sraj	li	%r5, exc;						\
214189101Sraj	stw	%r5, FRAME_EXC+8(%r1);					\
215189100Sraj	/* save DBCR0 */						\
216189100Sraj	mfspr	%r3, SPR_DBCR0;						\
217189101Sraj	stw	%r3, FRAME_BOOKE_DBCR0+8(%r1);				\
218176771Sraj	/* save xSSR0-1 */						\
219176771Sraj	lwz	%r30, (savearea+CPUSAVE_SRR0)(%r2);			\
220176771Sraj	lwz	%r31, (savearea+CPUSAVE_SRR1)(%r2);			\
221189101Sraj	stw	%r30, FRAME_SRR0+8(%r1);				\
222266001Sian	stw	%r31, FRAME_SRR1+8(%r1);				\
223266001Sian	lwz	%r2,PC_CURTHREAD(%r2)	/* set curthread pointer */
224176771Sraj
225176771Sraj/*
226176771Sraj *
227176771Sraj * isrr0-1 - save restore registers to restore CPU state to (may be
228176771Sraj *           SRR0-1, CSRR0-1, MCSRR0-1
229176771Sraj *
230176771Sraj * Notes:
231176771Sraj *  - potential TLB miss: YES. The deref'd kstack may be not covered
232176771Sraj */
233176771Sraj#define	FRAME_LEAVE(isrr0, isrr1)					\
234176771Sraj	/* restore CTR, XER, LR, CR */					\
235176771Sraj	lwz	%r4, FRAME_CTR+8(%r1);					\
236176771Sraj	lwz	%r5, FRAME_XER+8(%r1);					\
237176771Sraj	lwz	%r6, FRAME_LR+8(%r1);					\
238176771Sraj	lwz	%r7, FRAME_CR+8(%r1);					\
239176771Sraj	mtctr	%r4;							\
240176771Sraj	mtxer	%r5;							\
241176771Sraj	mtlr	%r6;							\
242176771Sraj	mtcr	%r7;							\
243189100Sraj	/* restore DBCR0 */						\
244189100Sraj	lwz	%r4, FRAME_BOOKE_DBCR0+8(%r1);				\
245189100Sraj	mtspr	SPR_DBCR0, %r4;						\
246176771Sraj	/* restore xSRR0-1 */						\
247176771Sraj	lwz	%r30, FRAME_SRR0+8(%r1);				\
248176771Sraj	lwz	%r31, FRAME_SRR1+8(%r1);				\
249176771Sraj	mtspr	isrr0, %r30;						\
250176771Sraj	mtspr	isrr1, %r31;						\
251176771Sraj	/* restore R2-31, SP */						\
252176771Sraj	lmw	%r2, FRAME_2+8(%r1) ;					\
253176771Sraj	lwz	%r0, FRAME_0+8(%r1);					\
254176771Sraj	lwz	%r1, FRAME_1+8(%r1);					\
255176771Sraj	isync
256176771Sraj
257176771Sraj/*
258176771Sraj * TLB miss prolog
259176771Sraj *
260176771Sraj * saves LR, CR, SRR0-1, R20-31 in the TLBSAVE area
261176771Sraj *
262176771Sraj * Notes:
263176771Sraj *  - potential TLB miss: NO. It is crucial that we do not generate a TLB
264187153Sraj *    miss within the TLB prolog itself!
265176771Sraj *  - TLBSAVE is always translated
266176771Sraj */
267176771Sraj#define TLB_PROLOG							\
268176771Sraj	mtsprg4	%r1;			/* Save SP */			\
269176771Sraj	mtsprg5 %r28;							\
270176771Sraj	mtsprg6 %r29;							\
271176771Sraj	/* calculate TLB nesting level and TLBSAVE instance address */	\
272176771Sraj	GET_CPUINFO(%r1);	 	/* Per-cpu structure */		\
273176771Sraj	lwz	%r28, PC_BOOKE_TLB_LEVEL(%r1);				\
274192532Sraj	rlwinm	%r29, %r28, 6, 23, 25;	/* 4 x TLBSAVE_LEN */		\
275176771Sraj	addi	%r28, %r28, 1;						\
276176771Sraj	stw	%r28, PC_BOOKE_TLB_LEVEL(%r1);				\
277176771Sraj	addi	%r29, %r29, PC_BOOKE_TLBSAVE@l; 			\
278176771Sraj	add	%r1, %r1, %r29;		/* current TLBSAVE ptr */	\
279176771Sraj									\
280176771Sraj	/* save R20-31 */						\
281176771Sraj	mfsprg5 %r28;		 					\
282176771Sraj	mfsprg6 %r29;							\
283176771Sraj	stmw	%r20, (TLBSAVE_BOOKE_R20)(%r1);				\
284176771Sraj	/* save LR, CR */						\
285176771Sraj	mflr	%r30;		 					\
286176771Sraj	mfcr	%r31;							\
287176771Sraj	stw	%r30, (TLBSAVE_BOOKE_LR)(%r1);				\
288176771Sraj	stw	%r31, (TLBSAVE_BOOKE_CR)(%r1);				\
289176771Sraj	/* save SRR0-1 */						\
290176771Sraj	mfsrr0	%r30;		/* execution addr at interrupt time */	\
291176771Sraj	mfsrr1	%r31;		/* MSR at interrupt time*/		\
292176771Sraj	stw	%r30, (TLBSAVE_BOOKE_SRR0)(%r1);	/* save SRR0 */	\
293176771Sraj	stw	%r31, (TLBSAVE_BOOKE_SRR1)(%r1);	/* save SRR1 */	\
294176771Sraj	isync;								\
295176771Sraj	mfsprg4	%r1
296176771Sraj
297176771Sraj/*
298176771Sraj * restores LR, CR, SRR0-1, R20-31 from the TLBSAVE area
299176771Sraj *
300176771Sraj * same notes as for the TLB_PROLOG
301176771Sraj */
302176771Sraj#define TLB_RESTORE							\
303176771Sraj	mtsprg4	%r1;			/* Save SP */			\
304176771Sraj	GET_CPUINFO(%r1);	 	/* Per-cpu structure */		\
305176771Sraj	/* calculate TLB nesting level and TLBSAVE instance addr */	\
306176771Sraj	lwz	%r28, PC_BOOKE_TLB_LEVEL(%r1);				\
307176771Sraj	subi	%r28, %r28, 1;						\
308176771Sraj	stw	%r28, PC_BOOKE_TLB_LEVEL(%r1);				\
309192532Sraj	rlwinm	%r29, %r28, 6, 23, 25; /* 4 x TLBSAVE_LEN */		\
310176771Sraj	addi	%r29, %r29, PC_BOOKE_TLBSAVE@l;				\
311176771Sraj	add	%r1, %r1, %r29;						\
312176771Sraj									\
313176771Sraj	/* restore LR, CR */						\
314176771Sraj	lwz	%r30, (TLBSAVE_BOOKE_LR)(%r1);				\
315176771Sraj	lwz	%r31, (TLBSAVE_BOOKE_CR)(%r1);				\
316176771Sraj	mtlr	%r30;							\
317176771Sraj	mtcr	%r31;							\
318176771Sraj	/* restore SRR0-1 */						\
319176771Sraj	lwz	%r30, (TLBSAVE_BOOKE_SRR0)(%r1);			\
320176771Sraj	lwz	%r31, (TLBSAVE_BOOKE_SRR1)(%r1);			\
321176771Sraj	mtsrr0	%r30;							\
322176771Sraj	mtsrr1	%r31;							\
323176771Sraj	/* restore R20-31 */						\
324176771Sraj	lmw	%r20, (TLBSAVE_BOOKE_R20)(%r1);				\
325176771Sraj	mfsprg4	%r1
326176771Sraj
327192532Sraj#ifdef SMP
328192532Sraj#define TLB_LOCK							\
329192532Sraj	GET_CPUINFO(%r20);						\
330192532Sraj	lwz	%r21, PC_CURTHREAD(%r20);				\
331192532Sraj	lwz	%r22, PC_BOOKE_TLB_LOCK(%r20);				\
332192532Sraj									\
333192532Sraj1:	lwarx	%r23, 0, %r22;						\
334215119Sraj	cmpwi	%r23, TLB_UNLOCKED;					\
335192532Sraj	beq	2f;							\
336192532Sraj									\
337192532Sraj	/* check if this is recursion */				\
338192532Sraj	cmplw	cr0, %r21, %r23;					\
339192532Sraj	bne-	1b;							\
340192532Sraj									\
341192532Sraj2:	/* try to acquire lock */					\
342192532Sraj	stwcx.	%r21, 0, %r22;						\
343192532Sraj	bne-	1b;							\
344192532Sraj									\
345192532Sraj	/* got it, update recursion counter */				\
346192532Sraj	lwz	%r21, RES_RECURSE(%r22);				\
347192532Sraj	addi	%r21, %r21, 1;						\
348192532Sraj	stw	%r21, RES_RECURSE(%r22);				\
349192532Sraj	isync;								\
350192532Sraj	msync
351176771Sraj
352192532Sraj#define TLB_UNLOCK							\
353192532Sraj	GET_CPUINFO(%r20);						\
354192532Sraj	lwz	%r21, PC_CURTHREAD(%r20);				\
355192532Sraj	lwz	%r22, PC_BOOKE_TLB_LOCK(%r20);				\
356192532Sraj									\
357192532Sraj	/* update recursion counter */					\
358192532Sraj	lwz	%r23, RES_RECURSE(%r22);				\
359192532Sraj	subi	%r23, %r23, 1;						\
360192532Sraj	stw	%r23, RES_RECURSE(%r22);				\
361192532Sraj									\
362192532Sraj	cmpwi	%r23, 0;						\
363192532Sraj	bne	1f;							\
364192532Sraj	isync;								\
365192532Sraj	msync;								\
366192532Sraj									\
367192532Sraj	/* release the lock */						\
368215119Sraj	li	%r23, TLB_UNLOCKED;					\
369192532Sraj	stw	%r23, 0(%r22);						\
370192532Sraj1:	isync;								\
371192532Sraj	msync
372192532Sraj#else
373192532Sraj#define TLB_LOCK
374192532Sraj#define TLB_UNLOCK
375192532Sraj#endif	/* SMP */
376192532Sraj
377176771Sraj#define INTERRUPT(label)						\
378176771Sraj	.globl	label;							\
379176771Sraj	.align	5;							\
380176771Sraj	CNAME(label):
381176771Sraj
382176771Sraj/*
383176771Sraj * Interrupt handling routines in BookE can be flexibly placed and do not have
384176771Sraj * to live in pre-defined vectors location. Note they need to be TLB-mapped at
385176771Sraj * all times in order to be able to handle exceptions. We thus arrange for
386176771Sraj * them to be part of kernel text which is always TLB-accessible.
387176771Sraj *
388176771Sraj * The interrupt handling routines have to be 16 bytes aligned: we align them
389176771Sraj * to 32 bytes (cache line length) which supposedly performs better.
390176771Sraj *
391176771Sraj */
392176771Sraj	.text
393176771Sraj	.globl CNAME(interrupt_vector_base)
394176771Sraj	.align 5
395176771Srajinterrupt_vector_base:
396176771Sraj
397187153Sraj/*****************************************************************************
398176771Sraj * Critical input interrupt
399187153Sraj ****************************************************************************/
400176771SrajINTERRUPT(int_critical_input)
401176771Sraj	STANDARD_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_CSRR0, SPR_CSRR1)
402176771Sraj	FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_CRIT)
403176771Sraj	addi	%r3, %r1, 8
404176771Sraj	bl	CNAME(powerpc_crit_interrupt)
405176771Sraj	FRAME_LEAVE(SPR_CSRR0, SPR_CSRR1)
406176771Sraj	rfci
407176771Sraj
408176771Sraj
409187153Sraj/*****************************************************************************
410176771Sraj * Machine check interrupt
411187153Sraj ****************************************************************************/
412176771SrajINTERRUPT(int_machine_check)
413176771Sraj	STANDARD_PROLOG(SPR_SPRG3, PC_BOOKE_MCHKSAVE, SPR_MCSRR0, SPR_MCSRR1)
414176771Sraj	FRAME_SETUP(SPR_SPRG3, PC_BOOKE_MCHKSAVE, EXC_MCHK)
415176771Sraj	addi	%r3, %r1, 8
416176771Sraj	bl	CNAME(powerpc_mchk_interrupt)
417176771Sraj	FRAME_LEAVE(SPR_MCSRR0, SPR_MCSRR1)
418176771Sraj	rfmci
419176771Sraj
420176771Sraj
421187153Sraj/*****************************************************************************
422176771Sraj * Data storage interrupt
423187153Sraj ****************************************************************************/
424176771SrajINTERRUPT(int_data_storage)
425176771Sraj	STANDARD_PROLOG(SPR_SPRG1, PC_DISISAVE, SPR_SRR0, SPR_SRR1)
426176771Sraj	FRAME_SETUP(SPR_SPRG1, PC_DISISAVE, EXC_DSI)
427176771Sraj	b	trap_common
428176771Sraj
429176771Sraj
430187153Sraj/*****************************************************************************
431176771Sraj * Instruction storage interrupt
432187153Sraj ****************************************************************************/
433176771SrajINTERRUPT(int_instr_storage)
434176771Sraj	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
435176771Sraj	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_ISI)
436176771Sraj	b	trap_common
437176771Sraj
438176771Sraj
439187153Sraj/*****************************************************************************
440176771Sraj * External input interrupt
441187153Sraj ****************************************************************************/
442176771SrajINTERRUPT(int_external_input)
443176771Sraj	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
444176771Sraj	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_EXI)
445205495Smarcel	addi	%r3, %r1, 8
446176771Sraj	bl	CNAME(powerpc_extr_interrupt)
447176771Sraj	b	trapexit
448176771Sraj
449176771Sraj
450176771SrajINTERRUPT(int_alignment)
451176771Sraj	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
452176771Sraj	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_ALI)
453176771Sraj	b	trap_common
454176771Sraj
455176771Sraj
456176771SrajINTERRUPT(int_program)
457176771Sraj	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
458176771Sraj	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_PGM)
459176771Sraj	b	trap_common
460176771Sraj
461176771Sraj
462187153Sraj/*****************************************************************************
463176771Sraj * System call
464187153Sraj ****************************************************************************/
465176771SrajINTERRUPT(int_syscall)
466176771Sraj	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
467176771Sraj	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SC)
468176771Sraj	b	trap_common
469176771Sraj
470176771Sraj
471187153Sraj/*****************************************************************************
472176771Sraj * Decrementer interrupt
473187153Sraj ****************************************************************************/
474176771SrajINTERRUPT(int_decrementer)
475176771Sraj	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
476176771Sraj	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_DECR)
477176771Sraj	addi	%r3, %r1, 8
478176771Sraj	bl	CNAME(powerpc_decr_interrupt)
479176771Sraj	b	trapexit
480176771Sraj
481176771Sraj
482187153Sraj/*****************************************************************************
483176771Sraj * Fixed interval timer
484187153Sraj ****************************************************************************/
485176771SrajINTERRUPT(int_fixed_interval_timer)
486176771Sraj	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
487176771Sraj	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_FIT)
488176771Sraj	b	trap_common
489176771Sraj
490176771Sraj
491187153Sraj/*****************************************************************************
492176771Sraj * Watchdog interrupt
493187153Sraj ****************************************************************************/
494176771SrajINTERRUPT(int_watchdog)
495176771Sraj	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
496176771Sraj	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_WDOG)
497176771Sraj	b	trap_common
498176771Sraj
499176771Sraj
500187153Sraj/*****************************************************************************
501176771Sraj * Data TLB miss interrupt
502176771Sraj *
503187153Sraj * There can be nested TLB misses - while handling a TLB miss we reference
504187153Sraj * data structures that may be not covered by translations. We support up to
505176771Sraj * TLB_NESTED_MAX-1 nested misses.
506176771Sraj *
507176771Sraj * Registers use:
508176771Sraj *	r31 - dear
509187153Sraj *	r30 - unused
510176771Sraj *	r29 - saved mas0
511176771Sraj *	r28 - saved mas1
512176771Sraj *	r27 - saved mas2
513176771Sraj *	r26 - pmap address
514176771Sraj *	r25 - pte address
515176771Sraj *
516176771Sraj *	r20:r23 - scratch registers
517187153Sraj ****************************************************************************/
518176771SrajINTERRUPT(int_data_tlb_error)
519176771Sraj	TLB_PROLOG
520192532Sraj	TLB_LOCK
521176771Sraj
522176771Sraj	mfdear	%r31
523176771Sraj
524176771Sraj	/*
525187149Sraj	 * Save MAS0-MAS2 registers. There might be another tlb miss during
526187149Sraj	 * pte lookup overwriting current contents (which was hw filled).
527176771Sraj	 */
528176771Sraj	mfspr	%r29, SPR_MAS0
529176771Sraj	mfspr	%r28, SPR_MAS1
530176771Sraj	mfspr	%r27, SPR_MAS2
531176771Sraj
532176771Sraj	/* Check faulting address. */
533176771Sraj	lis	%r21, VM_MAXUSER_ADDRESS@h
534176771Sraj	ori	%r21, %r21, VM_MAXUSER_ADDRESS@l
535176771Sraj	cmplw	cr0, %r31, %r21
536176771Sraj	blt	search_user_pmap
537176771Sraj
538176771Sraj	/* If it's kernel address, allow only supervisor mode misses. */
539176771Sraj	mfsrr1	%r21
540176771Sraj	mtcr	%r21
541176771Sraj	bt	17, search_failed	/* check MSR[PR] */
542176771Sraj
543176771Srajsearch_kernel_pmap:
544176771Sraj	/* Load r26 with kernel_pmap address */
545176771Sraj	lis	%r26, kernel_pmap_store@h
546176771Sraj	ori	%r26, %r26, kernel_pmap_store@l
547176771Sraj
548176771Sraj	/* Force kernel tid, set TID to 0 in MAS1. */
549176771Sraj	li	%r21, 0
550176771Sraj	rlwimi	%r28, %r21, 0, 8, 15	/* clear TID bits */
551176771Sraj
552176771Srajtlb_miss_handle:
553176771Sraj	/* This may result in nested tlb miss. */
554176771Sraj	bl	pte_lookup		/* returns PTE address in R25 */
555176771Sraj
556176771Sraj	cmpwi	%r25, 0			/* pte found? */
557176771Sraj	beq	search_failed
558176771Sraj
559176771Sraj	/* Finish up, write TLB entry. */
560176771Sraj	bl	tlb_fill_entry
561176771Sraj
562176771Srajtlb_miss_return:
563192532Sraj	TLB_UNLOCK
564176771Sraj	TLB_RESTORE
565176771Sraj	rfi
566176771Sraj
567176771Srajsearch_user_pmap:
568176771Sraj	/* Load r26 with current user space process pmap */
569176771Sraj	GET_CPUINFO(%r26)
570176771Sraj	lwz	%r26, PC_CURPMAP(%r26)
571176771Sraj
572176771Sraj	b	tlb_miss_handle
573176771Sraj
574176771Srajsearch_failed:
575176771Sraj	/*
576176771Sraj	 * Whenever we don't find a TLB mapping in PT, set a TLB0 entry with
577176771Sraj	 * the faulting virtual address anyway, but put a fake RPN and no
578176771Sraj	 * access rights. This should cause a following {D,I}SI exception.
579176771Sraj	 */
580176771Sraj	lis	%r23, 0xffff0000@h	/* revoke all permissions */
581176771Sraj
582176771Sraj	/* Load MAS registers. */
583176771Sraj	mtspr	SPR_MAS0, %r29
584176771Sraj	isync
585176771Sraj	mtspr	SPR_MAS1, %r28
586176771Sraj	isync
587176771Sraj	mtspr	SPR_MAS2, %r27
588176771Sraj	isync
589176771Sraj	mtspr	SPR_MAS3, %r23
590176771Sraj	isync
591176771Sraj
592176771Sraj	tlbwe
593176771Sraj	msync
594176771Sraj	isync
595176771Sraj	b	tlb_miss_return
596176771Sraj
597187149Sraj/*****************************************************************************
598176771Sraj *
599187149Sraj * Return pte address that corresponds to given pmap/va.  If there is no valid
600187149Sraj * entry return 0.
601176771Sraj *
602176771Sraj * input: r26 - pmap
603176771Sraj * input: r31 - dear
604176771Sraj * output: r25 - pte address
605176771Sraj *
606176771Sraj * scratch regs used: r21
607187149Sraj *
608187149Sraj ****************************************************************************/
609176771Srajpte_lookup:
610176771Sraj	cmpwi	%r26, 0
611176771Sraj	beq	1f			/* fail quickly if pmap is invalid */
612176771Sraj
613176771Sraj	srwi	%r21, %r31, PDIR_SHIFT		/* pdir offset */
614176771Sraj	slwi	%r21, %r21, PDIR_ENTRY_SHIFT	/* multiply by pdir entry size */
615176771Sraj
616176771Sraj	addi	%r25, %r26, PM_PDIR	/* pmap pm_dir[] address */
617176771Sraj	add	%r25, %r25, %r21	/* offset within pm_pdir[] table */
618187153Sraj	/*
619187153Sraj	 * Get ptbl address, i.e. pmap->pm_pdir[pdir_idx]
620187153Sraj	 * This load may cause a Data TLB miss for non-kernel pmap!
621187153Sraj	 */
622187153Sraj	lwz	%r25, 0(%r25)
623176771Sraj	cmpwi	%r25, 0
624176771Sraj	beq	2f
625176771Sraj
626176771Sraj	lis	%r21, PTBL_MASK@h
627176771Sraj	ori	%r21, %r21, PTBL_MASK@l
628176771Sraj	and	%r21, %r21, %r31
629176771Sraj
630176771Sraj	/* ptbl offset, multiply by ptbl entry size */
631176771Sraj	srwi	%r21, %r21, (PTBL_SHIFT - PTBL_ENTRY_SHIFT)
632176771Sraj
633176771Sraj	add	%r25, %r25, %r21		/* address of pte entry */
634187153Sraj	/*
635187153Sraj	 * Get pte->flags
636187153Sraj	 * This load may cause a Data TLB miss for non-kernel pmap!
637187153Sraj	 */
638187153Sraj	lwz	%r21, PTE_FLAGS(%r25)
639176771Sraj	andis.	%r21, %r21, PTE_VALID@h
640176771Sraj	bne	2f
641176771Sraj1:
642176771Sraj	li	%r25, 0
643176771Sraj2:
644176771Sraj	blr
645176771Sraj
646187149Sraj/*****************************************************************************
647176771Sraj *
648187149Sraj * Load MAS1-MAS3 registers with data, write TLB entry
649187149Sraj *
650176771Sraj * input:
651176771Sraj * r29 - mas0
652176771Sraj * r28 - mas1
653176771Sraj * r27 - mas2
654176771Sraj * r25 - pte
655176771Sraj *
656176771Sraj * output: none
657176771Sraj *
658176771Sraj * scratch regs: r21-r23
659187149Sraj *
660187149Sraj ****************************************************************************/
661176771Srajtlb_fill_entry:
662187149Sraj	/*
663187149Sraj	 * Update PTE flags: we have to do it atomically, as pmap_protect()
664187149Sraj	 * running on other CPUs could attempt to update the flags at the same
665187149Sraj	 * time.
666187149Sraj	 */
667187149Sraj	li	%r23, PTE_FLAGS
668187149Sraj1:
669187149Sraj	lwarx	%r21, %r23, %r25		/* get pte->flags */
670176771Sraj	oris	%r21, %r21, PTE_REFERENCED@h	/* set referenced bit */
671176771Sraj
672238033Smarcel	andi.	%r22, %r21, (PTE_SW | PTE_UW)@l	/* check if writable */
673187149Sraj	beq	2f
674176771Sraj	oris	%r21, %r21, PTE_MODIFIED@h	/* set modified bit */
675187149Sraj2:
676187149Sraj	stwcx.	%r21, %r23, %r25		/* write it back */
677187149Sraj	bne-	1b
678176771Sraj
679176771Sraj	/* Update MAS2. */
680176771Sraj	rlwimi	%r27, %r21, 0, 27, 30		/* insert WIMG bits from pte */
681176771Sraj
682176771Sraj	/* Setup MAS3 value in r23. */
683176771Sraj	lwz	%r23, PTE_RPN(%r25)		/* get pte->rpn */
684176771Sraj
685176771Sraj	rlwimi	%r23, %r21, 24, 26, 31		/* insert protection bits from pte */
686176771Sraj
687176771Sraj	/* Load MAS registers. */
688176771Sraj	mtspr	SPR_MAS0, %r29
689176771Sraj	isync
690176771Sraj	mtspr	SPR_MAS1, %r28
691176771Sraj	isync
692176771Sraj	mtspr	SPR_MAS2, %r27
693176771Sraj	isync
694176771Sraj	mtspr	SPR_MAS3, %r23
695176771Sraj	isync
696176771Sraj
697176771Sraj	tlbwe
698176771Sraj	isync
699176771Sraj	msync
700176771Sraj	blr
701176771Sraj
702187153Sraj/*****************************************************************************
703176771Sraj * Instruction TLB miss interrupt
704176771Sraj *
705176771Sraj * Same notes as for the Data TLB miss
706187153Sraj ****************************************************************************/
707176771SrajINTERRUPT(int_inst_tlb_error)
708176771Sraj	TLB_PROLOG
709192532Sraj	TLB_LOCK
710176771Sraj
711176771Sraj	mfsrr0	%r31			/* faulting address */
712176771Sraj
713176771Sraj	/*
714176771Sraj	 * Save MAS0-MAS2 registers. There might be another tlb miss during pte
715176771Sraj	 * lookup overwriting current contents (which was hw filled).
716176771Sraj	 */
717176771Sraj	mfspr	%r29, SPR_MAS0
718176771Sraj	mfspr	%r28, SPR_MAS1
719176771Sraj	mfspr	%r27, SPR_MAS2
720176771Sraj
721176771Sraj	mfsrr1	%r21
722176771Sraj	mtcr	%r21
723176771Sraj
724176771Sraj	/* check MSR[PR] */
725176771Sraj	bt	17, search_user_pmap
726176771Sraj	b	search_kernel_pmap
727176771Sraj
728176771Sraj
729176771Sraj	.globl	interrupt_vector_top
730176771Srajinterrupt_vector_top:
731176771Sraj
732187153Sraj/*****************************************************************************
733176771Sraj * Debug interrupt
734187153Sraj ****************************************************************************/
735176771SrajINTERRUPT(int_debug)
736176771Sraj	STANDARD_CRIT_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_CSRR0, SPR_CSRR1)
737176771Sraj	FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_DEBUG)
738266001Sian	GET_CPUINFO(%r3)
739266001Sian	lwz	%r3, (PC_BOOKE_CRITSAVE+CPUSAVE_SRR0)(%r3)
740176771Sraj	lis	%r4, interrupt_vector_base@ha
741176771Sraj	addi	%r4, %r4, interrupt_vector_base@l
742176771Sraj	cmplw	cr0, %r3, %r4
743176771Sraj	blt	1f
744176771Sraj	lis	%r4, interrupt_vector_top@ha
745176771Sraj	addi	%r4, %r4, interrupt_vector_top@l
746176771Sraj	cmplw	cr0, %r3, %r4
747176771Sraj	bge	1f
748176771Sraj	/* Disable single-stepping for the interrupt handlers. */
749176771Sraj	lwz	%r3, FRAME_SRR1+8(%r1);
750187153Sraj	rlwinm	%r3, %r3, 0, 23, 21
751176771Sraj	stw	%r3, FRAME_SRR1+8(%r1);
752176771Sraj	/* Restore srr0 and srr1 as they could have been clobbered. */
753266001Sian	GET_CPUINFO(%r4)
754266001Sian	lwz	%r3, (PC_BOOKE_CRITSAVE+CPUSAVE_SRR0+8)(%r4);
755176771Sraj	mtspr	SPR_SRR0, %r3
756266001Sian	lwz	%r4, (PC_BOOKE_CRITSAVE+CPUSAVE_SRR1+8)(%r4);
757176771Sraj	mtspr	SPR_SRR1, %r4
758176771Sraj	b	9f
759176771Sraj1:
760176771Sraj	addi	%r3, %r1, 8
761176771Sraj	bl	CNAME(trap)
762176771Sraj	/*
763176771Sraj	 * Handle ASTs, needed for proper support of single-stepping.
764176771Sraj	 * We actually need to return to the process with an rfi.
765176771Sraj	 */
766176771Sraj	b	trapexit
767176771Sraj9:
768176771Sraj	FRAME_LEAVE(SPR_CSRR0, SPR_CSRR1)
769176771Sraj	rfci
770176771Sraj
771176771Sraj
772187153Sraj/*****************************************************************************
773176771Sraj * Common trap code
774187153Sraj ****************************************************************************/
775176771Srajtrap_common:
776176771Sraj	/* Call C trap dispatcher */
777176771Sraj	addi	%r3, %r1, 8
778176771Sraj	bl	CNAME(trap)
779176771Sraj
780176771Sraj	.globl	CNAME(trapexit)		/* exported for db_backtrace use */
781176771SrajCNAME(trapexit):
782176771Sraj	/* disable interrupts */
783176771Sraj	wrteei	0
784176771Sraj
785176771Sraj	/* Test AST pending - makes sense for user process only */
786176771Sraj	lwz	%r5, FRAME_SRR1+8(%r1)
787176771Sraj	mtcr	%r5
788176771Sraj	bf	17, 1f
789176771Sraj
790176771Sraj	GET_CPUINFO(%r3)
791176771Sraj	lwz	%r4, PC_CURTHREAD(%r3)
792176771Sraj	lwz	%r4, TD_FLAGS(%r4)
793187153Sraj	lis	%r5, (TDF_ASTPENDING | TDF_NEEDRESCHED)@h
794187153Sraj	ori	%r5, %r5, (TDF_ASTPENDING | TDF_NEEDRESCHED)@l
795176771Sraj	and.	%r4, %r4, %r5
796176771Sraj	beq	1f
797176771Sraj
798176771Sraj	/* re-enable interrupts before calling ast() */
799176771Sraj	wrteei	1
800176771Sraj
801176771Sraj	addi	%r3, %r1, 8
802176771Sraj	bl	CNAME(ast)
803176771Sraj	.globl	CNAME(asttrapexit)	/* db_backtrace code sentinel #2 */
804176771SrajCNAME(asttrapexit):
805176771Sraj	b	trapexit		/* test ast ret value ? */
806176771Sraj1:
807176771Sraj	FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
808176771Sraj	rfi
809176771Sraj
810176771Sraj
811176771Sraj#if defined(KDB)
812176771Sraj/*
813176771Sraj * Deliberate entry to dbtrap
814176771Sraj */
815178628Smarcel	.globl	CNAME(breakpoint)
816178628SmarcelCNAME(breakpoint):
817176771Sraj	mtsprg1	%r1
818176771Sraj	mfmsr	%r3
819176771Sraj	mtsrr1	%r3
820187153Sraj	andi.	%r3, %r3, ~(PSL_EE | PSL_ME)@l
821176771Sraj	mtmsr	%r3			/* disable interrupts */
822176771Sraj	isync
823176771Sraj	GET_CPUINFO(%r3)
824187153Sraj	stw	%r30, (PC_DBSAVE+CPUSAVE_R30)(%r3)
825187153Sraj	stw	%r31, (PC_DBSAVE+CPUSAVE_R31)(%r3)
826176771Sraj
827176771Sraj	mflr	%r31
828176771Sraj	mtsrr0	%r31
829176771Sraj
830176771Sraj	mfdear	%r30
831176771Sraj	mfesr	%r31
832176771Sraj	stw	%r30, (PC_DBSAVE+CPUSAVE_BOOKE_DEAR)(%r3)
833176771Sraj	stw	%r31, (PC_DBSAVE+CPUSAVE_BOOKE_ESR)(%r3)
834176771Sraj
835176771Sraj	mfsrr0	%r30
836176771Sraj	mfsrr1	%r31
837176771Sraj	stw	%r30, (PC_DBSAVE+CPUSAVE_SRR0)(%r3)
838176771Sraj	stw	%r31, (PC_DBSAVE+CPUSAVE_SRR1)(%r3)
839176771Sraj	isync
840176771Sraj
841176771Sraj	mfcr	%r30
842176771Sraj
843176771Sraj/*
844176771Sraj * Now the kdb trap catching code.
845176771Sraj */
846176771Srajdbtrap:
847176771Sraj	FRAME_SETUP(SPR_SPRG1, PC_DBSAVE, EXC_DEBUG)
848176771Sraj/* Call C trap code: */
849187153Sraj	addi	%r3, %r1, 8
850176771Sraj	bl	CNAME(db_trap_glue)
851187153Sraj	or.	%r3, %r3, %r3
852176771Sraj	bne	dbleave
853176771Sraj/* This wasn't for KDB, so switch to real trap: */
854176771Sraj	b	trap_common
855176771Sraj
856176771Srajdbleave:
857176771Sraj	FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
858176771Sraj	rfi
859176771Sraj#endif /* KDB */
860192532Sraj
861192532Sraj#ifdef SMP
862192532SrajENTRY(tlb_lock)
863192532Sraj	GET_CPUINFO(%r5)
864192532Sraj	lwz	%r5, PC_CURTHREAD(%r5)
865192532Sraj1:	lwarx	%r4, 0, %r3
866215119Sraj	cmpwi	%r4, TLB_UNLOCKED
867192532Sraj	bne	1b
868192532Sraj	stwcx.	%r5, 0, %r3
869192532Sraj	bne-	1b
870192532Sraj	isync
871192532Sraj	msync
872192532Sraj	blr
873192532Sraj
874192532SrajENTRY(tlb_unlock)
875192532Sraj	isync
876192532Sraj	msync
877215119Sraj	li	%r4, TLB_UNLOCKED
878192532Sraj	stw	%r4, 0(%r3)
879192532Sraj	isync
880192532Sraj	msync
881192532Sraj	blr
882215119Sraj
883192532Sraj/*
884192532Sraj * TLB miss spin locks. For each CPU we have a reservation granule (32 bytes);
885192532Sraj * only a single word from this granule will actually be used as a spin lock
886192532Sraj * for mutual exclusion between TLB miss handler and pmap layer that
887192532Sraj * manipulates page table contents.
888192532Sraj */
889192532Sraj	.data
890192532Sraj	.align	5
891192532SrajGLOBAL(tlb0_miss_locks)
892192532Sraj	.space	RES_GRANULE * MAXCPU
893192532Sraj#endif
894