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