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 */