Print this page
de-linting of .s files
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/sun4u/ml/trap_table.s
+++ new/usr/src/uts/sun4u/ml/trap_table.s
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 -#if !defined(lint)
27 26 #include "assym.h"
28 -#endif /* !lint */
29 27 #include <sys/asm_linkage.h>
30 28 #include <sys/privregs.h>
31 29 #include <sys/sun4asi.h>
32 30 #include <sys/spitregs.h>
33 31 #include <sys/cheetahregs.h>
34 32 #include <sys/machtrap.h>
35 33 #include <sys/machthread.h>
36 34 #include <sys/machbrand.h>
37 35 #include <sys/pcb.h>
38 36 #include <sys/pte.h>
39 37 #include <sys/mmu.h>
40 38 #include <sys/machpcb.h>
41 39 #include <sys/async.h>
42 40 #include <sys/intreg.h>
43 41 #include <sys/scb.h>
44 42 #include <sys/psr_compat.h>
45 43 #include <sys/syscall.h>
46 44 #include <sys/machparam.h>
47 45 #include <sys/traptrace.h>
48 46 #include <vm/hat_sfmmu.h>
49 47 #include <sys/archsystm.h>
50 48 #include <sys/utrap.h>
51 49 #include <sys/clock.h>
52 50 #include <sys/intr.h>
53 51 #include <sys/fpu/fpu_simulator.h>
54 52 #include <vm/seg_spt.h>
55 53
56 54 /*
57 55 * WARNING: If you add a fast trap handler which can be invoked by a
58 56 * non-privileged user, you may have to use the FAST_TRAP_DONE macro
59 57 * instead of "done" instruction to return back to the user mode. See
60 58 * comments for the "fast_trap_done" entry point for more information.
61 59 *
62 60 * An alternate FAST_TRAP_DONE_CHK_INTR macro should be used for the
63 61 * cases where you always want to process any pending interrupts before
64 62 * returning back to the user mode.
65 63 */
66 64 #define FAST_TRAP_DONE \
67 65 ba,a fast_trap_done
68 66
69 67 #define FAST_TRAP_DONE_CHK_INTR \
70 68 ba,a fast_trap_done_chk_intr
71 69
72 70 /*
73 71 * SPARC V9 Trap Table
74 72 *
75 73 * Most of the trap handlers are made from common building
76 74 * blocks, and some are instantiated multiple times within
77 75 * the trap table. So, I build a bunch of macros, then
78 76 * populate the table using only the macros.
79 77 *
80 78 * Many macros branch to sys_trap. Its calling convention is:
81 79 * %g1 kernel trap handler
82 80 * %g2, %g3 args for above
83 81 * %g4 desire %pil
84 82 */
85 83
86 84 #ifdef TRAPTRACE
87 85
88 86 /*
89 87 * Tracing macro. Adds two instructions if TRAPTRACE is defined.
90 88 */
91 89 #define TT_TRACE(label) \
92 90 ba label ;\
93 91 rd %pc, %g7
94 92 #define TT_TRACE_INS 2
95 93
96 94 #define TT_TRACE_L(label) \
97 95 ba label ;\
98 96 rd %pc, %l4 ;\
99 97 clr %l4
100 98 #define TT_TRACE_L_INS 3
101 99
102 100 #else
103 101
104 102 #define TT_TRACE(label)
105 103 #define TT_TRACE_INS 0
106 104
107 105 #define TT_TRACE_L(label)
108 106 #define TT_TRACE_L_INS 0
109 107
↓ open down ↓ |
71 lines elided |
↑ open up ↑ |
110 108 #endif
111 109
112 110 /*
113 111 * This first set are funneled to trap() with %tt as the type.
114 112 * Trap will then either panic or send the user a signal.
115 113 */
116 114 /*
117 115 * NOT is used for traps that just shouldn't happen.
118 116 * It comes in both single and quadruple flavors.
119 117 */
120 -#if !defined(lint)
121 118 .global trap
122 -#endif /* !lint */
123 119 #define NOT \
124 120 TT_TRACE(trace_gen) ;\
125 121 set trap, %g1 ;\
126 122 rdpr %tt, %g3 ;\
127 123 ba,pt %xcc, sys_trap ;\
128 124 sub %g0, 1, %g4 ;\
129 125 .align 32
130 126 #define NOT4 NOT; NOT; NOT; NOT
131 127 /*
132 128 * RED is for traps that use the red mode handler.
133 129 * We should never see these either.
134 130 */
135 131 #define RED NOT
136 132 /*
137 133 * BAD is used for trap vectors we don't have a kernel
138 134 * handler for.
139 135 * It also comes in single and quadruple versions.
140 136 */
141 137 #define BAD NOT
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
142 138 #define BAD4 NOT4
143 139
144 140 #define DONE \
145 141 done; \
146 142 .align 32
147 143
148 144 /*
149 145 * TRAP vectors to the trap() function.
150 146 * It's main use is for user errors.
151 147 */
152 -#if !defined(lint)
153 148 .global trap
154 -#endif /* !lint */
155 149 #define TRAP(arg) \
156 150 TT_TRACE(trace_gen) ;\
157 151 set trap, %g1 ;\
158 152 mov arg, %g3 ;\
159 153 ba,pt %xcc, sys_trap ;\
160 154 sub %g0, 1, %g4 ;\
161 155 .align 32
162 156
163 157 /*
164 158 * SYSCALL is used for unsupported syscall interfaces (with 'which'
165 159 * set to 'nosys') and legacy support of old SunOS 4.x syscalls (with
166 160 * 'which' set to 'syscall_trap32').
167 161 *
168 162 * The SYSCALL_TRAP* macros are used for syscall entry points.
169 163 * SYSCALL_TRAP is used to support LP64 syscalls and SYSCALL_TRAP32
170 164 * is used to support ILP32. Each macro can only be used once
171 165 * since they each define a symbol. The symbols are used as hot patch
172 166 * points by the brand infrastructure to dynamically enable and disable
173 167 * brand syscall interposition. See the comments around BRAND_CALLBACK
174 168 * and brand_plat_interposition_enable() for more information.
175 169 */
176 170 #define SYSCALL_NOTT(which) \
177 171 set (which), %g1 ;\
178 172 ba,pt %xcc, sys_trap ;\
179 173 sub %g0, 1, %g4 ;\
180 174 .align 32
181 175
182 176 #define SYSCALL(which) \
183 177 TT_TRACE(trace_gen) ;\
184 178 SYSCALL_NOTT(which)
185 179
186 180 #define SYSCALL_TRAP32 \
187 181 TT_TRACE(trace_gen) ;\
188 182 ALTENTRY(syscall_trap32_patch_point) \
189 183 SYSCALL_NOTT(syscall_trap32)
190 184
191 185 #define SYSCALL_TRAP \
192 186 TT_TRACE(trace_gen) ;\
193 187 ALTENTRY(syscall_trap_patch_point) \
194 188 SYSCALL_NOTT(syscall_trap)
195 189
196 190 #define FLUSHW(h_name) \
197 191 .global h_name ;\
198 192 h_name: ;\
199 193 set trap, %g1 ;\
200 194 mov T_FLUSHW, %g3 ;\
201 195 sub %g0, 1, %g4 ;\
202 196 save ;\
203 197 flushw ;\
204 198 restore ;\
205 199 FAST_TRAP_DONE ;\
206 200 .align 32
207 201
208 202 /*
209 203 * GOTO just jumps to a label.
210 204 * It's used for things that can be fixed without going thru sys_trap.
211 205 */
212 206 #define GOTO(label) \
213 207 .global label ;\
214 208 ba,a label ;\
215 209 .empty ;\
216 210 .align 32
217 211
218 212 /*
219 213 * GOTO_TT just jumps to a label.
220 214 * correctable ECC error traps at level 0 and 1 will use this macro.
221 215 * It's used for things that can be fixed without going thru sys_trap.
222 216 */
223 217 #define GOTO_TT(label, ttlabel) \
224 218 .global label ;\
225 219 TT_TRACE(ttlabel) ;\
226 220 ba,a label ;\
227 221 .empty ;\
228 222 .align 32
229 223
230 224 /*
231 225 * Privileged traps
232 226 * Takes breakpoint if privileged, calls trap() if not.
233 227 */
234 228 #define PRIV(label) \
235 229 rdpr %tstate, %g1 ;\
236 230 btst TSTATE_PRIV, %g1 ;\
237 231 bnz label ;\
238 232 rdpr %tt, %g3 ;\
239 233 set trap, %g1 ;\
240 234 ba,pt %xcc, sys_trap ;\
241 235 sub %g0, 1, %g4 ;\
242 236 .align 32
243 237
244 238
245 239 /*
246 240 * DTrace traps.
247 241 */
248 242 #define DTRACE_PID \
249 243 .global dtrace_pid_probe ;\
250 244 set dtrace_pid_probe, %g1 ;\
251 245 ba,pt %xcc, user_trap ;\
252 246 sub %g0, 1, %g4 ;\
253 247 .align 32
254 248
255 249 #define DTRACE_RETURN \
256 250 .global dtrace_return_probe ;\
257 251 set dtrace_return_probe, %g1 ;\
258 252 ba,pt %xcc, user_trap ;\
259 253 sub %g0, 1, %g4 ;\
260 254 .align 32
261 255
262 256 /*
263 257 * REGISTER WINDOW MANAGEMENT MACROS
264 258 */
265 259
266 260 /*
267 261 * various convenient units of padding
268 262 */
269 263 #define SKIP(n) .skip 4*(n)
270 264
271 265 /*
272 266 * CLEAN_WINDOW is the simple handler for cleaning a register window.
↓ open down ↓ |
108 lines elided |
↑ open up ↑ |
273 267 */
274 268 #define CLEAN_WINDOW \
275 269 TT_TRACE_L(trace_win) ;\
276 270 rdpr %cleanwin, %l0; inc %l0; wrpr %l0, %cleanwin ;\
277 271 clr %l0; clr %l1; clr %l2; clr %l3 ;\
278 272 clr %l4; clr %l5; clr %l6; clr %l7 ;\
279 273 clr %o0; clr %o1; clr %o2; clr %o3 ;\
280 274 clr %o4; clr %o5; clr %o6; clr %o7 ;\
281 275 retry; .align 128
282 276
283 -#if !defined(lint)
284 -
285 277 /*
286 278 * If we get an unresolved tlb miss while in a window handler, the fault
287 279 * handler will resume execution at the last instruction of the window
288 280 * hander, instead of delivering the fault to the kernel. Spill handlers
289 281 * use this to spill windows into the wbuf.
290 282 *
291 283 * The mixed handler works by checking %sp, and branching to the correct
292 284 * handler. This is done by branching back to label 1: for 32b frames,
293 285 * or label 2: for 64b frames; which implies the handler order is: 32b,
294 286 * 64b, mixed. The 1: and 2: labels are offset into the routines to
295 287 * allow the branchs' delay slots to contain useful instructions.
296 288 */
297 289
298 290 /*
299 291 * SPILL_32bit spills a 32-bit-wide kernel register window. It
300 292 * assumes that the kernel context and the nucleus context are the
301 293 * same. The stack pointer is required to be eight-byte aligned even
302 294 * though this code only needs it to be four-byte aligned.
303 295 */
304 296 #define SPILL_32bit(tail) \
305 297 srl %sp, 0, %sp ;\
306 298 1: st %l0, [%sp + 0] ;\
307 299 st %l1, [%sp + 4] ;\
308 300 st %l2, [%sp + 8] ;\
309 301 st %l3, [%sp + 12] ;\
310 302 st %l4, [%sp + 16] ;\
311 303 st %l5, [%sp + 20] ;\
312 304 st %l6, [%sp + 24] ;\
313 305 st %l7, [%sp + 28] ;\
314 306 st %i0, [%sp + 32] ;\
315 307 st %i1, [%sp + 36] ;\
316 308 st %i2, [%sp + 40] ;\
317 309 st %i3, [%sp + 44] ;\
318 310 st %i4, [%sp + 48] ;\
319 311 st %i5, [%sp + 52] ;\
320 312 st %i6, [%sp + 56] ;\
321 313 st %i7, [%sp + 60] ;\
322 314 TT_TRACE_L(trace_win) ;\
323 315 saved ;\
324 316 retry ;\
325 317 SKIP(31-19-TT_TRACE_L_INS) ;\
326 318 ba,a,pt %xcc, fault_32bit_/**/tail ;\
327 319 .empty
328 320
329 321 /*
330 322 * SPILL_32bit_asi spills a 32-bit-wide register window into a 32-bit
331 323 * wide address space via the designated asi. It is used to spill
332 324 * non-kernel windows. The stack pointer is required to be eight-byte
333 325 * aligned even though this code only needs it to be four-byte
334 326 * aligned.
335 327 */
336 328 #define SPILL_32bit_asi(asi_num, tail) \
337 329 srl %sp, 0, %sp ;\
338 330 1: sta %l0, [%sp + %g0]asi_num ;\
339 331 mov 4, %g1 ;\
340 332 sta %l1, [%sp + %g1]asi_num ;\
341 333 mov 8, %g2 ;\
342 334 sta %l2, [%sp + %g2]asi_num ;\
343 335 mov 12, %g3 ;\
344 336 sta %l3, [%sp + %g3]asi_num ;\
345 337 add %sp, 16, %g4 ;\
346 338 sta %l4, [%g4 + %g0]asi_num ;\
347 339 sta %l5, [%g4 + %g1]asi_num ;\
348 340 sta %l6, [%g4 + %g2]asi_num ;\
349 341 sta %l7, [%g4 + %g3]asi_num ;\
350 342 add %g4, 16, %g4 ;\
351 343 sta %i0, [%g4 + %g0]asi_num ;\
352 344 sta %i1, [%g4 + %g1]asi_num ;\
353 345 sta %i2, [%g4 + %g2]asi_num ;\
354 346 sta %i3, [%g4 + %g3]asi_num ;\
355 347 add %g4, 16, %g4 ;\
356 348 sta %i4, [%g4 + %g0]asi_num ;\
357 349 sta %i5, [%g4 + %g1]asi_num ;\
358 350 sta %i6, [%g4 + %g2]asi_num ;\
359 351 sta %i7, [%g4 + %g3]asi_num ;\
360 352 TT_TRACE_L(trace_win) ;\
361 353 saved ;\
362 354 retry ;\
363 355 SKIP(31-25-TT_TRACE_L_INS) ;\
364 356 ba,a,pt %xcc, fault_32bit_/**/tail ;\
365 357 .empty
366 358
367 359 /*
368 360 * SPILL_32bit_tt1 spills a 32-bit-wide register window into a 32-bit
369 361 * wide address space via the designated asi. It is used to spill
370 362 * windows at tl>1 where performance isn't the primary concern and
371 363 * where we don't want to use unnecessary registers. The stack
372 364 * pointer is required to be eight-byte aligned even though this code
373 365 * only needs it to be four-byte aligned.
374 366 */
375 367 #define SPILL_32bit_tt1(asi_num, tail) \
376 368 mov asi_num, %asi ;\
377 369 1: srl %sp, 0, %sp ;\
378 370 sta %l0, [%sp + 0]%asi ;\
379 371 sta %l1, [%sp + 4]%asi ;\
380 372 sta %l2, [%sp + 8]%asi ;\
381 373 sta %l3, [%sp + 12]%asi ;\
382 374 sta %l4, [%sp + 16]%asi ;\
383 375 sta %l5, [%sp + 20]%asi ;\
384 376 sta %l6, [%sp + 24]%asi ;\
385 377 sta %l7, [%sp + 28]%asi ;\
386 378 sta %i0, [%sp + 32]%asi ;\
387 379 sta %i1, [%sp + 36]%asi ;\
388 380 sta %i2, [%sp + 40]%asi ;\
389 381 sta %i3, [%sp + 44]%asi ;\
390 382 sta %i4, [%sp + 48]%asi ;\
391 383 sta %i5, [%sp + 52]%asi ;\
392 384 sta %i6, [%sp + 56]%asi ;\
393 385 sta %i7, [%sp + 60]%asi ;\
394 386 TT_TRACE_L(trace_win) ;\
395 387 saved ;\
396 388 retry ;\
397 389 SKIP(31-20-TT_TRACE_L_INS) ;\
398 390 ba,a,pt %xcc, fault_32bit_/**/tail ;\
399 391 .empty
400 392
401 393
402 394 /*
403 395 * FILL_32bit fills a 32-bit-wide kernel register window. It assumes
404 396 * that the kernel context and the nucleus context are the same. The
405 397 * stack pointer is required to be eight-byte aligned even though this
406 398 * code only needs it to be four-byte aligned.
407 399 */
408 400 #define FILL_32bit(tail) \
409 401 srl %sp, 0, %sp ;\
410 402 1: TT_TRACE_L(trace_win) ;\
411 403 ld [%sp + 0], %l0 ;\
412 404 ld [%sp + 4], %l1 ;\
413 405 ld [%sp + 8], %l2 ;\
414 406 ld [%sp + 12], %l3 ;\
415 407 ld [%sp + 16], %l4 ;\
416 408 ld [%sp + 20], %l5 ;\
417 409 ld [%sp + 24], %l6 ;\
418 410 ld [%sp + 28], %l7 ;\
419 411 ld [%sp + 32], %i0 ;\
420 412 ld [%sp + 36], %i1 ;\
421 413 ld [%sp + 40], %i2 ;\
422 414 ld [%sp + 44], %i3 ;\
423 415 ld [%sp + 48], %i4 ;\
424 416 ld [%sp + 52], %i5 ;\
425 417 ld [%sp + 56], %i6 ;\
426 418 ld [%sp + 60], %i7 ;\
427 419 restored ;\
428 420 retry ;\
429 421 SKIP(31-19-TT_TRACE_L_INS) ;\
430 422 ba,a,pt %xcc, fault_32bit_/**/tail ;\
431 423 .empty
432 424
433 425 /*
434 426 * FILL_32bit_asi fills a 32-bit-wide register window from a 32-bit
435 427 * wide address space via the designated asi. It is used to fill
436 428 * non-kernel windows. The stack pointer is required to be eight-byte
437 429 * aligned even though this code only needs it to be four-byte
438 430 * aligned.
439 431 */
440 432 #define FILL_32bit_asi(asi_num, tail) \
441 433 srl %sp, 0, %sp ;\
442 434 1: TT_TRACE_L(trace_win) ;\
443 435 mov 4, %g1 ;\
444 436 lda [%sp + %g0]asi_num, %l0 ;\
445 437 mov 8, %g2 ;\
446 438 lda [%sp + %g1]asi_num, %l1 ;\
447 439 mov 12, %g3 ;\
448 440 lda [%sp + %g2]asi_num, %l2 ;\
449 441 lda [%sp + %g3]asi_num, %l3 ;\
450 442 add %sp, 16, %g4 ;\
451 443 lda [%g4 + %g0]asi_num, %l4 ;\
452 444 lda [%g4 + %g1]asi_num, %l5 ;\
453 445 lda [%g4 + %g2]asi_num, %l6 ;\
454 446 lda [%g4 + %g3]asi_num, %l7 ;\
455 447 add %g4, 16, %g4 ;\
456 448 lda [%g4 + %g0]asi_num, %i0 ;\
457 449 lda [%g4 + %g1]asi_num, %i1 ;\
458 450 lda [%g4 + %g2]asi_num, %i2 ;\
459 451 lda [%g4 + %g3]asi_num, %i3 ;\
460 452 add %g4, 16, %g4 ;\
461 453 lda [%g4 + %g0]asi_num, %i4 ;\
462 454 lda [%g4 + %g1]asi_num, %i5 ;\
463 455 lda [%g4 + %g2]asi_num, %i6 ;\
464 456 lda [%g4 + %g3]asi_num, %i7 ;\
465 457 restored ;\
466 458 retry ;\
467 459 SKIP(31-25-TT_TRACE_L_INS) ;\
468 460 ba,a,pt %xcc, fault_32bit_/**/tail ;\
469 461 .empty
470 462
471 463 /*
472 464 * FILL_32bit_tt1 fills a 32-bit-wide register window from a 32-bit
473 465 * wide address space via the designated asi. It is used to fill
474 466 * windows at tl>1 where performance isn't the primary concern and
475 467 * where we don't want to use unnecessary registers. The stack
476 468 * pointer is required to be eight-byte aligned even though this code
477 469 * only needs it to be four-byte aligned.
478 470 */
479 471 #define FILL_32bit_tt1(asi_num, tail) \
480 472 mov asi_num, %asi ;\
481 473 1: srl %sp, 0, %sp ;\
482 474 TT_TRACE_L(trace_win) ;\
483 475 lda [%sp + 0]%asi, %l0 ;\
484 476 lda [%sp + 4]%asi, %l1 ;\
485 477 lda [%sp + 8]%asi, %l2 ;\
486 478 lda [%sp + 12]%asi, %l3 ;\
487 479 lda [%sp + 16]%asi, %l4 ;\
488 480 lda [%sp + 20]%asi, %l5 ;\
489 481 lda [%sp + 24]%asi, %l6 ;\
490 482 lda [%sp + 28]%asi, %l7 ;\
491 483 lda [%sp + 32]%asi, %i0 ;\
492 484 lda [%sp + 36]%asi, %i1 ;\
493 485 lda [%sp + 40]%asi, %i2 ;\
494 486 lda [%sp + 44]%asi, %i3 ;\
495 487 lda [%sp + 48]%asi, %i4 ;\
496 488 lda [%sp + 52]%asi, %i5 ;\
497 489 lda [%sp + 56]%asi, %i6 ;\
498 490 lda [%sp + 60]%asi, %i7 ;\
499 491 restored ;\
500 492 retry ;\
501 493 SKIP(31-20-TT_TRACE_L_INS) ;\
502 494 ba,a,pt %xcc, fault_32bit_/**/tail ;\
503 495 .empty
504 496
505 497
506 498 /*
507 499 * SPILL_64bit spills a 64-bit-wide kernel register window. It
508 500 * assumes that the kernel context and the nucleus context are the
509 501 * same. The stack pointer is required to be eight-byte aligned.
510 502 */
511 503 #define SPILL_64bit(tail) \
512 504 2: stx %l0, [%sp + V9BIAS64 + 0] ;\
513 505 stx %l1, [%sp + V9BIAS64 + 8] ;\
514 506 stx %l2, [%sp + V9BIAS64 + 16] ;\
515 507 stx %l3, [%sp + V9BIAS64 + 24] ;\
516 508 stx %l4, [%sp + V9BIAS64 + 32] ;\
517 509 stx %l5, [%sp + V9BIAS64 + 40] ;\
518 510 stx %l6, [%sp + V9BIAS64 + 48] ;\
519 511 stx %l7, [%sp + V9BIAS64 + 56] ;\
520 512 stx %i0, [%sp + V9BIAS64 + 64] ;\
521 513 stx %i1, [%sp + V9BIAS64 + 72] ;\
522 514 stx %i2, [%sp + V9BIAS64 + 80] ;\
523 515 stx %i3, [%sp + V9BIAS64 + 88] ;\
524 516 stx %i4, [%sp + V9BIAS64 + 96] ;\
525 517 stx %i5, [%sp + V9BIAS64 + 104] ;\
526 518 stx %i6, [%sp + V9BIAS64 + 112] ;\
527 519 stx %i7, [%sp + V9BIAS64 + 120] ;\
528 520 TT_TRACE_L(trace_win) ;\
529 521 saved ;\
530 522 retry ;\
531 523 SKIP(31-18-TT_TRACE_L_INS) ;\
532 524 ba,a,pt %xcc, fault_64bit_/**/tail ;\
533 525 .empty
534 526
535 527 /*
536 528 * SPILL_64bit_asi spills a 64-bit-wide register window into a 64-bit
537 529 * wide address space via the designated asi. It is used to spill
538 530 * non-kernel windows. The stack pointer is required to be eight-byte
539 531 * aligned.
540 532 */
541 533 #define SPILL_64bit_asi(asi_num, tail) \
542 534 mov 0 + V9BIAS64, %g1 ;\
543 535 2: stxa %l0, [%sp + %g1]asi_num ;\
544 536 mov 8 + V9BIAS64, %g2 ;\
545 537 stxa %l1, [%sp + %g2]asi_num ;\
546 538 mov 16 + V9BIAS64, %g3 ;\
547 539 stxa %l2, [%sp + %g3]asi_num ;\
548 540 mov 24 + V9BIAS64, %g4 ;\
549 541 stxa %l3, [%sp + %g4]asi_num ;\
550 542 add %sp, 32, %g5 ;\
551 543 stxa %l4, [%g5 + %g1]asi_num ;\
552 544 stxa %l5, [%g5 + %g2]asi_num ;\
553 545 stxa %l6, [%g5 + %g3]asi_num ;\
554 546 stxa %l7, [%g5 + %g4]asi_num ;\
555 547 add %g5, 32, %g5 ;\
556 548 stxa %i0, [%g5 + %g1]asi_num ;\
557 549 stxa %i1, [%g5 + %g2]asi_num ;\
558 550 stxa %i2, [%g5 + %g3]asi_num ;\
559 551 stxa %i3, [%g5 + %g4]asi_num ;\
560 552 add %g5, 32, %g5 ;\
561 553 stxa %i4, [%g5 + %g1]asi_num ;\
562 554 stxa %i5, [%g5 + %g2]asi_num ;\
563 555 stxa %i6, [%g5 + %g3]asi_num ;\
564 556 stxa %i7, [%g5 + %g4]asi_num ;\
565 557 TT_TRACE_L(trace_win) ;\
566 558 saved ;\
567 559 retry ;\
568 560 SKIP(31-25-TT_TRACE_L_INS) ;\
569 561 ba,a,pt %xcc, fault_64bit_/**/tail ;\
570 562 .empty
571 563
572 564 /*
573 565 * SPILL_64bit_tt1 spills a 64-bit-wide register window into a 64-bit
574 566 * wide address space via the designated asi. It is used to spill
575 567 * windows at tl>1 where performance isn't the primary concern and
576 568 * where we don't want to use unnecessary registers. The stack
577 569 * pointer is required to be eight-byte aligned.
578 570 */
579 571 #define SPILL_64bit_tt1(asi_num, tail) \
580 572 mov asi_num, %asi ;\
581 573 2: stxa %l0, [%sp + V9BIAS64 + 0]%asi ;\
582 574 stxa %l1, [%sp + V9BIAS64 + 8]%asi ;\
583 575 stxa %l2, [%sp + V9BIAS64 + 16]%asi ;\
584 576 stxa %l3, [%sp + V9BIAS64 + 24]%asi ;\
585 577 stxa %l4, [%sp + V9BIAS64 + 32]%asi ;\
586 578 stxa %l5, [%sp + V9BIAS64 + 40]%asi ;\
587 579 stxa %l6, [%sp + V9BIAS64 + 48]%asi ;\
588 580 stxa %l7, [%sp + V9BIAS64 + 56]%asi ;\
589 581 stxa %i0, [%sp + V9BIAS64 + 64]%asi ;\
590 582 stxa %i1, [%sp + V9BIAS64 + 72]%asi ;\
591 583 stxa %i2, [%sp + V9BIAS64 + 80]%asi ;\
592 584 stxa %i3, [%sp + V9BIAS64 + 88]%asi ;\
593 585 stxa %i4, [%sp + V9BIAS64 + 96]%asi ;\
594 586 stxa %i5, [%sp + V9BIAS64 + 104]%asi ;\
595 587 stxa %i6, [%sp + V9BIAS64 + 112]%asi ;\
596 588 stxa %i7, [%sp + V9BIAS64 + 120]%asi ;\
597 589 TT_TRACE_L(trace_win) ;\
598 590 saved ;\
599 591 retry ;\
600 592 SKIP(31-19-TT_TRACE_L_INS) ;\
601 593 ba,a,pt %xcc, fault_64bit_/**/tail ;\
602 594 .empty
603 595
604 596
605 597 /*
606 598 * FILL_64bit fills a 64-bit-wide kernel register window. It assumes
607 599 * that the kernel context and the nucleus context are the same. The
608 600 * stack pointer is required to be eight-byte aligned.
609 601 */
610 602 #define FILL_64bit(tail) \
611 603 2: TT_TRACE_L(trace_win) ;\
612 604 ldx [%sp + V9BIAS64 + 0], %l0 ;\
613 605 ldx [%sp + V9BIAS64 + 8], %l1 ;\
614 606 ldx [%sp + V9BIAS64 + 16], %l2 ;\
615 607 ldx [%sp + V9BIAS64 + 24], %l3 ;\
616 608 ldx [%sp + V9BIAS64 + 32], %l4 ;\
617 609 ldx [%sp + V9BIAS64 + 40], %l5 ;\
618 610 ldx [%sp + V9BIAS64 + 48], %l6 ;\
619 611 ldx [%sp + V9BIAS64 + 56], %l7 ;\
620 612 ldx [%sp + V9BIAS64 + 64], %i0 ;\
621 613 ldx [%sp + V9BIAS64 + 72], %i1 ;\
622 614 ldx [%sp + V9BIAS64 + 80], %i2 ;\
623 615 ldx [%sp + V9BIAS64 + 88], %i3 ;\
624 616 ldx [%sp + V9BIAS64 + 96], %i4 ;\
625 617 ldx [%sp + V9BIAS64 + 104], %i5 ;\
626 618 ldx [%sp + V9BIAS64 + 112], %i6 ;\
627 619 ldx [%sp + V9BIAS64 + 120], %i7 ;\
628 620 restored ;\
629 621 retry ;\
630 622 SKIP(31-18-TT_TRACE_L_INS) ;\
631 623 ba,a,pt %xcc, fault_64bit_/**/tail ;\
632 624 .empty
633 625
634 626 /*
635 627 * FILL_64bit_asi fills a 64-bit-wide register window from a 64-bit
636 628 * wide address space via the designated asi. It is used to fill
637 629 * non-kernel windows. The stack pointer is required to be eight-byte
638 630 * aligned.
639 631 */
640 632 #define FILL_64bit_asi(asi_num, tail) \
641 633 mov V9BIAS64 + 0, %g1 ;\
642 634 2: TT_TRACE_L(trace_win) ;\
643 635 ldxa [%sp + %g1]asi_num, %l0 ;\
644 636 mov V9BIAS64 + 8, %g2 ;\
645 637 ldxa [%sp + %g2]asi_num, %l1 ;\
646 638 mov V9BIAS64 + 16, %g3 ;\
647 639 ldxa [%sp + %g3]asi_num, %l2 ;\
648 640 mov V9BIAS64 + 24, %g4 ;\
649 641 ldxa [%sp + %g4]asi_num, %l3 ;\
650 642 add %sp, 32, %g5 ;\
651 643 ldxa [%g5 + %g1]asi_num, %l4 ;\
652 644 ldxa [%g5 + %g2]asi_num, %l5 ;\
653 645 ldxa [%g5 + %g3]asi_num, %l6 ;\
654 646 ldxa [%g5 + %g4]asi_num, %l7 ;\
655 647 add %g5, 32, %g5 ;\
656 648 ldxa [%g5 + %g1]asi_num, %i0 ;\
657 649 ldxa [%g5 + %g2]asi_num, %i1 ;\
658 650 ldxa [%g5 + %g3]asi_num, %i2 ;\
659 651 ldxa [%g5 + %g4]asi_num, %i3 ;\
660 652 add %g5, 32, %g5 ;\
661 653 ldxa [%g5 + %g1]asi_num, %i4 ;\
662 654 ldxa [%g5 + %g2]asi_num, %i5 ;\
663 655 ldxa [%g5 + %g3]asi_num, %i6 ;\
664 656 ldxa [%g5 + %g4]asi_num, %i7 ;\
665 657 restored ;\
666 658 retry ;\
667 659 SKIP(31-25-TT_TRACE_L_INS) ;\
668 660 ba,a,pt %xcc, fault_64bit_/**/tail ;\
669 661 .empty
670 662
671 663 /*
672 664 * FILL_64bit_tt1 fills a 64-bit-wide register window from a 64-bit
673 665 * wide address space via the designated asi. It is used to fill
674 666 * windows at tl>1 where performance isn't the primary concern and
675 667 * where we don't want to use unnecessary registers. The stack
676 668 * pointer is required to be eight-byte aligned.
677 669 */
678 670 #define FILL_64bit_tt1(asi_num, tail) \
679 671 mov asi_num, %asi ;\
680 672 TT_TRACE_L(trace_win) ;\
681 673 ldxa [%sp + V9BIAS64 + 0]%asi, %l0 ;\
682 674 ldxa [%sp + V9BIAS64 + 8]%asi, %l1 ;\
683 675 ldxa [%sp + V9BIAS64 + 16]%asi, %l2 ;\
684 676 ldxa [%sp + V9BIAS64 + 24]%asi, %l3 ;\
685 677 ldxa [%sp + V9BIAS64 + 32]%asi, %l4 ;\
686 678 ldxa [%sp + V9BIAS64 + 40]%asi, %l5 ;\
687 679 ldxa [%sp + V9BIAS64 + 48]%asi, %l6 ;\
688 680 ldxa [%sp + V9BIAS64 + 56]%asi, %l7 ;\
689 681 ldxa [%sp + V9BIAS64 + 64]%asi, %i0 ;\
690 682 ldxa [%sp + V9BIAS64 + 72]%asi, %i1 ;\
691 683 ldxa [%sp + V9BIAS64 + 80]%asi, %i2 ;\
692 684 ldxa [%sp + V9BIAS64 + 88]%asi, %i3 ;\
↓ open down ↓ |
398 lines elided |
↑ open up ↑ |
693 685 ldxa [%sp + V9BIAS64 + 96]%asi, %i4 ;\
694 686 ldxa [%sp + V9BIAS64 + 104]%asi, %i5 ;\
695 687 ldxa [%sp + V9BIAS64 + 112]%asi, %i6 ;\
696 688 ldxa [%sp + V9BIAS64 + 120]%asi, %i7 ;\
697 689 restored ;\
698 690 retry ;\
699 691 SKIP(31-19-TT_TRACE_L_INS) ;\
700 692 ba,a,pt %xcc, fault_64bit_/**/tail ;\
701 693 .empty
702 694
703 -#endif /* !lint */
704 -
705 695 /*
706 696 * SPILL_mixed spills either size window, depending on
707 697 * whether %sp is even or odd, to a 32-bit address space.
708 698 * This may only be used in conjunction with SPILL_32bit/
709 699 * SPILL_64bit. New versions of SPILL_mixed_{tt1,asi} would be
710 700 * needed for use with SPILL_{32,64}bit_{tt1,asi}. Particular
711 701 * attention should be paid to the instructions that belong
712 702 * in the delay slots of the branches depending on the type
713 703 * of spill handler being branched to.
714 704 * Clear upper 32 bits of %sp if it is odd.
715 705 * We won't need to clear them in 64 bit kernel.
716 706 */
717 707 #define SPILL_mixed \
718 708 btst 1, %sp ;\
719 709 bz,a,pt %xcc, 1b ;\
720 710 srl %sp, 0, %sp ;\
721 711 ba,pt %xcc, 2b ;\
722 712 nop ;\
723 713 .align 128
724 714
725 715 /*
726 716 * FILL_mixed(ASI) fills either size window, depending on
727 717 * whether %sp is even or odd, from a 32-bit address space.
728 718 * This may only be used in conjunction with FILL_32bit/
729 719 * FILL_64bit. New versions of FILL_mixed_{tt1,asi} would be
730 720 * needed for use with FILL_{32,64}bit_{tt1,asi}. Particular
731 721 * attention should be paid to the instructions that belong
732 722 * in the delay slots of the branches depending on the type
733 723 * of fill handler being branched to.
734 724 * Clear upper 32 bits of %sp if it is odd.
735 725 * We won't need to clear them in 64 bit kernel.
736 726 */
737 727 #define FILL_mixed \
738 728 btst 1, %sp ;\
739 729 bz,a,pt %xcc, 1b ;\
740 730 srl %sp, 0, %sp ;\
741 731 ba,pt %xcc, 2b ;\
742 732 nop ;\
743 733 .align 128
744 734
745 735
746 736 /*
747 737 * SPILL_32clean/SPILL_64clean spill 32-bit and 64-bit register windows,
748 738 * respectively, into the address space via the designated asi. The
749 739 * unbiased stack pointer is required to be eight-byte aligned (even for
750 740 * the 32-bit case even though this code does not require such strict
751 741 * alignment).
752 742 *
753 743 * With SPARC v9 the spill trap takes precedence over the cleanwin trap
754 744 * so when cansave == 0, canrestore == 6, and cleanwin == 6 the next save
755 745 * will cause cwp + 2 to be spilled but will not clean cwp + 1. That
756 746 * window may contain kernel data so in user_rtt we set wstate to call
757 747 * these spill handlers on the first user spill trap. These handler then
758 748 * spill the appropriate window but also back up a window and clean the
759 749 * window that didn't get a cleanwin trap.
760 750 */
761 751 #define SPILL_32clean(asi_num, tail) \
762 752 srl %sp, 0, %sp ;\
763 753 sta %l0, [%sp + %g0]asi_num ;\
764 754 mov 4, %g1 ;\
765 755 sta %l1, [%sp + %g1]asi_num ;\
766 756 mov 8, %g2 ;\
767 757 sta %l2, [%sp + %g2]asi_num ;\
768 758 mov 12, %g3 ;\
769 759 sta %l3, [%sp + %g3]asi_num ;\
770 760 add %sp, 16, %g4 ;\
771 761 sta %l4, [%g4 + %g0]asi_num ;\
772 762 sta %l5, [%g4 + %g1]asi_num ;\
773 763 sta %l6, [%g4 + %g2]asi_num ;\
774 764 sta %l7, [%g4 + %g3]asi_num ;\
775 765 add %g4, 16, %g4 ;\
776 766 sta %i0, [%g4 + %g0]asi_num ;\
777 767 sta %i1, [%g4 + %g1]asi_num ;\
778 768 sta %i2, [%g4 + %g2]asi_num ;\
779 769 sta %i3, [%g4 + %g3]asi_num ;\
780 770 add %g4, 16, %g4 ;\
781 771 sta %i4, [%g4 + %g0]asi_num ;\
782 772 sta %i5, [%g4 + %g1]asi_num ;\
783 773 sta %i6, [%g4 + %g2]asi_num ;\
784 774 sta %i7, [%g4 + %g3]asi_num ;\
785 775 TT_TRACE_L(trace_win) ;\
786 776 b .spill_clean ;\
787 777 mov WSTATE_USER32, %g7 ;\
788 778 SKIP(31-25-TT_TRACE_L_INS) ;\
789 779 ba,a,pt %xcc, fault_32bit_/**/tail ;\
790 780 .empty
791 781
792 782 #define SPILL_64clean(asi_num, tail) \
793 783 mov 0 + V9BIAS64, %g1 ;\
794 784 stxa %l0, [%sp + %g1]asi_num ;\
795 785 mov 8 + V9BIAS64, %g2 ;\
796 786 stxa %l1, [%sp + %g2]asi_num ;\
797 787 mov 16 + V9BIAS64, %g3 ;\
798 788 stxa %l2, [%sp + %g3]asi_num ;\
799 789 mov 24 + V9BIAS64, %g4 ;\
800 790 stxa %l3, [%sp + %g4]asi_num ;\
801 791 add %sp, 32, %g5 ;\
802 792 stxa %l4, [%g5 + %g1]asi_num ;\
803 793 stxa %l5, [%g5 + %g2]asi_num ;\
804 794 stxa %l6, [%g5 + %g3]asi_num ;\
805 795 stxa %l7, [%g5 + %g4]asi_num ;\
806 796 add %g5, 32, %g5 ;\
807 797 stxa %i0, [%g5 + %g1]asi_num ;\
808 798 stxa %i1, [%g5 + %g2]asi_num ;\
809 799 stxa %i2, [%g5 + %g3]asi_num ;\
810 800 stxa %i3, [%g5 + %g4]asi_num ;\
811 801 add %g5, 32, %g5 ;\
812 802 stxa %i4, [%g5 + %g1]asi_num ;\
813 803 stxa %i5, [%g5 + %g2]asi_num ;\
814 804 stxa %i6, [%g5 + %g3]asi_num ;\
815 805 stxa %i7, [%g5 + %g4]asi_num ;\
816 806 TT_TRACE_L(trace_win) ;\
817 807 b .spill_clean ;\
818 808 mov WSTATE_USER64, %g7 ;\
819 809 SKIP(31-25-TT_TRACE_L_INS) ;\
820 810 ba,a,pt %xcc, fault_64bit_/**/tail ;\
821 811 .empty
822 812
823 813
824 814 /*
825 815 * Floating point disabled.
826 816 */
827 817 #define FP_DISABLED_TRAP \
828 818 TT_TRACE(trace_gen) ;\
829 819 ba,pt %xcc,.fp_disabled ;\
830 820 nop ;\
831 821 .align 32
832 822
833 823 /*
834 824 * Floating point exceptions.
835 825 */
836 826 #define FP_IEEE_TRAP \
837 827 TT_TRACE(trace_gen) ;\
↓ open down ↓ |
123 lines elided |
↑ open up ↑ |
838 828 ba,pt %xcc,.fp_ieee_exception ;\
839 829 nop ;\
840 830 .align 32
841 831
842 832 #define FP_TRAP \
843 833 TT_TRACE(trace_gen) ;\
844 834 ba,pt %xcc,.fp_exception ;\
845 835 nop ;\
846 836 .align 32
847 837
848 -#if !defined(lint)
849 838 /*
850 839 * asynchronous traps at level 0 and level 1
851 840 *
852 841 * The first instruction must be a membar for UltraSPARC-III
853 842 * to stop RED state entry if the store queue has many
854 843 * pending bad stores (PRM, Chapter 11).
855 844 */
856 845 #define ASYNC_TRAP(ttype, ttlabel, table_name)\
857 846 .global table_name ;\
858 847 table_name: ;\
859 848 membar #Sync ;\
860 849 TT_TRACE(ttlabel) ;\
861 850 ba async_err ;\
862 851 mov ttype, %g5 ;\
863 852 .align 32
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
864 853
865 854 /*
866 855 * Defaults to BAD entry, but establishes label to be used for
867 856 * architecture-specific overwrite of trap table entry.
868 857 */
869 858 #define LABELED_BAD(table_name) \
870 859 .global table_name ;\
871 860 table_name: ;\
872 861 BAD
873 862
874 -#endif /* !lint */
875 -
876 863 /*
877 864 * illegal instruction trap
878 865 */
879 866 #define ILLTRAP_INSTR \
880 867 membar #Sync ;\
881 868 TT_TRACE(trace_gen) ;\
882 869 or %g0, P_UTRAP4, %g2 ;\
883 870 or %g0, T_UNIMP_INSTR, %g3 ;\
884 871 sethi %hi(.check_v9utrap), %g4 ;\
885 872 jmp %g4 + %lo(.check_v9utrap) ;\
886 873 nop ;\
887 874 .align 32
888 875
889 876 /*
890 877 * tag overflow trap
891 878 */
892 879 #define TAG_OVERFLOW \
893 880 TT_TRACE(trace_gen) ;\
894 881 or %g0, P_UTRAP10, %g2 ;\
895 882 or %g0, T_TAG_OVERFLOW, %g3 ;\
896 883 sethi %hi(.check_v9utrap), %g4 ;\
897 884 jmp %g4 + %lo(.check_v9utrap) ;\
898 885 nop ;\
899 886 .align 32
900 887
901 888 /*
902 889 * divide by zero trap
903 890 */
904 891 #define DIV_BY_ZERO \
905 892 TT_TRACE(trace_gen) ;\
906 893 or %g0, P_UTRAP11, %g2 ;\
907 894 or %g0, T_IDIV0, %g3 ;\
908 895 sethi %hi(.check_v9utrap), %g4 ;\
909 896 jmp %g4 + %lo(.check_v9utrap) ;\
910 897 nop ;\
911 898 .align 32
912 899
913 900 /*
914 901 * trap instruction for V9 user trap handlers
915 902 */
916 903 #define TRAP_INSTR \
917 904 TT_TRACE(trace_gen) ;\
918 905 or %g0, T_SOFTWARE_TRAP, %g3 ;\
919 906 sethi %hi(.check_v9utrap), %g4 ;\
920 907 jmp %g4 + %lo(.check_v9utrap) ;\
921 908 nop ;\
922 909 .align 32
923 910 #define TRP4 TRAP_INSTR; TRAP_INSTR; TRAP_INSTR; TRAP_INSTR
924 911
925 912 /*
926 913 * LEVEL_INTERRUPT is for level N interrupts.
927 914 * VECTOR_INTERRUPT is for the vector trap.
928 915 */
929 916 #define LEVEL_INTERRUPT(level) \
930 917 .global tt_pil/**/level ;\
931 918 tt_pil/**/level: ;\
932 919 ba,pt %xcc, pil_interrupt ;\
933 920 mov level, %g4 ;\
934 921 .align 32
935 922
936 923 #define LEVEL14_INTERRUPT \
937 924 ba pil14_interrupt ;\
938 925 mov PIL_14, %g4 ;\
939 926 .align 32
940 927
941 928 #define LEVEL15_INTERRUPT \
942 929 ba pil15_interrupt ;\
943 930 mov PIL_15, %g4 ;\
944 931 .align 32
945 932
946 933 #define VECTOR_INTERRUPT \
947 934 ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g1 ;\
948 935 btst IRSR_BUSY, %g1 ;\
949 936 bnz,pt %xcc, vec_interrupt ;\
950 937 nop ;\
951 938 ba,a,pt %xcc, vec_intr_spurious ;\
952 939 .empty ;\
953 940 .align 32
954 941
955 942 /*
956 943 * MMU Trap Handlers.
957 944 */
958 945 #define SWITCH_GLOBALS /* mmu->alt, alt->mmu */ \
959 946 rdpr %pstate, %g5 ;\
960 947 wrpr %g5, PSTATE_MG | PSTATE_AG, %pstate
961 948
962 949 #define IMMU_EXCEPTION \
963 950 membar #Sync ;\
964 951 SWITCH_GLOBALS ;\
965 952 wr %g0, ASI_IMMU, %asi ;\
966 953 rdpr %tpc, %g2 ;\
967 954 ldxa [MMU_SFSR]%asi, %g3 ;\
968 955 ba,pt %xcc, .mmu_exception_end ;\
969 956 mov T_INSTR_EXCEPTION, %g1 ;\
970 957 .align 32
971 958
972 959 #define DMMU_EXCEPTION \
973 960 SWITCH_GLOBALS ;\
974 961 wr %g0, ASI_DMMU, %asi ;\
975 962 ldxa [MMU_TAG_ACCESS]%asi, %g2 ;\
976 963 ldxa [MMU_SFSR]%asi, %g3 ;\
977 964 ba,pt %xcc, .mmu_exception_end ;\
978 965 mov T_DATA_EXCEPTION, %g1 ;\
979 966 .align 32
980 967
981 968 #define DMMU_EXC_AG_PRIV \
982 969 wr %g0, ASI_DMMU, %asi ;\
983 970 ldxa [MMU_SFAR]%asi, %g2 ;\
984 971 ba,pt %xcc, .mmu_priv_exception ;\
985 972 ldxa [MMU_SFSR]%asi, %g3 ;\
986 973 .align 32
987 974
988 975 #define DMMU_EXC_AG_NOT_ALIGNED \
989 976 wr %g0, ASI_DMMU, %asi ;\
990 977 ldxa [MMU_SFAR]%asi, %g2 ;\
991 978 ba,pt %xcc, .mmu_exception_not_aligned ;\
992 979 ldxa [MMU_SFSR]%asi, %g3 ;\
993 980 .align 32
994 981
995 982 /*
996 983 * SPARC V9 IMPL. DEP. #109(1) and (2) and #110(1) and (2)
997 984 */
998 985 #define DMMU_EXC_LDDF_NOT_ALIGNED \
999 986 btst 1, %sp ;\
1000 987 bnz,pt %xcc, .lddf_exception_not_aligned ;\
1001 988 wr %g0, ASI_DMMU, %asi ;\
1002 989 ldxa [MMU_SFAR]%asi, %g2 ;\
1003 990 ba,pt %xcc, .mmu_exception_not_aligned ;\
1004 991 ldxa [MMU_SFSR]%asi, %g3 ;\
1005 992 .align 32
1006 993
1007 994 #define DMMU_EXC_STDF_NOT_ALIGNED \
1008 995 btst 1, %sp ;\
1009 996 bnz,pt %xcc, .stdf_exception_not_aligned ;\
1010 997 wr %g0, ASI_DMMU, %asi ;\
1011 998 ldxa [MMU_SFAR]%asi, %g2 ;\
1012 999 ba,pt %xcc, .mmu_exception_not_aligned ;\
1013 1000 ldxa [MMU_SFSR]%asi, %g3 ;\
1014 1001 .align 32
1015 1002
1016 1003 /*
1017 1004 * Flush the TLB using either the primary, secondary, or nucleus flush
1018 1005 * operation based on whether the ctx from the tag access register matches
1019 1006 * the primary or secondary context (flush the nucleus if neither matches).
1020 1007 *
1021 1008 * Requires a membar #Sync before next ld/st.
1022 1009 * exits with:
1023 1010 * g2 = tag access register
1024 1011 * g3 = ctx number
1025 1012 */
1026 1013 #if TAGACC_CTX_MASK != CTXREG_CTX_MASK
1027 1014 #error "TAGACC_CTX_MASK != CTXREG_CTX_MASK"
1028 1015 #endif
1029 1016 #define DTLB_DEMAP_ENTRY \
1030 1017 mov MMU_TAG_ACCESS, %g1 ;\
1031 1018 mov MMU_PCONTEXT, %g5 ;\
1032 1019 ldxa [%g1]ASI_DMMU, %g2 ;\
1033 1020 sethi %hi(TAGACC_CTX_MASK), %g4 ;\
1034 1021 or %g4, %lo(TAGACC_CTX_MASK), %g4 ;\
1035 1022 and %g2, %g4, %g3 /* g3 = ctx */ ;\
1036 1023 ldxa [%g5]ASI_DMMU, %g6 /* g6 = primary ctx */ ;\
1037 1024 and %g6, %g4, %g6 /* &= CTXREG_CTX_MASK */ ;\
1038 1025 cmp %g3, %g6 ;\
1039 1026 be,pt %xcc, 1f ;\
1040 1027 andn %g2, %g4, %g1 /* ctx = primary */ ;\
1041 1028 mov MMU_SCONTEXT, %g5 ;\
1042 1029 ldxa [%g5]ASI_DMMU, %g6 /* g6 = secondary ctx */ ;\
1043 1030 and %g6, %g4, %g6 /* &= CTXREG_CTX_MASK */ ;\
1044 1031 cmp %g3, %g6 ;\
1045 1032 be,a,pt %xcc, 1f ;\
1046 1033 or %g1, DEMAP_SECOND, %g1 ;\
1047 1034 or %g1, DEMAP_NUCLEUS, %g1 ;\
1048 1035 1: stxa %g0, [%g1]ASI_DTLB_DEMAP /* MMU_DEMAP_PAGE */ ;\
1049 1036 membar #Sync
1050 1037
1051 1038 #if defined(cscope)
1052 1039 /*
1053 1040 * Define labels to direct cscope quickly to labels that
1054 1041 * are generated by macro expansion of DTLB_MISS().
1055 1042 */
1056 1043 .global tt0_dtlbmiss
1057 1044 tt0_dtlbmiss:
1058 1045 .global tt1_dtlbmiss
1059 1046 tt1_dtlbmiss:
1060 1047 nop
1061 1048 #endif
1062 1049
1063 1050 /*
1064 1051 * Needs to be exactly 32 instructions
1065 1052 *
1066 1053 * UTLB NOTE: If we don't hit on the 8k pointer then we branch
1067 1054 * to a special 4M tsb handler. It would be nice if that handler
1068 1055 * could live in this file but currently it seems better to allow
1069 1056 * it to fall thru to sfmmu_tsb_miss.
1070 1057 */
1071 1058 #ifdef UTSB_PHYS
1072 1059 #define DTLB_MISS(table_name) ;\
1073 1060 .global table_name/**/_dtlbmiss ;\
1074 1061 table_name/**/_dtlbmiss: ;\
1075 1062 mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\
1076 1063 ldxa [%g0]ASI_DMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\
1077 1064 ldxa [%g6]ASI_DMMU, %g2 /* g2 = tag access */ ;\
1078 1065 sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\
1079 1066 srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\
1080 1067 cmp %g3, INVALID_CONTEXT ;\
1081 1068 ble,pn %xcc, sfmmu_kdtlb_miss ;\
1082 1069 srax %g2, PREDISM_BASESHIFT, %g6 /* g6 > 0 ISM predicted */ ;\
1083 1070 brgz,pn %g6, sfmmu_udtlb_slowpath_ismpred ;\
1084 1071 srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\
1085 1072 ldda [%g1]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, %g5 data */;\
1086 1073 cmp %g4, %g7 ;\
1087 1074 bne,pn %xcc, sfmmu_udtlb_slowpath_noismpred ;\
1088 1075 nop ;\
1089 1076 TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\
1090 1077 stxa %g5, [%g0]ASI_DTLB_IN /* trapstat expects TTE */ ;\
1091 1078 retry /* in %g5 */ ;\
1092 1079 unimp 0 ;\
1093 1080 unimp 0 ;\
1094 1081 unimp 0 ;\
1095 1082 unimp 0 ;\
1096 1083 unimp 0 ;\
1097 1084 unimp 0 ;\
1098 1085 unimp 0 ;\
1099 1086 unimp 0 ;\
1100 1087 unimp 0 ;\
1101 1088 unimp 0 ;\
1102 1089 unimp 0 ;\
1103 1090 unimp 0 ;\
1104 1091 unimp 0 ;\
1105 1092 unimp 0 ;\
1106 1093 .align 128
1107 1094
1108 1095 #else /* UTSB_PHYS */
1109 1096 #define DTLB_MISS(table_name) ;\
1110 1097 .global table_name/**/_dtlbmiss ;\
1111 1098 table_name/**/_dtlbmiss: ;\
1112 1099 mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\
1113 1100 ldxa [%g0]ASI_DMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\
1114 1101 ldxa [%g6]ASI_DMMU, %g2 /* g2 = tag access */ ;\
1115 1102 sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\
1116 1103 srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\
1117 1104 cmp %g3, INVALID_CONTEXT ;\
1118 1105 ble,pn %xcc, sfmmu_kdtlb_miss ;\
1119 1106 srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\
1120 1107 brlz,pn %g1, sfmmu_udtlb_slowpath ;\
1121 1108 nop ;\
1122 1109 ldda [%g1]ASI_NQUAD_LD, %g4 /* g4 = tag, %g5 data */ ;\
1123 1110 cmp %g4, %g7 ;\
1124 1111 bne,pn %xcc, sfmmu_tsb_miss_tt /* no 4M TSB, miss */ ;\
1125 1112 mov -1, %g3 /* set 4M tsbe ptr to -1 */ ;\
1126 1113 TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\
1127 1114 stxa %g5, [%g0]ASI_DTLB_IN /* trapstat expects TTE */ ;\
1128 1115 retry /* in %g5 */ ;\
1129 1116 unimp 0 ;\
1130 1117 unimp 0 ;\
1131 1118 unimp 0 ;\
1132 1119 unimp 0 ;\
1133 1120 unimp 0 ;\
1134 1121 unimp 0 ;\
1135 1122 unimp 0 ;\
1136 1123 unimp 0 ;\
1137 1124 unimp 0 ;\
1138 1125 unimp 0 ;\
1139 1126 unimp 0 ;\
1140 1127 unimp 0 ;\
1141 1128 unimp 0 ;\
1142 1129 unimp 0 ;\
1143 1130 .align 128
1144 1131 #endif /* UTSB_PHYS */
1145 1132
1146 1133 #if defined(cscope)
1147 1134 /*
1148 1135 * Define labels to direct cscope quickly to labels that
1149 1136 * are generated by macro expansion of ITLB_MISS().
1150 1137 */
1151 1138 .global tt0_itlbmiss
1152 1139 tt0_itlbmiss:
1153 1140 .global tt1_itlbmiss
1154 1141 tt1_itlbmiss:
1155 1142 nop
1156 1143 #endif
1157 1144
1158 1145 /*
1159 1146 * Instruction miss handler.
1160 1147 * ldda instructions will have their ASI patched
1161 1148 * by sfmmu_patch_ktsb at runtime.
1162 1149 * MUST be EXACTLY 32 instructions or we'll break.
1163 1150 */
1164 1151 #ifdef UTSB_PHYS
1165 1152 #define ITLB_MISS(table_name) \
1166 1153 .global table_name/**/_itlbmiss ;\
1167 1154 table_name/**/_itlbmiss: ;\
1168 1155 mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\
1169 1156 ldxa [%g0]ASI_IMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\
1170 1157 ldxa [%g6]ASI_IMMU, %g2 /* g2 = tag access */ ;\
1171 1158 sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\
1172 1159 srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\
1173 1160 cmp %g3, INVALID_CONTEXT ;\
1174 1161 ble,pn %xcc, sfmmu_kitlb_miss ;\
1175 1162 srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\
1176 1163 ldda [%g1]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, g5 = data */ ;\
1177 1164 cmp %g4, %g7 ;\
1178 1165 bne,pn %xcc, sfmmu_uitlb_slowpath ;\
1179 1166 andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\
1180 1167 bz,pn %icc, exec_fault ;\
1181 1168 nop ;\
1182 1169 TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\
1183 1170 stxa %g5, [%g0]ASI_ITLB_IN /* trapstat expects %g5 */ ;\
1184 1171 retry ;\
1185 1172 unimp 0 ;\
1186 1173 unimp 0 ;\
1187 1174 unimp 0 ;\
1188 1175 unimp 0 ;\
1189 1176 unimp 0 ;\
1190 1177 unimp 0 ;\
1191 1178 unimp 0 ;\
1192 1179 unimp 0 ;\
1193 1180 unimp 0 ;\
1194 1181 unimp 0 ;\
1195 1182 unimp 0 ;\
1196 1183 unimp 0 ;\
1197 1184 unimp 0 ;\
1198 1185 unimp 0 ;\
1199 1186 .align 128
1200 1187
1201 1188 #else /* UTSB_PHYS */
1202 1189 #define ITLB_MISS(table_name) \
1203 1190 .global table_name/**/_itlbmiss ;\
1204 1191 table_name/**/_itlbmiss: ;\
1205 1192 mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\
1206 1193 ldxa [%g0]ASI_IMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\
1207 1194 ldxa [%g6]ASI_IMMU, %g2 /* g2 = tag access */ ;\
1208 1195 sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\
1209 1196 srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\
1210 1197 cmp %g3, INVALID_CONTEXT ;\
1211 1198 ble,pn %xcc, sfmmu_kitlb_miss ;\
1212 1199 srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\
1213 1200 brlz,pn %g1, sfmmu_uitlb_slowpath /* if >1 TSB branch */ ;\
1214 1201 nop ;\
1215 1202 ldda [%g1]ASI_NQUAD_LD, %g4 /* g4 = tag, g5 = data */ ;\
1216 1203 cmp %g4, %g7 ;\
1217 1204 bne,pn %xcc, sfmmu_tsb_miss_tt /* br if 8k ptr miss */ ;\
1218 1205 mov -1, %g3 /* set 4M TSB ptr to -1 */ ;\
1219 1206 andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\
1220 1207 bz,pn %icc, exec_fault ;\
1221 1208 nop ;\
1222 1209 TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\
1223 1210 stxa %g5, [%g0]ASI_ITLB_IN /* trapstat expects %g5 */ ;\
1224 1211 retry ;\
1225 1212 unimp 0 ;\
1226 1213 unimp 0 ;\
1227 1214 unimp 0 ;\
1228 1215 unimp 0 ;\
1229 1216 unimp 0 ;\
1230 1217 unimp 0 ;\
1231 1218 unimp 0 ;\
1232 1219 unimp 0 ;\
1233 1220 unimp 0 ;\
1234 1221 unimp 0 ;\
1235 1222 unimp 0 ;\
1236 1223 .align 128
1237 1224 #endif /* UTSB_PHYS */
1238 1225
1239 1226
1240 1227 /*
1241 1228 * This macro is the first level handler for fast protection faults.
1242 1229 * It first demaps the tlb entry which generated the fault and then
1243 1230 * attempts to set the modify bit on the hash. It needs to be
1244 1231 * exactly 32 instructions.
1245 1232 */
1246 1233 #define DTLB_PROT \
1247 1234 DTLB_DEMAP_ENTRY /* 20 instructions */ ;\
1248 1235 /* ;\
1249 1236 * At this point: ;\
1250 1237 * g1 = ???? ;\
1251 1238 * g2 = tag access register ;\
1252 1239 * g3 = ctx number ;\
1253 1240 * g4 = ???? ;\
1254 1241 */ ;\
1255 1242 TT_TRACE(trace_dataprot) /* 2 instr ifdef TRAPTRACE */ ;\
1256 1243 /* clobbers g1 and g6 */ ;\
1257 1244 ldxa [%g0]ASI_DMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\
1258 1245 brnz,pt %g3, sfmmu_uprot_trap /* user trap */ ;\
1259 1246 nop ;\
1260 1247 ba,a,pt %xcc, sfmmu_kprot_trap /* kernel trap */ ;\
1261 1248 unimp 0 ;\
1262 1249 unimp 0 ;\
1263 1250 unimp 0 ;\
1264 1251 unimp 0 ;\
1265 1252 unimp 0 ;\
1266 1253 unimp 0 ;\
1267 1254 .align 128
1268 1255
1269 1256 #define DMMU_EXCEPTION_TL1 ;\
1270 1257 SWITCH_GLOBALS ;\
1271 1258 ba,a,pt %xcc, mmu_trap_tl1 ;\
1272 1259 nop ;\
1273 1260 .align 32
1274 1261
1275 1262 #define MISALIGN_ADDR_TL1 ;\
1276 1263 ba,a,pt %xcc, mmu_trap_tl1 ;\
1277 1264 nop ;\
1278 1265 .align 32
1279 1266
1280 1267 /*
1281 1268 * Trace a tsb hit
1282 1269 * g1 = tsbe pointer (in/clobbered)
1283 1270 * g2 = tag access register (in)
1284 1271 * g3 - g4 = scratch (clobbered)
1285 1272 * g5 = tsbe data (in)
1286 1273 * g6 = scratch (clobbered)
1287 1274 * g7 = pc we jumped here from (in)
1288 1275 * ttextra = value to OR in to trap type (%tt) (in)
1289 1276 */
1290 1277 #ifdef TRAPTRACE
1291 1278 #define TRACE_TSBHIT(ttextra) \
1292 1279 membar #Sync ;\
1293 1280 sethi %hi(FLUSH_ADDR), %g6 ;\
1294 1281 flush %g6 ;\
1295 1282 TRACE_PTR(%g3, %g6) ;\
1296 1283 GET_TRACE_TICK(%g6, %g4) ;\
1297 1284 stxa %g6, [%g3 + TRAP_ENT_TICK]%asi ;\
1298 1285 stxa %g2, [%g3 + TRAP_ENT_SP]%asi /* tag access */ ;\
1299 1286 stxa %g5, [%g3 + TRAP_ENT_F1]%asi /* tsb data */ ;\
1300 1287 rdpr %tnpc, %g6 ;\
1301 1288 stxa %g6, [%g3 + TRAP_ENT_F2]%asi ;\
1302 1289 stxa %g1, [%g3 + TRAP_ENT_F3]%asi /* tsb pointer */ ;\
1303 1290 stxa %g0, [%g3 + TRAP_ENT_F4]%asi ;\
1304 1291 rdpr %tpc, %g6 ;\
1305 1292 stxa %g6, [%g3 + TRAP_ENT_TPC]%asi ;\
1306 1293 rdpr %tl, %g6 ;\
1307 1294 stha %g6, [%g3 + TRAP_ENT_TL]%asi ;\
1308 1295 rdpr %tt, %g6 ;\
1309 1296 or %g6, (ttextra), %g6 ;\
1310 1297 stha %g6, [%g3 + TRAP_ENT_TT]%asi ;\
1311 1298 ldxa [%g0]ASI_IMMU, %g1 /* tag target */ ;\
↓ open down ↓ |
426 lines elided |
↑ open up ↑ |
1312 1299 ldxa [%g0]ASI_DMMU, %g4 ;\
1313 1300 cmp %g6, FAST_IMMU_MISS_TT ;\
1314 1301 movne %icc, %g4, %g1 ;\
1315 1302 stxa %g1, [%g3 + TRAP_ENT_TSTATE]%asi /* tsb tag */ ;\
1316 1303 stxa %g0, [%g3 + TRAP_ENT_TR]%asi ;\
1317 1304 TRACE_NEXT(%g3, %g4, %g6)
1318 1305 #else
1319 1306 #define TRACE_TSBHIT(ttextra)
1320 1307 #endif
1321 1308
1322 -#if defined(lint)
1323 -
1324 -struct scb trap_table;
1325 -struct scb scb; /* trap_table/scb are the same object */
1326 -
1327 -#else /* lint */
1328 -
1329 1309 /*
1330 1310 * =======================================================================
1331 1311 * SPARC V9 TRAP TABLE
1332 1312 *
1333 1313 * The trap table is divided into two halves: the first half is used when
1334 1314 * taking traps when TL=0; the second half is used when taking traps from
1335 1315 * TL>0. Note that handlers in the second half of the table might not be able
1336 1316 * to make the same assumptions as handlers in the first half of the table.
1337 1317 *
1338 1318 * Worst case trap nesting so far:
1339 1319 *
1340 1320 * at TL=0 client issues software trap requesting service
1341 1321 * at TL=1 nucleus wants a register window
1342 1322 * at TL=2 register window clean/spill/fill takes a TLB miss
1343 1323 * at TL=3 processing TLB miss
1344 1324 * at TL=4 handle asynchronous error
1345 1325 *
1346 1326 * Note that a trap from TL=4 to TL=5 places Spitfire in "RED mode".
1347 1327 *
1348 1328 * =======================================================================
1349 1329 */
1350 1330 .section ".text"
1351 1331 .align 4
1352 1332 .global trap_table, scb, trap_table0, trap_table1, etrap_table
1353 1333 .type trap_table, #object
1354 1334 .type scb, #object
1355 1335 trap_table:
1356 1336 scb:
1357 1337 trap_table0:
1358 1338 /* hardware traps */
1359 1339 NOT; /* 000 reserved */
1360 1340 RED; /* 001 power on reset */
1361 1341 RED; /* 002 watchdog reset */
1362 1342 RED; /* 003 externally initiated reset */
1363 1343 RED; /* 004 software initiated reset */
1364 1344 RED; /* 005 red mode exception */
1365 1345 NOT; NOT; /* 006 - 007 reserved */
1366 1346 IMMU_EXCEPTION; /* 008 instruction access exception */
1367 1347 NOT; /* 009 instruction access MMU miss */
1368 1348 ASYNC_TRAP(T_INSTR_ERROR, trace_gen, tt0_iae);
1369 1349 /* 00A instruction access error */
1370 1350 NOT; NOT4; /* 00B - 00F reserved */
1371 1351 ILLTRAP_INSTR; /* 010 illegal instruction */
1372 1352 TRAP(T_PRIV_INSTR); /* 011 privileged opcode */
1373 1353 NOT; /* 012 unimplemented LDD */
1374 1354 NOT; /* 013 unimplemented STD */
1375 1355 NOT4; NOT4; NOT4; /* 014 - 01F reserved */
1376 1356 FP_DISABLED_TRAP; /* 020 fp disabled */
1377 1357 FP_IEEE_TRAP; /* 021 fp exception ieee 754 */
1378 1358 FP_TRAP; /* 022 fp exception other */
1379 1359 TAG_OVERFLOW; /* 023 tag overflow */
1380 1360 CLEAN_WINDOW; /* 024 - 027 clean window */
1381 1361 DIV_BY_ZERO; /* 028 division by zero */
1382 1362 NOT; /* 029 internal processor error */
1383 1363 NOT; NOT; NOT4; /* 02A - 02F reserved */
1384 1364 DMMU_EXCEPTION; /* 030 data access exception */
1385 1365 NOT; /* 031 data access MMU miss */
1386 1366 ASYNC_TRAP(T_DATA_ERROR, trace_gen, tt0_dae);
1387 1367 /* 032 data access error */
1388 1368 NOT; /* 033 data access protection */
1389 1369 DMMU_EXC_AG_NOT_ALIGNED; /* 034 mem address not aligned */
1390 1370 DMMU_EXC_LDDF_NOT_ALIGNED; /* 035 LDDF mem address not aligned */
1391 1371 DMMU_EXC_STDF_NOT_ALIGNED; /* 036 STDF mem address not aligned */
1392 1372 DMMU_EXC_AG_PRIV; /* 037 privileged action */
1393 1373 NOT; /* 038 LDQF mem address not aligned */
1394 1374 NOT; /* 039 STQF mem address not aligned */
1395 1375 NOT; NOT; NOT4; /* 03A - 03F reserved */
1396 1376 LABELED_BAD(tt0_asdat); /* 040 async data error */
1397 1377 LEVEL_INTERRUPT(1); /* 041 interrupt level 1 */
1398 1378 LEVEL_INTERRUPT(2); /* 042 interrupt level 2 */
1399 1379 LEVEL_INTERRUPT(3); /* 043 interrupt level 3 */
1400 1380 LEVEL_INTERRUPT(4); /* 044 interrupt level 4 */
1401 1381 LEVEL_INTERRUPT(5); /* 045 interrupt level 5 */
1402 1382 LEVEL_INTERRUPT(6); /* 046 interrupt level 6 */
1403 1383 LEVEL_INTERRUPT(7); /* 047 interrupt level 7 */
1404 1384 LEVEL_INTERRUPT(8); /* 048 interrupt level 8 */
1405 1385 LEVEL_INTERRUPT(9); /* 049 interrupt level 9 */
1406 1386 LEVEL_INTERRUPT(10); /* 04A interrupt level 10 */
1407 1387 LEVEL_INTERRUPT(11); /* 04B interrupt level 11 */
1408 1388 LEVEL_INTERRUPT(12); /* 04C interrupt level 12 */
1409 1389 LEVEL_INTERRUPT(13); /* 04D interrupt level 13 */
1410 1390 LEVEL14_INTERRUPT; /* 04E interrupt level 14 */
1411 1391 LEVEL15_INTERRUPT; /* 04F interrupt level 15 */
1412 1392 NOT4; NOT4; NOT4; NOT4; /* 050 - 05F reserved */
1413 1393 VECTOR_INTERRUPT; /* 060 interrupt vector */
1414 1394 GOTO(kmdb_trap); /* 061 PA watchpoint */
1415 1395 GOTO(kmdb_trap); /* 062 VA watchpoint */
1416 1396 GOTO_TT(ce_err, trace_gen); /* 063 corrected ECC error */
1417 1397 ITLB_MISS(tt0); /* 064 instruction access MMU miss */
1418 1398 DTLB_MISS(tt0); /* 068 data access MMU miss */
1419 1399 DTLB_PROT; /* 06C data access protection */
1420 1400 LABELED_BAD(tt0_fecc); /* 070 fast ecache ECC error */
1421 1401 LABELED_BAD(tt0_dperr); /* 071 Cheetah+ dcache parity error */
1422 1402 LABELED_BAD(tt0_iperr); /* 072 Cheetah+ icache parity error */
1423 1403 NOT; /* 073 reserved */
1424 1404 NOT4; NOT4; NOT4; /* 074 - 07F reserved */
1425 1405 NOT4; /* 080 spill 0 normal */
1426 1406 SPILL_32bit_asi(ASI_AIUP,sn0); /* 084 spill 1 normal */
1427 1407 SPILL_64bit_asi(ASI_AIUP,sn0); /* 088 spill 2 normal */
1428 1408 SPILL_32clean(ASI_AIUP,sn0); /* 08C spill 3 normal */
1429 1409 SPILL_64clean(ASI_AIUP,sn0); /* 090 spill 4 normal */
1430 1410 SPILL_32bit(not); /* 094 spill 5 normal */
1431 1411 SPILL_64bit(not); /* 098 spill 6 normal */
1432 1412 SPILL_mixed; /* 09C spill 7 normal */
1433 1413 NOT4; /* 0A0 spill 0 other */
1434 1414 SPILL_32bit_asi(ASI_AIUS,so0); /* 0A4 spill 1 other */
1435 1415 SPILL_64bit_asi(ASI_AIUS,so0); /* 0A8 spill 2 other */
1436 1416 SPILL_32bit_asi(ASI_AIUS,so0); /* 0AC spill 3 other */
1437 1417 SPILL_64bit_asi(ASI_AIUS,so0); /* 0B0 spill 4 other */
1438 1418 NOT4; /* 0B4 spill 5 other */
1439 1419 NOT4; /* 0B8 spill 6 other */
1440 1420 NOT4; /* 0BC spill 7 other */
1441 1421 NOT4; /* 0C0 fill 0 normal */
1442 1422 FILL_32bit_asi(ASI_AIUP,fn0); /* 0C4 fill 1 normal */
1443 1423 FILL_64bit_asi(ASI_AIUP,fn0); /* 0C8 fill 2 normal */
1444 1424 FILL_32bit_asi(ASI_AIUP,fn0); /* 0CC fill 3 normal */
1445 1425 FILL_64bit_asi(ASI_AIUP,fn0); /* 0D0 fill 4 normal */
1446 1426 FILL_32bit(not); /* 0D4 fill 5 normal */
1447 1427 FILL_64bit(not); /* 0D8 fill 6 normal */
1448 1428 FILL_mixed; /* 0DC fill 7 normal */
1449 1429 NOT4; /* 0E0 fill 0 other */
1450 1430 NOT4; /* 0E4 fill 1 other */
1451 1431 NOT4; /* 0E8 fill 2 other */
1452 1432 NOT4; /* 0EC fill 3 other */
1453 1433 NOT4; /* 0F0 fill 4 other */
1454 1434 NOT4; /* 0F4 fill 5 other */
1455 1435 NOT4; /* 0F8 fill 6 other */
1456 1436 NOT4; /* 0FC fill 7 other */
1457 1437 /* user traps */
1458 1438 GOTO(syscall_trap_4x); /* 100 old system call */
1459 1439 TRAP(T_BREAKPOINT); /* 101 user breakpoint */
1460 1440 TRAP(T_DIV0); /* 102 user divide by zero */
1461 1441 FLUSHW(tt0_flushw); /* 103 flush windows */
1462 1442 GOTO(.clean_windows); /* 104 clean windows */
1463 1443 BAD; /* 105 range check ?? */
1464 1444 GOTO(.fix_alignment); /* 106 do unaligned references */
1465 1445 BAD; /* 107 unused */
1466 1446 SYSCALL_TRAP32; /* 108 ILP32 system call on LP64 */
1467 1447 GOTO(set_trap0_addr); /* 109 set trap0 address */
1468 1448 BAD; BAD; BAD4; /* 10A - 10F unused */
1469 1449 TRP4; TRP4; TRP4; TRP4; /* 110 - 11F V9 user trap handlers */
1470 1450 GOTO(.getcc); /* 120 get condition codes */
1471 1451 GOTO(.setcc); /* 121 set condition codes */
1472 1452 GOTO(.getpsr); /* 122 get psr */
1473 1453 GOTO(.setpsr); /* 123 set psr (some fields) */
1474 1454 GOTO(get_timestamp); /* 124 get timestamp */
1475 1455 GOTO(get_virtime); /* 125 get lwp virtual time */
1476 1456 PRIV(self_xcall); /* 126 self xcall */
1477 1457 GOTO(get_hrestime); /* 127 get hrestime */
1478 1458 BAD; /* 128 ST_SETV9STACK */
1479 1459 GOTO(.getlgrp); /* 129 get lgrpid */
1480 1460 BAD; BAD; BAD4; /* 12A - 12F unused */
1481 1461 BAD4; BAD4; /* 130 - 137 unused */
1482 1462 DTRACE_PID; /* 138 dtrace pid tracing provider */
1483 1463 BAD; /* 139 unused */
1484 1464 DTRACE_RETURN; /* 13A dtrace pid return probe */
1485 1465 BAD; BAD4; /* 13B - 13F unused */
1486 1466 SYSCALL_TRAP; /* 140 LP64 system call */
1487 1467 SYSCALL(nosys); /* 141 unused system call trap */
1488 1468 #ifdef DEBUG_USER_TRAPTRACECTL
1489 1469 GOTO(.traptrace_freeze); /* 142 freeze traptrace */
1490 1470 GOTO(.traptrace_unfreeze); /* 143 unfreeze traptrace */
1491 1471 #else
1492 1472 SYSCALL(nosys); /* 142 unused system call trap */
1493 1473 SYSCALL(nosys); /* 143 unused system call trap */
1494 1474 #endif
1495 1475 BAD4; BAD4; BAD4; /* 144 - 14F unused */
1496 1476 BAD4; BAD4; BAD4; BAD4; /* 150 - 15F unused */
1497 1477 BAD4; BAD4; BAD4; BAD4; /* 160 - 16F unused */
1498 1478 BAD; /* 170 - unused */
1499 1479 BAD; /* 171 - unused */
1500 1480 BAD; BAD; /* 172 - 173 unused */
1501 1481 BAD4; BAD4; /* 174 - 17B unused */
1502 1482 #ifdef PTL1_PANIC_DEBUG
1503 1483 mov PTL1_BAD_DEBUG, %g1; GOTO(ptl1_panic);
1504 1484 /* 17C test ptl1_panic */
1505 1485 #else
1506 1486 BAD; /* 17C unused */
1507 1487 #endif /* PTL1_PANIC_DEBUG */
1508 1488 PRIV(kmdb_trap); /* 17D kmdb enter (L1-A) */
1509 1489 PRIV(kmdb_trap); /* 17E kmdb breakpoint */
1510 1490 PRIV(kctx_obp_bpt); /* 17F obp breakpoint */
1511 1491 /* reserved */
1512 1492 NOT4; NOT4; NOT4; NOT4; /* 180 - 18F reserved */
1513 1493 NOT4; NOT4; NOT4; NOT4; /* 190 - 19F reserved */
1514 1494 NOT4; NOT4; NOT4; NOT4; /* 1A0 - 1AF reserved */
1515 1495 NOT4; NOT4; NOT4; NOT4; /* 1B0 - 1BF reserved */
1516 1496 NOT4; NOT4; NOT4; NOT4; /* 1C0 - 1CF reserved */
1517 1497 NOT4; NOT4; NOT4; NOT4; /* 1D0 - 1DF reserved */
1518 1498 NOT4; NOT4; NOT4; NOT4; /* 1E0 - 1EF reserved */
1519 1499 NOT4; NOT4; NOT4; NOT4; /* 1F0 - 1FF reserved */
1520 1500 trap_table1:
1521 1501 NOT4; NOT4; NOT; NOT; /* 000 - 009 unused */
1522 1502 ASYNC_TRAP(T_INSTR_ERROR + T_TL1, trace_gen, tt1_iae);
1523 1503 /* 00A instruction access error */
1524 1504 NOT; NOT4; /* 00B - 00F unused */
1525 1505 NOT4; NOT4; NOT4; NOT4; /* 010 - 01F unused */
1526 1506 NOT4; /* 020 - 023 unused */
1527 1507 CLEAN_WINDOW; /* 024 - 027 clean window */
1528 1508 NOT4; NOT4; /* 028 - 02F unused */
1529 1509 DMMU_EXCEPTION_TL1; /* 030 data access exception */
1530 1510 NOT; /* 031 unused */
1531 1511 ASYNC_TRAP(T_DATA_ERROR + T_TL1, trace_gen, tt1_dae);
1532 1512 /* 032 data access error */
1533 1513 NOT; /* 033 unused */
1534 1514 MISALIGN_ADDR_TL1; /* 034 mem address not aligned */
1535 1515 NOT; NOT; NOT; NOT4; NOT4 /* 035 - 03F unused */
1536 1516 LABELED_BAD(tt1_asdat); /* 040 async data error */
1537 1517 NOT; NOT; NOT; /* 041 - 043 unused */
1538 1518 NOT4; NOT4; NOT4; /* 044 - 04F unused */
1539 1519 NOT4; NOT4; NOT4; NOT4; /* 050 - 05F unused */
1540 1520 NOT; /* 060 unused */
1541 1521 GOTO(kmdb_trap_tl1); /* 061 PA watchpoint */
1542 1522 GOTO(kmdb_trap_tl1); /* 062 VA watchpoint */
1543 1523 GOTO_TT(ce_err_tl1, trace_gen); /* 063 corrected ECC error */
1544 1524 ITLB_MISS(tt1); /* 064 instruction access MMU miss */
1545 1525 DTLB_MISS(tt1); /* 068 data access MMU miss */
1546 1526 DTLB_PROT; /* 06C data access protection */
1547 1527 LABELED_BAD(tt1_fecc); /* 070 fast ecache ECC error */
1548 1528 LABELED_BAD(tt1_dperr); /* 071 Cheetah+ dcache parity error */
1549 1529 LABELED_BAD(tt1_iperr); /* 072 Cheetah+ icache parity error */
1550 1530 NOT; /* 073 reserved */
1551 1531 NOT4; NOT4; NOT4; /* 074 - 07F reserved */
1552 1532 NOT4; /* 080 spill 0 normal */
1553 1533 SPILL_32bit_tt1(ASI_AIUP,sn1); /* 084 spill 1 normal */
1554 1534 SPILL_64bit_tt1(ASI_AIUP,sn1); /* 088 spill 2 normal */
1555 1535 SPILL_32bit_tt1(ASI_AIUP,sn1); /* 08C spill 3 normal */
1556 1536 SPILL_64bit_tt1(ASI_AIUP,sn1); /* 090 spill 4 normal */
1557 1537 SPILL_32bit(not); /* 094 spill 5 normal */
1558 1538 SPILL_64bit(not); /* 098 spill 6 normal */
1559 1539 SPILL_mixed; /* 09C spill 7 normal */
1560 1540 NOT4; /* 0A0 spill 0 other */
1561 1541 SPILL_32bit_tt1(ASI_AIUS,so1); /* 0A4 spill 1 other */
1562 1542 SPILL_64bit_tt1(ASI_AIUS,so1); /* 0A8 spill 2 other */
1563 1543 SPILL_32bit_tt1(ASI_AIUS,so1); /* 0AC spill 3 other */
1564 1544 SPILL_64bit_tt1(ASI_AIUS,so1); /* 0B0 spill 4 other */
1565 1545 NOT4; /* 0B4 spill 5 other */
1566 1546 NOT4; /* 0B8 spill 6 other */
1567 1547 NOT4; /* 0BC spill 7 other */
1568 1548 NOT4; /* 0C0 fill 0 normal */
1569 1549 FILL_32bit_tt1(ASI_AIUP,fn1); /* 0C4 fill 1 normal */
1570 1550 FILL_64bit_tt1(ASI_AIUP,fn1); /* 0C8 fill 2 normal */
1571 1551 FILL_32bit_tt1(ASI_AIUP,fn1); /* 0CC fill 3 normal */
1572 1552 FILL_64bit_tt1(ASI_AIUP,fn1); /* 0D0 fill 4 normal */
1573 1553 FILL_32bit(not); /* 0D4 fill 5 normal */
1574 1554 FILL_64bit(not); /* 0D8 fill 6 normal */
1575 1555 FILL_mixed; /* 0DC fill 7 normal */
1576 1556 NOT4; NOT4; NOT4; NOT4; /* 0E0 - 0EF unused */
1577 1557 NOT4; NOT4; NOT4; NOT4; /* 0F0 - 0FF unused */
1578 1558 LABELED_BAD(tt1_swtrap0); /* 100 fast ecache ECC error (cont) */
1579 1559 LABELED_BAD(tt1_swtrap1); /* 101 Ch+ D$ parity error (cont) */
1580 1560 LABELED_BAD(tt1_swtrap2); /* 102 Ch+ I$ parity error (cont) */
1581 1561 NOT; /* 103 reserved */
1582 1562 /*
1583 1563 * We only reserve the above four special case soft traps for code running
1584 1564 * at TL>0, so we can truncate the trap table here.
1585 1565 */
1586 1566 etrap_table:
1587 1567 .size trap_table, (.-trap_table)
1588 1568 .size scb, (.-scb)
1589 1569
1590 1570 /*
1591 1571 * We get to exec_fault in the case of an instruction miss and tte
1592 1572 * has no execute bit set. We go to tl0 to handle it.
1593 1573 *
1594 1574 * g1 = tsbe pointer (in/clobbered)
1595 1575 * g2 = tag access register (in)
1596 1576 * g3 - g4 = scratch (clobbered)
1597 1577 * g5 = tsbe data (in)
1598 1578 * g6 = scratch (clobbered)
1599 1579 */
1600 1580 ALTENTRY(exec_fault)
1601 1581 TRACE_TSBHIT(0x200)
1602 1582 SWITCH_GLOBALS
1603 1583 mov MMU_TAG_ACCESS, %g4
1604 1584 ldxa [%g4]ASI_IMMU, %g2 ! arg1 = addr
1605 1585 mov T_INSTR_MMU_MISS, %g3 ! arg2 = traptype
1606 1586 set trap, %g1
1607 1587 ba,pt %xcc, sys_trap
1608 1588 mov -1, %g4
1609 1589
1610 1590 .mmu_exception_not_aligned:
1611 1591 rdpr %tstate, %g1
1612 1592 btst TSTATE_PRIV, %g1
1613 1593 bnz,pn %icc, 2f
1614 1594 nop
1615 1595 CPU_ADDR(%g1, %g4) ! load CPU struct addr
1616 1596 ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer
1617 1597 ldn [%g1 + T_PROCP], %g1 ! load proc pointer
1618 1598 ldn [%g1 + P_UTRAPS], %g5 ! are there utraps?
1619 1599 brz,pt %g5, 2f
1620 1600 nop
1621 1601 ldn [%g5 + P_UTRAP15], %g5 ! unaligned utrap?
1622 1602 brz,pn %g5, 2f
1623 1603 nop
1624 1604 btst 1, %sp
1625 1605 bz,pt %xcc, 1f ! 32 bit user program
1626 1606 nop
1627 1607 ba,pt %xcc, .setup_v9utrap ! 64 bit user program
1628 1608 nop
1629 1609 1:
1630 1610 ba,pt %xcc, .setup_utrap
1631 1611 or %g2, %g0, %g7
1632 1612 2:
1633 1613 ba,pt %xcc, .mmu_exception_end
1634 1614 mov T_ALIGNMENT, %g1
1635 1615
1636 1616 .mmu_priv_exception:
1637 1617 rdpr %tstate, %g1
1638 1618 btst TSTATE_PRIV, %g1
1639 1619 bnz,pn %icc, 1f
1640 1620 nop
1641 1621 CPU_ADDR(%g1, %g4) ! load CPU struct addr
1642 1622 ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer
1643 1623 ldn [%g1 + T_PROCP], %g1 ! load proc pointer
1644 1624 ldn [%g1 + P_UTRAPS], %g5 ! are there utraps?
1645 1625 brz,pt %g5, 1f
1646 1626 nop
1647 1627 ldn [%g5 + P_UTRAP16], %g5
1648 1628 brnz,pt %g5, .setup_v9utrap
1649 1629 nop
1650 1630 1:
1651 1631 mov T_PRIV_INSTR, %g1
1652 1632
1653 1633 .mmu_exception_end:
1654 1634 CPU_INDEX(%g4, %g5)
1655 1635 set cpu_core, %g5
1656 1636 sllx %g4, CPU_CORE_SHIFT, %g4
1657 1637 add %g4, %g5, %g4
1658 1638 lduh [%g4 + CPUC_DTRACE_FLAGS], %g5
1659 1639 andcc %g5, CPU_DTRACE_NOFAULT, %g0
1660 1640 bz %xcc, .mmu_exception_tlb_chk
1661 1641 or %g5, CPU_DTRACE_BADADDR, %g5
1662 1642 stuh %g5, [%g4 + CPUC_DTRACE_FLAGS]
1663 1643 done
1664 1644
1665 1645 .mmu_exception_tlb_chk:
1666 1646 GET_CPU_IMPL(%g5) ! check SFSR.FT to see if this
1667 1647 cmp %g5, PANTHER_IMPL ! is a TLB parity error. But
1668 1648 bne 2f ! we only do this check while
1669 1649 mov 1, %g4 ! running on Panther CPUs
1670 1650 sllx %g4, PN_SFSR_PARITY_SHIFT, %g4 ! since US-I/II use the same
1671 1651 andcc %g3, %g4, %g0 ! bit for something else which
1672 1652 bz 2f ! will be handled later.
1673 1653 nop
1674 1654 .mmu_exception_is_tlb_parity:
1675 1655 .weak itlb_parity_trap
1676 1656 .weak dtlb_parity_trap
1677 1657 set itlb_parity_trap, %g4
1678 1658 cmp %g1, T_INSTR_EXCEPTION ! branch to the itlb or
1679 1659 be 3f ! dtlb parity handler
1680 1660 nop ! if this trap is due
1681 1661 set dtlb_parity_trap, %g4
1682 1662 cmp %g1, T_DATA_EXCEPTION ! to a IMMU exception
1683 1663 be 3f ! or DMMU exception.
1684 1664 nop
1685 1665 2:
1686 1666 sllx %g3, 32, %g3
1687 1667 or %g3, %g1, %g3
1688 1668 set trap, %g1
1689 1669 ba,pt %xcc, sys_trap
1690 1670 sub %g0, 1, %g4
1691 1671 3:
1692 1672 jmp %g4 ! off to the appropriate
1693 1673 nop ! TLB parity handler
1694 1674
1695 1675 .fp_disabled:
1696 1676 CPU_ADDR(%g1, %g4) ! load CPU struct addr
1697 1677 ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer
1698 1678 #ifdef SF_ERRATA_30 /* call causes fp-disabled */
1699 1679 brz,a,pn %g1, 2f
1700 1680 nop
1701 1681 #endif
1702 1682 rdpr %tstate, %g4
1703 1683 btst TSTATE_PRIV, %g4
1704 1684 #ifdef SF_ERRATA_30 /* call causes fp-disabled */
1705 1685 bnz,pn %icc, 2f
1706 1686 nop
1707 1687 #else
1708 1688 bnz,a,pn %icc, ptl1_panic
1709 1689 mov PTL1_BAD_FPTRAP, %g1
1710 1690 #endif
1711 1691 ldn [%g1 + T_PROCP], %g1 ! load proc pointer
1712 1692 ldn [%g1 + P_UTRAPS], %g5 ! are there utraps?
1713 1693 brz,a,pt %g5, 2f
1714 1694 nop
1715 1695 ldn [%g5 + P_UTRAP7], %g5 ! fp_disabled utrap?
1716 1696 brz,a,pn %g5, 2f
1717 1697 nop
1718 1698 btst 1, %sp
1719 1699 bz,a,pt %xcc, 1f ! 32 bit user program
1720 1700 nop
1721 1701 ba,a,pt %xcc, .setup_v9utrap ! 64 bit user program
1722 1702 nop
1723 1703 1:
1724 1704 ba,pt %xcc, .setup_utrap
1725 1705 or %g0, %g0, %g7
1726 1706 2:
1727 1707 set fp_disabled, %g1
1728 1708 ba,pt %xcc, sys_trap
1729 1709 sub %g0, 1, %g4
1730 1710
1731 1711 .fp_ieee_exception:
1732 1712 rdpr %tstate, %g1
1733 1713 btst TSTATE_PRIV, %g1
1734 1714 bnz,a,pn %icc, ptl1_panic
1735 1715 mov PTL1_BAD_FPTRAP, %g1
1736 1716 CPU_ADDR(%g1, %g4) ! load CPU struct addr
1737 1717 stx %fsr, [%g1 + CPU_TMP1]
1738 1718 ldx [%g1 + CPU_TMP1], %g2
1739 1719 ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer
1740 1720 ldn [%g1 + T_PROCP], %g1 ! load proc pointer
1741 1721 ldn [%g1 + P_UTRAPS], %g5 ! are there utraps?
1742 1722 brz,a,pt %g5, 1f
1743 1723 nop
1744 1724 ldn [%g5 + P_UTRAP8], %g5
1745 1725 brnz,a,pt %g5, .setup_v9utrap
1746 1726 nop
1747 1727 1:
1748 1728 set _fp_ieee_exception, %g1
1749 1729 ba,pt %xcc, sys_trap
1750 1730 sub %g0, 1, %g4
1751 1731
1752 1732 /*
1753 1733 * Register Inputs:
1754 1734 * %g5 user trap handler
1755 1735 * %g7 misaligned addr - for alignment traps only
1756 1736 */
1757 1737 .setup_utrap:
1758 1738 set trap, %g1 ! setup in case we go
1759 1739 mov T_FLUSH_PCB, %g3 ! through sys_trap on
1760 1740 sub %g0, 1, %g4 ! the save instruction below
1761 1741
1762 1742 /*
1763 1743 * If the DTrace pid provider is single stepping a copied-out
1764 1744 * instruction, t->t_dtrace_step will be set. In that case we need
1765 1745 * to abort the single-stepping (since execution of the instruction
1766 1746 * was interrupted) and use the value of t->t_dtrace_npc as the %npc.
1767 1747 */
1768 1748 save %sp, -SA(MINFRAME32), %sp ! window for trap handler
1769 1749 CPU_ADDR(%g1, %g4) ! load CPU struct addr
1770 1750 ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer
1771 1751 ldub [%g1 + T_DTRACE_STEP], %g2 ! load t->t_dtrace_step
1772 1752 rdpr %tnpc, %l2 ! arg1 == tnpc
1773 1753 brz,pt %g2, 1f
1774 1754 rdpr %tpc, %l1 ! arg0 == tpc
1775 1755
1776 1756 ldub [%g1 + T_DTRACE_AST], %g2 ! load t->t_dtrace_ast
1777 1757 ldn [%g1 + T_DTRACE_NPC], %l2 ! arg1 = t->t_dtrace_npc (step)
1778 1758 brz,pt %g2, 1f
1779 1759 st %g0, [%g1 + T_DTRACE_FT] ! zero all pid provider flags
1780 1760 stub %g2, [%g1 + T_ASTFLAG] ! aston(t) if t->t_dtrace_ast
1781 1761 1:
1782 1762 mov %g7, %l3 ! arg2 == misaligned address
1783 1763
1784 1764 rdpr %tstate, %g1 ! cwp for trap handler
1785 1765 rdpr %cwp, %g4
1786 1766 bclr TSTATE_CWP_MASK, %g1
1787 1767 wrpr %g1, %g4, %tstate
1788 1768 wrpr %g0, %g5, %tnpc ! trap handler address
1789 1769 FAST_TRAP_DONE
1790 1770 /* NOTREACHED */
1791 1771
1792 1772 .check_v9utrap:
1793 1773 rdpr %tstate, %g1
1794 1774 btst TSTATE_PRIV, %g1
1795 1775 bnz,a,pn %icc, 3f
1796 1776 nop
1797 1777 CPU_ADDR(%g4, %g1) ! load CPU struct addr
1798 1778 ldn [%g4 + CPU_THREAD], %g5 ! load thread pointer
1799 1779 ldn [%g5 + T_PROCP], %g5 ! load proc pointer
1800 1780 ldn [%g5 + P_UTRAPS], %g5 ! are there utraps?
1801 1781
1802 1782 cmp %g3, T_SOFTWARE_TRAP
1803 1783 bne,a,pt %icc, 1f
1804 1784 nop
1805 1785
1806 1786 brz,pt %g5, 3f ! if p_utraps == NULL goto trap()
1807 1787 rdpr %tt, %g3 ! delay - get actual hw trap type
1808 1788
1809 1789 sub %g3, 254, %g1 ! UT_TRAP_INSTRUCTION_16 = p_utraps[18]
1810 1790 ba,pt %icc, 2f
1811 1791 smul %g1, CPTRSIZE, %g2
1812 1792 1:
1813 1793 brz,a,pt %g5, 3f ! if p_utraps == NULL goto trap()
1814 1794 nop
1815 1795
1816 1796 cmp %g3, T_UNIMP_INSTR
1817 1797 bne,a,pt %icc, 2f
1818 1798 nop
1819 1799
1820 1800 mov 1, %g1
1821 1801 st %g1, [%g4 + CPU_TL1_HDLR] ! set CPU_TL1_HDLR
1822 1802 rdpr %tpc, %g1 ! ld trapping instruction using
1823 1803 lduwa [%g1]ASI_AIUP, %g1 ! "AS IF USER" ASI which could fault
1824 1804 st %g0, [%g4 + CPU_TL1_HDLR] ! clr CPU_TL1_HDLR
1825 1805
1826 1806 sethi %hi(0xc1c00000), %g4 ! setup mask for illtrap instruction
1827 1807 andcc %g1, %g4, %g4 ! and instruction with mask
1828 1808 bnz,a,pt %icc, 3f ! if %g4 == zero, %g1 is an ILLTRAP
1829 1809 nop ! fall thru to setup
1830 1810 2:
1831 1811 ldn [%g5 + %g2], %g5
1832 1812 brnz,a,pt %g5, .setup_v9utrap
1833 1813 nop
1834 1814 3:
1835 1815 set trap, %g1
1836 1816 ba,pt %xcc, sys_trap
1837 1817 sub %g0, 1, %g4
1838 1818 /* NOTREACHED */
1839 1819
1840 1820 /*
1841 1821 * Register Inputs:
1842 1822 * %g5 user trap handler
1843 1823 */
1844 1824 .setup_v9utrap:
1845 1825 set trap, %g1 ! setup in case we go
1846 1826 mov T_FLUSH_PCB, %g3 ! through sys_trap on
1847 1827 sub %g0, 1, %g4 ! the save instruction below
1848 1828
1849 1829 /*
1850 1830 * If the DTrace pid provider is single stepping a copied-out
1851 1831 * instruction, t->t_dtrace_step will be set. In that case we need
1852 1832 * to abort the single-stepping (since execution of the instruction
1853 1833 * was interrupted) and use the value of t->t_dtrace_npc as the %npc.
1854 1834 */
1855 1835 save %sp, -SA(MINFRAME64), %sp ! window for trap handler
1856 1836 CPU_ADDR(%g1, %g4) ! load CPU struct addr
1857 1837 ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer
1858 1838 ldub [%g1 + T_DTRACE_STEP], %g2 ! load t->t_dtrace_step
1859 1839 rdpr %tnpc, %l7 ! arg1 == tnpc
1860 1840 brz,pt %g2, 1f
1861 1841 rdpr %tpc, %l6 ! arg0 == tpc
1862 1842
1863 1843 ldub [%g1 + T_DTRACE_AST], %g2 ! load t->t_dtrace_ast
1864 1844 ldn [%g1 + T_DTRACE_NPC], %l7 ! arg1 == t->t_dtrace_npc (step)
1865 1845 brz,pt %g2, 1f
1866 1846 st %g0, [%g1 + T_DTRACE_FT] ! zero all pid provider flags
1867 1847 stub %g2, [%g1 + T_ASTFLAG] ! aston(t) if t->t_dtrace_ast
1868 1848 1:
1869 1849 rdpr %tstate, %g2 ! cwp for trap handler
1870 1850 rdpr %cwp, %g4
1871 1851 bclr TSTATE_CWP_MASK, %g2
1872 1852 wrpr %g2, %g4, %tstate
1873 1853
1874 1854 ldn [%g1 + T_PROCP], %g4 ! load proc pointer
1875 1855 ldn [%g4 + P_AS], %g4 ! load as pointer
1876 1856 ldn [%g4 + A_USERLIMIT], %g4 ! load as userlimit
1877 1857 cmp %l7, %g4 ! check for single-step set
1878 1858 bne,pt %xcc, 4f
1879 1859 nop
1880 1860 ldn [%g1 + T_LWP], %g1 ! load klwp pointer
1881 1861 ld [%g1 + PCB_STEP], %g4 ! load single-step flag
1882 1862 cmp %g4, STEP_ACTIVE ! step flags set in pcb?
1883 1863 bne,pt %icc, 4f
1884 1864 nop
1885 1865 stn %g5, [%g1 + PCB_TRACEPC] ! save trap handler addr in pcb
1886 1866 mov %l7, %g4 ! on entry to precise user trap
1887 1867 add %l6, 4, %l7 ! handler, %l6 == pc, %l7 == npc
1888 1868 ! at time of trap
1889 1869 wrpr %g0, %g4, %tnpc ! generate FLTBOUNDS,
1890 1870 ! %g4 == userlimit
1891 1871 FAST_TRAP_DONE
1892 1872 /* NOTREACHED */
1893 1873 4:
1894 1874 wrpr %g0, %g5, %tnpc ! trap handler address
1895 1875 FAST_TRAP_DONE_CHK_INTR
1896 1876 /* NOTREACHED */
1897 1877
1898 1878 .fp_exception:
1899 1879 CPU_ADDR(%g1, %g4)
1900 1880 stx %fsr, [%g1 + CPU_TMP1]
1901 1881 ldx [%g1 + CPU_TMP1], %g2
1902 1882
1903 1883 /*
1904 1884 * Cheetah takes unfinished_FPop trap for certain range of operands
1905 1885 * to the "fitos" instruction. Instead of going through the slow
1906 1886 * software emulation path, we try to simulate the "fitos" instruction
1907 1887 * via "fitod" and "fdtos" provided the following conditions are met:
1908 1888 *
1909 1889 * fpu_exists is set (if DEBUG)
1910 1890 * not in privileged mode
1911 1891 * ftt is unfinished_FPop
1912 1892 * NXM IEEE trap is not enabled
1913 1893 * instruction at %tpc is "fitos"
1914 1894 *
1915 1895 * Usage:
1916 1896 * %g1 per cpu address
1917 1897 * %g2 %fsr
1918 1898 * %g6 user instruction
1919 1899 *
1920 1900 * Note that we can take a memory access related trap while trying
1921 1901 * to fetch the user instruction. Therefore, we set CPU_TL1_HDLR
1922 1902 * flag to catch those traps and let the SFMMU code deal with page
1923 1903 * fault and data access exception.
1924 1904 */
1925 1905 #if defined(DEBUG) || defined(NEED_FPU_EXISTS)
1926 1906 sethi %hi(fpu_exists), %g7
1927 1907 ld [%g7 + %lo(fpu_exists)], %g7
1928 1908 brz,pn %g7, .fp_exception_cont
1929 1909 nop
1930 1910 #endif
1931 1911 rdpr %tstate, %g7 ! branch if in privileged mode
1932 1912 btst TSTATE_PRIV, %g7
1933 1913 bnz,pn %xcc, .fp_exception_cont
1934 1914 srl %g2, FSR_FTT_SHIFT, %g7 ! extract ftt from %fsr
1935 1915 and %g7, (FSR_FTT>>FSR_FTT_SHIFT), %g7
1936 1916 cmp %g7, FTT_UNFIN
1937 1917 set FSR_TEM_NX, %g5
1938 1918 bne,pn %xcc, .fp_exception_cont ! branch if NOT unfinished_FPop
1939 1919 andcc %g2, %g5, %g0
1940 1920 bne,pn %xcc, .fp_exception_cont ! branch if FSR_TEM_NX enabled
1941 1921 rdpr %tpc, %g5 ! get faulting PC
1942 1922
1943 1923 or %g0, 1, %g7
1944 1924 st %g7, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag
1945 1925 lda [%g5]ASI_USER, %g6 ! get user's instruction
1946 1926 st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag
1947 1927
1948 1928 set FITOS_INSTR_MASK, %g7
1949 1929 and %g6, %g7, %g7
1950 1930 set FITOS_INSTR, %g5
1951 1931 cmp %g7, %g5
1952 1932 bne,pn %xcc, .fp_exception_cont ! branch if not FITOS_INSTR
1953 1933 nop
1954 1934
1955 1935 /*
1956 1936 * This is unfinished FPops trap for "fitos" instruction. We
1957 1937 * need to simulate "fitos" via "fitod" and "fdtos" instruction
1958 1938 * sequence.
1959 1939 *
1960 1940 * We need a temporary FP register to do the conversion. Since
1961 1941 * both source and destination operands for the "fitos" instruction
1962 1942 * have to be within %f0-%f31, we use an FP register from the upper
1963 1943 * half to guarantee that it won't collide with the source or the
1964 1944 * dest operand. However, we do have to save and restore its value.
1965 1945 *
1966 1946 * We use %d62 as a temporary FP register for the conversion and
1967 1947 * branch to appropriate instruction within the conversion tables
1968 1948 * based upon the rs2 and rd values.
1969 1949 */
1970 1950
1971 1951 std %d62, [%g1 + CPU_TMP1] ! save original value
1972 1952
1973 1953 srl %g6, FITOS_RS2_SHIFT, %g7
1974 1954 and %g7, FITOS_REG_MASK, %g7
1975 1955 set _fitos_fitod_table, %g4
1976 1956 sllx %g7, 2, %g7
1977 1957 jmp %g4 + %g7
1978 1958 ba,pt %xcc, _fitos_fitod_done
1979 1959 .empty
1980 1960
1981 1961 _fitos_fitod_table:
1982 1962 fitod %f0, %d62
1983 1963 fitod %f1, %d62
1984 1964 fitod %f2, %d62
1985 1965 fitod %f3, %d62
1986 1966 fitod %f4, %d62
1987 1967 fitod %f5, %d62
1988 1968 fitod %f6, %d62
1989 1969 fitod %f7, %d62
1990 1970 fitod %f8, %d62
1991 1971 fitod %f9, %d62
1992 1972 fitod %f10, %d62
1993 1973 fitod %f11, %d62
1994 1974 fitod %f12, %d62
1995 1975 fitod %f13, %d62
1996 1976 fitod %f14, %d62
1997 1977 fitod %f15, %d62
1998 1978 fitod %f16, %d62
1999 1979 fitod %f17, %d62
2000 1980 fitod %f18, %d62
2001 1981 fitod %f19, %d62
2002 1982 fitod %f20, %d62
2003 1983 fitod %f21, %d62
2004 1984 fitod %f22, %d62
2005 1985 fitod %f23, %d62
2006 1986 fitod %f24, %d62
2007 1987 fitod %f25, %d62
2008 1988 fitod %f26, %d62
2009 1989 fitod %f27, %d62
2010 1990 fitod %f28, %d62
2011 1991 fitod %f29, %d62
2012 1992 fitod %f30, %d62
2013 1993 fitod %f31, %d62
2014 1994 _fitos_fitod_done:
2015 1995
2016 1996 /*
2017 1997 * Now convert data back into single precision
2018 1998 */
2019 1999 srl %g6, FITOS_RD_SHIFT, %g7
2020 2000 and %g7, FITOS_REG_MASK, %g7
2021 2001 set _fitos_fdtos_table, %g4
2022 2002 sllx %g7, 2, %g7
2023 2003 jmp %g4 + %g7
2024 2004 ba,pt %xcc, _fitos_fdtos_done
2025 2005 .empty
2026 2006
2027 2007 _fitos_fdtos_table:
2028 2008 fdtos %d62, %f0
2029 2009 fdtos %d62, %f1
2030 2010 fdtos %d62, %f2
2031 2011 fdtos %d62, %f3
2032 2012 fdtos %d62, %f4
2033 2013 fdtos %d62, %f5
2034 2014 fdtos %d62, %f6
2035 2015 fdtos %d62, %f7
2036 2016 fdtos %d62, %f8
2037 2017 fdtos %d62, %f9
2038 2018 fdtos %d62, %f10
2039 2019 fdtos %d62, %f11
2040 2020 fdtos %d62, %f12
2041 2021 fdtos %d62, %f13
2042 2022 fdtos %d62, %f14
2043 2023 fdtos %d62, %f15
2044 2024 fdtos %d62, %f16
2045 2025 fdtos %d62, %f17
2046 2026 fdtos %d62, %f18
2047 2027 fdtos %d62, %f19
2048 2028 fdtos %d62, %f20
2049 2029 fdtos %d62, %f21
2050 2030 fdtos %d62, %f22
2051 2031 fdtos %d62, %f23
2052 2032 fdtos %d62, %f24
2053 2033 fdtos %d62, %f25
2054 2034 fdtos %d62, %f26
2055 2035 fdtos %d62, %f27
2056 2036 fdtos %d62, %f28
2057 2037 fdtos %d62, %f29
2058 2038 fdtos %d62, %f30
2059 2039 fdtos %d62, %f31
2060 2040 _fitos_fdtos_done:
2061 2041
2062 2042 ldd [%g1 + CPU_TMP1], %d62 ! restore %d62
2063 2043
2064 2044 #if DEBUG
2065 2045 /*
2066 2046 * Update FPop_unfinished trap kstat
2067 2047 */
2068 2048 set fpustat+FPUSTAT_UNFIN_KSTAT, %g7
2069 2049 ldx [%g7], %g5
2070 2050 1:
2071 2051 add %g5, 1, %g6
2072 2052
2073 2053 casxa [%g7] ASI_N, %g5, %g6
2074 2054 cmp %g5, %g6
2075 2055 bne,a,pn %xcc, 1b
2076 2056 or %g0, %g6, %g5
2077 2057
2078 2058 /*
2079 2059 * Update fpu_sim_fitos kstat
2080 2060 */
2081 2061 set fpuinfo+FPUINFO_FITOS_KSTAT, %g7
2082 2062 ldx [%g7], %g5
2083 2063 1:
2084 2064 add %g5, 1, %g6
2085 2065
2086 2066 casxa [%g7] ASI_N, %g5, %g6
2087 2067 cmp %g5, %g6
2088 2068 bne,a,pn %xcc, 1b
2089 2069 or %g0, %g6, %g5
2090 2070 #endif /* DEBUG */
2091 2071
2092 2072 FAST_TRAP_DONE
2093 2073
2094 2074 .fp_exception_cont:
2095 2075 /*
2096 2076 * Let _fp_exception deal with simulating FPop instruction.
2097 2077 * Note that we need to pass %fsr in %g2 (already read above).
2098 2078 */
2099 2079
2100 2080 set _fp_exception, %g1
2101 2081 ba,pt %xcc, sys_trap
2102 2082 sub %g0, 1, %g4
2103 2083
2104 2084 .global opl_cleanw_patch
2105 2085 opl_cleanw_patch:
2106 2086 .clean_windows:
2107 2087 set trap, %g1
2108 2088 mov T_FLUSH_PCB, %g3
2109 2089 sub %g0, 1, %g4
2110 2090 save
2111 2091 flushw
2112 2092 restore
2113 2093 wrpr %g0, %g0, %cleanwin ! no clean windows
2114 2094
2115 2095 CPU_ADDR(%g4, %g5)
2116 2096 ldn [%g4 + CPU_MPCB], %g4
2117 2097 brz,a,pn %g4, 1f
2118 2098 nop
2119 2099 ld [%g4 + MPCB_WSTATE], %g5
2120 2100 add %g5, WSTATE_CLEAN_OFFSET, %g5
2121 2101 wrpr %g0, %g5, %wstate
2122 2102 1: FAST_TRAP_DONE
2123 2103
2124 2104 /*
2125 2105 * .spill_clean: clean the previous window, restore the wstate, and
2126 2106 * "done".
2127 2107 *
2128 2108 * Entry: %g7 contains new wstate
2129 2109 */
2130 2110 .spill_clean:
2131 2111 sethi %hi(nwin_minus_one), %g5
2132 2112 ld [%g5 + %lo(nwin_minus_one)], %g5 ! %g5 = nwin - 1
2133 2113 rdpr %cwp, %g6 ! %g6 = %cwp
2134 2114 deccc %g6 ! %g6--
2135 2115 movneg %xcc, %g5, %g6 ! if (%g6<0) %g6 = nwin-1
2136 2116 wrpr %g6, %cwp
2137 2117 TT_TRACE_L(trace_win)
2138 2118 clr %l0
2139 2119 clr %l1
2140 2120 clr %l2
2141 2121 clr %l3
2142 2122 clr %l4
2143 2123 clr %l5
2144 2124 clr %l6
2145 2125 clr %l7
2146 2126 wrpr %g0, %g7, %wstate
2147 2127 saved
2148 2128 retry ! restores correct %cwp
2149 2129
2150 2130 .fix_alignment:
2151 2131 CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2
2152 2132 ldn [%g1 + CPU_THREAD], %g1 ! load thread pointer
2153 2133 ldn [%g1 + T_PROCP], %g1
2154 2134 mov 1, %g2
2155 2135 stb %g2, [%g1 + P_FIXALIGNMENT]
2156 2136 FAST_TRAP_DONE
2157 2137
2158 2138 #define STDF_REG(REG, ADDR, TMP) \
2159 2139 sll REG, 3, REG ;\
2160 2140 mark1: set start1, TMP ;\
2161 2141 jmp REG + TMP ;\
2162 2142 nop ;\
2163 2143 start1: ba,pt %xcc, done1 ;\
2164 2144 std %f0, [ADDR + CPU_TMP1] ;\
2165 2145 ba,pt %xcc, done1 ;\
2166 2146 std %f32, [ADDR + CPU_TMP1] ;\
2167 2147 ba,pt %xcc, done1 ;\
2168 2148 std %f2, [ADDR + CPU_TMP1] ;\
2169 2149 ba,pt %xcc, done1 ;\
2170 2150 std %f34, [ADDR + CPU_TMP1] ;\
2171 2151 ba,pt %xcc, done1 ;\
2172 2152 std %f4, [ADDR + CPU_TMP1] ;\
2173 2153 ba,pt %xcc, done1 ;\
2174 2154 std %f36, [ADDR + CPU_TMP1] ;\
2175 2155 ba,pt %xcc, done1 ;\
2176 2156 std %f6, [ADDR + CPU_TMP1] ;\
2177 2157 ba,pt %xcc, done1 ;\
2178 2158 std %f38, [ADDR + CPU_TMP1] ;\
2179 2159 ba,pt %xcc, done1 ;\
2180 2160 std %f8, [ADDR + CPU_TMP1] ;\
2181 2161 ba,pt %xcc, done1 ;\
2182 2162 std %f40, [ADDR + CPU_TMP1] ;\
2183 2163 ba,pt %xcc, done1 ;\
2184 2164 std %f10, [ADDR + CPU_TMP1] ;\
2185 2165 ba,pt %xcc, done1 ;\
2186 2166 std %f42, [ADDR + CPU_TMP1] ;\
2187 2167 ba,pt %xcc, done1 ;\
2188 2168 std %f12, [ADDR + CPU_TMP1] ;\
2189 2169 ba,pt %xcc, done1 ;\
2190 2170 std %f44, [ADDR + CPU_TMP1] ;\
2191 2171 ba,pt %xcc, done1 ;\
2192 2172 std %f14, [ADDR + CPU_TMP1] ;\
2193 2173 ba,pt %xcc, done1 ;\
2194 2174 std %f46, [ADDR + CPU_TMP1] ;\
2195 2175 ba,pt %xcc, done1 ;\
2196 2176 std %f16, [ADDR + CPU_TMP1] ;\
2197 2177 ba,pt %xcc, done1 ;\
2198 2178 std %f48, [ADDR + CPU_TMP1] ;\
2199 2179 ba,pt %xcc, done1 ;\
2200 2180 std %f18, [ADDR + CPU_TMP1] ;\
2201 2181 ba,pt %xcc, done1 ;\
2202 2182 std %f50, [ADDR + CPU_TMP1] ;\
2203 2183 ba,pt %xcc, done1 ;\
2204 2184 std %f20, [ADDR + CPU_TMP1] ;\
2205 2185 ba,pt %xcc, done1 ;\
2206 2186 std %f52, [ADDR + CPU_TMP1] ;\
2207 2187 ba,pt %xcc, done1 ;\
2208 2188 std %f22, [ADDR + CPU_TMP1] ;\
2209 2189 ba,pt %xcc, done1 ;\
2210 2190 std %f54, [ADDR + CPU_TMP1] ;\
2211 2191 ba,pt %xcc, done1 ;\
2212 2192 std %f24, [ADDR + CPU_TMP1] ;\
2213 2193 ba,pt %xcc, done1 ;\
2214 2194 std %f56, [ADDR + CPU_TMP1] ;\
2215 2195 ba,pt %xcc, done1 ;\
2216 2196 std %f26, [ADDR + CPU_TMP1] ;\
2217 2197 ba,pt %xcc, done1 ;\
2218 2198 std %f58, [ADDR + CPU_TMP1] ;\
2219 2199 ba,pt %xcc, done1 ;\
2220 2200 std %f28, [ADDR + CPU_TMP1] ;\
2221 2201 ba,pt %xcc, done1 ;\
2222 2202 std %f60, [ADDR + CPU_TMP1] ;\
2223 2203 ba,pt %xcc, done1 ;\
2224 2204 std %f30, [ADDR + CPU_TMP1] ;\
2225 2205 ba,pt %xcc, done1 ;\
2226 2206 std %f62, [ADDR + CPU_TMP1] ;\
2227 2207 done1:
2228 2208
2229 2209 #define LDDF_REG(REG, ADDR, TMP) \
2230 2210 sll REG, 3, REG ;\
2231 2211 mark2: set start2, TMP ;\
2232 2212 jmp REG + TMP ;\
2233 2213 nop ;\
2234 2214 start2: ba,pt %xcc, done2 ;\
2235 2215 ldd [ADDR + CPU_TMP1], %f0 ;\
2236 2216 ba,pt %xcc, done2 ;\
2237 2217 ldd [ADDR + CPU_TMP1], %f32 ;\
2238 2218 ba,pt %xcc, done2 ;\
2239 2219 ldd [ADDR + CPU_TMP1], %f2 ;\
2240 2220 ba,pt %xcc, done2 ;\
2241 2221 ldd [ADDR + CPU_TMP1], %f34 ;\
2242 2222 ba,pt %xcc, done2 ;\
2243 2223 ldd [ADDR + CPU_TMP1], %f4 ;\
2244 2224 ba,pt %xcc, done2 ;\
2245 2225 ldd [ADDR + CPU_TMP1], %f36 ;\
2246 2226 ba,pt %xcc, done2 ;\
2247 2227 ldd [ADDR + CPU_TMP1], %f6 ;\
2248 2228 ba,pt %xcc, done2 ;\
2249 2229 ldd [ADDR + CPU_TMP1], %f38 ;\
2250 2230 ba,pt %xcc, done2 ;\
2251 2231 ldd [ADDR + CPU_TMP1], %f8 ;\
2252 2232 ba,pt %xcc, done2 ;\
2253 2233 ldd [ADDR + CPU_TMP1], %f40 ;\
2254 2234 ba,pt %xcc, done2 ;\
2255 2235 ldd [ADDR + CPU_TMP1], %f10 ;\
2256 2236 ba,pt %xcc, done2 ;\
2257 2237 ldd [ADDR + CPU_TMP1], %f42 ;\
2258 2238 ba,pt %xcc, done2 ;\
2259 2239 ldd [ADDR + CPU_TMP1], %f12 ;\
2260 2240 ba,pt %xcc, done2 ;\
2261 2241 ldd [ADDR + CPU_TMP1], %f44 ;\
2262 2242 ba,pt %xcc, done2 ;\
2263 2243 ldd [ADDR + CPU_TMP1], %f14 ;\
2264 2244 ba,pt %xcc, done2 ;\
2265 2245 ldd [ADDR + CPU_TMP1], %f46 ;\
2266 2246 ba,pt %xcc, done2 ;\
2267 2247 ldd [ADDR + CPU_TMP1], %f16 ;\
2268 2248 ba,pt %xcc, done2 ;\
2269 2249 ldd [ADDR + CPU_TMP1], %f48 ;\
2270 2250 ba,pt %xcc, done2 ;\
2271 2251 ldd [ADDR + CPU_TMP1], %f18 ;\
2272 2252 ba,pt %xcc, done2 ;\
2273 2253 ldd [ADDR + CPU_TMP1], %f50 ;\
2274 2254 ba,pt %xcc, done2 ;\
2275 2255 ldd [ADDR + CPU_TMP1], %f20 ;\
2276 2256 ba,pt %xcc, done2 ;\
2277 2257 ldd [ADDR + CPU_TMP1], %f52 ;\
2278 2258 ba,pt %xcc, done2 ;\
2279 2259 ldd [ADDR + CPU_TMP1], %f22 ;\
2280 2260 ba,pt %xcc, done2 ;\
2281 2261 ldd [ADDR + CPU_TMP1], %f54 ;\
2282 2262 ba,pt %xcc, done2 ;\
2283 2263 ldd [ADDR + CPU_TMP1], %f24 ;\
2284 2264 ba,pt %xcc, done2 ;\
2285 2265 ldd [ADDR + CPU_TMP1], %f56 ;\
2286 2266 ba,pt %xcc, done2 ;\
2287 2267 ldd [ADDR + CPU_TMP1], %f26 ;\
2288 2268 ba,pt %xcc, done2 ;\
2289 2269 ldd [ADDR + CPU_TMP1], %f58 ;\
2290 2270 ba,pt %xcc, done2 ;\
2291 2271 ldd [ADDR + CPU_TMP1], %f28 ;\
2292 2272 ba,pt %xcc, done2 ;\
2293 2273 ldd [ADDR + CPU_TMP1], %f60 ;\
2294 2274 ba,pt %xcc, done2 ;\
2295 2275 ldd [ADDR + CPU_TMP1], %f30 ;\
2296 2276 ba,pt %xcc, done2 ;\
2297 2277 ldd [ADDR + CPU_TMP1], %f62 ;\
2298 2278 done2:
2299 2279
2300 2280 .lddf_exception_not_aligned:
2301 2281 /*
2302 2282 * Cheetah overwrites SFAR on a DTLB miss, hence read it now.
2303 2283 */
2304 2284 ldxa [MMU_SFAR]%asi, %g5 ! misaligned vaddr in %g5
2305 2285
2306 2286 #if defined(DEBUG) || defined(NEED_FPU_EXISTS)
2307 2287 sethi %hi(fpu_exists), %g2 ! check fpu_exists
2308 2288 ld [%g2 + %lo(fpu_exists)], %g2
2309 2289 brz,a,pn %g2, 4f
2310 2290 nop
2311 2291 #endif
2312 2292 CPU_ADDR(%g1, %g4)
2313 2293 or %g0, 1, %g4
2314 2294 st %g4, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag
2315 2295
2316 2296 rdpr %tpc, %g2
2317 2297 lda [%g2]ASI_AIUP, %g6 ! get the user's lddf instruction
2318 2298 srl %g6, 23, %g1 ! using ldda or not?
2319 2299 and %g1, 1, %g1
2320 2300 brz,a,pt %g1, 2f ! check for ldda instruction
2321 2301 nop
2322 2302 srl %g6, 13, %g1 ! check immflag
2323 2303 and %g1, 1, %g1
2324 2304 rdpr %tstate, %g2 ! %tstate in %g2
2325 2305 brnz,a,pn %g1, 1f
2326 2306 srl %g2, 31, %g1 ! get asi from %tstate
2327 2307 srl %g6, 5, %g1 ! get asi from instruction
2328 2308 and %g1, 0xFF, %g1 ! imm_asi field
2329 2309 1:
2330 2310 cmp %g1, ASI_P ! primary address space
2331 2311 be,a,pt %icc, 2f
2332 2312 nop
2333 2313 cmp %g1, ASI_PNF ! primary no fault address space
2334 2314 be,a,pt %icc, 2f
2335 2315 nop
2336 2316 cmp %g1, ASI_S ! secondary address space
2337 2317 be,a,pt %icc, 2f
2338 2318 nop
2339 2319 cmp %g1, ASI_SNF ! secondary no fault address space
2340 2320 bne,a,pn %icc, 3f
2341 2321 nop
2342 2322 2:
2343 2323 lduwa [%g5]ASI_USER, %g7 ! get first half of misaligned data
2344 2324 add %g5, 4, %g5 ! increment misaligned data address
2345 2325 lduwa [%g5]ASI_USER, %g5 ! get second half of misaligned data
2346 2326
2347 2327 sllx %g7, 32, %g7
2348 2328 or %g5, %g7, %g5 ! combine data
2349 2329 CPU_ADDR(%g7, %g1) ! save data on a per-cpu basis
2350 2330 stx %g5, [%g7 + CPU_TMP1] ! save in cpu_tmp1
2351 2331
2352 2332 srl %g6, 25, %g3 ! %g6 has the instruction
2353 2333 and %g3, 0x1F, %g3 ! %g3 has rd
2354 2334 LDDF_REG(%g3, %g7, %g4)
2355 2335
2356 2336 CPU_ADDR(%g1, %g4)
2357 2337 st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag
2358 2338 FAST_TRAP_DONE
2359 2339 3:
2360 2340 CPU_ADDR(%g1, %g4)
2361 2341 st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag
2362 2342 4:
2363 2343 set T_USER, %g3 ! trap type in %g3
2364 2344 or %g3, T_LDDF_ALIGN, %g3
2365 2345 mov %g5, %g2 ! misaligned vaddr in %g2
2366 2346 set fpu_trap, %g1 ! goto C for the little and
2367 2347 ba,pt %xcc, sys_trap ! no fault little asi's
2368 2348 sub %g0, 1, %g4
2369 2349
2370 2350 .stdf_exception_not_aligned:
2371 2351 /*
2372 2352 * Cheetah overwrites SFAR on a DTLB miss, hence read it now.
2373 2353 */
2374 2354 ldxa [MMU_SFAR]%asi, %g5 ! misaligned vaddr in %g5
2375 2355
2376 2356 #if defined(DEBUG) || defined(NEED_FPU_EXISTS)
2377 2357 sethi %hi(fpu_exists), %g7 ! check fpu_exists
2378 2358 ld [%g7 + %lo(fpu_exists)], %g3
2379 2359 brz,a,pn %g3, 4f
2380 2360 nop
2381 2361 #endif
2382 2362 CPU_ADDR(%g1, %g4)
2383 2363 or %g0, 1, %g4
2384 2364 st %g4, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag
2385 2365
2386 2366 rdpr %tpc, %g2
2387 2367 lda [%g2]ASI_AIUP, %g6 ! get the user's stdf instruction
2388 2368
2389 2369 srl %g6, 23, %g1 ! using stda or not?
2390 2370 and %g1, 1, %g1
2391 2371 brz,a,pt %g1, 2f ! check for stda instruction
2392 2372 nop
2393 2373 srl %g6, 13, %g1 ! check immflag
2394 2374 and %g1, 1, %g1
2395 2375 rdpr %tstate, %g2 ! %tstate in %g2
2396 2376 brnz,a,pn %g1, 1f
2397 2377 srl %g2, 31, %g1 ! get asi from %tstate
2398 2378 srl %g6, 5, %g1 ! get asi from instruction
2399 2379 and %g1, 0xFF, %g1 ! imm_asi field
2400 2380 1:
2401 2381 cmp %g1, ASI_P ! primary address space
2402 2382 be,a,pt %icc, 2f
2403 2383 nop
2404 2384 cmp %g1, ASI_S ! secondary address space
2405 2385 bne,a,pn %icc, 3f
2406 2386 nop
2407 2387 2:
2408 2388 srl %g6, 25, %g6
2409 2389 and %g6, 0x1F, %g6 ! %g6 has rd
2410 2390 CPU_ADDR(%g7, %g1)
2411 2391 STDF_REG(%g6, %g7, %g4) ! STDF_REG(REG, ADDR, TMP)
2412 2392
2413 2393 ldx [%g7 + CPU_TMP1], %g6
2414 2394 srlx %g6, 32, %g7
2415 2395 stuwa %g7, [%g5]ASI_USER ! first half
2416 2396 add %g5, 4, %g5 ! increment misaligned data address
2417 2397 stuwa %g6, [%g5]ASI_USER ! second half
2418 2398
2419 2399 CPU_ADDR(%g1, %g4)
2420 2400 st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag
2421 2401 FAST_TRAP_DONE
2422 2402 3:
2423 2403 CPU_ADDR(%g1, %g4)
2424 2404 st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag
2425 2405 4:
2426 2406 set T_USER, %g3 ! trap type in %g3
2427 2407 or %g3, T_STDF_ALIGN, %g3
2428 2408 mov %g5, %g2 ! misaligned vaddr in %g2
2429 2409 set fpu_trap, %g1 ! goto C for the little and
2430 2410 ba,pt %xcc, sys_trap ! nofault little asi's
2431 2411 sub %g0, 1, %g4
2432 2412
2433 2413 #ifdef DEBUG_USER_TRAPTRACECTL
2434 2414
2435 2415 .traptrace_freeze:
2436 2416 mov %l0, %g1 ; mov %l1, %g2 ; mov %l2, %g3 ; mov %l4, %g4
2437 2417 TT_TRACE_L(trace_win)
2438 2418 mov %g4, %l4 ; mov %g3, %l2 ; mov %g2, %l1 ; mov %g1, %l0
2439 2419 set trap_freeze, %g1
2440 2420 mov 1, %g2
2441 2421 st %g2, [%g1]
2442 2422 FAST_TRAP_DONE
2443 2423
2444 2424 .traptrace_unfreeze:
2445 2425 set trap_freeze, %g1
2446 2426 st %g0, [%g1]
2447 2427 mov %l0, %g1 ; mov %l1, %g2 ; mov %l2, %g3 ; mov %l4, %g4
2448 2428 TT_TRACE_L(trace_win)
2449 2429 mov %g4, %l4 ; mov %g3, %l2 ; mov %g2, %l1 ; mov %g1, %l0
2450 2430 FAST_TRAP_DONE
2451 2431
2452 2432 #endif /* DEBUG_USER_TRAPTRACECTL */
2453 2433
2454 2434 .getcc:
2455 2435 CPU_ADDR(%g1, %g2)
2456 2436 stx %o0, [%g1 + CPU_TMP1] ! save %o0
2457 2437 stx %o1, [%g1 + CPU_TMP2] ! save %o1
2458 2438 rdpr %tstate, %g3 ! get tstate
2459 2439 srlx %g3, PSR_TSTATE_CC_SHIFT, %o0 ! shift ccr to V8 psr
2460 2440 set PSR_ICC, %g2
2461 2441 and %o0, %g2, %o0 ! mask out the rest
2462 2442 srl %o0, PSR_ICC_SHIFT, %o0 ! right justify
2463 2443 rdpr %pstate, %o1
2464 2444 wrpr %o1, PSTATE_AG, %pstate ! get into normal globals
2465 2445 mov %o0, %g1 ! move ccr to normal %g1
2466 2446 wrpr %g0, %o1, %pstate ! back into alternate globals
2467 2447 ldx [%g1 + CPU_TMP1], %o0 ! restore %o0
2468 2448 ldx [%g1 + CPU_TMP2], %o1 ! restore %o1
2469 2449 FAST_TRAP_DONE
2470 2450
2471 2451 .setcc:
2472 2452 CPU_ADDR(%g1, %g2)
2473 2453 stx %o0, [%g1 + CPU_TMP1] ! save %o0
2474 2454 stx %o1, [%g1 + CPU_TMP2] ! save %o1
2475 2455 rdpr %pstate, %o0
2476 2456 wrpr %o0, PSTATE_AG, %pstate ! get into normal globals
2477 2457 mov %g1, %o1
2478 2458 wrpr %g0, %o0, %pstate ! back to alternates
2479 2459 sll %o1, PSR_ICC_SHIFT, %g2
2480 2460 set PSR_ICC, %g3
2481 2461 and %g2, %g3, %g2 ! mask out rest
2482 2462 sllx %g2, PSR_TSTATE_CC_SHIFT, %g2
2483 2463 rdpr %tstate, %g3 ! get tstate
2484 2464 srl %g3, 0, %g3 ! clear upper word
2485 2465 or %g3, %g2, %g3 ! or in new bits
2486 2466 wrpr %g3, %tstate
2487 2467 ldx [%g1 + CPU_TMP1], %o0 ! restore %o0
2488 2468 ldx [%g1 + CPU_TMP2], %o1 ! restore %o1
2489 2469 FAST_TRAP_DONE
2490 2470
2491 2471 /*
2492 2472 * getpsr(void)
2493 2473 * Note that the xcc part of the ccr is not provided.
2494 2474 * The V8 code shows why the V9 trap is not faster:
2495 2475 * #define GETPSR_TRAP() \
2496 2476 * mov %psr, %i0; jmp %l2; rett %l2+4; nop;
2497 2477 */
2498 2478
2499 2479 .type .getpsr, #function
2500 2480 .getpsr:
2501 2481 rdpr %tstate, %g1 ! get tstate
2502 2482 srlx %g1, PSR_TSTATE_CC_SHIFT, %o0 ! shift ccr to V8 psr
2503 2483 set PSR_ICC, %g2
2504 2484 and %o0, %g2, %o0 ! mask out the rest
2505 2485
2506 2486 rd %fprs, %g1 ! get fprs
2507 2487 and %g1, FPRS_FEF, %g2 ! mask out dirty upper/lower
2508 2488 sllx %g2, PSR_FPRS_FEF_SHIFT, %g2 ! shift fef to V8 psr.ef
2509 2489 or %o0, %g2, %o0 ! or result into psr.ef
2510 2490
2511 2491 set V9_PSR_IMPLVER, %g2 ! SI assigned impl/ver: 0xef
2512 2492 or %o0, %g2, %o0 ! or psr.impl/ver
2513 2493 FAST_TRAP_DONE
2514 2494 SET_SIZE(.getpsr)
2515 2495
2516 2496 /*
2517 2497 * setpsr(newpsr)
2518 2498 * Note that there is no support for ccr.xcc in the V9 code.
2519 2499 */
2520 2500
2521 2501 .type .setpsr, #function
2522 2502 .setpsr:
2523 2503 rdpr %tstate, %g1 ! get tstate
2524 2504 ! setx TSTATE_V8_UBITS, %g2
2525 2505 or %g0, CCR_ICC, %g3
2526 2506 sllx %g3, TSTATE_CCR_SHIFT, %g2
2527 2507
2528 2508 andn %g1, %g2, %g1 ! zero current user bits
2529 2509 set PSR_ICC, %g2
2530 2510 and %g2, %o0, %g2 ! clear all but psr.icc bits
2531 2511 sllx %g2, PSR_TSTATE_CC_SHIFT, %g3 ! shift to tstate.ccr.icc
2532 2512 wrpr %g1, %g3, %tstate ! write tstate
2533 2513
2534 2514 set PSR_EF, %g2
2535 2515 and %g2, %o0, %g2 ! clear all but fp enable bit
2536 2516 srlx %g2, PSR_FPRS_FEF_SHIFT, %g4 ! shift ef to V9 fprs.fef
2537 2517 wr %g0, %g4, %fprs ! write fprs
2538 2518
2539 2519 CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1
2540 2520 ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer
2541 2521 ldn [%g2 + T_LWP], %g3 ! load klwp pointer
2542 2522 ldn [%g3 + LWP_FPU], %g2 ! get lwp_fpu pointer
2543 2523 stuw %g4, [%g2 + FPU_FPRS] ! write fef value to fpu_fprs
2544 2524 srlx %g4, 2, %g4 ! shift fef value to bit 0
2545 2525 stub %g4, [%g2 + FPU_EN] ! write fef value to fpu_en
2546 2526 FAST_TRAP_DONE
2547 2527 SET_SIZE(.setpsr)
2548 2528
2549 2529 /*
2550 2530 * getlgrp
2551 2531 * get home lgrpid on which the calling thread is currently executing.
2552 2532 */
2553 2533 .type .getlgrp, #function
2554 2534 .getlgrp:
2555 2535 CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2
2556 2536 ld [%g1 + CPU_ID], %o0 ! load cpu_id
2557 2537 ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer
2558 2538 ldn [%g2 + T_LPL], %g2 ! load lpl pointer
2559 2539 ld [%g2 + LPL_LGRPID], %g1 ! load lpl_lgrpid
2560 2540 sra %g1, 0, %o1
2561 2541 FAST_TRAP_DONE
2562 2542 SET_SIZE(.getlgrp)
2563 2543
2564 2544 /*
2565 2545 * Entry for old 4.x trap (trap 0).
2566 2546 */
2567 2547 ENTRY_NP(syscall_trap_4x)
2568 2548 CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2
2569 2549 ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer
2570 2550 ldn [%g2 + T_LWP], %g2 ! load klwp pointer
2571 2551 ld [%g2 + PCB_TRAP0], %g2 ! lwp->lwp_pcb.pcb_trap0addr
2572 2552 brz,pn %g2, 1f ! has it been set?
2573 2553 st %l0, [%g1 + CPU_TMP1] ! delay - save some locals
2574 2554 st %l1, [%g1 + CPU_TMP2]
2575 2555 rdpr %tnpc, %l1 ! save old tnpc
2576 2556 wrpr %g0, %g2, %tnpc ! setup tnpc
2577 2557
2578 2558 rdpr %pstate, %l0
2579 2559 wrpr %l0, PSTATE_AG, %pstate ! switch to normal globals
2580 2560 mov %l1, %g6 ! pass tnpc to user code in %g6
2581 2561 wrpr %l0, %g0, %pstate ! switch back to alternate globals
2582 2562
2583 2563 ! Note that %g1 still contains CPU struct addr
2584 2564 ld [%g1 + CPU_TMP2], %l1 ! restore locals
2585 2565 ld [%g1 + CPU_TMP1], %l0
2586 2566 FAST_TRAP_DONE_CHK_INTR
2587 2567 1:
2588 2568 mov %g1, %l0
2589 2569 st %l1, [%g1 + CPU_TMP2]
2590 2570 rdpr %pstate, %l1
2591 2571 wrpr %l1, PSTATE_AG, %pstate
2592 2572 !
2593 2573 ! check for old syscall mmap which is the only different one which
2594 2574 ! must be the same. Others are handled in the compatibility library.
2595 2575 !
2596 2576 cmp %g1, OSYS_mmap ! compare to old 4.x mmap
2597 2577 movz %icc, SYS_mmap, %g1
2598 2578 wrpr %g0, %l1, %pstate
2599 2579 ld [%l0 + CPU_TMP2], %l1 ! restore locals
2600 2580 ld [%l0 + CPU_TMP1], %l0
2601 2581 SYSCALL(syscall_trap32)
2602 2582 SET_SIZE(syscall_trap_4x)
2603 2583
2604 2584 /*
2605 2585 * Handler for software trap 9.
2606 2586 * Set trap0 emulation address for old 4.x system call trap.
2607 2587 * XXX - this should be a system call.
2608 2588 */
2609 2589 ENTRY_NP(set_trap0_addr)
2610 2590 CPU_ADDR(%g1, %g2) ! load CPU struct addr to %g1 using %g2
2611 2591 ldn [%g1 + CPU_THREAD], %g2 ! load thread pointer
2612 2592 ldn [%g2 + T_LWP], %g2 ! load klwp pointer
2613 2593 st %l0, [%g1 + CPU_TMP1] ! save some locals
2614 2594 st %l1, [%g1 + CPU_TMP2]
2615 2595 rdpr %pstate, %l0
2616 2596 wrpr %l0, PSTATE_AG, %pstate
2617 2597 mov %g1, %l1
2618 2598 wrpr %g0, %l0, %pstate
2619 2599 andn %l1, 3, %l1 ! force alignment
2620 2600 st %l1, [%g2 + PCB_TRAP0] ! lwp->lwp_pcb.pcb_trap0addr
2621 2601 ld [%g1 + CPU_TMP1], %l0 ! restore locals
2622 2602 ld [%g1 + CPU_TMP2], %l1
2623 2603 FAST_TRAP_DONE
2624 2604 SET_SIZE(set_trap0_addr)
2625 2605
2626 2606 /*
2627 2607 * mmu_trap_tl1
2628 2608 * trap handler for unexpected mmu traps.
2629 2609 * simply checks if the trap was a user lddf/stdf alignment trap, in which
2630 2610 * case we go to fpu_trap or a user trap from the window handler, in which
2631 2611 * case we go save the state on the pcb. Otherwise, we go to ptl1_panic.
2632 2612 */
2633 2613 .type mmu_trap_tl1, #function
2634 2614 mmu_trap_tl1:
2635 2615 #ifdef TRAPTRACE
2636 2616 TRACE_PTR(%g5, %g6)
2637 2617 GET_TRACE_TICK(%g6, %g7)
2638 2618 stxa %g6, [%g5 + TRAP_ENT_TICK]%asi
2639 2619 rdpr %tl, %g6
2640 2620 stha %g6, [%g5 + TRAP_ENT_TL]%asi
2641 2621 rdpr %tt, %g6
2642 2622 stha %g6, [%g5 + TRAP_ENT_TT]%asi
2643 2623 rdpr %tstate, %g6
2644 2624 stxa %g6, [%g5 + TRAP_ENT_TSTATE]%asi
2645 2625 stna %sp, [%g5 + TRAP_ENT_SP]%asi
2646 2626 stna %g0, [%g5 + TRAP_ENT_TR]%asi
2647 2627 rdpr %tpc, %g6
2648 2628 stna %g6, [%g5 + TRAP_ENT_TPC]%asi
2649 2629 set MMU_SFAR, %g6
2650 2630 ldxa [%g6]ASI_DMMU, %g6
2651 2631 stxa %g6, [%g5 + TRAP_ENT_F1]%asi
2652 2632 CPU_PADDR(%g7, %g6);
2653 2633 add %g7, CPU_TL1_HDLR, %g7
2654 2634 lda [%g7]ASI_MEM, %g6
2655 2635 stxa %g6, [%g5 + TRAP_ENT_F2]%asi
2656 2636 set 0xdeadbeef, %g6
2657 2637 stna %g6, [%g5 + TRAP_ENT_F3]%asi
2658 2638 stna %g6, [%g5 + TRAP_ENT_F4]%asi
2659 2639 TRACE_NEXT(%g5, %g6, %g7)
2660 2640 #endif /* TRAPTRACE */
2661 2641
2662 2642 GET_CPU_IMPL(%g5)
2663 2643 cmp %g5, PANTHER_IMPL
2664 2644 bne mmu_trap_tl1_4
2665 2645 nop
2666 2646 rdpr %tt, %g5
2667 2647 cmp %g5, T_DATA_EXCEPTION
2668 2648 bne mmu_trap_tl1_4
2669 2649 nop
2670 2650 wr %g0, ASI_DMMU, %asi
2671 2651 ldxa [MMU_SFSR]%asi, %g5
2672 2652 mov 1, %g6
2673 2653 sllx %g6, PN_SFSR_PARITY_SHIFT, %g6
2674 2654 andcc %g5, %g6, %g0
2675 2655 bz mmu_trap_tl1_4
2676 2656
2677 2657 /*
2678 2658 * We are running on a Panther and have hit a DTLB parity error.
2679 2659 */
2680 2660 ldxa [MMU_TAG_ACCESS]%asi, %g2
2681 2661 mov %g5, %g3
2682 2662 ba,pt %xcc, .mmu_exception_is_tlb_parity
2683 2663 mov T_DATA_EXCEPTION, %g1
2684 2664
2685 2665 mmu_trap_tl1_4:
2686 2666 CPU_PADDR(%g7, %g6);
2687 2667 add %g7, CPU_TL1_HDLR, %g7 ! %g7 = &cpu_m.tl1_hdlr (PA)
2688 2668 /*
2689 2669 * AM is cleared on trap, so addresses are 64 bit
2690 2670 */
2691 2671 lda [%g7]ASI_MEM, %g6
2692 2672 brz,a,pt %g6, 1f
2693 2673 nop
2694 2674 /*
2695 2675 * We are going to update cpu_m.tl1_hdlr using physical address.
2696 2676 * Flush the D$ line, so that stale data won't be accessed later.
2697 2677 */
2698 2678 CPU_ADDR(%g6, %g5)
2699 2679 add %g6, CPU_TL1_HDLR, %g6 ! %g6 = &cpu_m.tl1_hdlr (VA)
2700 2680 GET_CPU_IMPL(%g5)
2701 2681 cmp %g5, CHEETAH_IMPL
2702 2682 bl,pt %icc, 3f
2703 2683 cmp %g5, SPITFIRE_IMPL
2704 2684 stxa %g0, [%g7]ASI_DC_INVAL
2705 2685 membar #Sync
2706 2686 ba,pt %xcc, 2f
2707 2687 nop
2708 2688 3:
2709 2689 bl,pt %icc, 2f
2710 2690 sethi %hi(dcache_line_mask), %g5
2711 2691 ld [%g5 + %lo(dcache_line_mask)], %g5
2712 2692 and %g6, %g5, %g5
2713 2693 stxa %g0, [%g5]ASI_DC_TAG
2714 2694 membar #Sync
2715 2695 2:
2716 2696 sta %g0, [%g7]ASI_MEM
2717 2697 SWITCH_GLOBALS ! back to mmu globals
2718 2698 ba,a,pt %xcc, sfmmu_mmu_trap ! handle page faults
2719 2699 1:
2720 2700 rdpr %tt, %g5
2721 2701 rdpr %tl, %g7
2722 2702 sub %g7, 1, %g6
2723 2703 wrpr %g6, %tl
2724 2704 rdpr %tt, %g6
2725 2705 wrpr %g7, %tl
2726 2706 and %g6, WTRAP_TTMASK, %g6
2727 2707 cmp %g6, WTRAP_TYPE
2728 2708 bne,a,pn %xcc, ptl1_panic
2729 2709 mov PTL1_BAD_MMUTRAP, %g1
2730 2710 rdpr %tpc, %g7
2731 2711 /* tpc should be in the trap table */
2732 2712 set trap_table, %g6
2733 2713 cmp %g7, %g6
2734 2714 blt,a,pn %xcc, ptl1_panic
2735 2715 mov PTL1_BAD_MMUTRAP, %g1
2736 2716 set etrap_table, %g6
2737 2717 cmp %g7, %g6
2738 2718 bge,a,pn %xcc, ptl1_panic
2739 2719 mov PTL1_BAD_MMUTRAP, %g1
2740 2720 cmp %g5, T_ALIGNMENT
2741 2721 move %icc, MMU_SFAR, %g6
2742 2722 movne %icc, MMU_TAG_ACCESS, %g6
2743 2723 ldxa [%g6]ASI_DMMU, %g6
2744 2724 andn %g7, WTRAP_ALIGN, %g7 /* 128 byte aligned */
2745 2725 add %g7, WTRAP_FAULTOFF, %g7
2746 2726 wrpr %g0, %g7, %tnpc
2747 2727 done
2748 2728 SET_SIZE(mmu_trap_tl1)
2749 2729
2750 2730 /*
2751 2731 * Several traps use kmdb_trap and kmdb_trap_tl1 as their handlers. These
2752 2732 * traps are valid only when kmdb is loaded. When the debugger is active,
2753 2733 * the code below is rewritten to transfer control to the appropriate
2754 2734 * debugger entry points.
2755 2735 */
2756 2736 .global kmdb_trap
2757 2737 .align 8
2758 2738 kmdb_trap:
2759 2739 ba,a trap_table0
2760 2740 jmp %g1 + 0
2761 2741 nop
2762 2742
2763 2743 .global kmdb_trap_tl1
2764 2744 .align 8
2765 2745 kmdb_trap_tl1:
2766 2746 ba,a trap_table0
2767 2747 jmp %g1 + 0
2768 2748 nop
2769 2749
2770 2750 /*
2771 2751 * This entry is copied from OBP's trap table during boot.
2772 2752 */
2773 2753 .global obp_bpt
2774 2754 .align 8
2775 2755 obp_bpt:
2776 2756 NOT
2777 2757
2778 2758 /*
2779 2759 * if kernel, set PCONTEXT to 0 for debuggers
2780 2760 * if user, clear nucleus page sizes
2781 2761 */
2782 2762 .global kctx_obp_bpt
2783 2763 kctx_obp_bpt:
2784 2764 set obp_bpt, %g2
2785 2765 1:
2786 2766 #ifndef _OPL
2787 2767 mov MMU_PCONTEXT, %g1
2788 2768 ldxa [%g1]ASI_DMMU, %g1
2789 2769 srlx %g1, CTXREG_NEXT_SHIFT, %g3
2790 2770 brz,pt %g3, 3f ! nucleus pgsz is 0, no problem
2791 2771 sllx %g3, CTXREG_NEXT_SHIFT, %g3
2792 2772 set CTXREG_CTX_MASK, %g4 ! check Pcontext
2793 2773 btst %g4, %g1
2794 2774 bz,a,pt %xcc, 2f
2795 2775 clr %g3 ! kernel: PCONTEXT=0
2796 2776 xor %g3, %g1, %g3 ! user: clr N_pgsz0/1 bits
2797 2777 2:
2798 2778 set DEMAP_ALL_TYPE, %g1
2799 2779 stxa %g0, [%g1]ASI_DTLB_DEMAP
2800 2780 stxa %g0, [%g1]ASI_ITLB_DEMAP
2801 2781 mov MMU_PCONTEXT, %g1
2802 2782 stxa %g3, [%g1]ASI_DMMU
2803 2783 membar #Sync
2804 2784 sethi %hi(FLUSH_ADDR), %g1
2805 2785 flush %g1 ! flush required by immu
2806 2786 #endif /* _OPL */
2807 2787 3:
2808 2788 jmp %g2
2809 2789 nop
2810 2790
2811 2791
2812 2792 #ifdef TRAPTRACE
2813 2793 /*
2814 2794 * TRAPTRACE support.
2815 2795 * labels here are branched to with "rd %pc, %g7" in the delay slot.
2816 2796 * Return is done by "jmp %g7 + 4".
2817 2797 */
2818 2798
2819 2799 trace_gen:
2820 2800 TRACE_PTR(%g3, %g6)
2821 2801 GET_TRACE_TICK(%g6, %g4)
2822 2802 stxa %g6, [%g3 + TRAP_ENT_TICK]%asi
2823 2803 rdpr %tl, %g6
2824 2804 stha %g6, [%g3 + TRAP_ENT_TL]%asi
2825 2805 rdpr %tt, %g6
2826 2806 stha %g6, [%g3 + TRAP_ENT_TT]%asi
2827 2807 rdpr %tstate, %g6
2828 2808 stxa %g6, [%g3 + TRAP_ENT_TSTATE]%asi
2829 2809 stna %sp, [%g3 + TRAP_ENT_SP]%asi
2830 2810 rdpr %tpc, %g6
2831 2811 stna %g6, [%g3 + TRAP_ENT_TPC]%asi
2832 2812 TRACE_NEXT(%g3, %g4, %g5)
2833 2813 jmp %g7 + 4
2834 2814 nop
2835 2815
2836 2816 trace_win:
2837 2817 TRACE_WIN_INFO(0, %l0, %l1, %l2)
2838 2818 ! Keep the locals as clean as possible, caller cleans %l4
2839 2819 clr %l2
2840 2820 clr %l1
2841 2821 jmp %l4 + 4
2842 2822 clr %l0
2843 2823
2844 2824 /*
2845 2825 * Trace a tsb hit
2846 2826 * g1 = tsbe pointer (in/clobbered)
2847 2827 * g2 = tag access register (in)
2848 2828 * g3 - g4 = scratch (clobbered)
2849 2829 * g5 = tsbe data (in)
2850 2830 * g6 = scratch (clobbered)
2851 2831 * g7 = pc we jumped here from (in)
2852 2832 */
2853 2833
2854 2834 ! Do not disturb %g5, it will be used after the trace
2855 2835 ALTENTRY(trace_tsbhit)
2856 2836 TRACE_TSBHIT(0)
2857 2837 jmp %g7 + 4
2858 2838 nop
2859 2839
2860 2840 /*
2861 2841 * Trace a TSB miss
2862 2842 *
2863 2843 * g1 = tsb8k pointer (in)
2864 2844 * g2 = tag access register (in)
2865 2845 * g3 = tsb4m pointer (in)
2866 2846 * g4 = tsbe tag (in/clobbered)
2867 2847 * g5 - g6 = scratch (clobbered)
2868 2848 * g7 = pc we jumped here from (in)
2869 2849 */
2870 2850 .global trace_tsbmiss
2871 2851 trace_tsbmiss:
2872 2852 membar #Sync
2873 2853 sethi %hi(FLUSH_ADDR), %g6
2874 2854 flush %g6
2875 2855 TRACE_PTR(%g5, %g6)
2876 2856 stxa %g2, [%g5 + TRAP_ENT_SP]%asi ! tag access
2877 2857 stxa %g4, [%g5 + TRAP_ENT_F1]%asi ! tsb tag
2878 2858 GET_TRACE_TICK(%g6, %g4)
2879 2859 stxa %g6, [%g5 + TRAP_ENT_TICK]%asi
2880 2860 rdpr %tnpc, %g6
2881 2861 stxa %g6, [%g5 + TRAP_ENT_F2]%asi
2882 2862 stna %g1, [%g5 + TRAP_ENT_F3]%asi ! tsb8k pointer
2883 2863 srlx %g1, 32, %g6
2884 2864 stna %g6, [%g5 + TRAP_ENT_F4]%asi ! huh?
2885 2865 rdpr %tpc, %g6
2886 2866 stna %g6, [%g5 + TRAP_ENT_TPC]%asi
2887 2867 rdpr %tl, %g6
2888 2868 stha %g6, [%g5 + TRAP_ENT_TL]%asi
2889 2869 rdpr %tt, %g6
2890 2870 or %g6, TT_MMU_MISS, %g4
2891 2871 stha %g4, [%g5 + TRAP_ENT_TT]%asi
2892 2872 cmp %g6, FAST_IMMU_MISS_TT
2893 2873 be,a %icc, 1f
2894 2874 ldxa [%g0]ASI_IMMU, %g6
2895 2875 ldxa [%g0]ASI_DMMU, %g6
2896 2876 1: stxa %g6, [%g5 + TRAP_ENT_TSTATE]%asi ! tag target
2897 2877 stxa %g3, [%g5 + TRAP_ENT_TR]%asi ! tsb4m pointer
2898 2878 TRACE_NEXT(%g5, %g4, %g6)
2899 2879 jmp %g7 + 4
2900 2880 nop
2901 2881
2902 2882 /*
2903 2883 * g2 = tag access register (in)
2904 2884 * g3 = ctx number (in)
2905 2885 */
2906 2886 trace_dataprot:
2907 2887 membar #Sync
2908 2888 sethi %hi(FLUSH_ADDR), %g6
2909 2889 flush %g6
2910 2890 TRACE_PTR(%g1, %g6)
2911 2891 GET_TRACE_TICK(%g6, %g5)
2912 2892 stxa %g6, [%g1 + TRAP_ENT_TICK]%asi
2913 2893 rdpr %tpc, %g6
2914 2894 stna %g6, [%g1 + TRAP_ENT_TPC]%asi
2915 2895 rdpr %tstate, %g6
2916 2896 stxa %g6, [%g1 + TRAP_ENT_TSTATE]%asi
2917 2897 stxa %g2, [%g1 + TRAP_ENT_SP]%asi ! tag access reg
2918 2898 stxa %g0, [%g1 + TRAP_ENT_TR]%asi
2919 2899 stxa %g0, [%g1 + TRAP_ENT_F1]%asi
2920 2900 stxa %g0, [%g1 + TRAP_ENT_F2]%asi
2921 2901 stxa %g0, [%g1 + TRAP_ENT_F3]%asi
2922 2902 stxa %g0, [%g1 + TRAP_ENT_F4]%asi
2923 2903 rdpr %tl, %g6
2924 2904 stha %g6, [%g1 + TRAP_ENT_TL]%asi
2925 2905 rdpr %tt, %g6
2926 2906 stha %g6, [%g1 + TRAP_ENT_TT]%asi
2927 2907 TRACE_NEXT(%g1, %g4, %g5)
2928 2908 jmp %g7 + 4
2929 2909 nop
2930 2910
2931 2911 #endif /* TRAPTRACE */
2932 2912
2933 2913 .align 32
2934 2914 .global pil15_epilogue
2935 2915 pil15_epilogue:
2936 2916 ba pil_interrupt_common
2937 2917 nop
2938 2918 .align 32
2939 2919
2940 2920 /*
2941 2921 * fast_trap_done, fast_trap_done_chk_intr:
2942 2922 *
2943 2923 * Due to the design of UltraSPARC pipeline, pending interrupts are not
2944 2924 * taken immediately after a RETRY or DONE instruction which causes IE to
2945 2925 * go from 0 to 1. Instead, the instruction at %tpc or %tnpc is allowed
2946 2926 * to execute first before taking any interrupts. If that instruction
2947 2927 * results in other traps, and if the corresponding trap handler runs
2948 2928 * entirely at TL=1 with interrupts disabled, then pending interrupts
2949 2929 * won't be taken until after yet another instruction following the %tpc
2950 2930 * or %tnpc.
2951 2931 *
2952 2932 * A malicious user program can use this feature to block out interrupts
2953 2933 * for extended durations, which can result in send_mondo_timeout kernel
2954 2934 * panic.
2955 2935 *
2956 2936 * This problem is addressed by servicing any pending interrupts via
2957 2937 * sys_trap before returning back to the user mode from a fast trap
2958 2938 * handler. The "done" instruction within a fast trap handler, which
2959 2939 * runs entirely at TL=1 with interrupts disabled, is replaced with the
2960 2940 * FAST_TRAP_DONE macro, which branches control to this fast_trap_done
2961 2941 * entry point.
2962 2942 *
2963 2943 * We check for any pending interrupts here and force a sys_trap to
2964 2944 * service those interrupts, if any. To minimize overhead, pending
2965 2945 * interrupts are checked if the %tpc happens to be at 16K boundary,
2966 2946 * which allows a malicious program to execute at most 4K consecutive
2967 2947 * instructions before we service any pending interrupts. If a worst
2968 2948 * case fast trap handler takes about 2 usec, then interrupts will be
2969 2949 * blocked for at most 8 msec, less than a clock tick.
2970 2950 *
2971 2951 * For the cases where we don't know if the %tpc will cross a 16K
2972 2952 * boundary, we can't use the above optimization and always process
2973 2953 * any pending interrupts via fast_frap_done_chk_intr entry point.
2974 2954 *
2975 2955 * Entry Conditions:
2976 2956 * %pstate am:0 priv:1 ie:0
2977 2957 * globals are AG (not normal globals)
2978 2958 */
2979 2959
2980 2960 .global fast_trap_done, fast_trap_done_chk_intr
2981 2961 fast_trap_done:
2982 2962 rdpr %tpc, %g5
2983 2963 sethi %hi(0xffffc000), %g6 ! 1's complement of 0x3fff
2984 2964 andncc %g5, %g6, %g0 ! check lower 14 bits of %tpc
2985 2965 bz,a,pn %icc, 1f ! branch if zero (lower 32 bits only)
2986 2966 ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g5
2987 2967 done
2988 2968
2989 2969 ALTENTRY(fast_trap_done_check_interrupts)
2990 2970 fast_trap_done_chk_intr:
2991 2971 ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g5
2992 2972
2993 2973 1: rd SOFTINT, %g6
2994 2974 and %g5, IRSR_BUSY, %g5
2995 2975 orcc %g5, %g6, %g0
2996 2976 bnz,pn %xcc, 2f ! branch if any pending intr
2997 2977 nop
2998 2978 done
2999 2979
3000 2980 2:
3001 2981 /*
3002 2982 * We get here if there are any pending interrupts.
3003 2983 * Adjust %tpc/%tnpc as we'll be resuming via "retry"
3004 2984 * instruction.
3005 2985 */
3006 2986 rdpr %tnpc, %g5
3007 2987 wrpr %g0, %g5, %tpc
3008 2988 add %g5, 4, %g5
3009 2989 wrpr %g0, %g5, %tnpc
3010 2990
3011 2991 /*
3012 2992 * Force a dummy sys_trap call so that interrupts can be serviced.
3013 2993 */
3014 2994 set fast_trap_dummy_call, %g1
3015 2995 ba,pt %xcc, sys_trap
3016 2996 mov -1, %g4
3017 2997
3018 2998 fast_trap_dummy_call:
3019 2999 retl
3020 3000 nop
3021 3001
3022 3002 /*
3023 3003 * Currently the brand syscall interposition code is not enabled by
3024 3004 * default. Instead, when a branded zone is first booted the brand
3025 3005 * infrastructure will patch the trap table so that the syscall
3026 3006 * entry points are redirected to syscall_wrapper32 and syscall_wrapper
3027 3007 * for ILP32 and LP64 syscalls respectively. this is done in
3028 3008 * brand_plat_interposition_enable(). Note that the syscall wrappers
3029 3009 * below do not collect any trap trace data since the syscall hot patch
3030 3010 * points are reached after trap trace data has already been collected.
3031 3011 */
3032 3012 #define BRAND_CALLBACK(callback_id) \
3033 3013 CPU_ADDR(%g2, %g1) /* load CPU struct addr to %g2 */ ;\
3034 3014 ldn [%g2 + CPU_THREAD], %g3 /* load thread pointer */ ;\
3035 3015 ldn [%g3 + T_PROCP], %g3 /* get proc pointer */ ;\
3036 3016 ldn [%g3 + P_BRAND], %g3 /* get brand pointer */ ;\
3037 3017 brz %g3, 1f /* No brand? No callback. */ ;\
3038 3018 nop ;\
3039 3019 ldn [%g3 + B_MACHOPS], %g3 /* get machops list */ ;\
3040 3020 ldn [%g3 + (callback_id << 3)], %g3 ;\
3041 3021 brz %g3, 1f ;\
3042 3022 /* \
3043 3023 * This isn't pretty. We want a low-latency way for the callback \
3044 3024 * routine to decline to do anything. We just pass in an address \
3045 3025 * the routine can directly jmp back to, pretending that nothing \
3046 3026 * has happened. \
3047 3027 * \
3048 3028 * %g1: return address (where the brand handler jumps back to) \
3049 3029 * %g2: address of CPU structure \
3050 3030 * %g3: address of brand handler (where we will jump to) \
3051 3031 */ \
3052 3032 mov %pc, %g1 ;\
3053 3033 add %g1, 16, %g1 ;\
3054 3034 jmp %g3 ;\
3055 3035 nop ;\
3056 3036 1:
3057 3037
↓ open down ↓ |
1719 lines elided |
↑ open up ↑ |
3058 3038 ENTRY_NP(syscall_wrapper32)
3059 3039 BRAND_CALLBACK(BRAND_CB_SYSCALL32)
3060 3040 SYSCALL_NOTT(syscall_trap32)
3061 3041 SET_SIZE(syscall_wrapper32)
3062 3042
3063 3043 ENTRY_NP(syscall_wrapper)
3064 3044 BRAND_CALLBACK(BRAND_CB_SYSCALL)
3065 3045 SYSCALL_NOTT(syscall_trap)
3066 3046 SET_SIZE(syscall_wrapper)
3067 3047
3068 -#endif /* lint */
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX