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