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 */ 73void 74vtag_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 */ 1141: 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 152void 153vtag_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 */ 178void 179vtag_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 2061: 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 */ 234void 235vtag_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 2724: 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 2811: 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 3053: 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*/ 324void 325vtag_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 */ 352void 353vac_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 */ 368void 369vac_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 */ 384void 385vac_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 */ 402void 403vac_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 416int 417idsr_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 4351: 436 retl 437 nop 438 SET_SIZE(idsr_busy) 439 440#endif /* lint */ 441 442#if defined(lint) 443 444/* ARGSUSED */ 445void 446init_mondo(xcfunc_t *func, uint64_t arg1, uint64_t arg2) 447{} 448 449/* ARGSUSED */ 450void 451init_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 ! 4871: 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 */ 515void 516shipit(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 */ 541void 542flush_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*/ 578void 579flush_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*/ 599void 600kdi_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]; \ 663label/**/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 ;\ 944label/**/1: ;\ 945 wrpr tmp1, PSTATE_AG, %pstate ;\ 946 CLEAR_GLOBALS() ;\ 947 rdpr %pstate, tmp1 ;\ 948 wrpr tmp1, PSTATE_AG, %pstate ;\ 949label/**/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 ;\ 980label/**/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 1130void 1131ce_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 11511: 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 1168void 1169ce_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 1190void 1191async_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) 1213void 1214opl_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 1223opl_clr_freg: 1224 .word 0 1225 .align 16 1226 1227 .align MMU_PAGESIZE 1228opl_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 13050: 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 13127: 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 13171: 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 13418: 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) 13472: 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 13814: 1382 RESET_USER_RTT_REGS(%g2, %g3, opl_sync_trap_resetskip) 1383opl_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 13923: 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 13996: 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) 1407void 1408opl_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 1467opl_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 */ 1516opl_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 1529opl_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) 15391: 1540 RESET_MMU_REGS(%g2, %g3, %g4) 1541 ba %xcc, opl_uger_panic 1542 nop 1543 1544opl_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) 15541: 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 1565opl_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 1574opl_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 1583opl_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 1592opl_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 1601opl_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 1607opl_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 */ 1616opl_uger_panic_cmn: 1617 RESET_USER_RTT_REGS(%g4, %g5, opl_uger_panic_resetskip) 1618opl_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) 1628void 1629opl_ta3_trap(void) 1630{} 1631void 1632opl_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 1734void 1735opl_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 1754void 1755opl_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 1773void 1774opl_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 1792void 1793opl_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 */ 1817void 1818stick_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 */ 1841void 1842stick_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 18551: 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*/ 1872int 1873kdi_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*/ 1892int 1893dtrace_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 19111: 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 19301: 1931 1932 wrpr %g0, %l1, %pstate ! restore interrupts 1933 1934 ret 1935 restore %g0, %g0, %o0 1936 19370: 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 19451: 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 19571: 1958 call dtrace_blksuword32_err 1959 restore 1960 1961 SET_SIZE(dtrace_blksuword32) 1962#endif /* lint */ 1963 1964#if defined(lint) 1965/*ARGSUSED*/ 1966void 1967ras_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 */ 1982void 1983opl_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 */ 2014void 2015cpu_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*/ 2046void 2047cpu_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 2071void 2072cpu_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 */ 20942: 2095 rdpr %tick, %g2 /* get tick register */ 2096 wrpr %g3, %g2, %tick /* write tick register, */ 2097 /* clearing NPT bit */ 20981: 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 */ 21054: 2106 rd STICK, %g2 /* get stick register */ 2107 wr %g3, %g2, STICK /* write stick register, */ 2108 /* clearing NPT bit */ 21093: 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 2119void 2120cpu_halt_cpu(void) 2121{} 2122 2123void 2124cpu_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 */ 2152