1 /*-
2 * Copyright (C) 2006-2009 Semihalf, Rafal Jaworowski <raj@semihalf.com>
3 * Copyright (C) 2006 Semihalf, Marian Balakowicz <m8@semihalf.com>
4 * Copyright (C) 2006 Juniper Networks, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
21 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $FreeBSD$
30 */
31 /*-
32 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
33 * Copyright (C) 1995, 1996 TooLs GmbH.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by TooLs GmbH.
47 * 4. The name of TooLs GmbH may not be used to endorse or promote products
48 * derived from this software without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
51 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
52 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
53 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
55 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
56 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
57 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
58 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
59 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 *
61 * from: $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $
62 */
63
64 /*
65 * NOTICE: This is not a standalone file. to use it, #include it in
66 * your port's locore.S, like so:
67 *
68 * #include <powerpc/booke/trap_subr.S>
69 */
70
71 /*
72 * SPRG usage notes
73 *
74 * SPRG0 - pcpu pointer
75 * SPRG1 - all interrupts except TLB miss, critical, machine check
76 * SPRG2 - critical
77 * SPRG3 - machine check
78 * SPRG4-6 - scratch
79 *
80 */
81
82 /* Get the per-CPU data structure */
83 #define GET_CPUINFO(r) mfsprg0 r
84
85 #define RES_GRANULE 64
86 #define RES_LOCK 0 /* offset to the 'lock' word */
87 #ifdef __powerpc64__
88 #define RES_RECURSE 8 /* offset to the 'recurse' word */
89 #else
90 #define RES_RECURSE 4 /* offset to the 'recurse' word */
91 #endif
92
93 /*
94 * Standard interrupt prolog
95 *
96 * sprg_sp - SPRG{1-3} reg used to temporarily store the SP
97 * savearea - temp save area (pc_{tempsave, disisave, critsave, mchksave})
98 * isrr0-1 - save restore registers with CPU state at interrupt time (may be
99 * SRR0-1, CSRR0-1, MCSRR0-1
100 *
101 * 1. saves in the given savearea:
102 * - R30-31
103 * - DEAR, ESR
104 * - xSRR0-1
105 *
106 * 2. saves CR -> R30
107 *
108 * 3. switches to kstack if needed
109 *
110 * 4. notes:
111 * - R31 can be used as scratch register until a new frame is laid on
112 * the stack with FRAME_SETUP
113 *
114 * - potential TLB miss: NO. Saveareas are always acessible via TLB1
115 * permanent entries, and within this prolog we do not dereference any
116 * locations potentially not in the TLB
117 */
118 #define STANDARD_PROLOG(sprg_sp, savearea, isrr0, isrr1) \
119 mtspr sprg_sp, %r1; /* Save SP */ \
120 GET_CPUINFO(%r1); /* Per-cpu structure */ \
121 STORE %r30, (savearea+CPUSAVE_R30)(%r1); \
122 STORE %r31, (savearea+CPUSAVE_R31)(%r1); \
123 mfspr %r30, SPR_DEAR; \
124 mfspr %r31, SPR_ESR; \
125 STORE %r30, (savearea+CPUSAVE_BOOKE_DEAR)(%r1); \
126 STORE %r31, (savearea+CPUSAVE_BOOKE_ESR)(%r1); \
127 mfspr %r30, isrr0; \
128 mfspr %r31, isrr1; /* MSR at interrupt time */ \
129 STORE %r30, (savearea+CPUSAVE_SRR0)(%r1); \
130 STORE %r31, (savearea+CPUSAVE_SRR1)(%r1); \
131 isync; \
132 mfspr %r1, sprg_sp; /* Restore SP */ \
133 mfcr %r30; /* Save CR */ \
134 /* switch to per-thread kstack if intr taken in user mode */ \
135 mtcr %r31; /* MSR at interrupt time */ \
136 bf 17, 1f; \
137 GET_CPUINFO(%r1); /* Per-cpu structure */ \
138 LOAD %r1, PC_CURPCB(%r1); /* Per-thread kernel stack */ \
139 1:
140
141 #define STANDARD_CRIT_PROLOG(sprg_sp, savearea, isrr0, isrr1) \
142 mtspr sprg_sp, %r1; /* Save SP */ \
143 GET_CPUINFO(%r1); /* Per-cpu structure */ \
144 STORE %r30, (savearea+CPUSAVE_R30)(%r1); \
145 STORE %r31, (savearea+CPUSAVE_R31)(%r1); \
146 mfspr %r30, SPR_DEAR; \
147 mfspr %r31, SPR_ESR; \
148 STORE %r30, (savearea+CPUSAVE_BOOKE_DEAR)(%r1); \
149 STORE %r31, (savearea+CPUSAVE_BOOKE_ESR)(%r1); \
150 mfspr %r30, isrr0; \
151 mfspr %r31, isrr1; /* MSR at interrupt time */ \
152 STORE %r30, (savearea+CPUSAVE_SRR0)(%r1); \
153 STORE %r31, (savearea+CPUSAVE_SRR1)(%r1); \
154 mfspr %r30, SPR_SRR0; \
155 mfspr %r31, SPR_SRR1; /* MSR at interrupt time */ \
156 STORE %r30, (savearea+BOOKE_CRITSAVE_SRR0)(%r1); \
157 STORE %r31, (savearea+BOOKE_CRITSAVE_SRR1)(%r1); \
158 isync; \
159 mfspr %r1, sprg_sp; /* Restore SP */ \
160 mfcr %r30; /* Save CR */ \
161 /* switch to per-thread kstack if intr taken in user mode */ \
162 mtcr %r31; /* MSR at interrupt time */ \
163 bf 17, 1f; \
164 GET_CPUINFO(%r1); /* Per-cpu structure */ \
165 LOAD %r1, PC_CURPCB(%r1); /* Per-thread kernel stack */ \
166 1:
167
168 /*
169 * FRAME_SETUP assumes:
170 * SPRG{1-3} SP at the time interrupt occurred
171 * savearea r30-r31, DEAR, ESR, xSRR0-1
172 * r30 CR
173 * r31 scratch
174 * r1 kernel stack
175 *
176 * sprg_sp - SPRG reg containing SP at the time interrupt occurred
177 * savearea - temp save
178 * exc - exception number (EXC_xxx)
179 *
180 * 1. sets a new frame
181 * 2. saves in the frame:
182 * - R0, R1 (SP at the time of interrupt), R2, LR, CR
183 * - R3-31 (R30-31 first restored from savearea)
184 * - XER, CTR, DEAR, ESR (from savearea), xSRR0-1
185 *
186 * Notes:
187 * - potential TLB miss: YES, since we make dereferences to kstack, which
188 * can happen not covered (we can have up to two DTLB misses if fortunate
189 * enough i.e. when kstack crosses page boundary and both pages are
190 * untranslated)
191 */
192 #ifdef __powerpc64__
193 #define SAVE_REGS(r) \
194 std %r3, FRAME_3+CALLSIZE(r); \
195 std %r4, FRAME_4+CALLSIZE(r); \
196 std %r5, FRAME_5+CALLSIZE(r); \
197 std %r6, FRAME_6+CALLSIZE(r); \
198 std %r7, FRAME_7+CALLSIZE(r); \
199 std %r8, FRAME_8+CALLSIZE(r); \
200 std %r9, FRAME_9+CALLSIZE(r); \
201 std %r10, FRAME_10+CALLSIZE(r); \
202 std %r11, FRAME_11+CALLSIZE(r); \
203 std %r12, FRAME_12+CALLSIZE(r); \
204 std %r13, FRAME_13+CALLSIZE(r); \
205 std %r14, FRAME_14+CALLSIZE(r); \
206 std %r15, FRAME_15+CALLSIZE(r); \
207 std %r16, FRAME_16+CALLSIZE(r); \
208 std %r17, FRAME_17+CALLSIZE(r); \
209 std %r18, FRAME_18+CALLSIZE(r); \
210 std %r19, FRAME_19+CALLSIZE(r); \
211 std %r20, FRAME_20+CALLSIZE(r); \
212 std %r21, FRAME_21+CALLSIZE(r); \
213 std %r22, FRAME_22+CALLSIZE(r); \
214 std %r23, FRAME_23+CALLSIZE(r); \
215 std %r24, FRAME_24+CALLSIZE(r); \
216 std %r25, FRAME_25+CALLSIZE(r); \
217 std %r26, FRAME_26+CALLSIZE(r); \
218 std %r27, FRAME_27+CALLSIZE(r); \
219 std %r28, FRAME_28+CALLSIZE(r); \
220 std %r29, FRAME_29+CALLSIZE(r); \
221 std %r30, FRAME_30+CALLSIZE(r); \
222 std %r31, FRAME_31+CALLSIZE(r)
223 #define LD_REGS(r) \
224 ld %r3, FRAME_3+CALLSIZE(r); \
225 ld %r4, FRAME_4+CALLSIZE(r); \
226 ld %r5, FRAME_5+CALLSIZE(r); \
227 ld %r6, FRAME_6+CALLSIZE(r); \
228 ld %r7, FRAME_7+CALLSIZE(r); \
229 ld %r8, FRAME_8+CALLSIZE(r); \
230 ld %r9, FRAME_9+CALLSIZE(r); \
231 ld %r10, FRAME_10+CALLSIZE(r); \
232 ld %r11, FRAME_11+CALLSIZE(r); \
233 ld %r12, FRAME_12+CALLSIZE(r); \
234 ld %r13, FRAME_13+CALLSIZE(r); \
235 ld %r14, FRAME_14+CALLSIZE(r); \
236 ld %r15, FRAME_15+CALLSIZE(r); \
237 ld %r16, FRAME_16+CALLSIZE(r); \
238 ld %r17, FRAME_17+CALLSIZE(r); \
239 ld %r18, FRAME_18+CALLSIZE(r); \
240 ld %r19, FRAME_19+CALLSIZE(r); \
241 ld %r20, FRAME_20+CALLSIZE(r); \
242 ld %r21, FRAME_21+CALLSIZE(r); \
243 ld %r22, FRAME_22+CALLSIZE(r); \
244 ld %r23, FRAME_23+CALLSIZE(r); \
245 ld %r24, FRAME_24+CALLSIZE(r); \
246 ld %r25, FRAME_25+CALLSIZE(r); \
247 ld %r26, FRAME_26+CALLSIZE(r); \
248 ld %r27, FRAME_27+CALLSIZE(r); \
249 ld %r28, FRAME_28+CALLSIZE(r); \
250 ld %r29, FRAME_29+CALLSIZE(r); \
251 ld %r30, FRAME_30+CALLSIZE(r); \
252 ld %r31, FRAME_31+CALLSIZE(r)
253 #else
254 #define SAVE_REGS(r) \
255 stmw %r3, FRAME_3+CALLSIZE(r)
256 #define LD_REGS(r) \
257 lmw %r3, FRAME_3+CALLSIZE(r)
258 #endif
259 #define FRAME_SETUP(sprg_sp, savearea, exc) \
260 mfspr %r31, sprg_sp; /* get saved SP */ \
261 /* establish a new stack frame and put everything on it */ \
262 STU %r31, -(FRAMELEN+REDZONE)(%r1); \
263 STORE %r0, FRAME_0+CALLSIZE(%r1); /* save r0 in the trapframe */ \
264 STORE %r31, FRAME_1+CALLSIZE(%r1); /* save SP " " */ \
265 STORE %r2, FRAME_2+CALLSIZE(%r1); /* save r2 " " */ \
266 mflr %r31; \
267 STORE %r31, FRAME_LR+CALLSIZE(%r1); /* save LR " " */ \
268 STORE %r30, FRAME_CR+CALLSIZE(%r1); /* save CR " " */ \
269 GET_CPUINFO(%r2); \
270 LOAD %r30, (savearea+CPUSAVE_R30)(%r2); /* get saved r30 */ \
271 LOAD %r31, (savearea+CPUSAVE_R31)(%r2); /* get saved r31 */ \
272 /* save R3-31 */ \
273 SAVE_REGS(%r1); \
274 /* save DEAR, ESR */ \
275 LOAD %r28, (savearea+CPUSAVE_BOOKE_DEAR)(%r2); \
276 LOAD %r29, (savearea+CPUSAVE_BOOKE_ESR)(%r2); \
277 STORE %r28, FRAME_BOOKE_DEAR+CALLSIZE(%r1); \
278 STORE %r29, FRAME_BOOKE_ESR+CALLSIZE(%r1); \
279 /* save XER, CTR, exc number */ \
280 mfxer %r3; \
281 mfctr %r4; \
282 STORE %r3, FRAME_XER+CALLSIZE(%r1); \
283 STORE %r4, FRAME_CTR+CALLSIZE(%r1); \
284 li %r5, exc; \
285 STORE %r5, FRAME_EXC+CALLSIZE(%r1); \
286 /* save DBCR0 */ \
287 mfspr %r3, SPR_DBCR0; \
288 STORE %r3, FRAME_BOOKE_DBCR0+CALLSIZE(%r1); \
289 /* save xSSR0-1 */ \
290 LOAD %r30, (savearea+CPUSAVE_SRR0)(%r2); \
291 LOAD %r31, (savearea+CPUSAVE_SRR1)(%r2); \
292 STORE %r30, FRAME_SRR0+CALLSIZE(%r1); \
293 STORE %r31, FRAME_SRR1+CALLSIZE(%r1); \
294 LOAD THREAD_REG, PC_CURTHREAD(%r2); \
295
296 /*
297 *
298 * isrr0-1 - save restore registers to restore CPU state to (may be
299 * SRR0-1, CSRR0-1, MCSRR0-1
300 *
301 * Notes:
302 * - potential TLB miss: YES. The deref'd kstack may be not covered
303 */
304 #define FRAME_LEAVE(isrr0, isrr1) \
305 wrteei 0; \
306 /* restore CTR, XER, LR, CR */ \
307 LOAD %r4, FRAME_CTR+CALLSIZE(%r1); \
308 LOAD %r5, FRAME_XER+CALLSIZE(%r1); \
309 LOAD %r6, FRAME_LR+CALLSIZE(%r1); \
310 LOAD %r7, FRAME_CR+CALLSIZE(%r1); \
311 mtctr %r4; \
312 mtxer %r5; \
313 mtlr %r6; \
314 mtcr %r7; \
315 /* restore DBCR0 */ \
316 LOAD %r4, FRAME_BOOKE_DBCR0+CALLSIZE(%r1); \
317 mtspr SPR_DBCR0, %r4; \
318 /* restore xSRR0-1 */ \
319 LOAD %r30, FRAME_SRR0+CALLSIZE(%r1); \
320 LOAD %r31, FRAME_SRR1+CALLSIZE(%r1); \
321 mtspr isrr0, %r30; \
322 mtspr isrr1, %r31; \
323 /* restore R2-31, SP */ \
324 LD_REGS(%r1); \
325 LOAD %r2, FRAME_2+CALLSIZE(%r1); \
326 LOAD %r0, FRAME_0+CALLSIZE(%r1); \
327 LOAD %r1, FRAME_1+CALLSIZE(%r1); \
328 isync
329
330 /*
331 * TLB miss prolog
332 *
333 * saves LR, CR, SRR0-1, R20-31 in the TLBSAVE area
334 *
335 * Notes:
336 * - potential TLB miss: NO. It is crucial that we do not generate a TLB
337 * miss within the TLB prolog itself!
338 * - TLBSAVE is always translated
339 */
340 #ifdef __powerpc64__
341 #define TLB_SAVE_REGS(br) \
342 std %r20, (TLBSAVE_BOOKE_R20)(br); \
343 std %r21, (TLBSAVE_BOOKE_R21)(br); \
344 std %r22, (TLBSAVE_BOOKE_R22)(br); \
345 std %r23, (TLBSAVE_BOOKE_R23)(br); \
346 std %r24, (TLBSAVE_BOOKE_R24)(br); \
347 std %r25, (TLBSAVE_BOOKE_R25)(br); \
348 std %r26, (TLBSAVE_BOOKE_R26)(br); \
349 std %r27, (TLBSAVE_BOOKE_R27)(br); \
350 std %r28, (TLBSAVE_BOOKE_R28)(br); \
351 std %r29, (TLBSAVE_BOOKE_R29)(br); \
352 std %r30, (TLBSAVE_BOOKE_R30)(br); \
353 std %r31, (TLBSAVE_BOOKE_R31)(br);
354 #define TLB_RESTORE_REGS(br) \
355 ld %r20, (TLBSAVE_BOOKE_R20)(br); \
356 ld %r21, (TLBSAVE_BOOKE_R21)(br); \
357 ld %r22, (TLBSAVE_BOOKE_R22)(br); \
358 ld %r23, (TLBSAVE_BOOKE_R23)(br); \
359 ld %r24, (TLBSAVE_BOOKE_R24)(br); \
360 ld %r25, (TLBSAVE_BOOKE_R25)(br); \
361 ld %r26, (TLBSAVE_BOOKE_R26)(br); \
362 ld %r27, (TLBSAVE_BOOKE_R27)(br); \
363 ld %r28, (TLBSAVE_BOOKE_R28)(br); \
364 ld %r29, (TLBSAVE_BOOKE_R29)(br); \
365 ld %r30, (TLBSAVE_BOOKE_R30)(br); \
366 ld %r31, (TLBSAVE_BOOKE_R31)(br);
367 #define TLB_NEST(outr,inr) \
368 rlwinm outr, inr, 7, 23, 24; /* 8 x TLBSAVE_LEN */
369 #else
370 #define TLB_SAVE_REGS(br) \
371 stmw %r20, TLBSAVE_BOOKE_R20(br)
372 #define TLB_RESTORE_REGS(br) \
373 lmw %r20, TLBSAVE_BOOKE_R20(br)
374 #define TLB_NEST(outr,inr) \
375 rlwinm outr, inr, 6, 24, 25; /* 4 x TLBSAVE_LEN */
376 #endif
377 #define TLB_PROLOG \
378 mtspr SPR_SPRG4, %r1; /* Save SP */ \
379 mtspr SPR_SPRG5, %r28; \
380 mtspr SPR_SPRG6, %r29; \
381 /* calculate TLB nesting level and TLBSAVE instance address */ \
382 GET_CPUINFO(%r1); /* Per-cpu structure */ \
383 LOAD %r28, PC_BOOKE_TLB_LEVEL(%r1); \
384 TLB_NEST(%r29,%r28); \
385 addi %r28, %r28, 1; \
386 STORE %r28, PC_BOOKE_TLB_LEVEL(%r1); \
387 addi %r29, %r29, PC_BOOKE_TLBSAVE@l; \
388 add %r1, %r1, %r29; /* current TLBSAVE ptr */ \
389 \
390 /* save R20-31 */ \
391 mfspr %r28, SPR_SPRG5; \
392 mfspr %r29, SPR_SPRG6; \
393 TLB_SAVE_REGS(%r1); \
394 /* save LR, CR */ \
395 mflr %r30; \
396 mfcr %r31; \
397 STORE %r30, (TLBSAVE_BOOKE_LR)(%r1); \
398 STORE %r31, (TLBSAVE_BOOKE_CR)(%r1); \
399 /* save SRR0-1 */ \
400 mfsrr0 %r30; /* execution addr at interrupt time */ \
401 mfsrr1 %r31; /* MSR at interrupt time*/ \
402 STORE %r30, (TLBSAVE_BOOKE_SRR0)(%r1); /* save SRR0 */ \
403 STORE %r31, (TLBSAVE_BOOKE_SRR1)(%r1); /* save SRR1 */ \
404 isync; \
405 mfspr %r1, SPR_SPRG4
406
407 /*
408 * restores LR, CR, SRR0-1, R20-31 from the TLBSAVE area
409 *
410 * same notes as for the TLB_PROLOG
411 */
412 #define TLB_RESTORE \
413 mtspr SPR_SPRG4, %r1; /* Save SP */ \
414 GET_CPUINFO(%r1); /* Per-cpu structure */ \
415 /* calculate TLB nesting level and TLBSAVE instance addr */ \
416 LOAD %r28, PC_BOOKE_TLB_LEVEL(%r1); \
417 subi %r28, %r28, 1; \
418 STORE %r28, PC_BOOKE_TLB_LEVEL(%r1); \
419 TLB_NEST(%r29,%r28); \
420 addi %r29, %r29, PC_BOOKE_TLBSAVE@l; \
421 add %r1, %r1, %r29; \
422 \
423 /* restore LR, CR */ \
424 LOAD %r30, (TLBSAVE_BOOKE_LR)(%r1); \
425 LOAD %r31, (TLBSAVE_BOOKE_CR)(%r1); \
426 mtlr %r30; \
427 mtcr %r31; \
428 /* restore SRR0-1 */ \
429 LOAD %r30, (TLBSAVE_BOOKE_SRR0)(%r1); \
430 LOAD %r31, (TLBSAVE_BOOKE_SRR1)(%r1); \
431 mtsrr0 %r30; \
432 mtsrr1 %r31; \
433 /* restore R20-31 */ \
434 TLB_RESTORE_REGS(%r1); \
435 mfspr %r1, SPR_SPRG4
436
437 #ifdef SMP
438 #define TLB_LOCK \
439 GET_CPUINFO(%r20); \
440 LOAD %r21, PC_CURTHREAD(%r20); \
441 LOAD %r22, PC_BOOKE_TLB_LOCK(%r20); \
442 \
443 1: LOADX %r23, 0, %r22; \
444 CMPI %r23, TLB_UNLOCKED; \
445 beq 2f; \
446 \
447 /* check if this is recursion */ \
448 CMPL cr0, %r21, %r23; \
449 bne- 1b; \
450 \
451 2: /* try to acquire lock */ \
452 STOREX %r21, 0, %r22; \
453 bne- 1b; \
454 \
455 /* got it, update recursion counter */ \
456 lwz %r21, RES_RECURSE(%r22); \
457 addi %r21, %r21, 1; \
458 stw %r21, RES_RECURSE(%r22); \
459 isync; \
460 msync
461
462 #define TLB_UNLOCK \
463 GET_CPUINFO(%r20); \
464 LOAD %r21, PC_CURTHREAD(%r20); \
465 LOAD %r22, PC_BOOKE_TLB_LOCK(%r20); \
466 \
467 /* update recursion counter */ \
468 lwz %r23, RES_RECURSE(%r22); \
469 subi %r23, %r23, 1; \
470 stw %r23, RES_RECURSE(%r22); \
471 \
472 cmplwi %r23, 0; \
473 bne 1f; \
474 isync; \
475 msync; \
476 \
477 /* release the lock */ \
478 li %r23, TLB_UNLOCKED; \
479 STORE %r23, 0(%r22); \
480 1: isync; \
481 msync
482 #else
483 #define TLB_LOCK
484 #define TLB_UNLOCK
485 #endif /* SMP */
486
487 #define INTERRUPT(label) \
488 .globl label; \
489 .align 5; \
490 CNAME(label):
491
492 /*
493 * Interrupt handling routines in BookE can be flexibly placed and do not have
494 * to live in pre-defined vectors location. Note they need to be TLB-mapped at
495 * all times in order to be able to handle exceptions. We thus arrange for
496 * them to be part of kernel text which is always TLB-accessible.
497 *
498 * The interrupt handling routines have to be 16 bytes aligned: we align them
499 * to 32 bytes (cache line length) which supposedly performs better.
500 *
501 */
502 .text
503 .globl CNAME(interrupt_vector_base)
504 .align 5
505 interrupt_vector_base:
506 /*****************************************************************************
507 * Catch-all handler to handle uninstalled IVORs
508 ****************************************************************************/
509 INTERRUPT(int_unknown)
510 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
511 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_RSVD)
512 b trap_common
513
514 /*****************************************************************************
515 * Critical input interrupt
516 ****************************************************************************/
517 INTERRUPT(int_critical_input)
518 STANDARD_CRIT_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_CSRR0, SPR_CSRR1)
519 FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_CRIT)
520 GET_TOCBASE(%r2)
521 addi %r3, %r1, CALLSIZE
522 bl CNAME(powerpc_interrupt)
523 TOC_RESTORE
524 FRAME_LEAVE(SPR_CSRR0, SPR_CSRR1)
525 rfci
526
527
528 /*****************************************************************************
529 * Machine check interrupt
530 ****************************************************************************/
531 INTERRUPT(int_machine_check)
532 STANDARD_PROLOG(SPR_SPRG3, PC_BOOKE_MCHKSAVE, SPR_MCSRR0, SPR_MCSRR1)
533 FRAME_SETUP(SPR_SPRG3, PC_BOOKE_MCHKSAVE, EXC_MCHK)
534 GET_TOCBASE(%r2)
535 addi %r3, %r1, CALLSIZE
536 bl CNAME(powerpc_interrupt)
537 TOC_RESTORE
538 FRAME_LEAVE(SPR_MCSRR0, SPR_MCSRR1)
539 rfmci
540
541
542 /*****************************************************************************
543 * Data storage interrupt
544 ****************************************************************************/
545 INTERRUPT(int_data_storage)
546 STANDARD_PROLOG(SPR_SPRG1, PC_DISISAVE, SPR_SRR0, SPR_SRR1)
547 FRAME_SETUP(SPR_SPRG1, PC_DISISAVE, EXC_DSI)
548 b trap_common
549
550
551 /*****************************************************************************
552 * Instruction storage interrupt
553 ****************************************************************************/
554 INTERRUPT(int_instr_storage)
555 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
556 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_ISI)
557 b trap_common
558
559
560 /*****************************************************************************
561 * External input interrupt
562 ****************************************************************************/
563 INTERRUPT(int_external_input)
564 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
565 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_EXI)
566 b trap_common
567
568
569 INTERRUPT(int_alignment)
570 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
571 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_ALI)
572 b trap_common
573
574
575 INTERRUPT(int_program)
576 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
577 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_PGM)
578 b trap_common
579
580
581 INTERRUPT(int_fpu)
582 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
583 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_FPU)
584 b trap_common
585
586
587 /*****************************************************************************
588 * System call
589 ****************************************************************************/
590 INTERRUPT(int_syscall)
591 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
592 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SC)
593 b trap_common
594
595
596 /*****************************************************************************
597 * Decrementer interrupt
598 ****************************************************************************/
599 INTERRUPT(int_decrementer)
600 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
601 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_DECR)
602 b trap_common
603
604
605 /*****************************************************************************
606 * Fixed interval timer
607 ****************************************************************************/
608 INTERRUPT(int_fixed_interval_timer)
609 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
610 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_FIT)
611 b trap_common
612
613
614 /*****************************************************************************
615 * Watchdog interrupt
616 ****************************************************************************/
617 INTERRUPT(int_watchdog)
618 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
619 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_WDOG)
620 b trap_common
621
622
623 /*****************************************************************************
624 * Altivec Unavailable interrupt
625 ****************************************************************************/
626 INTERRUPT(int_vec)
627 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
628 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_VEC)
629 b trap_common
630
631
632 /*****************************************************************************
633 * Altivec Assist interrupt
634 ****************************************************************************/
635 INTERRUPT(int_vecast)
636 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
637 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_VECAST_E)
638 b trap_common
639
640
641 #ifdef __SPE__
642 /*****************************************************************************
643 * Floating point Assist interrupt
644 ****************************************************************************/
645 INTERRUPT(int_spe_fpdata)
646 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
647 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SPFPD)
648 addi %r3, %r1, CALLSIZE
649 bl spe_handle_fpdata
650 FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
651 rfi
652
653 INTERRUPT(int_spe_fpround)
654 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
655 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SPFPR)
656 addi %r3, %r1, CALLSIZE
657 bl spe_handle_fpround
658 FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
659 rfi
660 #endif
661
662
663 #ifdef HWPMC_HOOKS
664 /*****************************************************************************
665 * PMC Interrupt
666 ****************************************************************************/
667 INTERRUPT(int_performance_counter)
668 STANDARD_PROLOG(SPR_SPRG3, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
669 FRAME_SETUP(SPR_SPRG3, PC_TEMPSAVE, EXC_PERF)
670 b trap_common
671 #endif
672
673
674 /*****************************************************************************
675 * Data TLB miss interrupt
676 *
677 * There can be nested TLB misses - while handling a TLB miss we reference
678 * data structures that may be not covered by translations. We support up to
679 * TLB_NESTED_MAX-1 nested misses.
680 *
681 * Registers use:
682 * r31 - dear
683 * r30 - unused
684 * r29 - saved mas0
685 * r28 - saved mas1
686 * r27 - saved mas2
687 * r26 - pmap address
688 * r25 - pte address
689 *
690 * r20:r23 - scratch registers
691 ****************************************************************************/
692 INTERRUPT(int_data_tlb_error)
693 TLB_PROLOG
694 TLB_LOCK
695
696 mfspr %r31, SPR_DEAR
697
698 /*
699 * Save MAS0-MAS2 registers. There might be another tlb miss during
700 * pte lookup overwriting current contents (which was hw filled).
701 */
702 mfspr %r29, SPR_MAS0
703 mfspr %r28, SPR_MAS1
704 mfspr %r27, SPR_MAS2
705
706 /* Check faulting address. */
707 LOAD_ADDR(%r21, VM_MAXUSER_ADDRESS)
708 CMPL cr0, %r31, %r21
709 blt search_user_pmap
710
711 /* If it's kernel address, allow only supervisor mode misses. */
712 mfsrr1 %r21
713 mtcr %r21
714 bt 17, search_failed /* check MSR[PR] */
715
716 #ifdef __powerpc64__
717 srdi %r21, %r31, 48
718 cmpldi cr0, %r21, VM_MIN_KERNEL_ADDRESS@highest
719 #else
720 lis %r21, VM_MIN_KERNEL_ADDRESS@h
721 cmplw cr0, %r31, %r21
722 #endif
723 blt search_failed
724
725 search_kernel_pmap:
726 /* Load r26 with kernel_pmap address */
727 bl 1f
728 #ifdef __powerpc64__
729 .llong kernel_pmap_store-.
730 #else
731 .long kernel_pmap_store-.
732 #endif
733 1: mflr %r21
734 LOAD %r26, 0(%r21)
735 add %r26, %r21, %r26 /* kernel_pmap_store in r26 */
736
737 /* Force kernel tid, set TID to 0 in MAS1. */
738 li %r21, 0
739 rlwimi %r28, %r21, 0, 8, 15 /* clear TID bits */
740
741 tlb_miss_handle:
742 /* This may result in nested tlb miss. */
743 bl pte_lookup /* returns PTE address in R25 */
744
745 CMPI %r25, 0 /* pte found? */
746 beq search_failed
747
748 /* Finish up, write TLB entry. */
749 bl tlb_fill_entry
750
751 tlb_miss_return:
752 TLB_UNLOCK
753 TLB_RESTORE
754 rfi
755
756 search_user_pmap:
757 /* Load r26 with current user space process pmap */
758 GET_CPUINFO(%r26)
759 LOAD %r26, PC_CURPMAP(%r26)
760
761 b tlb_miss_handle
762
763 search_failed:
764 /*
765 * Whenever we don't find a TLB mapping in PT, set a TLB0 entry with
766 * the faulting virtual address anyway, but put a fake RPN and no
767 * access rights. This should cause a following {D,I}SI exception.
768 */
769 lis %r23, 0xffff0000@h /* revoke all permissions */
770
771 /* Load MAS registers. */
772 mtspr SPR_MAS0, %r29
773 mtspr SPR_MAS1, %r28
774 mtspr SPR_MAS2, %r27
775 mtspr SPR_MAS3, %r23
776
777 li %r23, 0
778 mtspr SPR_MAS7, %r23
779
780 isync
781 tlbwe
782 msync
783 isync
784 b tlb_miss_return
785
786 /*****************************************************************************
787 *
788 * Return pte address that corresponds to given pmap/va. If there is no valid
789 * entry return 0.
790 *
791 * input: r26 - pmap
792 * input: r31 - dear
793 * output: r25 - pte address
794 *
795 * scratch regs used: r21
796 *
797 ****************************************************************************/
798 pte_lookup:
799 CMPI %r26, 0
800 beq 1f /* fail quickly if pmap is invalid */
801
802 #ifdef __powerpc64__
803 rldicl %r21, %r31, (64 - PG_ROOT_L), (64 - PG_ROOT_NUM) /* pp2d offset */
804 slwi %r21, %r21, PG_ROOT_ENTRY_SHIFT /* multiply by pp2d entry size */
805 ld %r25, PM_ROOT(%r26) /* pmap pm_pp2d[] address */
806 ldx %r25, %r25, %r21 /* get pdir address, i.e. pmap->pm_pp2d[pp2d_idx] * */
807
808 cmpdi %r25, 0
809 beq 2f
810
811 rldicl %r21, %r31, (64 - PDIR_L1_L), (64 - PDIR_L1_NUM) /* pp2d offset */
812 slwi %r21, %r21, PDIR_L1_ENTRY_SHIFT /* multiply by pp2d entry size */
813 ldx %r25, %r25, %r21 /* get pdir address, i.e. pmap->pm_pp2d[pp2d_idx] * */
814
815 cmpdi %r25, 0
816 beq 2f
817
818 rldicl %r21, %r31, (64 - PDIR_L), (64 - PDIR_NUM) /* pdir offset */
819 slwi %r21, %r21, PDIR_ENTRY_SHIFT /* multiply by pdir entry size */
820 ldx %r25, %r25, %r21 /* get ptbl address, i.e. pmap->pm_pp2d[pp2d_idx][pdir_idx] */
821
822 cmpdi %r25, 0
823 beq 2f
824
825 rldicl %r21, %r31, (64 - PTBL_L), (64 - PTBL_NUM) /* ptbl offset */
826 slwi %r21, %r21, PTBL_ENTRY_SHIFT /* multiply by pte entry size */
827
828 #else
829 srwi %r21, %r31, PDIR_SHIFT /* pdir offset */
830 slwi %r21, %r21, PDIR_ENTRY_SHIFT /* multiply by pdir entry size */
831
832 lwz %r25, PM_PDIR(%r26) /* pmap pm_dir[] address */
833 /*
834 * Get ptbl address, i.e. pmap->pm_pdir[pdir_idx]
835 * This load may cause a Data TLB miss for non-kernel pmap!
836 */
837 lwzx %r25, %r25, %r21 /* offset within pm_pdir[] table */
838 cmpwi %r25, 0
839 beq 2f
840
841 lis %r21, PTBL_MASK@h
842 ori %r21, %r21, PTBL_MASK@l
843 and %r21, %r21, %r31
844
845 /* ptbl offset, multiply by ptbl entry size */
846 srwi %r21, %r21, (PTBL_SHIFT - PTBL_ENTRY_SHIFT)
847 #endif
848
849 add %r25, %r25, %r21 /* address of pte entry */
850 /*
851 * Get pte->flags
852 * This load may cause a Data TLB miss for non-kernel pmap!
853 */
854 lwz %r21, PTE_FLAGS(%r25)
855 andi. %r21, %r21, PTE_VALID@l
856 bne 2f
857 1:
858 li %r25, 0
859 2:
860 blr
861
862 /*****************************************************************************
863 *
864 * Load MAS1-MAS3 registers with data, write TLB entry
865 *
866 * input:
867 * r29 - mas0
868 * r28 - mas1
869 * r27 - mas2
870 * r25 - pte
871 *
872 * output: none
873 *
874 * scratch regs: r21-r23
875 *
876 ****************************************************************************/
877 tlb_fill_entry:
878 /*
879 * Update PTE flags: we have to do it atomically, as pmap_protect()
880 * running on other CPUs could attempt to update the flags at the same
881 * time.
882 */
883 li %r23, PTE_FLAGS
884 1:
885 lwarx %r21, %r23, %r25 /* get pte->flags */
886 oris %r21, %r21, PTE_REFERENCED@h /* set referenced bit */
887
888 andi. %r22, %r21, (PTE_SW | PTE_UW)@l /* check if writable */
889 beq 2f
890 ori %r21, %r21, PTE_MODIFIED@l /* set modified bit */
891 2:
892 stwcx. %r21, %r23, %r25 /* write it back */
893 bne- 1b
894
895 /* Update MAS2. */
896 rlwimi %r27, %r21, 13, 27, 30 /* insert WIMG bits from pte */
897
898 /* Setup MAS3 value in r23. */
899 LOAD %r23, PTE_RPN(%r25) /* get pte->rpn */
900 #ifdef __powerpc64__
901 rldicr %r22, %r23, 52, 51 /* extract MAS3 portion of RPN */
902 rldicl %r23, %r23, 20, 54 /* extract MAS7 portion of RPN */
903
904 rlwimi %r22, %r21, 30, 26, 31 /* insert protection bits from pte */
905 #else
906 rlwinm %r22, %r23, 20, 0, 11 /* extract MAS3 portion of RPN */
907
908 rlwimi %r22, %r21, 30, 26, 31 /* insert protection bits from pte */
909 rlwimi %r22, %r21, 20, 12, 19 /* insert lower 8 RPN bits to MAS3 */
910 rlwinm %r23, %r23, 20, 24, 31 /* MAS7 portion of RPN */
911 #endif
912
913 /* Load MAS registers. */
914 mtspr SPR_MAS0, %r29
915 mtspr SPR_MAS1, %r28
916 mtspr SPR_MAS2, %r27
917 mtspr SPR_MAS3, %r22
918 mtspr SPR_MAS7, %r23
919
920 isync
921 tlbwe
922 isync
923 msync
924 blr
925
926 /*****************************************************************************
927 * Instruction TLB miss interrupt
928 *
929 * Same notes as for the Data TLB miss
930 ****************************************************************************/
931 INTERRUPT(int_inst_tlb_error)
932 TLB_PROLOG
933 TLB_LOCK
934
935 mfsrr0 %r31 /* faulting address */
936
937 /*
938 * Save MAS0-MAS2 registers. There might be another tlb miss during pte
939 * lookup overwriting current contents (which was hw filled).
940 */
941 mfspr %r29, SPR_MAS0
942 mfspr %r28, SPR_MAS1
943 mfspr %r27, SPR_MAS2
944
945 mfsrr1 %r21
946 mtcr %r21
947
948 /* check MSR[PR] */
949 bt 17, search_user_pmap
950 b search_kernel_pmap
951
952
953 .globl interrupt_vector_top
954 interrupt_vector_top:
955
956 /*****************************************************************************
957 * Debug interrupt
958 ****************************************************************************/
959 INTERRUPT(int_debug)
960 STANDARD_CRIT_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_CSRR0, SPR_CSRR1)
961 FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_DEBUG)
962 bl int_debug_int
963 FRAME_LEAVE(SPR_CSRR0, SPR_CSRR1)
964 rfci
965
966 INTERRUPT(int_debug_ed)
967 STANDARD_CRIT_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_DSRR0, SPR_DSRR1)
968 FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_DEBUG)
969 bl int_debug_int
970 FRAME_LEAVE(SPR_DSRR0, SPR_DSRR1)
971 rfdi
972 /* .long 0x4c00004e */
973
974 /* Internal helper for debug interrupt handling. */
975 /* Common code between e500v1/v2 and e500mc-based cores. */
976 int_debug_int:
977 mflr %r14
978 GET_CPUINFO(%r3)
979 LOAD %r3, (PC_BOOKE_CRITSAVE+CPUSAVE_SRR0)(%r3)
980 bl 0f
981 ADDR(interrupt_vector_base-.)
982 ADDR(interrupt_vector_top-.)
983 0: mflr %r5
984 LOAD %r4,0(%r5) /* interrupt_vector_base in r4 */
985 add %r4,%r4,%r5
986 CMPL cr0, %r3, %r4
987 blt trap_common
988 LOAD %r4,WORD_SIZE(%r5) /* interrupt_vector_top in r4 */
989 add %r4,%r4,%r5
990 addi %r4,%r4,4
991 CMPL cr0, %r3, %r4
992 bge trap_common
993 /* Disable single-stepping for the interrupt handlers. */
994 LOAD %r3, FRAME_SRR1+CALLSIZE(%r1);
995 rlwinm %r3, %r3, 0, 23, 21
996 STORE %r3, FRAME_SRR1+CALLSIZE(%r1);
997 /* Restore srr0 and srr1 as they could have been clobbered. */
998 GET_CPUINFO(%r4)
999 LOAD %r3, (PC_BOOKE_CRITSAVE+BOOKE_CRITSAVE_SRR0)(%r4);
1000 mtspr SPR_SRR0, %r3
1001 LOAD %r4, (PC_BOOKE_CRITSAVE+BOOKE_CRITSAVE_SRR1)(%r4);
1002 mtspr SPR_SRR1, %r4
1003 mtlr %r14
1004 blr
1005
1006 /*****************************************************************************
1007 * Common trap code
1008 ****************************************************************************/
1009 trap_common:
1010 /* Call C trap dispatcher */
1011 GET_TOCBASE(%r2)
1012 addi %r3, %r1, CALLSIZE
1013 bl CNAME(powerpc_interrupt)
1014 TOC_RESTORE
1015
1016 .globl CNAME(trapexit) /* exported for db_backtrace use */
1017 CNAME(trapexit):
1018 /* disable interrupts */
1019 wrteei 0
1020
1021 /* Test AST pending - makes sense for user process only */
1022 LOAD %r5, FRAME_SRR1+CALLSIZE(%r1)
1023 mtcr %r5
1024 bf 17, 1f
1025
1026 GET_CPUINFO(%r3)
1027 LOAD %r4, PC_CURTHREAD(%r3)
1028 lwz %r4, TD_AST(%r4)
1029 cmpwi %r4, 0
1030 beq 1f
1031
1032 /* re-enable interrupts before calling ast() */
1033 wrteei 1
1034
1035 addi %r3, %r1, CALLSIZE
1036 bl CNAME(ast)
1037 TOC_RESTORE
1038 .globl CNAME(asttrapexit) /* db_backtrace code sentinel #2 */
1039 CNAME(asttrapexit):
1040 b trapexit /* test ast ret value ? */
1041 1:
1042 FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
1043 rfi
1044
1045
1046 #if defined(KDB)
1047 /*
1048 * Deliberate entry to dbtrap
1049 */
1050 /* .globl CNAME(breakpoint)*/
1051 ASENTRY_NOPROF(breakpoint)
1052 mtsprg1 %r1
1053 mfmsr %r3
1054 mtsrr1 %r3
1055 li %r4, ~(PSL_EE | PSL_ME)@l
1056 oris %r4, %r4, ~(PSL_EE | PSL_ME)@h
1057 and %r3, %r3, %r4
1058 mtmsr %r3 /* disable interrupts */
1059 isync
1060 GET_CPUINFO(%r3)
1061 STORE %r30, (PC_DBSAVE+CPUSAVE_R30)(%r3)
1062 STORE %r31, (PC_DBSAVE+CPUSAVE_R31)(%r3)
1063
1064 mflr %r31
1065 mtsrr0 %r31
1066
1067 mfspr %r30, SPR_DEAR
1068 mfspr %r31, SPR_ESR
1069 STORE %r30, (PC_DBSAVE+CPUSAVE_BOOKE_DEAR)(%r3)
1070 STORE %r31, (PC_DBSAVE+CPUSAVE_BOOKE_ESR)(%r3)
1071
1072 mfsrr0 %r30
1073 mfsrr1 %r31
1074 STORE %r30, (PC_DBSAVE+CPUSAVE_SRR0)(%r3)
1075 STORE %r31, (PC_DBSAVE+CPUSAVE_SRR1)(%r3)
1076 isync
1077
1078 mfcr %r30
1079
1080 /*
1081 * Now the kdb trap catching code.
1082 */
1083 dbtrap:
1084 FRAME_SETUP(SPR_SPRG1, PC_DBSAVE, EXC_DEBUG)
1085 /* Call C trap code: */
1086 GET_TOCBASE(%r2)
1087 addi %r3, %r1, CALLSIZE
1088 bl CNAME(db_trap_glue)
1089 TOC_RESTORE
1090 or. %r3, %r3, %r3
1091 bne dbleave
1092 /* This wasn't for KDB, so switch to real trap: */
1093 b trap_common
1094
1095 dbleave:
1096 FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
1097 rfi
1098 ASEND(breakpoint)
1099 #endif /* KDB */
1100
1101 #ifdef SMP
1102 ENTRY(tlb_lock)
1103 GET_CPUINFO(%r5)
1104 LOAD %r5, PC_CURTHREAD(%r5)
1105 1: LOADX %r4, 0, %r3
1106 CMPI %r4, TLB_UNLOCKED
1107 bne 1b
1108 STOREX %r5, 0, %r3
1109 bne- 1b
1110 isync
1111 msync
1112 blr
1113 END(tlb_lock)
1114
1115 ENTRY(tlb_unlock)
1116 isync
1117 msync
1118 li %r4, TLB_UNLOCKED
1119 STORE %r4, 0(%r3)
1120 isync
1121 msync
1122 blr
1123 END(tlb_unlock)
1124
1125 /*
1126 * TLB miss spin locks. For each CPU we have a reservation granule (32 bytes);
1127 * only a single word from this granule will actually be used as a spin lock
1128 * for mutual exclusion between TLB miss handler and pmap layer that
1129 * manipulates page table contents.
1130 */
1131 .data
1132 .align 5
1133 GLOBAL(tlb0_miss_locks)
1134 .space RES_GRANULE * MAXCPU
1135 #endif
Cache object: 2838375d75185cf8d0236f722a358576
|