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