Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/powerpc/aim/trap_subr32.S
39507 views
1
/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $ */
2
3
/*-
4
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
5
* Copyright (C) 1995, 1996 TooLs GmbH.
6
* All rights reserved.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
* 3. All advertising materials mentioning features or use of this software
17
* must display the following acknowledgement:
18
* This product includes software developed by TooLs GmbH.
19
* 4. The name of TooLs GmbH may not be used to endorse or promote products
20
* derived from this software without specific prior written permission.
21
*
22
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
*/
33
34
/*
35
* NOTICE: This is not a standalone file. to use it, #include it in
36
* your port's locore.S, like so:
37
*
38
* #include <powerpc/aim/trap_subr.S>
39
*/
40
41
/*
42
* Save/restore segment registers
43
*/
44
#define RESTORE_SRS(pmap,sr) mtsr 0,sr; \
45
lwz sr,1*4(pmap); mtsr 1,sr; \
46
lwz sr,2*4(pmap); mtsr 2,sr; \
47
lwz sr,3*4(pmap); mtsr 3,sr; \
48
lwz sr,4*4(pmap); mtsr 4,sr; \
49
lwz sr,5*4(pmap); mtsr 5,sr; \
50
lwz sr,6*4(pmap); mtsr 6,sr; \
51
lwz sr,7*4(pmap); mtsr 7,sr; \
52
lwz sr,8*4(pmap); mtsr 8,sr; \
53
lwz sr,9*4(pmap); mtsr 9,sr; \
54
lwz sr,10*4(pmap); mtsr 10,sr; \
55
lwz sr,11*4(pmap); mtsr 11,sr; \
56
/* Skip segment 12 (USER_SR), which is restored differently */ \
57
lwz sr,13*4(pmap); mtsr 13,sr; \
58
lwz sr,14*4(pmap); mtsr 14,sr; \
59
lwz sr,15*4(pmap); mtsr 15,sr; isync;
60
61
/*
62
* User SRs are loaded through a pointer to the current pmap.
63
*/
64
#define RESTORE_USER_SRS(pmap,sr) \
65
GET_CPUINFO(pmap); \
66
lwz pmap,PC_CURPMAP(pmap); \
67
lwzu sr,PM_SR(pmap); \
68
RESTORE_SRS(pmap,sr) \
69
/* Restore SR 12 */ \
70
lwz sr,12*4(pmap); mtsr 12,sr; isync
71
72
/*
73
* Kernel SRs are loaded directly from kernel_pmap_
74
*/
75
#define RESTORE_KERN_SRS(pmap,sr) \
76
lwz pmap,TRAP_TOCBASE(0); \
77
lwz pmap,CNAME(kernel_pmap_store)@got(pmap); \
78
lwzu sr,PM_SR(pmap); \
79
RESTORE_SRS(pmap,sr)
80
81
/*
82
* FRAME_SETUP assumes:
83
* SPRG1 SP (1)
84
* SPRG3 trap type
85
* savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps)
86
* r28 LR
87
* r29 CR
88
* r30 scratch
89
* r31 scratch
90
* r1 kernel stack
91
* SRR0/1 as at start of trap
92
*/
93
#define FRAME_SETUP(savearea) \
94
/* Have to enable translation to allow access of kernel stack: */ \
95
GET_CPUINFO(%r31); \
96
mfsrr0 %r30; \
97
stw %r30,(savearea+CPUSAVE_SRR0)(%r31); /* save SRR0 */ \
98
mfsrr1 %r30; \
99
stw %r30,(savearea+CPUSAVE_SRR1)(%r31); /* save SRR1 */ \
100
mfmsr %r30; \
101
ori %r30,%r30,(PSL_DR|PSL_IR|PSL_RI)@l; /* relocation on */ \
102
mtmsr %r30; /* stack can now be accessed */ \
103
isync; \
104
mfsprg1 %r31; /* get saved SP */ \
105
stwu %r31,-FRAMELEN(%r1); /* save it in the callframe */ \
106
stw %r0, FRAME_0+8(%r1); /* save r0 in the trapframe */ \
107
stw %r31,FRAME_1+8(%r1); /* save SP " " */ \
108
stw %r2, FRAME_2+8(%r1); /* save r2 " " */ \
109
stw %r28,FRAME_LR+8(%r1); /* save LR " " */ \
110
stw %r29,FRAME_CR+8(%r1); /* save CR " " */ \
111
GET_CPUINFO(%r2); \
112
lwz %r28,(savearea+CPUSAVE_R28)(%r2); /* get saved r28 */ \
113
lwz %r29,(savearea+CPUSAVE_R29)(%r2); /* get saved r29 */ \
114
lwz %r30,(savearea+CPUSAVE_R30)(%r2); /* get saved r30 */ \
115
lwz %r31,(savearea+CPUSAVE_R31)(%r2); /* get saved r31 */ \
116
stw %r3, FRAME_3+8(%r1); /* save r3-r31 */ \
117
stw %r4, FRAME_4+8(%r1); \
118
stw %r5, FRAME_5+8(%r1); \
119
stw %r6, FRAME_6+8(%r1); \
120
stw %r7, FRAME_7+8(%r1); \
121
stw %r8, FRAME_8+8(%r1); \
122
stw %r9, FRAME_9+8(%r1); \
123
stw %r10, FRAME_10+8(%r1); \
124
stw %r11, FRAME_11+8(%r1); \
125
stw %r12, FRAME_12+8(%r1); \
126
stw %r13, FRAME_13+8(%r1); \
127
stw %r14, FRAME_14+8(%r1); \
128
stw %r15, FRAME_15+8(%r1); \
129
stw %r16, FRAME_16+8(%r1); \
130
stw %r17, FRAME_17+8(%r1); \
131
stw %r18, FRAME_18+8(%r1); \
132
stw %r19, FRAME_19+8(%r1); \
133
stw %r20, FRAME_20+8(%r1); \
134
stw %r21, FRAME_21+8(%r1); \
135
stw %r22, FRAME_22+8(%r1); \
136
stw %r23, FRAME_23+8(%r1); \
137
stw %r24, FRAME_24+8(%r1); \
138
stw %r25, FRAME_25+8(%r1); \
139
stw %r26, FRAME_26+8(%r1); \
140
stw %r27, FRAME_27+8(%r1); \
141
stw %r28, FRAME_28+8(%r1); \
142
stw %r29, FRAME_29+8(%r1); \
143
stw %r30, FRAME_30+8(%r1); \
144
stw %r31, FRAME_31+8(%r1); \
145
lwz %r28,(savearea+CPUSAVE_AIM_DAR)(%r2); /* saved DAR */ \
146
lwz %r29,(savearea+CPUSAVE_AIM_DSISR)(%r2);/* saved DSISR */\
147
lwz %r30,(savearea+CPUSAVE_SRR0)(%r2); /* saved SRR0 */ \
148
lwz %r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */ \
149
mfxer %r3; \
150
mfctr %r4; \
151
mfsprg3 %r5; \
152
stw %r3, FRAME_XER+8(1); /* save xer/ctr/exc */ \
153
stw %r4, FRAME_CTR+8(1); \
154
stw %r5, FRAME_EXC+8(1); \
155
stw %r28,FRAME_AIM_DAR+8(1); \
156
stw %r29,FRAME_AIM_DSISR+8(1); /* save dsisr/srr0/srr1 */ \
157
stw %r30,FRAME_SRR0+8(1); \
158
stw %r31,FRAME_SRR1+8(1); \
159
lwz %r2,PC_CURTHREAD(%r2) /* set curthread pointer */
160
161
#define FRAME_LEAVE(savearea) \
162
/* Disable exceptions: */ \
163
mfmsr %r2; \
164
andi. %r2,%r2,~PSL_EE@l; \
165
mtmsr %r2; \
166
isync; \
167
/* Now restore regs: */ \
168
lwz %r2,FRAME_SRR0+8(%r1); \
169
lwz %r3,FRAME_SRR1+8(%r1); \
170
lwz %r4,FRAME_CTR+8(%r1); \
171
lwz %r5,FRAME_XER+8(%r1); \
172
lwz %r6,FRAME_LR+8(%r1); \
173
GET_CPUINFO(%r7); \
174
stw %r2,(savearea+CPUSAVE_SRR0)(%r7); /* save SRR0 */ \
175
stw %r3,(savearea+CPUSAVE_SRR1)(%r7); /* save SRR1 */ \
176
lwz %r7,FRAME_CR+8(%r1); \
177
mtctr %r4; \
178
mtxer %r5; \
179
mtlr %r6; \
180
mtsprg1 %r7; /* save cr */ \
181
lwz %r31,FRAME_31+8(%r1); /* restore r0-31 */ \
182
lwz %r30,FRAME_30+8(%r1); \
183
lwz %r29,FRAME_29+8(%r1); \
184
lwz %r28,FRAME_28+8(%r1); \
185
lwz %r27,FRAME_27+8(%r1); \
186
lwz %r26,FRAME_26+8(%r1); \
187
lwz %r25,FRAME_25+8(%r1); \
188
lwz %r24,FRAME_24+8(%r1); \
189
lwz %r23,FRAME_23+8(%r1); \
190
lwz %r22,FRAME_22+8(%r1); \
191
lwz %r21,FRAME_21+8(%r1); \
192
lwz %r20,FRAME_20+8(%r1); \
193
lwz %r19,FRAME_19+8(%r1); \
194
lwz %r18,FRAME_18+8(%r1); \
195
lwz %r17,FRAME_17+8(%r1); \
196
lwz %r16,FRAME_16+8(%r1); \
197
lwz %r15,FRAME_15+8(%r1); \
198
lwz %r14,FRAME_14+8(%r1); \
199
lwz %r13,FRAME_13+8(%r1); \
200
lwz %r12,FRAME_12+8(%r1); \
201
lwz %r11,FRAME_11+8(%r1); \
202
lwz %r10,FRAME_10+8(%r1); \
203
lwz %r9, FRAME_9+8(%r1); \
204
lwz %r8, FRAME_8+8(%r1); \
205
lwz %r7, FRAME_7+8(%r1); \
206
lwz %r6, FRAME_6+8(%r1); \
207
lwz %r5, FRAME_5+8(%r1); \
208
lwz %r4, FRAME_4+8(%r1); \
209
lwz %r3, FRAME_3+8(%r1); \
210
lwz %r2, FRAME_2+8(%r1); \
211
lwz %r0, FRAME_0+8(%r1); \
212
lwz %r1, FRAME_1+8(%r1); \
213
/* Can't touch %r1 from here on */ \
214
mtsprg2 %r2; /* save r2 & r3 */ \
215
mtsprg3 %r3; \
216
/* Disable translation, machine check and recoverability: */ \
217
mfmsr %r2; \
218
andi. %r2,%r2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \
219
mtmsr %r2; \
220
isync; \
221
/* Decide whether we return to user mode: */ \
222
GET_CPUINFO(%r2); \
223
lwz %r3,(savearea+CPUSAVE_SRR1)(%r2); \
224
mtcr %r3; \
225
bf 17,1f; /* branch if PSL_PR is false */ \
226
/* Restore user SRs */ \
227
RESTORE_USER_SRS(%r2,%r3); \
228
1: mfsprg1 %r2; /* restore cr */ \
229
mtcr %r2; \
230
GET_CPUINFO(%r2); \
231
lwz %r3,(savearea+CPUSAVE_SRR0)(%r2); /* restore srr0 */ \
232
mtsrr0 %r3; \
233
lwz %r3,(savearea+CPUSAVE_SRR1)(%r2); /* restore srr1 */ \
234
\
235
/* Make sure HV bit of MSR propagated to SRR1 */ \
236
mfmsr %r2; \
237
or %r3,%r2,%r3; \
238
\
239
mtsrr1 %r3; \
240
mfsprg2 %r2; /* restore r2 & r3 */ \
241
mfsprg3 %r3
242
243
#ifdef KDTRACE_HOOKS
244
.data
245
.globl dtrace_invop_calltrap_addr
246
.align 4
247
.type dtrace_invop_calltrap_addr, @object
248
.size dtrace_invop_calltrap_addr, 4
249
dtrace_invop_calltrap_addr:
250
.word 0
251
.word 0
252
253
.text
254
#endif
255
256
/*
257
* The next two routines are 64-bit glue code. The first is used to test if
258
* we are on a 64-bit system. By copying it to the illegal instruction
259
* handler, we can test for 64-bit mode by trying to execute a 64-bit
260
* instruction and seeing what happens. The second gets copied in front
261
* of all the other handlers to restore 32-bit bridge mode when traps
262
* are taken.
263
*/
264
265
/* 64-bit test code. Sets SPRG2 to 0 if an illegal instruction is executed */
266
267
.globl CNAME(testppc64),CNAME(testppc64size)
268
CNAME(testppc64):
269
mtsprg1 %r31
270
mfsrr0 %r31
271
addi %r31, %r31, 4
272
mtsrr0 %r31
273
274
li %r31, 0
275
mtsprg2 %r31
276
mfsprg1 %r31
277
278
rfi
279
CNAME(testppc64size) = .-CNAME(testppc64)
280
281
282
/* 64-bit bridge mode restore snippet. Gets copied in front of everything else
283
* on 64-bit systems. */
284
285
.globl CNAME(restorebridge),CNAME(restorebridgesize)
286
CNAME(restorebridge):
287
mtsprg1 %r31
288
mfmsr %r31
289
clrldi %r31,%r31,1
290
mtmsrd %r31
291
mfsprg1 %r31
292
isync
293
CNAME(restorebridgesize) = .-CNAME(restorebridge)
294
295
/*
296
* Processor reset exception handler. These are typically
297
* the first instructions the processor executes after a
298
* software reset. We do this in two bits so that we are
299
* not still hanging around in the trap handling region
300
* once the MMU is turned on.
301
*/
302
.globl CNAME(rstcode), CNAME(rstcodeend)
303
CNAME(rstcode):
304
lwz %r31, TRAP_GENTRAP(0)
305
addi %r31, %r31, (cpu_reset - generictrap)
306
mtlr %r31
307
blrl
308
CNAME(rstcodeend):
309
310
cpu_reset:
311
bl 1f
312
313
.space 124
314
315
1:
316
mflr %r1
317
addi %r1,%r1,(124-16)@l
318
lwz %r30,TRAP_TOCBASE(0)
319
320
bl CNAME(cpudep_ap_early_bootstrap)
321
lis %r3,1@l
322
bl CNAME(pmap_cpu_bootstrap)
323
bl CNAME(cpudep_ap_bootstrap)
324
mr %r1,%r3
325
bl CNAME(cpudep_ap_setup)
326
GET_CPUINFO(%r5)
327
lwz %r3,(PC_RESTORE)(%r5)
328
cmplwi %cr0,%r3,0
329
beq %cr0,2f
330
li %r4, 1
331
b CNAME(longjmp)
332
2:
333
#ifdef SMP
334
bl CNAME(machdep_ap_bootstrap)
335
#endif
336
337
/* Should not be reached */
338
9:
339
b 9b
340
341
/*
342
* This code gets copied to all the trap vectors
343
* (except ISI/DSI, ALI, and the interrupts)
344
*/
345
346
.globl CNAME(trapcode),CNAME(trapcodeend)
347
CNAME(trapcode):
348
mtsprg1 %r1 /* save SP */
349
mflr %r1 /* Save the old LR in r1 */
350
mtsprg2 %r1 /* And then in SPRG2 */
351
lwz %r1, TRAP_ENTRY(0) /* Get branch address */
352
mtlr %r1
353
li %r1, 0xe0 /* How to get the vector from LR */
354
blrl /* LR & (0xff00 | r1) is exception # */
355
CNAME(trapcodeend):
356
357
/*
358
* For ALI: has to save DSISR and DAR
359
*/
360
.globl CNAME(alitrap),CNAME(aliend)
361
CNAME(alitrap):
362
mtsprg1 %r1 /* save SP */
363
GET_CPUINFO(%r1)
364
stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) /* free r28-r31 */
365
stw %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
366
stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
367
stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
368
mfdar %r30
369
mfdsisr %r31
370
stw %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
371
stw %r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
372
mfsprg1 %r1 /* restore SP, in case of branch */
373
mflr %r28 /* save LR */
374
mfcr %r29 /* save CR */
375
376
/* Put our exception vector in SPRG3 */
377
li %r31, EXC_ALI
378
mtsprg3 %r31
379
380
/* Test whether we already had PR set */
381
mfsrr1 %r31
382
mtcr %r31
383
384
/* Jump to s_trap */
385
lwz %r31, TRAP_GENTRAP(0)
386
addi %r31, %r31, (s_trap - generictrap)
387
mtlr %r31
388
blrl
389
CNAME(aliend):
390
391
/*
392
* G2 specific: instuction TLB miss.
393
*/
394
.globl CNAME(imisstrap),CNAME(imisssize)
395
CNAME(imisstrap):
396
mfspr %r2, SPR_HASH1 /* get first pointer */
397
addi %r1, 0, 8 /* load 8 for counter */
398
mfctr %r0 /* save counter */
399
mfspr %r3, SPR_ICMP /* get first compare value */
400
addi %r2, %r2, -8 /* pre dec the pointer */
401
im0:
402
mtctr %r1 /* load counter */
403
im1:
404
lwzu %r1, 8(%r2) /* get next pte */
405
cmp 0, 0, %r1, %r3 /* see if found pte */
406
bdnzf 2, im1 /* dec count br if cmp ne and if
407
* count not zero */
408
bne instr_sec_hash /* if not found set up second hash
409
* or exit */
410
lwz %r1, +4(%r2) /* load tlb entry lower-word */
411
andi. %r3, %r1, 8 /* check G bit */
412
bne do_isi_prot /* if guarded, take an ISI */
413
mtctr %r0 /* restore counter */
414
mfspr %r0, SPR_IMISS /* get the miss address for the tlbli */
415
mfspr %r3, SPR_SRR1 /* get the saved cr0 bits */
416
mtcrf 0x80, %r3 /* restore CR0 */
417
mtspr SPR_RPA, %r1 /* set the pte */
418
ori %r1, %r1, 0x100 /* set reference bit */
419
srwi %r1, %r1, 8 /* get byte 7 of pte */
420
tlbli %r0 /* load the itlb */
421
stb %r1, +6(%r2) /* update page table */
422
rfi /* return to executing program */
423
424
instr_sec_hash:
425
andi. %r1, %r3, 0x0040 /* see if we have done second hash */
426
bne do_isi /* if so, go to ISI interrupt */
427
mfspr %r2, SPR_HASH2 /* get the second pointer */
428
ori %r3, %r3, 0x0040 /* change the compare value */
429
addi %r1, 0, 8 /* load 8 for counter */
430
addi %r2, %r2, -8 /* pre dec for update on load */
431
b im0 /* try second hash */
432
433
/* Create a faked ISI interrupt as the address was not found */
434
do_isi_prot:
435
mfspr %r3, SPR_SRR1 /* get srr1 */
436
andi. %r2, %r3, 0xffff /* clean upper srr1 */
437
addis %r2, %r2, 0x0800 /* or in srr<4> = 1 to flag prot
438
* violation */
439
b isi1
440
do_isi:
441
mfspr %r3, SPR_SRR1 /* get srr1 */
442
andi. %r2, %r3, 0xffff /* clean srr1 */
443
addis %r2, %r2, 0x4000 /* or in srr1<1> = 1 to flag pte
444
* not found */
445
isi1:
446
mtctr %r0 /* restore counter */
447
mtspr SPR_SRR1, %r2 /* set srr1 */
448
mfmsr %r0 /* get msr */
449
xoris %r0, %r0, 0x2 /* flip the msr<tgpr> bit */
450
mtcrf 0x80, %r3 /* restore CR0 */
451
mtmsr %r0 /* flip back to the native gprs */
452
ba EXC_ISI /* go to instr. access interrupt */
453
454
CNAME(imisssize) = .-CNAME(imisstrap)
455
456
/*
457
* G2 specific: data load TLB miss.
458
*/
459
.globl CNAME(dlmisstrap),CNAME(dlmisssize)
460
CNAME(dlmisstrap):
461
mfspr %r2, SPR_HASH1 /* get first pointer */
462
addi %r1, 0, 8 /* load 8 for counter */
463
mfctr %r0 /* save counter */
464
mfspr %r3, SPR_DCMP /* get first compare value */
465
addi %r2, %r2, -8 /* pre dec the pointer */
466
dm0:
467
mtctr %r1 /* load counter */
468
dm1:
469
lwzu %r1, 8(%r2) /* get next pte */
470
cmp 0, 0, %r1, %r3 /* see if found pte */
471
bdnzf 2, dm1 /* dec count br if cmp ne and if
472
* count not zero */
473
bne data_sec_hash /* if not found set up second hash
474
* or exit */
475
lwz %r1, +4(%r2) /* load tlb entry lower-word */
476
mtctr %r0 /* restore counter */
477
mfspr %r0, SPR_DMISS /* get the miss address for the tlbld */
478
mfspr %r3, SPR_SRR1 /* get the saved cr0 bits */
479
mtcrf 0x80, %r3 /* restore CR0 */
480
mtspr SPR_RPA, %r1 /* set the pte */
481
ori %r1, %r1, 0x100 /* set reference bit */
482
srwi %r1, %r1, 8 /* get byte 7 of pte */
483
tlbld %r0 /* load the dtlb */
484
stb %r1, +6(%r2) /* update page table */
485
rfi /* return to executing program */
486
487
data_sec_hash:
488
andi. %r1, %r3, 0x0040 /* see if we have done second hash */
489
bne do_dsi /* if so, go to DSI interrupt */
490
mfspr %r2, SPR_HASH2 /* get the second pointer */
491
ori %r3, %r3, 0x0040 /* change the compare value */
492
addi %r1, 0, 8 /* load 8 for counter */
493
addi %r2, %r2, -8 /* pre dec for update on load */
494
b dm0 /* try second hash */
495
496
CNAME(dlmisssize) = .-CNAME(dlmisstrap)
497
498
/*
499
* G2 specific: data store TLB miss.
500
*/
501
.globl CNAME(dsmisstrap),CNAME(dsmisssize)
502
CNAME(dsmisstrap):
503
mfspr %r2, SPR_HASH1 /* get first pointer */
504
addi %r1, 0, 8 /* load 8 for counter */
505
mfctr %r0 /* save counter */
506
mfspr %r3, SPR_DCMP /* get first compare value */
507
addi %r2, %r2, -8 /* pre dec the pointer */
508
ds0:
509
mtctr %r1 /* load counter */
510
ds1:
511
lwzu %r1, 8(%r2) /* get next pte */
512
cmp 0, 0, %r1, %r3 /* see if found pte */
513
bdnzf 2, ds1 /* dec count br if cmp ne and if
514
* count not zero */
515
bne data_store_sec_hash /* if not found set up second hash
516
* or exit */
517
lwz %r1, +4(%r2) /* load tlb entry lower-word */
518
andi. %r3, %r1, 0x80 /* check the C-bit */
519
beq data_store_chk_prot /* if (C==0)
520
* go check protection modes */
521
ds2:
522
mtctr %r0 /* restore counter */
523
mfspr %r0, SPR_DMISS /* get the miss address for the tlbld */
524
mfspr %r3, SPR_SRR1 /* get the saved cr0 bits */
525
mtcrf 0x80, %r3 /* restore CR0 */
526
mtspr SPR_RPA, %r1 /* set the pte */
527
tlbld %r0 /* load the dtlb */
528
rfi /* return to executing program */
529
530
data_store_sec_hash:
531
andi. %r1, %r3, 0x0040 /* see if we have done second hash */
532
bne do_dsi /* if so, go to DSI interrupt */
533
mfspr %r2, SPR_HASH2 /* get the second pointer */
534
ori %r3, %r3, 0x0040 /* change the compare value */
535
addi %r1, 0, 8 /* load 8 for counter */
536
addi %r2, %r2, -8 /* pre dec for update on load */
537
b ds0 /* try second hash */
538
539
/* Check the protection before setting PTE(c-bit) */
540
data_store_chk_prot:
541
rlwinm. %r3,%r1,30,0,1 /* test PP */
542
bge- chk0 /* if (PP == 00 or PP == 01)
543
* goto chk0: */
544
andi. %r3, %r1, 1 /* test PP[0] */
545
beq+ chk2 /* return if PP[0] == 0 */
546
b do_dsi_prot /* else DSIp */
547
chk0:
548
mfspr %r3,SPR_SRR1 /* get old msr */
549
andis. %r3,%r3,0x0008 /* test the KEY bit (SRR1-bit 12) */
550
beq chk2 /* if (KEY==0) goto chk2: */
551
b do_dsi_prot /* else do_dsi_prot */
552
chk2:
553
ori %r1, %r1, 0x180 /* set reference and change bit */
554
sth %r1, 6(%r2) /* update page table */
555
b ds2 /* and back we go */
556
557
/* Create a faked DSI interrupt as the address was not found */
558
do_dsi:
559
mfspr %r3, SPR_SRR1 /* get srr1 */
560
rlwinm %r1,%r3,9,6,6 /* get srr1<flag> to bit 6 for
561
* load/store, zero rest */
562
addis %r1, %r1, 0x4000 /* or in dsisr<1> = 1 to flag pte
563
* not found */
564
b dsi1
565
566
do_dsi_prot:
567
mfspr %r3, SPR_SRR1 /* get srr1 */
568
rlwinm %r1,%r3,9,6,6 /* get srr1<flag> to bit 6 for
569
*load/store, zero rest */
570
addis %r1, %r1, 0x0800 /* or in dsisr<4> = 1 to flag prot
571
* violation */
572
573
dsi1:
574
mtctr %r0 /* restore counter */
575
andi. %r2, %r3, 0xffff /* clear upper bits of srr1 */
576
mtspr SPR_SRR1, %r2 /* set srr1 */
577
mtspr SPR_DSISR, %r1 /* load the dsisr */
578
mfspr %r1, SPR_DMISS /* get miss address */
579
rlwinm. %r2,%r2,0,31,31 /* test LE bit */
580
beq dsi2 /* if little endian then: */
581
xor %r1, %r1, 0x07 /* de-mung the data address */
582
dsi2:
583
mtspr SPR_DAR, %r1 /* put in dar */
584
mfmsr %r0 /* get msr */
585
xoris %r0, %r0, 0x2 /* flip the msr<tgpr> bit */
586
mtcrf 0x80, %r3 /* restore CR0 */
587
mtmsr %r0 /* flip back to the native gprs */
588
ba EXC_DSI /* branch to DSI interrupt */
589
590
CNAME(dsmisssize) = .-CNAME(dsmisstrap)
591
592
/*
593
* Similar to the above for DSI
594
* Has to handle BAT spills
595
* and standard pagetable spills
596
*/
597
.globl CNAME(dsitrap),CNAME(dsiend)
598
CNAME(dsitrap):
599
mtsprg1 %r1 /* save SP */
600
GET_CPUINFO(%r1)
601
stw %r28,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* free r28-r31 */
602
stw %r29,(PC_DISISAVE+CPUSAVE_R29)(%r1)
603
stw %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
604
stw %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
605
mfsprg1 %r1 /* restore SP */
606
mfcr %r29 /* save CR */
607
mfxer %r30 /* save XER */
608
mtsprg2 %r30 /* in SPRG2 */
609
mfsrr1 %r31 /* test kernel mode */
610
mtcr %r31
611
bt 17,1f /* branch if PSL_PR is set */
612
mfdar %r31 /* get fault address */
613
rlwinm %r31,%r31,7,25,28 /* get segment * 8 */
614
615
/* get batu */
616
lwz %r30,TRAP_TOCBASE(0)
617
lwz %r30,CNAME(battable)@got(%r30)
618
add %r31,%r30,%r31
619
lwz %r30,0(%r31)
620
mtcr %r30
621
bf 30,1f /* branch if supervisor valid is
622
false */
623
/* get batl */
624
lwz %r31,4(%r31)
625
/* We randomly use the highest two bat registers here */
626
mftb %r28
627
andi. %r28,%r28,1
628
bne 2f
629
mtdbatu 2,%r30
630
mtdbatl 2,%r31
631
b 3f
632
2:
633
mtdbatu 3,%r30
634
mtdbatl 3,%r31
635
3:
636
mfsprg2 %r30 /* restore XER */
637
mtxer %r30
638
mtcr %r29 /* restore CR */
639
mtsprg1 %r1
640
GET_CPUINFO(%r1)
641
lwz %r28,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* restore r28-r31 */
642
lwz %r29,(PC_DISISAVE+CPUSAVE_R29)(%r1)
643
lwz %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
644
lwz %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
645
mfsprg1 %r1
646
rfi /* return to trapped code */
647
1:
648
mflr %r28 /* save LR (SP already saved) */
649
650
/* Jump to disitrap */
651
lwz %r1, TRAP_GENTRAP(0)
652
addi %r1, %r1, (disitrap - generictrap)
653
mtlr %r1
654
blrl
655
CNAME(dsiend):
656
657
/*
658
* Preamble code for DSI/ISI traps
659
*/
660
disitrap:
661
/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
662
mflr %r1
663
andi. %r1,%r1,0xff00
664
mtsprg3 %r1
665
666
GET_CPUINFO(%r1)
667
lwz %r30,(PC_DISISAVE+CPUSAVE_R28)(%r1)
668
stw %r30,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
669
lwz %r31,(PC_DISISAVE+CPUSAVE_R29)(%r1)
670
stw %r31,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
671
lwz %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
672
stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
673
lwz %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
674
stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
675
mfdar %r30
676
mfdsisr %r31
677
stw %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
678
stw %r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
679
680
#ifdef KDB
681
/* Try to detect a kernel stack overflow */
682
mfsrr1 %r31
683
mtcr %r31
684
bt 17,realtrap /* branch is user mode */
685
mfsprg1 %r31 /* get old SP */
686
clrrwi %r31,%r31,12 /* Round SP down to nearest page */
687
sub. %r30,%r31,%r30 /* SP - DAR */
688
bge 1f
689
neg %r30,%r30 /* modulo value */
690
1: cmplwi %cr0,%r30,4096 /* is DAR within a page of SP? */
691
bge %cr0,realtrap /* no, too far away. */
692
693
/* Now convert this DSI into a DDB trap. */
694
GET_CPUINFO(%r1)
695
lwz %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) /* get DAR */
696
stw %r30,(PC_DBSAVE +CPUSAVE_AIM_DAR)(%r1) /* save DAR */
697
lwz %r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1) /* get DSISR */
698
stw %r31,(PC_DBSAVE +CPUSAVE_AIM_DSISR)(%r1) /* save DSISR */
699
lwz %r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* get r28 */
700
stw %r30,(PC_DBSAVE +CPUSAVE_R28)(%r1) /* save r28 */
701
lwz %r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) /* get r29 */
702
stw %r31,(PC_DBSAVE +CPUSAVE_R29)(%r1) /* save r29 */
703
lwz %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) /* get r30 */
704
stw %r30,(PC_DBSAVE +CPUSAVE_R30)(%r1) /* save r30 */
705
lwz %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get r31 */
706
stw %r31,(PC_DBSAVE +CPUSAVE_R31)(%r1) /* save r31 */
707
b dbtrap
708
#endif
709
710
/* XXX need stack probe here */
711
realtrap:
712
/* Test whether we already had PR set */
713
mfsrr1 %r1
714
mtcr %r1
715
mfsprg1 %r1 /* restore SP (might have been
716
overwritten) */
717
bf 17,k_trap /* branch if PSL_PR is false */
718
GET_CPUINFO(%r1)
719
lwz %r1,PC_CURPCB(%r1)
720
RESTORE_KERN_SRS(%r30,%r31) /* enable kernel mapping */
721
b s_trap
722
723
/*
724
* generictrap does some standard setup for trap handling to minimize
725
* the code that need be installed in the actual vectors. It expects
726
* the following conditions.
727
*
728
* R1 - Trap vector = LR & (0xff00 | R1)
729
* SPRG1 - Original R1 contents
730
* SPRG2 - Original LR
731
*/
732
733
.globl CNAME(generictrap64)
734
generictrap64:
735
mtsprg3 %r31
736
mfmsr %r31
737
clrldi %r31,%r31,1
738
mtmsrd %r31
739
mfsprg3 %r31
740
isync
741
742
.globl CNAME(generictrap)
743
generictrap:
744
/* Save R1 for computing the exception vector */
745
mtsprg3 %r1
746
747
/* Save interesting registers */
748
GET_CPUINFO(%r1)
749
stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) /* free r28-r31 */
750
stw %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
751
stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
752
stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
753
mfsprg1 %r1 /* restore SP, in case of branch */
754
mfsprg2 %r28 /* save LR */
755
mfcr %r29 /* save CR */
756
757
/* Compute the exception vector from the link register */
758
mfsprg3 %r31
759
ori %r31,%r31,0xff00
760
mflr %r30
761
and %r30,%r30,%r31
762
mtsprg3 %r30
763
764
/* Test whether we already had PR set */
765
mfsrr1 %r31
766
mtcr %r31
767
768
s_trap:
769
bf 17,k_trap /* branch if PSL_PR is false */
770
GET_CPUINFO(%r1)
771
u_trap:
772
lwz %r1,PC_CURPCB(%r1)
773
RESTORE_KERN_SRS(%r30,%r31) /* enable kernel mapping */
774
775
/*
776
* Now the common trap catching code.
777
*/
778
k_trap:
779
FRAME_SETUP(PC_TEMPSAVE)
780
/* Restore USER_SR */
781
GET_CPUINFO(%r30)
782
lwz %r30,PC_CURPCB(%r30)
783
lwz %r30,PCB_AIM_USR_VSID(%r30)
784
mtsr USER_SR,%r30; sync; isync
785
/* Call C interrupt dispatcher: */
786
trapagain:
787
addi %r3,%r1,8
788
bl CNAME(powerpc_interrupt)
789
.globl CNAME(trapexit) /* backtrace code sentinel */
790
CNAME(trapexit):
791
792
/* Disable interrupts: */
793
mfmsr %r3
794
andi. %r3,%r3,~PSL_EE@l
795
mtmsr %r3
796
isync
797
/* Test AST pending: */
798
lwz %r5,FRAME_SRR1+8(%r1)
799
mtcr %r5
800
bf 17,1f /* branch if PSL_PR is false */
801
802
GET_CPUINFO(%r3) /* get per-CPU pointer */
803
lwz %r4, TD_AST(%r2) /* get thread ast value
804
* (r2 is curthread) */
805
cmpwi %r4, 0
806
beq 1f
807
mfmsr %r3 /* re-enable interrupts */
808
ori %r3,%r3,PSL_EE@l
809
mtmsr %r3
810
isync
811
addi %r3,%r1,8
812
bl CNAME(ast)
813
.globl CNAME(asttrapexit) /* backtrace code sentinel #2 */
814
CNAME(asttrapexit):
815
b trapexit /* test ast ret value ? */
816
1:
817
FRAME_LEAVE(PC_TEMPSAVE)
818
819
.globl CNAME(rfi_patch1) /* replace rfi with rfid on ppc64 */
820
CNAME(rfi_patch1):
821
rfi
822
823
.globl CNAME(rfid_patch)
824
CNAME(rfid_patch):
825
rfid
826
827
#if defined(KDB)
828
/*
829
* Deliberate entry to dbtrap
830
*/
831
.globl CNAME(breakpoint)
832
CNAME(breakpoint):
833
mtsprg1 %r1
834
mfmsr %r3
835
mtsrr1 %r3
836
andi. %r3,%r3,~(PSL_EE|PSL_ME)@l
837
mtmsr %r3 /* disable interrupts */
838
isync
839
GET_CPUINFO(%r3)
840
stw %r28,(PC_DBSAVE+CPUSAVE_R28)(%r3)
841
stw %r29,(PC_DBSAVE+CPUSAVE_R29)(%r3)
842
stw %r30,(PC_DBSAVE+CPUSAVE_R30)(%r3)
843
stw %r31,(PC_DBSAVE+CPUSAVE_R31)(%r3)
844
mflr %r28
845
li %r29,EXC_BPT
846
mtlr %r29
847
mfcr %r29
848
mtsrr0 %r28
849
850
/*
851
* Now the kdb trap catching code.
852
*/
853
dbtrap:
854
/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
855
mflr %r1
856
andi. %r1,%r1,0xff00
857
mtsprg3 %r1
858
859
lwz %r1,TRAP_TOCBASE(0) /* get new SP */
860
lwz %r1,trapstk@got(%r1)
861
addi %r1,%r1,TRAPSTKSZ-16
862
863
FRAME_SETUP(PC_DBSAVE)
864
/* Call C trap code: */
865
addi %r3,%r1,8
866
bl CNAME(db_trap_glue)
867
or. %r3,%r3,%r3
868
bne dbleave
869
/* This wasn't for KDB, so switch to real trap: */
870
lwz %r3,FRAME_EXC+8(%r1) /* save exception */
871
GET_CPUINFO(%r4)
872
stw %r3,(PC_DBSAVE+CPUSAVE_R31)(%r4)
873
FRAME_LEAVE(PC_DBSAVE)
874
mtsprg1 %r1 /* prepare for entrance to realtrap */
875
GET_CPUINFO(%r1)
876
stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
877
stw %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
878
stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
879
stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
880
mflr %r28
881
mfcr %r29
882
lwz %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)
883
mtsprg3 %r31 /* SPRG3 was clobbered by FRAME_LEAVE */
884
mfsprg1 %r1
885
b realtrap
886
dbleave:
887
FRAME_LEAVE(PC_DBSAVE)
888
.globl CNAME(rfi_patch2) /* replace rfi with rfid on ppc64 */
889
CNAME(rfi_patch2):
890
rfi
891
892
/*
893
* In case of KDB we want a separate trap catcher for it
894
*/
895
.globl CNAME(dblow),CNAME(dbend)
896
CNAME(dblow):
897
mtsprg1 %r1 /* save SP */
898
mtsprg2 %r29 /* save r29 */
899
mfcr %r29 /* save CR in r29 */
900
mfsrr1 %r1
901
mtcr %r1
902
bf 17,1f /* branch if privileged */
903
/* Unprivileged case */
904
mtcr %r29 /* put the condition register back */
905
mfsprg2 %r29 /* ... and r29 */
906
mflr %r1 /* save LR */
907
mtsprg2 %r1 /* And then in SPRG2 */
908
909
lwz %r1, TRAP_ENTRY(0) /* Get branch address */
910
mtlr %r1
911
li %r1, 0 /* How to get the vector from LR */
912
blrl /* LR & (0xff00 | r1) is exception # */
913
1:
914
/* Privileged, so drop to KDB */
915
GET_CPUINFO(%r1)
916
stw %r28,(PC_DBSAVE+CPUSAVE_R28)(%r1) /* free r28 */
917
mfsprg2 %r28 /* r29 holds cr... */
918
stw %r28,(PC_DBSAVE+CPUSAVE_R29)(%r1) /* free r29 */
919
stw %r30,(PC_DBSAVE+CPUSAVE_R30)(%r1) /* free r30 */
920
stw %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) /* free r31 */
921
mflr %r28 /* save LR */
922
923
/* Jump to dbtrap */
924
lwz %r1, TRAP_GENTRAP(0)
925
addi %r1, %r1, (dbtrap - generictrap)
926
mtlr %r1
927
blrl
928
CNAME(dbend):
929
#endif /* KDB */
930
931