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 * Assembly code support for the Olympus-C module 26 */ 27 28 #if !defined(lint) 29 #include "assym.h" 30 #endif /* lint */ 31 32 #include <sys/asm_linkage.h> 33 #include <sys/mmu.h> 34 #include <vm/hat_sfmmu.h> 35 #include <sys/machparam.h> 36 #include <sys/machcpuvar.h> 37 #include <sys/machthread.h> 38 #include <sys/machtrap.h> 39 #include <sys/privregs.h> 40 #include <sys/asm_linkage.h> 41 #include <sys/trap.h> 42 #include <sys/opl_olympus_regs.h> 43 #include <sys/opl_module.h> 44 #include <sys/xc_impl.h> 45 #include <sys/intreg.h> 46 #include <sys/async.h> 47 #include <sys/clock.h> 48 #include <sys/cmpregs.h> 49 50 #ifdef TRAPTRACE 51 #include <sys/traptrace.h> 52 #endif /* TRAPTRACE */ 53 54 /* 55 * Macro that flushes the entire Ecache. 56 * 57 * arg1 = ecache size 58 * arg2 = ecache linesize 59 * arg3 = ecache flush address - Not used for olympus-C 60 */ 61 #define ECACHE_FLUSHALL(arg1, arg2, arg3, tmp1) \ 62 mov ASI_L2_CTRL_U2_FLUSH, arg1; \ 63 mov ASI_L2_CTRL_RW_ADDR, arg2; \ 64 stxa arg1, [arg2]ASI_L2_CTRL 65 66 /* 67 * SPARC64-VI MMU and Cache operations. 68 */ 69 70 #if defined(lint) 71 72 /* ARGSUSED */ 73 void 74 vtag_flushpage(caddr_t vaddr, uint64_t sfmmup) 75 {} 76 77 #else /* lint */ 78 79 ENTRY_NP(vtag_flushpage) 80 /* 81 * flush page from the tlb 82 * 83 * %o0 = vaddr 84 * %o1 = sfmmup 85 */ 86 rdpr %pstate, %o5 87 #ifdef DEBUG 88 PANIC_IF_INTR_DISABLED_PSTR(%o5, opl_di_l3, %g1) 89 #endif /* DEBUG */ 90 /* 91 * disable ints 92 */ 93 andn %o5, PSTATE_IE, %o4 94 wrpr %o4, 0, %pstate 95 96 /* 97 * Then, blow out the tlb 98 * Interrupts are disabled to prevent the primary ctx register 99 * from changing underneath us. 100 */ 101 sethi %hi(ksfmmup), %o3 102 ldx [%o3 + %lo(ksfmmup)], %o3 103 cmp %o3, %o1 104 bne,pt %xcc, 1f ! if not kernel as, go to 1 105 sethi %hi(FLUSH_ADDR), %o3 106 /* 107 * For Kernel demaps use primary. type = page implicitly 108 */ 109 stxa %g0, [%o0]ASI_DTLB_DEMAP /* dmmu flush for KCONTEXT */ 110 stxa %g0, [%o0]ASI_ITLB_DEMAP /* immu flush for KCONTEXT */ 111 flush %o3 112 retl 113 wrpr %g0, %o5, %pstate /* enable interrupts */ 114 1: 115 /* 116 * User demap. We need to set the primary context properly. 117 * Secondary context cannot be used for SPARC64-VI IMMU. 118 * %o0 = vaddr 119 * %o1 = sfmmup 120 * %o3 = FLUSH_ADDR 121 */ 122 SFMMU_CPU_CNUM(%o1, %g1, %g2) ! %g1 = sfmmu cnum on this CPU 123 124 ldub [%o1 + SFMMU_CEXT], %o4 ! %o4 = sfmmup->sfmmu_cext 125 sll %o4, CTXREG_EXT_SHIFT, %o4 126 or %g1, %o4, %g1 ! %g1 = primary pgsz | cnum 127 128 wrpr %g0, 1, %tl 129 set MMU_PCONTEXT, %o4 130 or DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %o0, %o0 131 ldxa [%o4]ASI_DMMU, %o2 ! %o2 = save old ctxnum 132 srlx %o2, CTXREG_NEXT_SHIFT, %o1 ! need to preserve nucleus pgsz 133 sllx %o1, CTXREG_NEXT_SHIFT, %o1 ! %o1 = nucleus pgsz 134 or %g1, %o1, %g1 ! %g1 = nucleus pgsz | primary pgsz | cnum 135 stxa %g1, [%o4]ASI_DMMU ! wr new ctxum 136 137 stxa %g0, [%o0]ASI_DTLB_DEMAP 138 stxa %g0, [%o0]ASI_ITLB_DEMAP 139 stxa %o2, [%o4]ASI_DMMU /* restore old ctxnum */ 140 flush %o3 141 wrpr %g0, 0, %tl 142 143 retl 144 wrpr %g0, %o5, %pstate /* enable interrupts */ 145 SET_SIZE(vtag_flushpage) 146 147 #endif /* lint */ 148 149 150 #if defined(lint) 151 152 void 153 vtag_flushall(void) 154 {} 155 156 #else /* lint */ 157 158 ENTRY_NP2(vtag_flushall, demap_all) 159 /* 160 * flush the tlb 161 */ 162 sethi %hi(FLUSH_ADDR), %o3 163 set DEMAP_ALL_TYPE, %g1 164 stxa %g0, [%g1]ASI_DTLB_DEMAP 165 stxa %g0, [%g1]ASI_ITLB_DEMAP 166 flush %o3 167 retl 168 nop 169 SET_SIZE(demap_all) 170 SET_SIZE(vtag_flushall) 171 172 #endif /* lint */ 173 174 175 #if defined(lint) 176 177 /* ARGSUSED */ 178 void 179 vtag_flushpage_tl1(uint64_t vaddr, uint64_t sfmmup) 180 {} 181 182 #else /* lint */ 183 184 ENTRY_NP(vtag_flushpage_tl1) 185 /* 186 * x-trap to flush page from tlb and tsb 187 * 188 * %g1 = vaddr, zero-extended on 32-bit kernel 189 * %g2 = sfmmup 190 * 191 * assumes TSBE_TAG = 0 192 */ 193 srln %g1, MMU_PAGESHIFT, %g1 194 195 sethi %hi(ksfmmup), %g3 196 ldx [%g3 + %lo(ksfmmup)], %g3 197 cmp %g3, %g2 198 bne,pt %xcc, 1f ! if not kernel as, go to 1 199 slln %g1, MMU_PAGESHIFT, %g1 /* g1 = vaddr */ 200 201 /* We need to demap in the kernel context */ 202 or DEMAP_NUCLEUS | DEMAP_PAGE_TYPE, %g1, %g1 203 stxa %g0, [%g1]ASI_DTLB_DEMAP 204 stxa %g0, [%g1]ASI_ITLB_DEMAP 205 retry 206 1: 207 /* We need to demap in a user context */ 208 or DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %g1, %g1 209 210 SFMMU_CPU_CNUM(%g2, %g6, %g3) ! %g6 = sfmmu cnum on this CPU 211 212 ldub [%g2 + SFMMU_CEXT], %g4 ! %g4 = sfmmup->cext 213 sll %g4, CTXREG_EXT_SHIFT, %g4 214 or %g6, %g4, %g6 ! %g6 = primary pgsz | cnum 215 216 set MMU_PCONTEXT, %g4 217 ldxa [%g4]ASI_DMMU, %g5 ! %g5 = save old ctxnum 218 srlx %g5, CTXREG_NEXT_SHIFT, %g2 ! %g2 = nucleus pgsz 219 sllx %g2, CTXREG_NEXT_SHIFT, %g2 ! preserve nucleus pgsz 220 or %g6, %g2, %g6 ! %g6 = nucleus pgsz | primary pgsz | cnum 221 stxa %g6, [%g4]ASI_DMMU ! wr new ctxum 222 stxa %g0, [%g1]ASI_DTLB_DEMAP 223 stxa %g0, [%g1]ASI_ITLB_DEMAP 224 stxa %g5, [%g4]ASI_DMMU ! restore old ctxnum 225 retry 226 SET_SIZE(vtag_flushpage_tl1) 227 228 #endif /* lint */ 229 230 231 #if defined(lint) 232 233 /* ARGSUSED */ 234 void 235 vtag_flush_pgcnt_tl1(uint64_t vaddr, uint64_t sfmmup_pgcnt) 236 {} 237 238 #else /* lint */ 239 240 ENTRY_NP(vtag_flush_pgcnt_tl1) 241 /* 242 * x-trap to flush pgcnt MMU_PAGESIZE pages from tlb 243 * 244 * %g1 = vaddr, zero-extended on 32-bit kernel 245 * %g2 = <sfmmup58|pgcnt6> 246 * 247 * NOTE: this handler relies on the fact that no 248 * interrupts or traps can occur during the loop 249 * issuing the TLB_DEMAP operations. It is assumed 250 * that interrupts are disabled and this code is 251 * fetching from the kernel locked text address. 252 * 253 * assumes TSBE_TAG = 0 254 */ 255 set SFMMU_PGCNT_MASK, %g4 256 and %g4, %g2, %g3 /* g3 = pgcnt - 1 */ 257 add %g3, 1, %g3 /* g3 = pgcnt */ 258 259 andn %g2, SFMMU_PGCNT_MASK, %g2 /* g2 = sfmmup */ 260 srln %g1, MMU_PAGESHIFT, %g1 261 262 sethi %hi(ksfmmup), %g4 263 ldx [%g4 + %lo(ksfmmup)], %g4 264 cmp %g4, %g2 265 bne,pn %xcc, 1f /* if not kernel as, go to 1 */ 266 slln %g1, MMU_PAGESHIFT, %g1 /* g1 = vaddr */ 267 268 /* We need to demap in the kernel context */ 269 or DEMAP_NUCLEUS | DEMAP_PAGE_TYPE, %g1, %g1 270 set MMU_PAGESIZE, %g2 /* g2 = pgsize */ 271 sethi %hi(FLUSH_ADDR), %g5 272 4: 273 stxa %g0, [%g1]ASI_DTLB_DEMAP 274 stxa %g0, [%g1]ASI_ITLB_DEMAP 275 flush %g5 ! flush required by immu 276 277 deccc %g3 /* decr pgcnt */ 278 bnz,pt %icc,4b 279 add %g1, %g2, %g1 /* next page */ 280 retry 281 1: 282 /* 283 * We need to demap in a user context 284 * 285 * g2 = sfmmup 286 * g3 = pgcnt 287 */ 288 SFMMU_CPU_CNUM(%g2, %g5, %g6) ! %g5 = sfmmu cnum on this CPU 289 290 or DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %g1, %g1 291 292 ldub [%g2 + SFMMU_CEXT], %g4 ! %g4 = sfmmup->cext 293 sll %g4, CTXREG_EXT_SHIFT, %g4 294 or %g5, %g4, %g5 295 296 set MMU_PCONTEXT, %g4 297 ldxa [%g4]ASI_DMMU, %g6 /* rd old ctxnum */ 298 srlx %g6, CTXREG_NEXT_SHIFT, %g2 /* %g2 = nucleus pgsz */ 299 sllx %g2, CTXREG_NEXT_SHIFT, %g2 /* preserve nucleus pgsz */ 300 or %g5, %g2, %g5 /* %g5 = nucleus pgsz | primary pgsz | cnum */ 301 stxa %g5, [%g4]ASI_DMMU /* wr new ctxum */ 302 303 set MMU_PAGESIZE, %g2 /* g2 = pgsize */ 304 sethi %hi(FLUSH_ADDR), %g5 305 3: 306 stxa %g0, [%g1]ASI_DTLB_DEMAP 307 stxa %g0, [%g1]ASI_ITLB_DEMAP 308 flush %g5 ! flush required by immu 309 310 deccc %g3 /* decr pgcnt */ 311 bnz,pt %icc,3b 312 add %g1, %g2, %g1 /* next page */ 313 314 stxa %g6, [%g4]ASI_DMMU /* restore old ctxnum */ 315 retry 316 SET_SIZE(vtag_flush_pgcnt_tl1) 317 318 #endif /* lint */ 319 320 321 #if defined(lint) 322 323 /*ARGSUSED*/ 324 void 325 vtag_flushall_tl1(uint64_t dummy1, uint64_t dummy2) 326 {} 327 328 #else /* lint */ 329 330 ENTRY_NP(vtag_flushall_tl1) 331 /* 332 * x-trap to flush tlb 333 */ 334 set DEMAP_ALL_TYPE, %g4 335 stxa %g0, [%g4]ASI_DTLB_DEMAP 336 stxa %g0, [%g4]ASI_ITLB_DEMAP 337 retry 338 SET_SIZE(vtag_flushall_tl1) 339 340 #endif /* lint */ 341 342 343 /* 344 * VAC (virtual address conflict) does not apply to OPL. 345 * VAC resolution is managed by the Olympus processor hardware. 346 * As a result, all OPL VAC flushing routines are no-ops. 347 */ 348 349 #if defined(lint) 350 351 /* ARGSUSED */ 352 void 353 vac_flushpage(pfn_t pfnum, int vcolor) 354 {} 355 356 #else /* lint */ 357 358 ENTRY(vac_flushpage) 359 retl 360 nop 361 SET_SIZE(vac_flushpage) 362 363 #endif /* lint */ 364 365 #if defined(lint) 366 367 /* ARGSUSED */ 368 void 369 vac_flushpage_tl1(uint64_t pfnum, uint64_t vcolor) 370 {} 371 372 #else /* lint */ 373 374 ENTRY_NP(vac_flushpage_tl1) 375 retry 376 SET_SIZE(vac_flushpage_tl1) 377 378 #endif /* lint */ 379 380 381 #if defined(lint) 382 383 /* ARGSUSED */ 384 void 385 vac_flushcolor(int vcolor, pfn_t pfnum) 386 {} 387 388 #else /* lint */ 389 390 ENTRY(vac_flushcolor) 391 retl 392 nop 393 SET_SIZE(vac_flushcolor) 394 395 #endif /* lint */ 396 397 398 399 #if defined(lint) 400 401 /* ARGSUSED */ 402 void 403 vac_flushcolor_tl1(uint64_t vcolor, uint64_t pfnum) 404 {} 405 406 #else /* lint */ 407 408 ENTRY(vac_flushcolor_tl1) 409 retry 410 SET_SIZE(vac_flushcolor_tl1) 411 412 #endif /* lint */ 413 414 #if defined(lint) 415 416 int 417 idsr_busy(void) 418 { 419 return (0); 420 } 421 422 #else /* lint */ 423 424 /* 425 * Determine whether or not the IDSR is busy. 426 * Entry: no arguments 427 * Returns: 1 if busy, 0 otherwise 428 */ 429 ENTRY(idsr_busy) 430 ldxa [%g0]ASI_INTR_DISPATCH_STATUS, %g1 431 clr %o0 432 btst IDSR_BUSY, %g1 433 bz,a,pt %xcc, 1f 434 mov 1, %o0 435 1: 436 retl 437 nop 438 SET_SIZE(idsr_busy) 439 440 #endif /* lint */ 441 442 #if defined(lint) 443 444 /* ARGSUSED */ 445 void 446 init_mondo(xcfunc_t *func, uint64_t arg1, uint64_t arg2) 447 {} 448 449 /* ARGSUSED */ 450 void 451 init_mondo_nocheck(xcfunc_t *func, uint64_t arg1, uint64_t arg2) 452 {} 453 454 #else /* lint */ 455 456 .global _dispatch_status_busy 457 _dispatch_status_busy: 458 .asciz "ASI_INTR_DISPATCH_STATUS error: busy" 459 .align 4 460 461 /* 462 * Setup interrupt dispatch data registers 463 * Entry: 464 * %o0 - function or inumber to call 465 * %o1, %o2 - arguments (2 uint64_t's) 466 */ 467 .seg "text" 468 469 ENTRY(init_mondo) 470 #ifdef DEBUG 471 ! 472 ! IDSR should not be busy at the moment 473 ! 474 ldxa [%g0]ASI_INTR_DISPATCH_STATUS, %g1 475 btst IDSR_BUSY, %g1 476 bz,pt %xcc, 1f 477 nop 478 sethi %hi(_dispatch_status_busy), %o0 479 call panic 480 or %o0, %lo(_dispatch_status_busy), %o0 481 #endif /* DEBUG */ 482 483 ALTENTRY(init_mondo_nocheck) 484 ! 485 ! interrupt vector dispatch data reg 0 486 ! 487 1: 488 mov IDDR_0, %g1 489 mov IDDR_1, %g2 490 mov IDDR_2, %g3 491 stxa %o0, [%g1]ASI_INTR_DISPATCH 492 493 ! 494 ! interrupt vector dispatch data reg 1 495 ! 496 stxa %o1, [%g2]ASI_INTR_DISPATCH 497 498 ! 499 ! interrupt vector dispatch data reg 2 500 ! 501 stxa %o2, [%g3]ASI_INTR_DISPATCH 502 503 membar #Sync 504 retl 505 nop 506 SET_SIZE(init_mondo_nocheck) 507 SET_SIZE(init_mondo) 508 509 #endif /* lint */ 510 511 512 #if defined(lint) 513 514 /* ARGSUSED */ 515 void 516 shipit(int upaid, int bn) 517 { return; } 518 519 #else /* lint */ 520 521 /* 522 * Ship mondo to aid using busy/nack pair bn 523 */ 524 ENTRY_NP(shipit) 525 sll %o0, IDCR_PID_SHIFT, %g1 ! IDCR<23:14> = agent id 526 sll %o1, IDCR_BN_SHIFT, %g2 ! IDCR<28:24> = b/n pair 527 or %g1, IDCR_OFFSET, %g1 ! IDCR<13:0> = 0x70 528 or %g1, %g2, %g1 529 stxa %g0, [%g1]ASI_INTR_DISPATCH ! interrupt vector dispatch 530 membar #Sync 531 retl 532 nop 533 SET_SIZE(shipit) 534 535 #endif /* lint */ 536 537 538 #if defined(lint) 539 540 /* ARGSUSED */ 541 void 542 flush_instr_mem(caddr_t vaddr, size_t len) 543 {} 544 545 #else /* lint */ 546 547 /* 548 * flush_instr_mem: 549 * Flush 1 page of the I-$ starting at vaddr 550 * %o0 vaddr 551 * %o1 bytes to be flushed 552 * 553 * SPARC64-VI maintains consistency of the on-chip Instruction Cache with 554 * the stores from all processors so that a FLUSH instruction is only needed 555 * to ensure pipeline is consistent. This means a single flush is sufficient at 556 * the end of a sequence of stores that updates the instruction stream to 557 * ensure correct operation. 558 */ 559 560 ENTRY(flush_instr_mem) 561 flush %o0 ! address irrelevant 562 retl 563 nop 564 SET_SIZE(flush_instr_mem) 565 566 #endif /* lint */ 567 568 569 /* 570 * flush_ecache: 571 * %o0 - 64 bit physical address 572 * %o1 - ecache size 573 * %o2 - ecache linesize 574 */ 575 #if defined(lint) 576 577 /*ARGSUSED*/ 578 void 579 flush_ecache(uint64_t physaddr, size_t ecache_size, size_t ecache_linesize) 580 {} 581 582 #else /* !lint */ 583 584 ENTRY(flush_ecache) 585 586 /* 587 * Flush the entire Ecache. 588 */ 589 ECACHE_FLUSHALL(%o1, %o2, %o0, %o4) 590 retl 591 nop 592 SET_SIZE(flush_ecache) 593 594 #endif /* lint */ 595 596 #if defined(lint) 597 598 /*ARGSUSED*/ 599 void 600 kdi_flush_idcache(int dcache_size, int dcache_lsize, int icache_size, 601 int icache_lsize) 602 { 603 } 604 605 #else /* lint */ 606 607 /* 608 * I/D cache flushing is not needed for OPL processors 609 */ 610 ENTRY(kdi_flush_idcache) 611 retl 612 nop 613 SET_SIZE(kdi_flush_idcache) 614 615 #endif /* lint */ 616 617 #ifdef TRAPTRACE 618 /* 619 * Simplified trap trace macro for OPL. Adapted from us3. 620 */ 621 #define OPL_TRAPTRACE(ptr, scr1, scr2, label) \ 622 CPU_INDEX(scr1, ptr); \ 623 sll scr1, TRAPTR_SIZE_SHIFT, scr1; \ 624 set trap_trace_ctl, ptr; \ 625 add ptr, scr1, scr1; \ 626 ld [scr1 + TRAPTR_LIMIT], ptr; \ 627 tst ptr; \ 628 be,pn %icc, label/**/1; \ 629 ldx [scr1 + TRAPTR_PBASE], ptr; \ 630 ld [scr1 + TRAPTR_OFFSET], scr1; \ 631 add ptr, scr1, ptr; \ 632 rd %asi, scr2; \ 633 wr %g0, TRAPTR_ASI, %asi; \ 634 rd STICK, scr1; \ 635 stxa scr1, [ptr + TRAP_ENT_TICK]%asi; \ 636 rdpr %tl, scr1; \ 637 stha scr1, [ptr + TRAP_ENT_TL]%asi; \ 638 rdpr %tt, scr1; \ 639 stha scr1, [ptr + TRAP_ENT_TT]%asi; \ 640 rdpr %tpc, scr1; \ 641 stna scr1, [ptr + TRAP_ENT_TPC]%asi; \ 642 rdpr %tstate, scr1; \ 643 stxa scr1, [ptr + TRAP_ENT_TSTATE]%asi; \ 644 stna %sp, [ptr + TRAP_ENT_SP]%asi; \ 645 stna %g0, [ptr + TRAP_ENT_TR]%asi; \ 646 stna %g0, [ptr + TRAP_ENT_F1]%asi; \ 647 stna %g0, [ptr + TRAP_ENT_F2]%asi; \ 648 stna %g0, [ptr + TRAP_ENT_F3]%asi; \ 649 stna %g0, [ptr + TRAP_ENT_F4]%asi; \ 650 wr %g0, scr2, %asi; \ 651 CPU_INDEX(ptr, scr1); \ 652 sll ptr, TRAPTR_SIZE_SHIFT, ptr; \ 653 set trap_trace_ctl, scr1; \ 654 add scr1, ptr, ptr; \ 655 ld [ptr + TRAPTR_OFFSET], scr1; \ 656 ld [ptr + TRAPTR_LIMIT], scr2; \ 657 st scr1, [ptr + TRAPTR_LAST_OFFSET]; \ 658 add scr1, TRAP_ENT_SIZE, scr1; \ 659 sub scr2, TRAP_ENT_SIZE, scr2; \ 660 cmp scr1, scr2; \ 661 movge %icc, 0, scr1; \ 662 st scr1, [ptr + TRAPTR_OFFSET]; \ 663 label/**/1: 664 #endif /* TRAPTRACE */ 665 666 667 668 /* 669 * Macros facilitating error handling. 670 */ 671 672 /* 673 * Save alternative global registers reg1, reg2, reg3 674 * to scratchpad registers 1, 2, 3 respectively. 675 */ 676 #define OPL_SAVE_GLOBAL(reg1, reg2, reg3) \ 677 stxa reg1, [%g0]ASI_SCRATCHPAD ;\ 678 mov OPL_SCRATCHPAD_SAVE_AG2, reg1 ;\ 679 stxa reg2, [reg1]ASI_SCRATCHPAD ;\ 680 mov OPL_SCRATCHPAD_SAVE_AG3, reg1 ;\ 681 stxa reg3, [reg1]ASI_SCRATCHPAD 682 683 /* 684 * Restore alternative global registers reg1, reg2, reg3 685 * from scratchpad registers 1, 2, 3 respectively. 686 */ 687 #define OPL_RESTORE_GLOBAL(reg1, reg2, reg3) \ 688 mov OPL_SCRATCHPAD_SAVE_AG3, reg1 ;\ 689 ldxa [reg1]ASI_SCRATCHPAD, reg3 ;\ 690 mov OPL_SCRATCHPAD_SAVE_AG2, reg1 ;\ 691 ldxa [reg1]ASI_SCRATCHPAD, reg2 ;\ 692 ldxa [%g0]ASI_SCRATCHPAD, reg1 693 694 /* 695 * Logs value `val' into the member `offset' of a structure 696 * at physical address `pa' 697 */ 698 #define LOG_REG(pa, offset, val) \ 699 add pa, offset, pa ;\ 700 stxa val, [pa]ASI_MEM 701 702 #define FLUSH_ALL_TLB(tmp1) \ 703 set DEMAP_ALL_TYPE, tmp1 ;\ 704 stxa %g0, [tmp1]ASI_ITLB_DEMAP ;\ 705 stxa %g0, [tmp1]ASI_DTLB_DEMAP ;\ 706 sethi %hi(FLUSH_ADDR), tmp1 ;\ 707 flush tmp1 708 709 /* 710 * Extracts the Physaddr to Logging Buffer field of the OPL_SCRATCHPAD_ERRLOG 711 * scratch register by zeroing all other fields. Result is in pa. 712 */ 713 #define LOG_ADDR(pa) \ 714 mov OPL_SCRATCHPAD_ERRLOG, pa ;\ 715 ldxa [pa]ASI_SCRATCHPAD, pa ;\ 716 sllx pa, 64-ERRLOG_REG_EIDR_SHIFT, pa ;\ 717 srlx pa, 64-ERRLOG_REG_EIDR_SHIFT+ERRLOG_REG_ERR_SHIFT, pa ;\ 718 sllx pa, ERRLOG_REG_ERR_SHIFT, pa 719 720 /* 721 * Advance the per-cpu error log buffer pointer to the next 722 * ERRLOG_SZ entry, making sure that it will modulo (wraparound) 723 * ERRLOG_BUFSIZ boundary. The args logpa, bufmask, tmp are 724 * unused input registers for this macro. 725 * 726 * Algorithm: 727 * 1. logpa = contents of errorlog scratchpad register 728 * 2. bufmask = ERRLOG_BUFSIZ - 1 729 * 3. tmp = logpa & ~(bufmask) (tmp is now logbase) 730 * 4. logpa += ERRLOG_SZ 731 * 5. logpa = logpa & bufmask (get new offset to logbase) 732 * 4. logpa = tmp | logpa 733 * 7. write logpa back into errorlog scratchpad register 734 * 735 * new logpa = (logpa & ~bufmask) | ((logpa + ERRLOG_SZ) & bufmask) 736 * 737 */ 738 #define UPDATE_LOGADD(logpa, bufmask, tmp) \ 739 set OPL_SCRATCHPAD_ERRLOG, tmp ;\ 740 ldxa [tmp]ASI_SCRATCHPAD, logpa ;\ 741 set (ERRLOG_BUFSZ-1), bufmask ;\ 742 andn logpa, bufmask, tmp ;\ 743 add logpa, ERRLOG_SZ, logpa ;\ 744 and logpa, bufmask, logpa ;\ 745 or tmp, logpa, logpa ;\ 746 set OPL_SCRATCHPAD_ERRLOG, tmp ;\ 747 stxa logpa, [tmp]ASI_SCRATCHPAD 748 749 /* Log error status registers into the log buffer */ 750 #define LOG_SYNC_REG(sfsr, sfar, tmp) \ 751 LOG_ADDR(tmp) ;\ 752 LOG_REG(tmp, LOG_SFSR_OFF, sfsr) ;\ 753 LOG_ADDR(tmp) ;\ 754 mov tmp, sfsr ;\ 755 LOG_REG(tmp, LOG_SFAR_OFF, sfar) ;\ 756 rd STICK, sfar ;\ 757 mov sfsr, tmp ;\ 758 LOG_REG(tmp, LOG_STICK_OFF, sfar) ;\ 759 rdpr %tl, tmp ;\ 760 sllx tmp, 32, sfar ;\ 761 rdpr %tt, tmp ;\ 762 or sfar, tmp, sfar ;\ 763 mov sfsr, tmp ;\ 764 LOG_REG(tmp, LOG_TL_OFF, sfar) ;\ 765 set OPL_SCRATCHPAD_ERRLOG, tmp ;\ 766 ldxa [tmp]ASI_SCRATCHPAD, sfar ;\ 767 mov sfsr, tmp ;\ 768 LOG_REG(tmp, LOG_ASI3_OFF, sfar) ;\ 769 rdpr %tpc, sfar ;\ 770 mov sfsr, tmp ;\ 771 LOG_REG(tmp, LOG_TPC_OFF, sfar) ;\ 772 UPDATE_LOGADD(sfsr, sfar, tmp) 773 774 #define LOG_UGER_REG(uger, tmp, tmp2) \ 775 LOG_ADDR(tmp) ;\ 776 mov tmp, tmp2 ;\ 777 LOG_REG(tmp2, LOG_UGER_OFF, uger) ;\ 778 mov tmp, uger ;\ 779 rd STICK, tmp2 ;\ 780 LOG_REG(tmp, LOG_STICK_OFF, tmp2) ;\ 781 rdpr %tl, tmp ;\ 782 sllx tmp, 32, tmp2 ;\ 783 rdpr %tt, tmp ;\ 784 or tmp2, tmp, tmp2 ;\ 785 mov uger, tmp ;\ 786 LOG_REG(tmp, LOG_TL_OFF, tmp2) ;\ 787 set OPL_SCRATCHPAD_ERRLOG, tmp2 ;\ 788 ldxa [tmp2]ASI_SCRATCHPAD, tmp2 ;\ 789 mov uger, tmp ;\ 790 LOG_REG(tmp, LOG_ASI3_OFF, tmp2) ;\ 791 rdpr %tstate, tmp2 ;\ 792 mov uger, tmp ;\ 793 LOG_REG(tmp, LOG_TSTATE_OFF, tmp2) ;\ 794 rdpr %tpc, tmp2 ;\ 795 mov uger, tmp ;\ 796 LOG_REG(tmp, LOG_TPC_OFF, tmp2) ;\ 797 UPDATE_LOGADD(uger, tmp, tmp2) 798 799 /* 800 * Scrub the STICK_COMPARE register to clear error by updating 801 * it to a reasonable value for interrupt generation. 802 * Ensure that we observe the CPU_ENABLE flag so that we 803 * don't accidentally enable TICK interrupt in STICK_COMPARE 804 * i.e. no clock interrupt will be generated if CPU_ENABLE flag 805 * is off. 806 */ 807 #define UPDATE_STICK_COMPARE(tmp1, tmp2) \ 808 CPU_ADDR(tmp1, tmp2) ;\ 809 lduh [tmp1 + CPU_FLAGS], tmp2 ;\ 810 andcc tmp2, CPU_ENABLE, %g0 ;\ 811 set OPL_UGER_STICK_DIFF, tmp2 ;\ 812 rd STICK, tmp1 ;\ 813 add tmp1, tmp2, tmp1 ;\ 814 mov 1, tmp2 ;\ 815 sllx tmp2, TICKINT_DIS_SHFT, tmp2 ;\ 816 or tmp1, tmp2, tmp2 ;\ 817 movnz %xcc, tmp1, tmp2 ;\ 818 wr tmp2, %g0, STICK_COMPARE 819 820 /* 821 * Reset registers that may be corrupted by IAUG_CRE error. 822 * To update interrupt handling related registers force the 823 * clock interrupt. 824 */ 825 #define IAG_CRE(tmp1, tmp2) \ 826 set OPL_SCRATCHPAD_ERRLOG, tmp1 ;\ 827 ldxa [tmp1]ASI_SCRATCHPAD, tmp1 ;\ 828 srlx tmp1, ERRLOG_REG_EIDR_SHIFT, tmp1 ;\ 829 set ERRLOG_REG_EIDR_MASK, tmp2 ;\ 830 and tmp1, tmp2, tmp1 ;\ 831 stxa tmp1, [%g0]ASI_EIDR ;\ 832 wr %g0, 0, SOFTINT ;\ 833 sethi %hi(hres_last_tick), tmp1 ;\ 834 ldx [tmp1 + %lo(hres_last_tick)], tmp1 ;\ 835 set OPL_UGER_STICK_DIFF, tmp2 ;\ 836 add tmp1, tmp2, tmp1 ;\ 837 wr tmp1, %g0, STICK ;\ 838 UPDATE_STICK_COMPARE(tmp1, tmp2) 839 840 841 #define CLEAR_FPREGS(tmp) \ 842 wr %g0, FPRS_FEF, %fprs ;\ 843 wr %g0, %g0, %gsr ;\ 844 sethi %hi(opl_clr_freg), tmp ;\ 845 or tmp, %lo(opl_clr_freg), tmp ;\ 846 ldx [tmp], %fsr ;\ 847 fzero %d0 ;\ 848 fzero %d2 ;\ 849 fzero %d4 ;\ 850 fzero %d6 ;\ 851 fzero %d8 ;\ 852 fzero %d10 ;\ 853 fzero %d12 ;\ 854 fzero %d14 ;\ 855 fzero %d16 ;\ 856 fzero %d18 ;\ 857 fzero %d20 ;\ 858 fzero %d22 ;\ 859 fzero %d24 ;\ 860 fzero %d26 ;\ 861 fzero %d28 ;\ 862 fzero %d30 ;\ 863 fzero %d32 ;\ 864 fzero %d34 ;\ 865 fzero %d36 ;\ 866 fzero %d38 ;\ 867 fzero %d40 ;\ 868 fzero %d42 ;\ 869 fzero %d44 ;\ 870 fzero %d46 ;\ 871 fzero %d48 ;\ 872 fzero %d50 ;\ 873 fzero %d52 ;\ 874 fzero %d54 ;\ 875 fzero %d56 ;\ 876 fzero %d58 ;\ 877 fzero %d60 ;\ 878 fzero %d62 ;\ 879 wr %g0, %g0, %fprs 880 881 #define CLEAR_GLOBALS() \ 882 mov %g0, %g1 ;\ 883 mov %g0, %g2 ;\ 884 mov %g0, %g3 ;\ 885 mov %g0, %g4 ;\ 886 mov %g0, %g5 ;\ 887 mov %g0, %g6 ;\ 888 mov %g0, %g7 889 890 /* 891 * We do not clear the alternative globals here because they 892 * are scratch registers, i.e. there is no code that reads from 893 * them without write to them firstly. In other words every 894 * read always follows write that makes extra write to the 895 * alternative globals unnecessary. 896 */ 897 #define CLEAR_GEN_REGS(tmp1, label) \ 898 set TSTATE_KERN, tmp1 ;\ 899 wrpr %g0, tmp1, %tstate ;\ 900 mov %g0, %y ;\ 901 mov %g0, %asi ;\ 902 mov %g0, %ccr ;\ 903 mov %g0, %l0 ;\ 904 mov %g0, %l1 ;\ 905 mov %g0, %l2 ;\ 906 mov %g0, %l3 ;\ 907 mov %g0, %l4 ;\ 908 mov %g0, %l5 ;\ 909 mov %g0, %l6 ;\ 910 mov %g0, %l7 ;\ 911 mov %g0, %i0 ;\ 912 mov %g0, %i1 ;\ 913 mov %g0, %i2 ;\ 914 mov %g0, %i3 ;\ 915 mov %g0, %i4 ;\ 916 mov %g0, %i5 ;\ 917 mov %g0, %i6 ;\ 918 mov %g0, %i7 ;\ 919 mov %g0, %o1 ;\ 920 mov %g0, %o2 ;\ 921 mov %g0, %o3 ;\ 922 mov %g0, %o4 ;\ 923 mov %g0, %o5 ;\ 924 mov %g0, %o6 ;\ 925 mov %g0, %o7 ;\ 926 mov %g0, %o0 ;\ 927 mov %g0, %g4 ;\ 928 mov %g0, %g5 ;\ 929 mov %g0, %g6 ;\ 930 mov %g0, %g7 ;\ 931 rdpr %tl, tmp1 ;\ 932 cmp tmp1, 1 ;\ 933 be,pt %xcc, label/**/1 ;\ 934 rdpr %pstate, tmp1 ;\ 935 wrpr tmp1, PSTATE_AG|PSTATE_IG, %pstate ;\ 936 CLEAR_GLOBALS() ;\ 937 rdpr %pstate, tmp1 ;\ 938 wrpr tmp1, PSTATE_IG|PSTATE_MG, %pstate ;\ 939 CLEAR_GLOBALS() ;\ 940 rdpr %pstate, tmp1 ;\ 941 wrpr tmp1, PSTATE_MG|PSTATE_AG, %pstate ;\ 942 ba,pt %xcc, label/**/2 ;\ 943 nop ;\ 944 label/**/1: ;\ 945 wrpr tmp1, PSTATE_AG, %pstate ;\ 946 CLEAR_GLOBALS() ;\ 947 rdpr %pstate, tmp1 ;\ 948 wrpr tmp1, PSTATE_AG, %pstate ;\ 949 label/**/2: 950 951 952 /* 953 * Reset all window related registers 954 */ 955 #define RESET_WINREG(tmp) \ 956 sethi %hi(nwin_minus_one), tmp ;\ 957 ld [tmp + %lo(nwin_minus_one)], tmp ;\ 958 wrpr %g0, tmp, %cwp ;\ 959 wrpr %g0, tmp, %cleanwin ;\ 960 sub tmp, 1, tmp ;\ 961 wrpr %g0, tmp, %cansave ;\ 962 wrpr %g0, %g0, %canrestore ;\ 963 wrpr %g0, %g0, %otherwin ;\ 964 wrpr %g0, PIL_MAX, %pil ;\ 965 wrpr %g0, WSTATE_KERN, %wstate 966 967 968 #define RESET_PREV_TSTATE(tmp1, tmp2, label) \ 969 rdpr %tl, tmp1 ;\ 970 subcc tmp1, 1, tmp1 ;\ 971 bz,pt %xcc, label/**/1 ;\ 972 nop ;\ 973 wrpr tmp1, %g0, %tl ;\ 974 set TSTATE_KERN, tmp2 ;\ 975 wrpr tmp2, %g0, %tstate ;\ 976 wrpr %g0, %g0, %tpc ;\ 977 wrpr %g0, %g0, %tnpc ;\ 978 add tmp1, 1, tmp1 ;\ 979 wrpr tmp1, %g0, %tl ;\ 980 label/**/1: 981 982 983 /* 984 * %pstate, %pc, %npc are propagated to %tstate, %tpc, %tnpc, 985 * and we reset these regiseter here. 986 */ 987 #define RESET_CUR_TSTATE(tmp) \ 988 set TSTATE_KERN, tmp ;\ 989 wrpr %g0, tmp, %tstate ;\ 990 wrpr %g0, 0, %tpc ;\ 991 wrpr %g0, 0, %tnpc ;\ 992 RESET_WINREG(tmp) 993 994 /* 995 * In case of urgent errors some MMU registers may be 996 * corrupted, so we set here some reasonable values for 997 * them. Note that resetting MMU registers also reset the context 998 * info, we will need to reset the window registers to prevent 999 * spill/fill that depends on context info for correct behaviour. 1000 * Note that the TLBs must be flushed before programming the context 1001 * registers. 1002 */ 1003 1004 #if !defined(lint) 1005 #define RESET_MMU_REGS(tmp1, tmp2, tmp3) \ 1006 FLUSH_ALL_TLB(tmp1) ;\ 1007 set MMU_PCONTEXT, tmp1 ;\ 1008 sethi %hi(kcontextreg), tmp2 ;\ 1009 ldx [tmp2 + %lo(kcontextreg)], tmp2 ;\ 1010 stxa tmp2, [tmp1]ASI_DMMU ;\ 1011 set MMU_SCONTEXT, tmp1 ;\ 1012 stxa tmp2, [tmp1]ASI_DMMU ;\ 1013 sethi %hi(ktsb_base), tmp1 ;\ 1014 ldx [tmp1 + %lo(ktsb_base)], tmp2 ;\ 1015 mov MMU_TSB, tmp3 ;\ 1016 stxa tmp2, [tmp3]ASI_IMMU ;\ 1017 stxa tmp2, [tmp3]ASI_DMMU ;\ 1018 membar #Sync ;\ 1019 RESET_WINREG(tmp1) 1020 1021 #define RESET_TSB_TAGPTR(tmp) \ 1022 set MMU_TAG_ACCESS, tmp ;\ 1023 stxa %g0, [tmp]ASI_IMMU ;\ 1024 stxa %g0, [tmp]ASI_DMMU ;\ 1025 membar #Sync 1026 #endif /* lint */ 1027 1028 /* 1029 * In case of errors in the MMU_TSB_PREFETCH registers we have to 1030 * reset them. We can use "0" as the reset value, this way we set 1031 * the "V" bit of the registers to 0, which will disable the prefetch 1032 * so the values of the other fields are irrelevant. 1033 */ 1034 #if !defined(lint) 1035 #define RESET_TSB_PREFETCH(tmp) \ 1036 set VA_UTSBPREF_8K, tmp ;\ 1037 stxa %g0, [tmp]ASI_ITSB_PREFETCH ;\ 1038 set VA_UTSBPREF_4M, tmp ;\ 1039 stxa %g0, [tmp]ASI_ITSB_PREFETCH ;\ 1040 set VA_KTSBPREF_8K, tmp ;\ 1041 stxa %g0, [tmp]ASI_ITSB_PREFETCH ;\ 1042 set VA_KTSBPREF_4M, tmp ;\ 1043 stxa %g0, [tmp]ASI_ITSB_PREFETCH ;\ 1044 set VA_UTSBPREF_8K, tmp ;\ 1045 stxa %g0, [tmp]ASI_DTSB_PREFETCH ;\ 1046 set VA_UTSBPREF_4M, tmp ;\ 1047 stxa %g0, [tmp]ASI_DTSB_PREFETCH ;\ 1048 set VA_KTSBPREF_8K, tmp ;\ 1049 stxa %g0, [tmp]ASI_DTSB_PREFETCH ;\ 1050 set VA_KTSBPREF_4M, tmp ;\ 1051 stxa %g0, [tmp]ASI_DTSB_PREFETCH 1052 #endif /* lint */ 1053 1054 /* 1055 * In case of errors in the MMU_SHARED_CONTEXT register we have to 1056 * reset its value. We can use "0" as the reset value, it will put 1057 * 0 in the IV field disabling the shared context support, and 1058 * making values of all the other fields of the register irrelevant. 1059 */ 1060 #if !defined(lint) 1061 #define RESET_SHARED_CTXT(tmp) \ 1062 set MMU_SHARED_CONTEXT, tmp ;\ 1063 stxa %g0, [tmp]ASI_DMMU 1064 #endif /* lint */ 1065 1066 /* 1067 * RESET_TO_PRIV() 1068 * 1069 * In many cases, we need to force the thread into privilege mode because 1070 * privilege mode is only thing in which the system continue to work 1071 * due to undeterminable user mode information that come from register 1072 * corruption. 1073 * 1074 * - opl_uger_ctxt 1075 * If the error is secondary TSB related register parity, we have no idea 1076 * what value is supposed to be for it. 1077 * 1078 * The below three cases %tstate is not accessible until it is overwritten 1079 * with some value, so we have no clue if the thread was running on user mode 1080 * or not 1081 * - opl_uger_pstate 1082 * If the error is %pstate parity, it propagates to %tstate. 1083 * - opl_uger_tstate 1084 * No need to say the reason 1085 * - opl_uger_r 1086 * If the error is %ccr or %asi parity, it propagates to %tstate 1087 * 1088 * For the above four cases, user mode info may not be available for 1089 * sys_trap() and user_trap() to work consistently. So we have to force 1090 * the thread into privilege mode. 1091 * 1092 * Forcing the thread to privilege mode requires forcing 1093 * regular %g7 to be CPU_THREAD. Because if it was running on user mode, 1094 * %g7 will be set in user_trap(). Also since the %sp may be in 1095 * an inconsistent state, we need to do a stack reset and switch to 1096 * something we know i.e. current thread's kernel stack. 1097 * We also reset the window registers and MMU registers just to 1098 * make sure. 1099 * 1100 * To set regular %g7, we need to clear PSTATE_AG bit and need to 1101 * use one local register. Note that we are panicking and will never 1102 * unwind back so it is ok to clobber a local. 1103 * 1104 * If the thread was running in user mode, the %tpc value itself might be 1105 * within the range of OBP addresses. %tpc must be forced to be zero to prevent 1106 * sys_trap() from going to prom_trap() 1107 * 1108 */ 1109 #define RESET_TO_PRIV(tmp, tmp1, tmp2, local) \ 1110 RESET_MMU_REGS(tmp, tmp1, tmp2) ;\ 1111 CPU_ADDR(tmp, tmp1) ;\ 1112 ldx [tmp + CPU_THREAD], local ;\ 1113 ldx [local + T_STACK], tmp ;\ 1114 sub tmp, STACK_BIAS, %sp ;\ 1115 rdpr %pstate, tmp ;\ 1116 wrpr tmp, PSTATE_AG, %pstate ;\ 1117 mov local, %g7 ;\ 1118 rdpr %pstate, local ;\ 1119 wrpr local, PSTATE_AG, %pstate ;\ 1120 wrpr %g0, 1, %tl ;\ 1121 set TSTATE_KERN, tmp ;\ 1122 rdpr %cwp, tmp1 ;\ 1123 or tmp, tmp1, tmp ;\ 1124 wrpr tmp, %g0, %tstate ;\ 1125 wrpr %g0, %tpc 1126 1127 1128 #if defined(lint) 1129 1130 void 1131 ce_err(void) 1132 {} 1133 1134 #else /* lint */ 1135 1136 /* 1137 * We normally don't expect CE traps since we disable the 1138 * 0x63 trap reporting at the start of day. There is a 1139 * small window before we disable them, so let check for 1140 * it. Otherwise, panic. 1141 */ 1142 1143 .align 128 1144 ENTRY_NP(ce_err) 1145 mov AFSR_ECR, %g1 1146 ldxa [%g1]ASI_ECR, %g1 1147 andcc %g1, ASI_ECR_RTE_UE | ASI_ECR_RTE_CEDG, %g0 1148 bz,pn %xcc, 1f 1149 nop 1150 retry 1151 1: 1152 /* 1153 * We did disabled the 0x63 trap reporting. 1154 * This shouldn't happen - panic. 1155 */ 1156 set trap, %g1 1157 rdpr %tt, %g3 1158 sethi %hi(sys_trap), %g5 1159 jmp %g5 + %lo(sys_trap) 1160 sub %g0, 1, %g4 1161 SET_SIZE(ce_err) 1162 1163 #endif /* lint */ 1164 1165 1166 #if defined(lint) 1167 1168 void 1169 ce_err_tl1(void) 1170 {} 1171 1172 #else /* lint */ 1173 1174 /* 1175 * We don't use trap for CE detection. 1176 */ 1177 ENTRY_NP(ce_err_tl1) 1178 set trap, %g1 1179 rdpr %tt, %g3 1180 sethi %hi(sys_trap), %g5 1181 jmp %g5 + %lo(sys_trap) 1182 sub %g0, 1, %g4 1183 SET_SIZE(ce_err_tl1) 1184 1185 #endif /* lint */ 1186 1187 1188 #if defined(lint) 1189 1190 void 1191 async_err(void) 1192 {} 1193 1194 #else /* lint */ 1195 1196 /* 1197 * async_err is the default handler for IAE/DAE traps. 1198 * For OPL, we patch in the right handler at start of day. 1199 * But if a IAE/DAE trap get generated before the handler 1200 * is patched, panic. 1201 */ 1202 ENTRY_NP(async_err) 1203 set trap, %g1 1204 rdpr %tt, %g3 1205 sethi %hi(sys_trap), %g5 1206 jmp %g5 + %lo(sys_trap) 1207 sub %g0, 1, %g4 1208 SET_SIZE(async_err) 1209 1210 #endif /* lint */ 1211 1212 #if defined(lint) 1213 void 1214 opl_sync_trap(void) 1215 {} 1216 #else /* lint */ 1217 1218 .seg ".data" 1219 .global opl_clr_freg 1220 .global opl_cpu0_err_log 1221 1222 .align 16 1223 opl_clr_freg: 1224 .word 0 1225 .align 16 1226 1227 .align MMU_PAGESIZE 1228 opl_cpu0_err_log: 1229 .skip MMU_PAGESIZE 1230 1231 /* 1232 * Common synchronous error trap handler (tt=0xA, 0x32) 1233 * All TL=0 and TL>0 0xA and 0x32 traps vector to this handler. 1234 * The error handling can be best summarized as follows: 1235 * 0. Do TRAPTRACE if enabled. 1236 * 1. Save globals %g1, %g2 & %g3 onto the scratchpad regs. 1237 * 2. The SFSR register is read and verified as valid by checking 1238 * SFSR.FV bit being set. If the SFSR.FV is not set, the 1239 * error cases cannot be decoded/determined and the SFPAR 1240 * register that contain the physical faultaddr is also 1241 * not valid. Also the SPFAR is only valid for UE/TO/BERR error 1242 * cases. Assuming the SFSR.FV is valid: 1243 * - BERR(bus error)/TO(timeout)/UE case 1244 * If any of these error cases are detected, read the SFPAR 1245 * to get the faultaddress. Generate ereport. 1246 * - TLB Parity case (only recoverable case) 1247 * For DAE, read SFAR for the faultaddress. For IAE, 1248 * use %tpc for faultaddress (SFAR is not valid in IAE) 1249 * Flush all the tlbs. 1250 * Subtract one from the recoverable error count stored in 1251 * the error log scratch register. If the threshold limit 1252 * is reached (zero) - generate ereport. Else 1253 * restore globals and retry (no ereport is generated). 1254 * - TLB Multiple hits 1255 * For DAE, read SFAR for the faultaddress. For IAE, 1256 * use %tpc for faultaddress (SFAR is not valid in IAE). 1257 * Flush all tlbs and generate ereport. 1258 * 3. TL=0 and TL>0 considerations 1259 * - Since both TL=0 & TL>1 traps are made to vector into 1260 * the same handler, the underlying assumption/design here is 1261 * that any nested error condition (if happens) occurs only 1262 * in the handler and the system is assumed to eventually 1263 * Red-mode. With this philosophy in mind, the recoverable 1264 * TLB Parity error case never check the TL level before it 1265 * retry. Note that this is ok for the TL>1 case (assuming we 1266 * don't have a nested error) since we always save the globals 1267 * %g1, %g2 & %g3 whenever we enter this trap handler. 1268 * - Additional TL=0 vs TL>1 handling includes: 1269 * - For UE error occuring under TL>1, special handling 1270 * is added to prevent the unlikely chance of a cpu-lockup 1271 * when a UE was originally detected in user stack and 1272 * the spill trap handler taken from sys_trap() so happened 1273 * to reference the same UE location. Under the above 1274 * condition (TL>1 and UE error), paranoid code is added 1275 * to reset window regs so that spill traps can't happen 1276 * during the unwind back to TL=0 handling. 1277 * Note that we can do that because we are not returning 1278 * back. 1279 * 4. Ereport generation. 1280 * - Ereport generation is performed when we unwind to the TL=0 1281 * handling code via sys_trap(). on_trap()/lofault protection 1282 * will apply there. 1283 * 1284 */ 1285 ENTRY_NP(opl_sync_trap) 1286 #ifdef TRAPTRACE 1287 OPL_TRAPTRACE(%g1, %g2, %g3, opl_sync_trap_lb) 1288 rdpr %tt, %g1 1289 #endif /* TRAPTRACE */ 1290 cmp %g1, T_INSTR_ERROR 1291 bne,pt %xcc, 0f 1292 mov MMU_SFSR, %g3 1293 ldxa [%g3]ASI_IMMU, %g1 ! IAE trap case tt = 0xa 1294 andcc %g1, SFSR_FV, %g0 1295 bz,a,pn %xcc, 2f ! Branch if SFSR is invalid and 1296 rdpr %tpc, %g2 ! use %tpc for faultaddr instead 1297 1298 sethi %hi(SFSR_UE|SFSR_BERR|SFSR_TO), %g3 1299 andcc %g1, %g3, %g0 ! Check for UE/BERR/TO errors 1300 bz,a,pt %xcc, 1f ! Branch if not UE/BERR/TO and 1301 rdpr %tpc, %g2 ! use %tpc as faultaddr 1302 set OPL_MMU_SFPAR, %g3 ! In the UE/BERR/TO cases, use 1303 ba,pt %xcc, 2f ! SFPAR as faultaddr 1304 ldxa [%g3]ASI_IMMU, %g2 1305 0: 1306 ldxa [%g3]ASI_DMMU, %g1 ! DAE trap case tt = 0x32 1307 andcc %g1, SFSR_FV, %g0 1308 bnz,pt %xcc, 7f ! branch if SFSR.FV is valid 1309 mov MMU_SFAR, %g2 ! set %g2 to use SFAR 1310 ba,pt %xcc, 2f ! SFSR.FV is not valid, read SFAR 1311 ldxa [%g2]ASI_DMMU, %g2 ! for faultaddr 1312 7: 1313 sethi %hi(SFSR_UE|SFSR_BERR|SFSR_TO), %g3 1314 andcc %g1, %g3, %g0 ! Check UE/BERR/TO for valid SFPAR 1315 movnz %xcc, OPL_MMU_SFPAR, %g2 ! Use SFPAR instead of SFAR for 1316 ldxa [%g2]ASI_DMMU, %g2 ! faultaddr 1317 1: 1318 sethi %hi(SFSR_TLB_PRT), %g3 1319 andcc %g1, %g3, %g0 1320 bz,pt %xcc, 8f ! branch for TLB multi-hit check 1321 nop 1322 /* 1323 * This is the TLB parity error case and it is the 1324 * only retryable error case. 1325 * Only %g1, %g2 and %g3 are allowed 1326 */ 1327 FLUSH_ALL_TLB(%g3) 1328 set OPL_SCRATCHPAD_ERRLOG, %g3 1329 ldxa [%g3]ASI_SCRATCHPAD, %g3 ! Read errlog scratchreg 1330 and %g3, ERRLOG_REG_NUMERR_MASK, %g3! Extract the error count 1331 subcc %g3, 1, %g0 ! Subtract one from the count 1332 bz,pn %xcc, 2f ! too many TLB parity errs in a certain 1333 nop ! period, branch to generate ereport 1334 LOG_SYNC_REG(%g1, %g2, %g3) ! Record into the error log 1335 set OPL_SCRATCHPAD_ERRLOG, %g3 1336 ldxa [%g3]ASI_SCRATCHPAD, %g2 1337 sub %g2, 1, %g2 ! decrement error counter by 1 1338 stxa %g2, [%g3]ASI_SCRATCHPAD ! update the errlog scratchreg 1339 OPL_RESTORE_GLOBAL(%g1, %g2, %g3) 1340 retry 1341 8: 1342 sethi %hi(SFSR_TLB_MUL), %g3 1343 andcc %g1, %g3, %g0 1344 bz,pt %xcc, 2f ! check for the TLB multi-hit errors 1345 nop 1346 FLUSH_ALL_TLB(%g3) 1347 2: 1348 /* 1349 * non-retryable error handling 1350 * now we can use other registers since 1351 * we will not be returning back 1352 */ 1353 mov %g1, %g5 ! %g5 = SFSR 1354 mov %g2, %g6 ! %g6 = SFPAR or SFAR/tpc 1355 LOG_SYNC_REG(%g1, %g2, %g3) ! Record into the error log 1356 1357 /* 1358 * Special case for UE on user stack. 1359 * There is a possibility that the same error may come back here 1360 * by touching the same UE in spill trap handler taken from 1361 * sys_trap(). It ends up with an infinite loop causing a cpu lockup. 1362 * Conditions for this handling this case are: 1363 * - SFSR_FV is valid and SFSR_UE is set 1364 * - we are at TL > 1 1365 * If the above conditions are true, we force %cansave to be a 1366 * big number to prevent spill trap in sys_trap(). Note that 1367 * we will not be returning back. 1368 */ 1369 rdpr %tt, %g4 ! %g4 == ttype 1370 rdpr %tl, %g1 ! %g1 == tl 1371 cmp %g1, 1 ! Check if TL == 1 1372 be,pt %xcc, 3f ! branch if we came from TL=0 1373 nop 1374 andcc %g5, SFSR_FV, %g0 ! see if SFSR.FV is valid 1375 bz,pn %xcc, 4f ! branch, checking UE is meaningless 1376 sethi %hi(SFSR_UE), %g2 1377 andcc %g5, %g2, %g0 ! check for UE 1378 bz,pt %xcc, 4f ! branch if not UE 1379 nop 1380 RESET_WINREG(%g1) ! reset windows to prevent spills 1381 4: 1382 RESET_USER_RTT_REGS(%g2, %g3, opl_sync_trap_resetskip) 1383 opl_sync_trap_resetskip: 1384 mov %g5, %g3 ! pass SFSR to the 3rd arg 1385 mov %g6, %g2 ! pass SFAR to the 2nd arg 1386 set opl_cpu_isync_tl1_error, %g1 1387 set opl_cpu_dsync_tl1_error, %g6 1388 cmp %g4, T_INSTR_ERROR 1389 movne %icc, %g6, %g1 1390 ba,pt %icc, 6f 1391 nop 1392 3: 1393 mov %g5, %g3 ! pass SFSR to the 3rd arg 1394 mov %g6, %g2 ! pass SFAR to the 2nd arg 1395 set opl_cpu_isync_tl0_error, %g1 1396 set opl_cpu_dsync_tl0_error, %g6 1397 cmp %g4, T_INSTR_ERROR 1398 movne %icc, %g6, %g1 1399 6: 1400 sethi %hi(sys_trap), %g5 1401 jmp %g5 + %lo(sys_trap) 1402 mov PIL_15, %g4 1403 SET_SIZE(opl_sync_trap) 1404 #endif /* lint */ 1405 1406 #if defined(lint) 1407 void 1408 opl_uger_trap(void) 1409 {} 1410 #else /* lint */ 1411 /* 1412 * Common Urgent error trap handler (tt=0x40) 1413 * All TL=0 and TL>0 0x40 traps vector to this handler. 1414 * The error handling can be best summarized as follows: 1415 * 1. Read the Urgent error status register (UGERSR) 1416 * Faultaddress is N/A here and it is not collected. 1417 * 2. Check to see if we have a multiple errors case 1418 * If so, we enable WEAK_ED (weak error detection) bit 1419 * to prevent any potential error storms and branch directly 1420 * to generate ereport. (we don't decode/handle individual 1421 * error cases when we get a multiple error situation) 1422 * 3. Now look for the recoverable error cases which include 1423 * IUG_DTLB, IUG_ITLB or COREERR errors. If any of the 1424 * recoverable errors are detected, do the following: 1425 * - Flush all tlbs. 1426 * - Verify that we came from TL=0, if not, generate 1427 * ereport. Note that the reason we don't recover 1428 * at TL>0 is because the AGs might be corrupted or 1429 * inconsistent. We can't save/restore them into 1430 * the scratchpad regs like we did for opl_sync_trap(). 1431 * - Check the INSTEND[5:4] bits in the UGERSR. If the 1432 * value is 0x3 (11b), this error is not recoverable. 1433 * Generate ereport. 1434 * - Subtract one from the recoverable error count stored in 1435 * the error log scratch register. If the threshold limit 1436 * is reached (zero) - generate ereport. 1437 * - If the count is within the limit, update the count 1438 * in the error log register (subtract one). Log the error 1439 * info in the log buffer. Capture traptrace if enabled. 1440 * Retry (no ereport generated) 1441 * 4. The rest of the error cases are unrecoverable and will 1442 * be handled according (flushing regs, etc as required). 1443 * For details on these error cases (UGER_CRE, UGER_CTXT, etc..) 1444 * consult the OPL cpu/mem philosophy doc. 1445 * Ereport will be generated for these errors. 1446 * 5. Ereport generation. 1447 * - Ereport generation for urgent error trap always 1448 * result in a panic when we unwind to the TL=0 handling 1449 * code via sys_trap(). on_trap()/lofault protection do 1450 * not apply there. 1451 */ 1452 ENTRY_NP(opl_uger_trap) 1453 set ASI_UGERSR, %g2 1454 ldxa [%g2]ASI_AFSR, %g1 ! Read the UGERSR reg 1455 1456 set UGESR_MULTI, %g2 1457 andcc %g1, %g2, %g0 ! Check for Multi-errs 1458 bz,pt %xcc, opl_uger_is_recover ! branch if not Multi-errs 1459 nop 1460 set AFSR_ECR, %g2 1461 ldxa [%g2]ASI_AFSR, %g3 ! Enable Weak error 1462 or %g3, ASI_ECR_WEAK_ED, %g3 ! detect mode to prevent 1463 stxa %g3, [%g2]ASI_AFSR ! potential error storms 1464 ba %xcc, opl_uger_panic1 1465 nop 1466 1467 opl_uger_is_recover: 1468 set UGESR_CAN_RECOVER, %g2 ! Check for recoverable 1469 andcc %g1, %g2, %g0 ! errors i.e.IUG_DTLB, 1470 bz,pt %xcc, opl_uger_cre ! IUG_ITLB or COREERR 1471 nop 1472 1473 /* 1474 * Fall thru to handle recoverable case 1475 * Need to do the following additional checks to determine 1476 * if this is indeed recoverable. 1477 * 1. Error trap came from TL=0 and 1478 * 2. INSTEND[5:4] bits in UGERSR is not 0x3 1479 * 3. Recoverable error count limit not reached 1480 * 1481 */ 1482 FLUSH_ALL_TLB(%g3) 1483 rdpr %tl, %g3 ! Read TL 1484 cmp %g3, 1 ! Check if we came from TL=0 1485 bne,pt %xcc, opl_uger_panic ! branch if came from TL>0 1486 nop 1487 srlx %g1, 4, %g2 ! shift INSTEND[5:4] -> [1:0] 1488 and %g2, 3, %g2 ! extract the shifted [1:0] bits 1489 cmp %g2, 3 ! check if INSTEND is recoverable 1490 be,pt %xcc, opl_uger_panic ! panic if ([1:0] = 11b) 1491 nop 1492 set OPL_SCRATCHPAD_ERRLOG, %g3 1493 ldxa [%g3]ASI_SCRATCHPAD, %g2 ! Read errlog scratch reg 1494 and %g2, ERRLOG_REG_NUMERR_MASK, %g3! Extract error count and 1495 subcc %g3, 1, %g3 ! subtract one from it 1496 bz,pt %xcc, opl_uger_panic ! If count reached zero, too many 1497 nop ! errors, branch to generate ereport 1498 sub %g2, 1, %g2 ! Subtract one from the count 1499 set OPL_SCRATCHPAD_ERRLOG, %g3 ! and write back the updated 1500 stxa %g2, [%g3]ASI_SCRATCHPAD ! count into the errlog reg 1501 LOG_UGER_REG(%g1, %g2, %g3) ! Log the error info 1502 #ifdef TRAPTRACE 1503 OPL_TRAPTRACE(%g1, %g2, %g3, opl_uger_trap_lb) 1504 #endif /* TRAPTRACE */ 1505 retry ! retry - no ereport 1506 1507 /* 1508 * Process the rest of the unrecoverable error cases 1509 * All error cases below ultimately branch to either 1510 * opl_uger_panic or opl_uger_panic1. 1511 * opl_uger_panic1 is the same as opl_uger_panic except 1512 * for the additional execution of the RESET_TO_PRIV() 1513 * macro that does a heavy handed reset. Read the 1514 * comments for RESET_TO_PRIV() macro for more info. 1515 */ 1516 opl_uger_cre: 1517 set UGESR_IAUG_CRE, %g2 1518 andcc %g1, %g2, %g0 1519 bz,pt %xcc, opl_uger_ctxt 1520 nop 1521 IAG_CRE(%g2, %g3) 1522 set AFSR_ECR, %g2 1523 ldxa [%g2]ASI_AFSR, %g3 1524 or %g3, ASI_ECR_WEAK_ED, %g3 1525 stxa %g3, [%g2]ASI_AFSR 1526 ba %xcc, opl_uger_panic 1527 nop 1528 1529 opl_uger_ctxt: 1530 set UGESR_IAUG_TSBCTXT, %g2 1531 andcc %g1, %g2, %g0 1532 bz,pt %xcc, opl_uger_tsbp 1533 nop 1534 GET_CPU_IMPL(%g2) 1535 cmp %g2, JUPITER_IMPL 1536 bne %xcc, 1f 1537 nop 1538 RESET_SHARED_CTXT(%g2) 1539 1: 1540 RESET_MMU_REGS(%g2, %g3, %g4) 1541 ba %xcc, opl_uger_panic 1542 nop 1543 1544 opl_uger_tsbp: 1545 set UGESR_IUG_TSBP, %g2 1546 andcc %g1, %g2, %g0 1547 bz,pt %xcc, opl_uger_pstate 1548 nop 1549 GET_CPU_IMPL(%g2) 1550 cmp %g2, JUPITER_IMPL 1551 bne %xcc, 1f 1552 nop 1553 RESET_TSB_PREFETCH(%g2) 1554 1: 1555 RESET_TSB_TAGPTR(%g2) 1556 1557 /* 1558 * IUG_TSBP error may corrupt MMU registers 1559 * Reset them here. 1560 */ 1561 RESET_MMU_REGS(%g2, %g3, %g4) 1562 ba %xcc, opl_uger_panic 1563 nop 1564 1565 opl_uger_pstate: 1566 set UGESR_IUG_PSTATE, %g2 1567 andcc %g1, %g2, %g0 1568 bz,pt %xcc, opl_uger_tstate 1569 nop 1570 RESET_CUR_TSTATE(%g2) 1571 ba %xcc, opl_uger_panic1 1572 nop 1573 1574 opl_uger_tstate: 1575 set UGESR_IUG_TSTATE, %g2 1576 andcc %g1, %g2, %g0 1577 bz,pt %xcc, opl_uger_f 1578 nop 1579 RESET_PREV_TSTATE(%g2, %g3, opl_uger_tstate_1) 1580 ba %xcc, opl_uger_panic1 1581 nop 1582 1583 opl_uger_f: 1584 set UGESR_IUG_F, %g2 1585 andcc %g1, %g2, %g0 1586 bz,pt %xcc, opl_uger_r 1587 nop 1588 CLEAR_FPREGS(%g2) 1589 ba %xcc, opl_uger_panic 1590 nop 1591 1592 opl_uger_r: 1593 set UGESR_IUG_R, %g2 1594 andcc %g1, %g2, %g0 1595 bz,pt %xcc, opl_uger_panic1 1596 nop 1597 CLEAR_GEN_REGS(%g2, opl_uger_r_1) 1598 ba %xcc, opl_uger_panic1 1599 nop 1600 1601 opl_uger_panic: 1602 mov %g1, %g2 ! %g2 = arg #1 1603 LOG_UGER_REG(%g1, %g3, %g4) 1604 ba %xcc, opl_uger_panic_cmn 1605 nop 1606 1607 opl_uger_panic1: 1608 mov %g1, %g2 ! %g2 = arg #1 1609 LOG_UGER_REG(%g1, %g3, %g4) 1610 RESET_TO_PRIV(%g1, %g3, %g4, %l0) 1611 1612 /* 1613 * Set up the argument for sys_trap. 1614 * %g2 = arg #1 already set above 1615 */ 1616 opl_uger_panic_cmn: 1617 RESET_USER_RTT_REGS(%g4, %g5, opl_uger_panic_resetskip) 1618 opl_uger_panic_resetskip: 1619 rdpr %tl, %g3 ! arg #2 1620 set opl_cpu_urgent_error, %g1 ! pc 1621 sethi %hi(sys_trap), %g5 1622 jmp %g5 + %lo(sys_trap) 1623 mov PIL_15, %g4 1624 SET_SIZE(opl_uger_trap) 1625 #endif /* lint */ 1626 1627 #if defined(lint) 1628 void 1629 opl_ta3_trap(void) 1630 {} 1631 void 1632 opl_cleanw_subr(void) 1633 {} 1634 #else /* lint */ 1635 /* 1636 * OPL ta3 support (note please, that win_reg 1637 * area size for each cpu is 2^7 bytes) 1638 */ 1639 1640 #define RESTORE_WREGS(tmp1, tmp2) \ 1641 CPU_INDEX(tmp1, tmp2) ;\ 1642 sethi %hi(opl_ta3_save), tmp2 ;\ 1643 ldx [tmp2 +%lo(opl_ta3_save)], tmp2 ;\ 1644 sllx tmp1, 7, tmp1 ;\ 1645 add tmp2, tmp1, tmp2 ;\ 1646 ldx [tmp2 + 0], %l0 ;\ 1647 ldx [tmp2 + 8], %l1 ;\ 1648 ldx [tmp2 + 16], %l2 ;\ 1649 ldx [tmp2 + 24], %l3 ;\ 1650 ldx [tmp2 + 32], %l4 ;\ 1651 ldx [tmp2 + 40], %l5 ;\ 1652 ldx [tmp2 + 48], %l6 ;\ 1653 ldx [tmp2 + 56], %l7 ;\ 1654 ldx [tmp2 + 64], %i0 ;\ 1655 ldx [tmp2 + 72], %i1 ;\ 1656 ldx [tmp2 + 80], %i2 ;\ 1657 ldx [tmp2 + 88], %i3 ;\ 1658 ldx [tmp2 + 96], %i4 ;\ 1659 ldx [tmp2 + 104], %i5 ;\ 1660 ldx [tmp2 + 112], %i6 ;\ 1661 ldx [tmp2 + 120], %i7 1662 1663 #define SAVE_WREGS(tmp1, tmp2) \ 1664 CPU_INDEX(tmp1, tmp2) ;\ 1665 sethi %hi(opl_ta3_save), tmp2 ;\ 1666 ldx [tmp2 +%lo(opl_ta3_save)], tmp2 ;\ 1667 sllx tmp1, 7, tmp1 ;\ 1668 add tmp2, tmp1, tmp2 ;\ 1669 stx %l0, [tmp2 + 0] ;\ 1670 stx %l1, [tmp2 + 8] ;\ 1671 stx %l2, [tmp2 + 16] ;\ 1672 stx %l3, [tmp2 + 24] ;\ 1673 stx %l4, [tmp2 + 32] ;\ 1674 stx %l5, [tmp2 + 40] ;\ 1675 stx %l6, [tmp2 + 48] ;\ 1676 stx %l7, [tmp2 + 56] ;\ 1677 stx %i0, [tmp2 + 64] ;\ 1678 stx %i1, [tmp2 + 72] ;\ 1679 stx %i2, [tmp2 + 80] ;\ 1680 stx %i3, [tmp2 + 88] ;\ 1681 stx %i4, [tmp2 + 96] ;\ 1682 stx %i5, [tmp2 + 104] ;\ 1683 stx %i6, [tmp2 + 112] ;\ 1684 stx %i7, [tmp2 + 120] 1685 1686 1687 /* 1688 * The purpose of this function is to make sure that the restore 1689 * instruction after the flushw does not cause a fill trap. The sun4u 1690 * fill trap handler can not handle a tlb fault of an unmapped stack 1691 * except at the restore instruction at user_rtt. On OPL systems the 1692 * stack can get unmapped between the flushw and restore instructions 1693 * since multiple strands share the tlb. 1694 */ 1695 ENTRY_NP(opl_ta3_trap) 1696 set trap, %g1 1697 mov T_FLUSHW, %g3 1698 sub %g0, 1, %g4 1699 rdpr %cwp, %g5 1700 SAVE_WREGS(%g2, %g6) 1701 save 1702 flushw 1703 rdpr %cwp, %g6 1704 wrpr %g5, %cwp 1705 RESTORE_WREGS(%g2, %g5) 1706 wrpr %g6, %cwp 1707 restored 1708 restore 1709 1710 ba,a fast_trap_done 1711 SET_SIZE(opl_ta3_trap) 1712 1713 ENTRY_NP(opl_cleanw_subr) 1714 set trap, %g1 1715 mov T_FLUSHW, %g3 1716 sub %g0, 1, %g4 1717 rdpr %cwp, %g5 1718 SAVE_WREGS(%g2, %g6) 1719 save 1720 flushw 1721 rdpr %cwp, %g6 1722 wrpr %g5, %cwp 1723 RESTORE_WREGS(%g2, %g5) 1724 wrpr %g6, %cwp 1725 restored 1726 restore 1727 jmp %g7 1728 nop 1729 SET_SIZE(opl_cleanw_subr) 1730 #endif /* lint */ 1731 1732 #if defined(lint) 1733 1734 void 1735 opl_serr_instr(void) 1736 {} 1737 1738 #else /* lint */ 1739 /* 1740 * The actual trap handler for tt=0x0a, and tt=0x32 1741 */ 1742 ENTRY_NP(opl_serr_instr) 1743 OPL_SAVE_GLOBAL(%g1,%g2,%g3) 1744 sethi %hi(opl_sync_trap), %g3 1745 jmp %g3 + %lo(opl_sync_trap) 1746 rdpr %tt, %g1 1747 .align 32 1748 SET_SIZE(opl_serr_instr) 1749 1750 #endif /* lint */ 1751 1752 #if defined(lint) 1753 1754 void 1755 opl_ugerr_instr(void) 1756 {} 1757 1758 #else /* lint */ 1759 /* 1760 * The actual trap handler for tt=0x40 1761 */ 1762 ENTRY_NP(opl_ugerr_instr) 1763 sethi %hi(opl_uger_trap), %g3 1764 jmp %g3 + %lo(opl_uger_trap) 1765 nop 1766 .align 32 1767 SET_SIZE(opl_ugerr_instr) 1768 1769 #endif /* lint */ 1770 1771 #if defined(lint) 1772 1773 void 1774 opl_ta3_instr(void) 1775 {} 1776 1777 #else /* lint */ 1778 /* 1779 * The actual trap handler for tt=0x103 (flushw) 1780 */ 1781 ENTRY_NP(opl_ta3_instr) 1782 sethi %hi(opl_ta3_trap), %g3 1783 jmp %g3 + %lo(opl_ta3_trap) 1784 nop 1785 .align 32 1786 SET_SIZE(opl_ta3_instr) 1787 1788 #endif /* lint */ 1789 1790 #if defined(lint) 1791 1792 void 1793 opl_ta4_instr(void) 1794 {} 1795 1796 #else /* lint */ 1797 /* 1798 * The patch for the .clean_windows code 1799 */ 1800 ENTRY_NP(opl_ta4_instr) 1801 sethi %hi(opl_cleanw_subr), %g3 1802 add %g3, %lo(opl_cleanw_subr), %g3 1803 jmpl %g3, %g7 1804 add %g7, 8, %g7 1805 nop 1806 nop 1807 nop 1808 SET_SIZE(opl_ta4_instr) 1809 1810 #endif /* lint */ 1811 1812 #if defined(lint) 1813 /* 1814 * Get timestamp (stick). 1815 */ 1816 /* ARGSUSED */ 1817 void 1818 stick_timestamp(int64_t *ts) 1819 { 1820 } 1821 1822 #else /* lint */ 1823 1824 ENTRY_NP(stick_timestamp) 1825 rd STICK, %g1 ! read stick reg 1826 sllx %g1, 1, %g1 1827 srlx %g1, 1, %g1 ! clear npt bit 1828 1829 retl 1830 stx %g1, [%o0] ! store the timestamp 1831 SET_SIZE(stick_timestamp) 1832 1833 #endif /* lint */ 1834 1835 1836 #if defined(lint) 1837 /* 1838 * Set STICK adjusted by skew. 1839 */ 1840 /* ARGSUSED */ 1841 void 1842 stick_adj(int64_t skew) 1843 { 1844 } 1845 1846 #else /* lint */ 1847 1848 ENTRY_NP(stick_adj) 1849 rdpr %pstate, %g1 ! save processor state 1850 andn %g1, PSTATE_IE, %g3 1851 ba 1f ! cache align stick adj 1852 wrpr %g0, %g3, %pstate ! turn off interrupts 1853 1854 .align 16 1855 1: nop 1856 1857 rd STICK, %g4 ! read stick reg 1858 add %g4, %o0, %o1 ! adjust stick with skew 1859 wr %o1, %g0, STICK ! write stick reg 1860 1861 retl 1862 wrpr %g1, %pstate ! restore processor state 1863 SET_SIZE(stick_adj) 1864 1865 #endif /* lint */ 1866 1867 #if defined(lint) 1868 /* 1869 * Debugger-specific stick retrieval 1870 */ 1871 /*ARGSUSED*/ 1872 int 1873 kdi_get_stick(uint64_t *stickp) 1874 { 1875 return (0); 1876 } 1877 1878 #else /* lint */ 1879 1880 ENTRY_NP(kdi_get_stick) 1881 rd STICK, %g1 1882 stx %g1, [%o0] 1883 retl 1884 mov %g0, %o0 1885 SET_SIZE(kdi_get_stick) 1886 1887 #endif /* lint */ 1888 1889 #if defined(lint) 1890 1891 /*ARGSUSED*/ 1892 int 1893 dtrace_blksuword32(uintptr_t addr, uint32_t *data, int tryagain) 1894 { return (0); } 1895 1896 #else 1897 1898 ENTRY(dtrace_blksuword32) 1899 save %sp, -SA(MINFRAME + 4), %sp 1900 1901 rdpr %pstate, %l1 1902 andn %l1, PSTATE_IE, %l2 ! disable interrupts to 1903 wrpr %g0, %l2, %pstate ! protect our FPU diddling 1904 1905 rd %fprs, %l0 1906 andcc %l0, FPRS_FEF, %g0 1907 bz,a,pt %xcc, 1f ! if the fpu is disabled 1908 wr %g0, FPRS_FEF, %fprs ! ... enable the fpu 1909 1910 st %f0, [%fp + STACK_BIAS - 4] ! save %f0 to the stack 1911 1: 1912 set 0f, %l5 1913 /* 1914 * We're about to write a block full or either total garbage 1915 * (not kernel data, don't worry) or user floating-point data 1916 * (so it only _looks_ like garbage). 1917 */ 1918 ld [%i1], %f0 ! modify the block 1919 membar #Sync 1920 stn %l5, [THREAD_REG + T_LOFAULT] ! set up the lofault handler 1921 stda %d0, [%i0]ASI_BLK_COMMIT_S ! store the modified block 1922 membar #Sync 1923 flush %i0 ! flush instruction pipeline 1924 stn %g0, [THREAD_REG + T_LOFAULT] ! remove the lofault handler 1925 1926 bz,a,pt %xcc, 1f 1927 wr %g0, %l0, %fprs ! restore %fprs 1928 1929 ld [%fp + STACK_BIAS - 4], %f0 ! restore %f0 1930 1: 1931 1932 wrpr %g0, %l1, %pstate ! restore interrupts 1933 1934 ret 1935 restore %g0, %g0, %o0 1936 1937 0: 1938 membar #Sync 1939 stn %g0, [THREAD_REG + T_LOFAULT] ! remove the lofault handler 1940 1941 bz,a,pt %xcc, 1f 1942 wr %g0, %l0, %fprs ! restore %fprs 1943 1944 ld [%fp + STACK_BIAS - 4], %f0 ! restore %f0 1945 1: 1946 1947 wrpr %g0, %l1, %pstate ! restore interrupts 1948 1949 /* 1950 * If tryagain is set (%i2) we tail-call dtrace_blksuword32_err() 1951 * which deals with watchpoints. Otherwise, just return -1. 1952 */ 1953 brnz,pt %i2, 1f 1954 nop 1955 ret 1956 restore %g0, -1, %o0 1957 1: 1958 call dtrace_blksuword32_err 1959 restore 1960 1961 SET_SIZE(dtrace_blksuword32) 1962 #endif /* lint */ 1963 1964 #if defined(lint) 1965 /*ARGSUSED*/ 1966 void 1967 ras_cntr_reset(void *arg) 1968 { 1969 } 1970 #else 1971 ENTRY_NP(ras_cntr_reset) 1972 set OPL_SCRATCHPAD_ERRLOG, %o1 1973 ldxa [%o1]ASI_SCRATCHPAD, %o0 1974 or %o0, ERRLOG_REG_NUMERR_MASK, %o0 1975 retl 1976 stxa %o0, [%o1]ASI_SCRATCHPAD 1977 SET_SIZE(ras_cntr_reset) 1978 #endif /* lint */ 1979 1980 #if defined(lint) 1981 /* ARGSUSED */ 1982 void 1983 opl_error_setup(uint64_t cpu_err_log_pa) 1984 { 1985 } 1986 1987 #else /* lint */ 1988 ENTRY_NP(opl_error_setup) 1989 /* 1990 * Initialize the error log scratchpad register 1991 */ 1992 ldxa [%g0]ASI_EIDR, %o2 1993 sethi %hi(ERRLOG_REG_EIDR_MASK), %o1 1994 or %o1, %lo(ERRLOG_REG_EIDR_MASK), %o1 1995 and %o2, %o1, %o3 1996 sllx %o3, ERRLOG_REG_EIDR_SHIFT, %o2 1997 or %o2, %o0, %o3 1998 or %o3, ERRLOG_REG_NUMERR_MASK, %o0 1999 set OPL_SCRATCHPAD_ERRLOG, %o1 2000 stxa %o0, [%o1]ASI_SCRATCHPAD 2001 /* 2002 * Disable all restrainable error traps 2003 */ 2004 mov AFSR_ECR, %o1 2005 ldxa [%o1]ASI_AFSR, %o0 2006 andn %o0, ASI_ECR_RTE_UE|ASI_ECR_RTE_CEDG, %o0 2007 retl 2008 stxa %o0, [%o1]ASI_AFSR 2009 SET_SIZE(opl_error_setup) 2010 #endif /* lint */ 2011 2012 #if defined(lint) 2013 /* ARGSUSED */ 2014 void 2015 cpu_early_feature_init(void) 2016 { 2017 } 2018 #else /* lint */ 2019 ENTRY_NP(cpu_early_feature_init) 2020 /* 2021 * Enable MMU translating multiple page sizes for 2022 * sITLB and sDTLB. 2023 */ 2024 mov LSU_MCNTL, %o0 2025 ldxa [%o0] ASI_MCNTL, %o1 2026 or %o1, MCNTL_MPG_SITLB | MCNTL_MPG_SDTLB, %o1 2027 stxa %o1, [%o0] ASI_MCNTL 2028 /* 2029 * Demap all previous entries. 2030 */ 2031 sethi %hi(FLUSH_ADDR), %o1 2032 set DEMAP_ALL_TYPE, %o0 2033 stxa %g0, [%o0]ASI_DTLB_DEMAP 2034 stxa %g0, [%o0]ASI_ITLB_DEMAP 2035 retl 2036 flush %o1 2037 SET_SIZE(cpu_early_feature_init) 2038 #endif /* lint */ 2039 2040 #if defined(lint) 2041 /* 2042 * This function is called for each (enabled) CPU. We use it to 2043 * initialize error handling related registers. 2044 */ 2045 /*ARGSUSED*/ 2046 void 2047 cpu_feature_init(void) 2048 {} 2049 #else /* lint */ 2050 ENTRY(cpu_feature_init) 2051 ! 2052 ! get the device_id and store the device_id 2053 ! in the appropriate cpunodes structure 2054 ! given the cpus index 2055 ! 2056 CPU_INDEX(%o0, %o1) 2057 mulx %o0, CPU_NODE_SIZE, %o0 2058 set cpunodes + DEVICE_ID, %o1 2059 ldxa [%g0] ASI_DEVICE_SERIAL_ID, %o2 2060 stx %o2, [%o0 + %o1] 2061 ! 2062 ! initialize CPU registers 2063 ! 2064 ba opl_cpu_reg_init 2065 nop 2066 SET_SIZE(cpu_feature_init) 2067 #endif /* lint */ 2068 2069 #if defined(lint) 2070 2071 void 2072 cpu_cleartickpnt(void) 2073 {} 2074 2075 #else /* lint */ 2076 /* 2077 * Clear the NPT (non-privileged trap) bit in the %tick/%stick 2078 * registers. In an effort to make the change in the 2079 * tick/stick counter as consistent as possible, we disable 2080 * all interrupts while we're changing the registers. We also 2081 * ensure that the read and write instructions are in the same 2082 * line in the instruction cache. 2083 */ 2084 ENTRY_NP(cpu_clearticknpt) 2085 rdpr %pstate, %g1 /* save processor state */ 2086 andn %g1, PSTATE_IE, %g3 /* turn off */ 2087 wrpr %g0, %g3, %pstate /* interrupts */ 2088 rdpr %tick, %g2 /* get tick register */ 2089 brgez,pn %g2, 1f /* if NPT bit off, we're done */ 2090 mov 1, %g3 /* create mask */ 2091 sllx %g3, 63, %g3 /* for NPT bit */ 2092 ba,a,pt %xcc, 2f 2093 .align 8 /* Ensure rd/wr in same i$ line */ 2094 2: 2095 rdpr %tick, %g2 /* get tick register */ 2096 wrpr %g3, %g2, %tick /* write tick register, */ 2097 /* clearing NPT bit */ 2098 1: 2099 rd STICK, %g2 /* get stick register */ 2100 brgez,pn %g2, 3f /* if NPT bit off, we're done */ 2101 mov 1, %g3 /* create mask */ 2102 sllx %g3, 63, %g3 /* for NPT bit */ 2103 ba,a,pt %xcc, 4f 2104 .align 8 /* Ensure rd/wr in same i$ line */ 2105 4: 2106 rd STICK, %g2 /* get stick register */ 2107 wr %g3, %g2, STICK /* write stick register, */ 2108 /* clearing NPT bit */ 2109 3: 2110 jmp %g4 + 4 2111 wrpr %g0, %g1, %pstate /* restore processor state */ 2112 2113 SET_SIZE(cpu_clearticknpt) 2114 2115 #endif /* lint */ 2116 2117 #if defined(lint) 2118 2119 void 2120 cpu_halt_cpu(void) 2121 {} 2122 2123 void 2124 cpu_smt_pause(void) 2125 {} 2126 2127 #else /* lint */ 2128 2129 /* 2130 * Halt the current strand with the suspend instruction. 2131 * The compiler/asm currently does not support this suspend 2132 * instruction mnemonic, use byte code for now. 2133 */ 2134 ENTRY_NP(cpu_halt_cpu) 2135 .word 0x81b01040 2136 retl 2137 nop 2138 SET_SIZE(cpu_halt_cpu) 2139 2140 /* 2141 * Pause the current strand with the sleep instruction. 2142 * The compiler/asm currently does not support this sleep 2143 * instruction mnemonic, use byte code for now. 2144 */ 2145 ENTRY_NP(cpu_smt_pause) 2146 .word 0x81b01060 2147 retl 2148 nop 2149 SET_SIZE(cpu_smt_pause) 2150 2151 #endif /* lint */