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 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  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/privregs.h>
  39 #include <sys/asm_linkage.h>
  40 #include <sys/machasi.h>
  41 #include <sys/trap.h>
  42 #include <sys/spitregs.h>
  43 #include <sys/xc_impl.h>
  44 #include <sys/intreg.h>
  45 #include <sys/async.h>
  46 
  47 #ifdef TRAPTRACE
  48 #include <sys/traptrace.h>
  49 #endif /* TRAPTRACE */
  50 
  51 #ifndef lint
  52 
  53 /* BEGIN CSTYLED */
  54 #define DCACHE_FLUSHPAGE(arg1, arg2, tmp1, tmp2, tmp3)                  \
  55         ldxa    [%g0]ASI_LSU, tmp1                                      ;\
  56         btst    LSU_DC, tmp1            /* is dcache enabled? */        ;\
  57         bz,pn   %icc, 1f                                                ;\
  58         sethi   %hi(dcache_linesize), tmp1                              ;\
  59         ld      [tmp1 + %lo(dcache_linesize)], tmp1                     ;\
  60         sethi   %hi(dflush_type), tmp2                                  ;\
  61         ld      [tmp2 + %lo(dflush_type)], tmp2                         ;\
  62         cmp     tmp2, FLUSHPAGE_TYPE                                    ;\
  63         be,pt   %icc, 2f                                                ;\
  64         sllx    arg1, SF_DC_VBIT_SHIFT, arg1    /* tag to compare */    ;\
  65         sethi   %hi(dcache_size), tmp3                                  ;\
  66         ld      [tmp3 + %lo(dcache_size)], tmp3                         ;\
  67         cmp     tmp2, FLUSHMATCH_TYPE                                   ;\
  68         be,pt   %icc, 3f                                                ;\
  69         nop                                                             ;\
  70         /*                                                              \
  71          * flushtype = FLUSHALL_TYPE, flush the whole thing             \
  72          * tmp3 = cache size                                            \
  73          * tmp1 = cache line size                                       \
  74          */                                                             \
  75         sub     tmp3, tmp1, tmp2                                        ;\
  76 4:                                                                      \
  77         stxa    %g0, [tmp2]ASI_DC_TAG                                   ;\
  78         membar  #Sync                                                   ;\
  79         cmp     %g0, tmp2                                               ;\
  80         bne,pt  %icc, 4b                                                ;\
  81         sub     tmp2, tmp1, tmp2                                        ;\
  82         ba,pt   %icc, 1f                                                ;\
  83         nop                                                             ;\
  84         /*                                                              \
  85          * flushtype = FLUSHPAGE_TYPE                                   \
  86          * arg1 = tag to compare against                                \
  87          * arg2 = virtual color                                         \
  88          * tmp1 = cache line size                                       \
  89          * tmp2 = tag from cache                                        \
  90          * tmp3 = counter                                               \
  91          */                                                             \
  92 2:                                                                      \
  93         set     MMU_PAGESIZE, tmp3                                      ;\
  94         sllx    arg2, MMU_PAGESHIFT, arg2  /* color to dcache page */   ;\
  95         sub     tmp3, tmp1, tmp3                                        ;\
  96 4:                                                                      \
  97         ldxa    [arg2 + tmp3]ASI_DC_TAG, tmp2   /* read tag */          ;\
  98         btst    SF_DC_VBIT_MASK, tmp2                                   ;\
  99         bz,pn   %icc, 5f          /* branch if no valid sub-blocks */   ;\
 100         andn    tmp2, SF_DC_VBIT_MASK, tmp2     /* clear out v bits */  ;\
 101         cmp     tmp2, arg1                                              ;\
 102         bne,pn  %icc, 5f                        /* br if tag miss */    ;\
 103         nop                                                             ;\
 104         stxa    %g0, [arg2 + tmp3]ASI_DC_TAG                            ;\
 105         membar  #Sync                                                   ;\
 106 5:                                                                      \
 107         cmp     %g0, tmp3                                               ;\
 108         bnz,pt  %icc, 4b                /* branch if not done */        ;\
 109         sub     tmp3, tmp1, tmp3                                        ;\
 110         ba,pt   %icc, 1f                                                ;\
 111         nop                                                             ;\
 112         /*                                                              \
 113          * flushtype = FLUSHMATCH_TYPE                                  \
 114          * arg1 = tag to compare against                                \
 115          * tmp1 = cache line size                                       \
 116          * tmp3 = cache size                                            \
 117          * arg2 = counter                                               \
 118          * tmp2 = cache tag                                             \
 119          */                                                             \
 120 3:                                                                      \
 121         sub     tmp3, tmp1, arg2                                        ;\
 122 4:                                                                      \
 123         ldxa    [arg2]ASI_DC_TAG, tmp2          /* read tag */          ;\
 124         btst    SF_DC_VBIT_MASK, tmp2                                   ;\
 125         bz,pn   %icc, 5f                /* br if no valid sub-blocks */ ;\
 126         andn    tmp2, SF_DC_VBIT_MASK, tmp2     /* clear out v bits */  ;\
 127         cmp     tmp2, arg1                                              ;\
 128         bne,pn  %icc, 5f                /* branch if tag miss */        ;\
 129         nop                                                             ;\
 130         stxa    %g0, [arg2]ASI_DC_TAG                                   ;\
 131         membar  #Sync                                                   ;\
 132 5:                                                                      \
 133         cmp     %g0, arg2                                               ;\
 134         bne,pt  %icc, 4b                /* branch if not done */        ;\
 135         sub     arg2, tmp1, arg2                                        ;\
 136 1:
 137 
 138 /*
 139  * macro that flushes the entire dcache color
 140  */
 141 #define DCACHE_FLUSHCOLOR(arg, tmp1, tmp2)                              \
 142         ldxa    [%g0]ASI_LSU, tmp1;                                     \
 143         btst    LSU_DC, tmp1;           /* is dcache enabled? */        \
 144         bz,pn   %icc, 1f;                                               \
 145         sethi   %hi(dcache_linesize), tmp1;                             \
 146         ld      [tmp1 + %lo(dcache_linesize)], tmp1;                    \
 147         set     MMU_PAGESIZE, tmp2;                                     \
 148         /*                                                              \
 149          * arg = virtual color                                          \
 150          * tmp2 = page size                                             \
 151          * tmp1 = cache line size                                       \
 152          */                                                             \
 153         sllx    arg, MMU_PAGESHIFT, arg; /* color to dcache page */     \
 154         sub     tmp2, tmp1, tmp2;                                       \
 155 2:                                                                      \
 156         stxa    %g0, [arg + tmp2]ASI_DC_TAG;                            \
 157         membar  #Sync;                                                  \
 158         cmp     %g0, tmp2;                                              \
 159         bne,pt  %icc, 2b;                                               \
 160         sub     tmp2, tmp1, tmp2;                                       \
 161 1:
 162 
 163 /*
 164  * macro that flushes the entire dcache
 165  */
 166 #define DCACHE_FLUSHALL(size, linesize, tmp)                            \
 167         ldxa    [%g0]ASI_LSU, tmp;                                      \
 168         btst    LSU_DC, tmp;            /* is dcache enabled? */        \
 169         bz,pn   %icc, 1f;                                               \
 170                                                                         \
 171         sub     size, linesize, tmp;                                    \
 172 2:                                                                      \
 173         stxa    %g0, [tmp]ASI_DC_TAG;                                   \
 174         membar  #Sync;                                                  \
 175         cmp     %g0, tmp;                                               \
 176         bne,pt  %icc, 2b;                                               \
 177         sub     tmp, linesize, tmp;                                     \
 178 1:
 179 
 180 /*
 181  * macro that flushes the entire icache
 182  */
 183 #define ICACHE_FLUSHALL(size, linesize, tmp)                            \
 184         ldxa    [%g0]ASI_LSU, tmp;                                      \
 185         btst    LSU_IC, tmp;                                            \
 186         bz,pn   %icc, 1f;                                               \
 187                                                                         \
 188         sub     size, linesize, tmp;                                    \
 189 2:                                                                      \
 190         stxa    %g0, [tmp]ASI_IC_TAG;                                   \
 191         membar  #Sync;                                                  \
 192         cmp     %g0, tmp;                                               \
 193         bne,pt  %icc, 2b;                                               \
 194         sub     tmp, linesize, tmp;                                     \
 195 1:
 196 
 197 #ifdef SF_ERRATA_32
 198 #define SF_WORKAROUND(tmp1, tmp2)                               \
 199         sethi   %hi(FLUSH_ADDR), tmp2                           ;\
 200         set     MMU_PCONTEXT, tmp1                              ;\
 201         stxa    %g0, [tmp1]ASI_DMMU                             ;\
 202         flush   tmp2                                            ;
 203 #else
 204 #define SF_WORKAROUND(tmp1, tmp2)
 205 #endif /* SF_ERRATA_32 */
 206 
 207 /*
 208  * arg1 = vaddr
 209  * arg2 = ctxnum
 210  *      - disable interrupts and clear address mask
 211  *        to access 64 bit physaddr
 212  *      - Blow out the TLB, flush user page.
 213  *        . use secondary context.
 214  */
 215 #define VTAG_FLUSHUPAGE(lbl, arg1, arg2, tmp1, tmp2, tmp3, tmp4) \
 216         rdpr    %pstate, tmp1                                   ;\
 217         andn    tmp1, PSTATE_IE, tmp2                           ;\
 218         wrpr    tmp2, 0, %pstate                                ;\
 219         sethi   %hi(FLUSH_ADDR), tmp2                           ;\
 220         set     MMU_SCONTEXT, tmp3                              ;\
 221         ldxa    [tmp3]ASI_DMMU, tmp4                            ;\
 222         or      DEMAP_SECOND | DEMAP_PAGE_TYPE, arg1, arg1      ;\
 223         cmp     tmp4, arg2                                      ;\
 224         be,a,pt %icc, lbl/**/4                                  ;\
 225           nop                                                   ;\
 226         stxa    arg2, [tmp3]ASI_DMMU                            ;\
 227 lbl/**/4:                                                       ;\
 228         stxa    %g0, [arg1]ASI_DTLB_DEMAP                       ;\
 229         stxa    %g0, [arg1]ASI_ITLB_DEMAP                       ;\
 230         flush   tmp2                                            ;\
 231         be,a,pt %icc, lbl/**/5                                  ;\
 232           nop                                                   ;\
 233         stxa    tmp4, [tmp3]ASI_DMMU                            ;\
 234         flush   tmp2                                            ;\
 235 lbl/**/5:                                                       ;\
 236         wrpr    %g0, tmp1, %pstate
 237 
 238         
 239 /*
 240  * macro that flushes all the user entries in dtlb
 241  * arg1 = dtlb entries
 242  *      - Before first compare:
 243  *              tmp4 = tte
 244  *              tmp5 = vaddr
 245  *              tmp6 = cntxnum
 246  */
 247 #define DTLB_FLUSH_UNLOCKED_UCTXS(lbl, arg1, tmp1, tmp2, tmp3, \
 248                                 tmp4, tmp5, tmp6) \
 249 lbl/**/0:                                                       ;\
 250         sllx    arg1, 3, tmp3                                   ;\
 251         SF_WORKAROUND(tmp1, tmp2)                               ;\
 252         ldxa    [tmp3]ASI_DTLB_ACCESS, tmp4                     ;\
 253         srlx    tmp4, 6, tmp4                                   ;\
 254         andcc   tmp4, 1, %g0                                    ;\
 255         bnz,pn  %xcc, lbl/**/1                                  ;\
 256         srlx    tmp4, 57, tmp4                                  ;\
 257         andcc   tmp4, 1, %g0                                    ;\
 258         beq,pn  %xcc, lbl/**/1                                  ;\
 259           nop                                                   ;\
 260         set     TAGREAD_CTX_MASK, tmp1                          ;\
 261         ldxa    [tmp3]ASI_DTLB_TAGREAD, tmp2                    ;\
 262         and     tmp2, tmp1, tmp6                                ;\
 263         andn    tmp2, tmp1, tmp5                                ;\
 264         set     KCONTEXT, tmp4                                  ;\
 265         cmp     tmp6, tmp4                                      ;\
 266         be      lbl/**/1                                        ;\
 267           nop                                                   ;\
 268         VTAG_FLUSHUPAGE(VD/**/lbl, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4) ;\
 269 lbl/**/1:                                                       ;\
 270         brgz,pt arg1, lbl/**/0                                  ;\
 271           sub     arg1, 1, arg1
 272 
 273 
 274 /*
 275  * macro that flushes all the user entries in itlb      
 276  * arg1 = itlb entries
 277  *      - Before first compare:
 278  *              tmp4 = tte
 279  *              tmp5 = vaddr
 280  *              tmp6 = cntxnum
 281  */
 282 #define ITLB_FLUSH_UNLOCKED_UCTXS(lbl, arg1, tmp1, tmp2, tmp3, \
 283                                 tmp4, tmp5, tmp6) \
 284 lbl/**/0:                                                       ;\
 285         sllx    arg1, 3, tmp3                                   ;\
 286         SF_WORKAROUND(tmp1, tmp2)                               ;\
 287         ldxa    [tmp3]ASI_ITLB_ACCESS, tmp4                     ;\
 288         srlx    tmp4, 6, tmp4                                   ;\
 289         andcc   tmp4, 1, %g0                                    ;\
 290         bnz,pn  %xcc, lbl/**/1                                  ;\
 291         srlx    tmp4, 57, tmp4                                  ;\
 292         andcc   tmp4, 1, %g0                                    ;\
 293         beq,pn  %xcc, lbl/**/1                                  ;\
 294           nop                                                   ;\
 295         set     TAGREAD_CTX_MASK, tmp1                          ;\
 296         ldxa    [tmp3]ASI_ITLB_TAGREAD, tmp2                    ;\
 297         and     tmp2, tmp1, tmp6                                ;\
 298         andn    tmp2, tmp1, tmp5                                ;\
 299         set     KCONTEXT, tmp4                                  ;\
 300         cmp     tmp6, tmp4                                      ;\
 301         be      lbl/**/1                                        ;\
 302           nop                                                   ;\
 303         VTAG_FLUSHUPAGE(VI/**/lbl, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4) ;\
 304 lbl/**/1:                                                       ;\
 305         brgz,pt arg1, lbl/**/0                                  ;\
 306         sub     arg1, 1, arg1
 307 
 308 
 309         
 310 /*
 311  * Macro for getting to offset from 'cpu_private' ptr. The 'cpu_private'
 312  * ptr is in the machcpu structure.
 313  * r_or_s:      Register or symbol off offset from 'cpu_private' ptr.
 314  * scr1:        Scratch, ptr is returned in this register.
 315  * scr2:        Scratch
 316  */
 317 #define GET_CPU_PRIVATE_PTR(r_or_s, scr1, scr2, label)          \
 318         CPU_ADDR(scr1, scr2);                                           \
 319         ldn     [scr1 + CPU_PRIVATE], scr1;                             \
 320         cmp     scr1, 0;                                                \
 321         be      label;                                                  \
 322          nop;                                                           \
 323         add     scr1, r_or_s, scr1;                                     \
 324 
 325 #ifdef HUMMINGBIRD
 326 /*
 327  * UltraSPARC-IIe processor supports both 4-way set associative and
 328  * direct map E$. For performance reasons, we flush E$ by placing it
 329  * in direct map mode for data load/store and restore the state after
 330  * we are done flushing it. Keep interrupts off while flushing in this
 331  * manner.
 332  *
 333  * We flush the entire ecache by starting at one end and loading each
 334  * successive ecache line for the 2*ecache-size range. We have to repeat
 335  * the flush operation to guarantee that the entire ecache has been
 336  * flushed.
 337  *
 338  * For flushing a specific physical address, we start at the aliased
 339  * address and load at set-size stride, wrapping around at 2*ecache-size
 340  * boundary and skipping the physical address being flushed. It takes
 341  * 10 loads to guarantee that the physical address has been flushed.
 342  */
 343 
 344 #define HB_ECACHE_FLUSH_CNT     2
 345 #define HB_PHYS_FLUSH_CNT       10      /* #loads to flush specific paddr */
 346 #endif /* HUMMINGBIRD */
 347 
 348 /* END CSTYLED */
 349 
 350 #endif  /* !lint */
 351 
 352 /*
 353  * Spitfire MMU and Cache operations.
 354  */
 355 
 356 #if defined(lint)
 357 
 358 /*ARGSUSED*/
 359 void
 360 vtag_flushpage(caddr_t vaddr, uint64_t sfmmup)
 361 {}
 362 
 363 /*ARGSUSED*/
 364 void
 365 vtag_flushall(void)
 366 {}
 367         
 368 /*ARGSUSED*/
 369 void
 370 vtag_flushall_uctxs(void)
 371 {}
 372                 
 373 /*ARGSUSED*/
 374 void
 375 vtag_flushpage_tl1(uint64_t vaddr, uint64_t sfmmup)
 376 {}
 377 
 378 /*ARGSUSED*/
 379 void
 380 vtag_flush_pgcnt_tl1(uint64_t vaddr, uint64_t sfmmup_pgcnt)
 381 {}
 382 
 383 /*ARGSUSED*/
 384 void
 385 vtag_flushall_tl1(uint64_t dummy1, uint64_t dummy2)
 386 {}
 387 
 388 /*ARGSUSED*/
 389 void
 390 vac_flushpage(pfn_t pfnum, int vcolor)
 391 {}
 392 
 393 /*ARGSUSED*/
 394 void
 395 vac_flushpage_tl1(uint64_t pfnum, uint64_t vcolor)
 396 {}
 397 
 398 /*ARGSUSED*/
 399 void
 400 init_mondo(xcfunc_t *func, uint64_t arg1, uint64_t arg2)
 401 {}
 402 
 403 /*ARGSUSED*/
 404 void
 405 init_mondo_nocheck(xcfunc_t *func, uint64_t arg1, uint64_t arg2)
 406 {}
 407 
 408 /*ARGSUSED*/
 409 void
 410 flush_instr_mem(caddr_t vaddr, size_t len)
 411 {}
 412 
 413 /*ARGSUSED*/
 414 void
 415 flush_ecache(uint64_t physaddr, size_t size, size_t linesize)
 416 {}
 417 
 418 /*ARGSUSED*/
 419 void
 420 get_ecache_dtag(uint32_t ecache_idx, uint64_t *ecache_data,
 421                 uint64_t *ecache_tag, uint64_t *oafsr, uint64_t *acc_afsr)
 422 {}
 423 
 424 /* ARGSUSED */
 425 uint64_t
 426 get_ecache_tag(uint32_t id, uint64_t *nafsr, uint64_t *acc_afsr)
 427 {
 428         return ((uint64_t)0);
 429 }
 430 
 431 /* ARGSUSED */
 432 uint64_t
 433 check_ecache_line(uint32_t id, uint64_t *acc_afsr)
 434 {
 435         return ((uint64_t)0);
 436 }
 437 
 438 /*ARGSUSED*/
 439 void
 440 kdi_flush_idcache(int dcache_size, int dcache_lsize,
 441     int icache_size, int icache_lsize)
 442 {}
 443 
 444 #else   /* lint */
 445 
 446         ENTRY_NP(vtag_flushpage)
 447         /*
 448          * flush page from the tlb
 449          *
 450          * %o0 = vaddr
 451          * %o1 = sfmmup
 452          */
 453         rdpr    %pstate, %o5
 454 #ifdef DEBUG
 455         PANIC_IF_INTR_DISABLED_PSTR(%o5, sfdi_label1, %g1)
 456 #endif /* DEBUG */
 457         /*
 458          * disable ints
 459          */
 460         andn    %o5, PSTATE_IE, %o4
 461         wrpr    %o4, 0, %pstate
 462 
 463         /*
 464          * Then, blow out the tlb
 465          * Interrupts are disabled to prevent the secondary ctx register
 466          * from changing underneath us.
 467          */
 468         sethi   %hi(ksfmmup), %o3
 469         ldx     [%o3 + %lo(ksfmmup)], %o3
 470         cmp     %o3, %o1
 471         bne,pt   %xcc, 1f                       ! if not kernel as, go to 1
 472           sethi %hi(FLUSH_ADDR), %o3
 473         /*
 474          * For KCONTEXT demaps use primary. type = page implicitly
 475          */
 476         stxa    %g0, [%o0]ASI_DTLB_DEMAP        /* dmmu flush for KCONTEXT */
 477         stxa    %g0, [%o0]ASI_ITLB_DEMAP        /* immu flush for KCONTEXT */
 478         flush   %o3
 479         b       5f
 480           nop
 481 1:
 482         /*
 483          * User demap.  We need to set the secondary context properly.
 484          * %o0 = vaddr
 485          * %o1 = sfmmup
 486          * %o3 = FLUSH_ADDR
 487          */
 488         SFMMU_CPU_CNUM(%o1, %g1, %g2)   /* %g1 = sfmmu cnum on this CPU */
 489         
 490         set     MMU_SCONTEXT, %o4
 491         ldxa    [%o4]ASI_DMMU, %o2              /* rd old ctxnum */
 492         or      DEMAP_SECOND | DEMAP_PAGE_TYPE, %o0, %o0
 493         cmp     %o2, %g1
 494         be,pt   %icc, 4f
 495           nop
 496         stxa    %g1, [%o4]ASI_DMMU              /* wr new ctxum */
 497 4:
 498         stxa    %g0, [%o0]ASI_DTLB_DEMAP
 499         stxa    %g0, [%o0]ASI_ITLB_DEMAP
 500         flush   %o3
 501         be,pt   %icc, 5f
 502           nop
 503         stxa    %o2, [%o4]ASI_DMMU              /* restore old ctxnum */
 504         flush   %o3
 505 5:
 506         retl
 507           wrpr  %g0, %o5, %pstate               /* enable interrupts */
 508         SET_SIZE(vtag_flushpage)
 509         
 510         .seg    ".text"
 511 .flushallmsg:
 512         .asciz  "sfmmu_asm: unimplemented flush operation"
 513 
 514         ENTRY_NP(vtag_flushall)
 515         sethi   %hi(.flushallmsg), %o0
 516         call    panic
 517           or    %o0, %lo(.flushallmsg), %o0
 518         SET_SIZE(vtag_flushall)
 519 
 520         ENTRY_NP(vtag_flushall_uctxs)
 521         /*
 522          * flush entire DTLB/ITLB.
 523          */
 524         CPU_INDEX(%g1, %g2)
 525         mulx    %g1, CPU_NODE_SIZE, %g1
 526         set     cpunodes, %g2
 527         add     %g1, %g2, %g1
 528         lduh    [%g1 + ITLB_SIZE], %g2          ! %g2 = # entries in ITLB
 529         lduh    [%g1 + DTLB_SIZE], %g1          ! %g1 = # entries in DTLB
 530         sub     %g2, 1, %g2                     ! %g2 = # entries in ITLB - 1
 531         sub     %g1, 1, %g1                     ! %g1 = # entries in DTLB - 1
 532 
 533         !
 534         ! Flush itlb's
 535         !
 536         ITLB_FLUSH_UNLOCKED_UCTXS(I, %g2, %g3, %g4, %o2, %o3, %o4, %o5)
 537 
 538         !
 539         ! Flush dtlb's
 540         !
 541         DTLB_FLUSH_UNLOCKED_UCTXS(D, %g1, %g3, %g4, %o2, %o3, %o4, %o5)
 542 
 543         membar  #Sync
 544         retl
 545           nop
 546         
 547         SET_SIZE(vtag_flushall_uctxs)
 548 
 549         ENTRY_NP(vtag_flushpage_tl1)
 550         /*
 551          * x-trap to flush page from tlb and tsb
 552          *
 553          * %g1 = vaddr, zero-extended on 32-bit kernel
 554          * %g2 = sfmmup
 555          *
 556          * assumes TSBE_TAG = 0
 557          */
 558         srln    %g1, MMU_PAGESHIFT, %g1
 559         slln    %g1, MMU_PAGESHIFT, %g1                 /* g1 = vaddr */
 560         
 561         SFMMU_CPU_CNUM(%g2, %g3, %g4)   /* %g3 = sfmmu cnum on this CPU */
 562 
 563         /* We need to set the secondary context properly. */
 564         set     MMU_SCONTEXT, %g4
 565         ldxa    [%g4]ASI_DMMU, %g5              /* rd old ctxnum */
 566         or      DEMAP_SECOND | DEMAP_PAGE_TYPE, %g1, %g1
 567         stxa    %g3, [%g4]ASI_DMMU              /* wr new ctxum */
 568         stxa    %g0, [%g1]ASI_DTLB_DEMAP
 569         stxa    %g0, [%g1]ASI_ITLB_DEMAP
 570         stxa    %g5, [%g4]ASI_DMMU              /* restore old ctxnum */
 571         membar #Sync
 572         retry
 573         SET_SIZE(vtag_flushpage_tl1)
 574 
 575         ENTRY_NP(vtag_flush_pgcnt_tl1)
 576         /*
 577          * x-trap to flush pgcnt MMU_PAGESIZE pages from tlb
 578          *
 579          * %g1 = vaddr, zero-extended on 32-bit kernel
 580          * %g2 = <sfmmup58 | pgcnt6>
 581          *
 582          * NOTE: this handler relies on the fact that no
 583          *      interrupts or traps can occur during the loop
 584          *      issuing the TLB_DEMAP operations. It is assumed
 585          *      that interrupts are disabled and this code is
 586          *      fetching from the kernel locked text address.
 587          *
 588          * assumes TSBE_TAG = 0
 589          */
 590         srln    %g1, MMU_PAGESHIFT, %g1
 591         slln    %g1, MMU_PAGESHIFT, %g1         /* g1 = vaddr */
 592         or      DEMAP_SECOND | DEMAP_PAGE_TYPE, %g1, %g1
 593         
 594         set     SFMMU_PGCNT_MASK, %g4
 595         and     %g4, %g2, %g3                   /* g3 = pgcnt - 1 */
 596         add     %g3, 1, %g3                     /* g3 = pgcnt */
 597 
 598         andn    %g2, SFMMU_PGCNT_MASK, %g2      /* g2 = sfmmup */
 599 
 600         SFMMU_CPU_CNUM(%g2, %g5, %g6)   ! %g5 = sfmmu cnum on this CPU
 601 
 602         /* We need to set the secondary context properly. */
 603         set     MMU_SCONTEXT, %g4
 604         ldxa    [%g4]ASI_DMMU, %g6              /* read old ctxnum */
 605         stxa    %g5, [%g4]ASI_DMMU              /* write new ctxum */
 606 
 607         set     MMU_PAGESIZE, %g2               /* g2 = pgsize */
 608         sethi    %hi(FLUSH_ADDR), %g5
 609 1:
 610         stxa    %g0, [%g1]ASI_DTLB_DEMAP
 611         stxa    %g0, [%g1]ASI_ITLB_DEMAP
 612         flush   %g5
 613         deccc   %g3                             /* decr pgcnt */
 614         bnz,pt  %icc,1b
 615           add   %g1, %g2, %g1                   /* go to nextpage */
 616 
 617         stxa    %g6, [%g4]ASI_DMMU              /* restore old ctxnum */
 618         membar #Sync
 619         retry
 620         SET_SIZE(vtag_flush_pgcnt_tl1)
 621 
 622         ! Not implemented on US1/US2
 623         ENTRY_NP(vtag_flushall_tl1)
 624         retry
 625         SET_SIZE(vtag_flushall_tl1)
 626 
 627 /*
 628  * vac_flushpage(pfnum, color)
 629  *      Flush 1 8k page of the D-$ with physical page = pfnum
 630  *      Algorithm:
 631  *              The spitfire dcache is a 16k direct mapped virtual indexed,
 632  *              physically tagged cache.  Given the pfnum we read all cache
 633  *              lines for the corresponding page in the cache (determined by
 634  *              the color).  Each cache line is compared with
 635  *              the tag created from the pfnum. If the tags match we flush
 636  *              the line.
 637  */
 638         .seg    ".data"
 639         .align  8
 640         .global dflush_type
 641 dflush_type:
 642         .word   FLUSHPAGE_TYPE
 643         .seg    ".text"
 644 
 645         ENTRY(vac_flushpage)
 646         /*
 647          * flush page from the d$
 648          *
 649          * %o0 = pfnum, %o1 = color
 650          */
 651         DCACHE_FLUSHPAGE(%o0, %o1, %o2, %o3, %o4)
 652         retl
 653         nop
 654         SET_SIZE(vac_flushpage)
 655 
 656         ENTRY_NP(vac_flushpage_tl1)
 657         /*
 658          * x-trap to flush page from the d$
 659          *
 660          * %g1 = pfnum, %g2 = color
 661          */
 662         DCACHE_FLUSHPAGE(%g1, %g2, %g3, %g4, %g5)
 663         retry
 664         SET_SIZE(vac_flushpage_tl1)
 665 
 666         ENTRY(vac_flushcolor)
 667         /*
 668          * %o0 = vcolor
 669          */
 670         DCACHE_FLUSHCOLOR(%o0, %o1, %o2)
 671         retl
 672           nop
 673         SET_SIZE(vac_flushcolor)
 674 
 675         ENTRY(vac_flushcolor_tl1)
 676         /*
 677          * %g1 = vcolor
 678          */
 679         DCACHE_FLUSHCOLOR(%g1, %g2, %g3)
 680         retry
 681         SET_SIZE(vac_flushcolor_tl1)
 682 
 683 
 684         .global _dispatch_status_busy
 685 _dispatch_status_busy:
 686         .asciz  "ASI_INTR_DISPATCH_STATUS error: busy"
 687         .align  4
 688 
 689 /*
 690  * Determine whether or not the IDSR is busy.
 691  * Entry: no arguments
 692  * Returns: 1 if busy, 0 otherwise
 693  */
 694         ENTRY(idsr_busy)
 695         ldxa    [%g0]ASI_INTR_DISPATCH_STATUS, %g1
 696         clr     %o0
 697         btst    IDSR_BUSY, %g1
 698         bz,a,pt %xcc, 1f
 699         mov     1, %o0
 700 1:
 701         retl
 702         nop
 703         SET_SIZE(idsr_busy)
 704         
 705 /*
 706  * Setup interrupt dispatch data registers
 707  * Entry:
 708  *      %o0 - function or inumber to call
 709  *      %o1, %o2 - arguments (2 uint64_t's)
 710  */
 711         .seg "text"
 712 
 713         ENTRY(init_mondo)
 714 #ifdef DEBUG
 715         !
 716         ! IDSR should not be busy at the moment
 717         !
 718         ldxa    [%g0]ASI_INTR_DISPATCH_STATUS, %g1
 719         btst    IDSR_BUSY, %g1
 720         bz,pt   %xcc, 1f
 721         nop
 722 
 723         sethi   %hi(_dispatch_status_busy), %o0
 724         call    panic
 725         or      %o0, %lo(_dispatch_status_busy), %o0
 726 #endif /* DEBUG */
 727 
 728         ALTENTRY(init_mondo_nocheck)
 729         !
 730         ! interrupt vector dispach data reg 0
 731         !
 732 1:
 733         mov     IDDR_0, %g1
 734         mov     IDDR_1, %g2
 735         mov     IDDR_2, %g3
 736         stxa    %o0, [%g1]ASI_INTR_DISPATCH
 737 
 738         !
 739         ! interrupt vector dispach data reg 1
 740         !
 741         stxa    %o1, [%g2]ASI_INTR_DISPATCH
 742 
 743         !
 744         ! interrupt vector dispach data reg 2
 745         !
 746         stxa    %o2, [%g3]ASI_INTR_DISPATCH
 747 
 748         retl
 749         membar  #Sync                   ! allowed to be in the delay slot
 750         SET_SIZE(init_mondo)
 751 
 752 /*
 753  * Ship mondo to upaid
 754  */
 755         ENTRY_NP(shipit)
 756         sll     %o0, IDCR_PID_SHIFT, %g1        ! IDCR<18:14> = upa id
 757         or      %g1, IDCR_OFFSET, %g1           ! IDCR<13:0> = 0x70
 758         stxa    %g0, [%g1]ASI_INTR_DISPATCH     ! interrupt vector dispatch
 759 #if defined(SF_ERRATA_54)
 760         membar  #Sync                           ! store must occur before load
 761         mov     0x20, %g3                       ! UDBH Control Register Read
 762         ldxa    [%g3]ASI_SDB_INTR_R, %g0
 763 #endif
 764         retl
 765         membar  #Sync
 766         SET_SIZE(shipit)
 767 
 768 
 769 /*
 770  * flush_instr_mem:
 771  *      Flush a portion of the I-$ starting at vaddr
 772  *      %o0 vaddr
 773  *      %o1 bytes to be flushed
 774  */
 775 
 776         ENTRY(flush_instr_mem)
 777         membar  #StoreStore                             ! Ensure the stores
 778                                                         ! are globally visible
 779 1:
 780         flush   %o0
 781         subcc   %o1, ICACHE_FLUSHSZ, %o1                ! bytes = bytes-0x20
 782         bgu,pt  %ncc, 1b
 783         add     %o0, ICACHE_FLUSHSZ, %o0                ! vaddr = vaddr+0x20
 784 
 785         retl
 786         nop
 787         SET_SIZE(flush_instr_mem)
 788 
 789 /*
 790  * flush_ecache:
 791  * Flush the entire e$ using displacement flush by reading through a
 792  * physically contiguous area. We use mmu bypass asi (ASI_MEM) while
 793  * reading this physical address range so that data doesn't go to d$.
 794  * incoming arguments:
 795  *      %o0 - 64 bit physical address
 796  *      %o1 - size of address range to read
 797  *      %o2 - ecache linesize
 798  */
 799         ENTRY(flush_ecache)
 800 #ifndef HUMMINGBIRD
 801         b       2f
 802           nop
 803 1:
 804         ldxa    [%o0 + %o1]ASI_MEM, %g0 ! start reading from physaddr + size
 805 2:
 806         subcc   %o1, %o2, %o1
 807         bcc,a,pt %ncc, 1b
 808           nop
 809 
 810 #else /* HUMMINGBIRD */
 811         /*
 812          * UltraSPARC-IIe processor supports both 4-way set associative
 813          * and direct map E$. For performance reasons, we flush E$ by
 814          * placing it in direct map mode for data load/store and restore
 815          * the state after we are done flushing it. It takes 2 iterations
 816          * to guarantee that the entire ecache has been flushed.
 817          *
 818          * Keep the interrupts disabled while flushing E$ in this manner.
 819          */
 820         rdpr    %pstate, %g4            ! current pstate (restored later)
 821         andn    %g4, PSTATE_IE, %g5
 822         wrpr    %g0, %g5, %pstate       ! disable interrupts
 823 
 824         ! Place E$ in direct map mode for data access
 825         or      %g0, 1, %g5
 826         sllx    %g5, HB_UPA_DMAP_DATA_BIT, %g5
 827         ldxa    [%g0]ASI_UPA_CONFIG, %g1 ! current UPA config (restored later)
 828         or      %g1, %g5, %g5
 829         membar  #Sync
 830         stxa    %g5, [%g0]ASI_UPA_CONFIG ! enable direct map for data access
 831         membar  #Sync
 832 
 833         ! flush entire ecache HB_ECACHE_FLUSH_CNT times
 834         mov     HB_ECACHE_FLUSH_CNT-1, %g5
 835 2:
 836         sub     %o1, %o2, %g3           ! start from last entry
 837 1:
 838         ldxa    [%o0 + %g3]ASI_MEM, %g0 ! start reading from physaddr + size
 839         subcc   %g3, %o2, %g3
 840         bgeu,a,pt %ncc, 1b
 841           nop
 842         brgz,a,pt %g5, 2b
 843           dec   %g5
 844 
 845         membar  #Sync
 846         stxa    %g1, [%g0]ASI_UPA_CONFIG ! restore UPA config reg
 847         membar  #Sync
 848         wrpr    %g0, %g4, %pstate       ! restore earlier pstate
 849 #endif /* HUMMINGBIRD */
 850 
 851         retl
 852         nop
 853         SET_SIZE(flush_ecache)
 854 
 855 /*
 856  * void kdi_flush_idcache(int dcache_size, int dcache_linesize,
 857  *                      int icache_size, int icache_linesize)
 858  */
 859         ENTRY(kdi_flush_idcache)
 860         DCACHE_FLUSHALL(%o0, %o1, %g1)
 861         ICACHE_FLUSHALL(%o2, %o3, %g1)
 862         membar  #Sync
 863         retl
 864         nop
 865         SET_SIZE(kdi_flush_idcache)
 866         
 867 
 868 /*
 869  * void get_ecache_dtag(uint32_t ecache_idx, uint64_t *data, uint64_t *tag,
 870  *                      uint64_t *oafsr, uint64_t *acc_afsr)
 871  *
 872  * Get ecache data and tag.  The ecache_idx argument is assumed to be aligned
 873  * on a 64-byte boundary.  The corresponding AFSR value is also read for each
 874  * 8 byte ecache data obtained. The ecache data is assumed to be a pointer
 875  * to an array of 16 uint64_t's (e$data & afsr value).  The action to read the
 876  * data and tag should be atomic to make sense.  We will be executing at PIL15
 877  * and will disable IE, so nothing can occur between the two reads.  We also
 878  * assume that the execution of this code does not interfere with what we are
 879  * reading - not really possible, but we'll live with it for now.
 880  * We also pass the old AFSR value before clearing it, and caller will take
 881  * appropriate actions if the important bits are non-zero. 
 882  *
 883  * If the caller wishes to track the AFSR in cases where the CP bit is
 884  * set, an address should be passed in for acc_afsr.  Otherwise, this
 885  * argument may be null.
 886  *
 887  * Register Usage:
 888  * i0: In: 32-bit e$ index
 889  * i1: In: addr of e$ data
 890  * i2: In: addr of e$ tag
 891  * i3: In: addr of old afsr
 892  * i4: In: addr of accumulated afsr - may be null
 893  */
 894         ENTRY(get_ecache_dtag)
 895         save    %sp, -SA(MINFRAME), %sp
 896         or      %g0, 1, %l4
 897         sllx    %l4, 39, %l4    ! set bit 39 for e$ data access
 898         or      %i0, %l4, %g6   ! %g6 = e$ addr for data read
 899         sllx    %l4, 1, %l4     ! set bit 40 for e$ tag access
 900         or      %i0, %l4, %l4   ! %l4 = e$ addr for tag read
 901 
 902         rdpr    %pstate, %i5
 903         andn    %i5, PSTATE_IE | PSTATE_AM, %i0
 904         wrpr    %i0, %g0, %pstate       ! clear IE, AM bits
 905 
 906         ldxa    [%g0]ASI_ESTATE_ERR, %g1
 907         stxa    %g0, [%g0]ASI_ESTATE_ERR        ! disable errors
 908         membar  #Sync
 909 
 910         ldxa    [%g0]ASI_AFSR, %i0      ! grab the old-afsr before tag read
 911         stx     %i0, [%i3]              ! write back the old-afsr
 912 
 913         ldxa    [%l4]ASI_EC_R, %g0      ! read tag into E$ tag reg
 914         ldxa    [%g0]ASI_EC_DIAG, %i0   ! read tag from E$ tag reg
 915         stx     %i0, [%i2]              ! write back tag result
 916 
 917         clr     %i2                     ! loop count
 918 
 919         brz     %i4, 1f                 ! acc_afsr == NULL?
 920           ldxa  [%g0]ASI_AFSR, %i0      ! grab the old-afsr before clearing
 921         srlx    %i0, P_AFSR_CP_SHIFT, %l0
 922         btst    1, %l0
 923         bz      1f
 924           nop
 925         ldx     [%i4], %g4
 926         or      %g4, %i0, %g4           ! aggregate AFSR in cpu private
 927         stx     %g4, [%i4]
 928 1:
 929         stxa    %i0, [%g0]ASI_AFSR      ! clear AFSR
 930         membar  #Sync
 931         ldxa    [%g6]ASI_EC_R, %i0      ! read the 8byte E$data
 932         stx     %i0, [%i1]              ! save the E$data
 933         add     %g6, 8, %g6
 934         add     %i1, 8, %i1
 935         ldxa    [%g0]ASI_AFSR, %i0      ! read AFSR for this 16byte read
 936         srlx    %i0, P_AFSR_CP_SHIFT, %l0
 937         btst    1, %l0
 938         bz      2f
 939           stx     %i0, [%i1]            ! save the AFSR
 940 
 941         brz     %i4, 2f                 ! acc_afsr == NULL?
 942           nop
 943         ldx     [%i4], %g4
 944         or      %g4, %i0, %g4           ! aggregate AFSR in cpu private
 945         stx     %g4, [%i4]
 946 2:
 947         add     %i2, 8, %i2
 948         cmp     %i2, 64
 949         bl,a    1b
 950           add     %i1, 8, %i1
 951         stxa    %i0, [%g0]ASI_AFSR              ! clear AFSR
 952         membar  #Sync
 953         stxa    %g1, [%g0]ASI_ESTATE_ERR        ! restore error enable
 954         membar  #Sync
 955         wrpr    %g0, %i5, %pstate
 956         ret
 957           restore
 958         SET_SIZE(get_ecache_dtag)
 959 #endif /* lint */
 960 
 961 #if defined(lint)
 962 /*
 963  * The ce_err function handles trap type 0x63 (corrected_ECC_error) at tl=0.
 964  * Steps: 1. GET AFSR  2. Get AFAR <40:4> 3. Get datapath error status
 965  *        4. Clear datapath error bit(s) 5. Clear AFSR error bit
 966  *        6. package data in %g2 and %g3 7. call cpu_ce_error vis sys_trap
 967  * %g2: [ 52:43 UDB lower | 42:33 UDB upper | 32:0 afsr ] - arg #3/arg #1
 968  * %g3: [ 40:4 afar ] - sys_trap->have_win: arg #4/arg #2
 969  */
 970 void
 971 ce_err(void)
 972 {}
 973 
 974 void
 975 ce_err_tl1(void)
 976 {}
 977 
 978 
 979 /*
 980  * The async_err function handles trap types 0x0A (instruction_access_error)
 981  * and 0x32 (data_access_error) at TL = 0 and TL > 0.  When we branch here,
 982  * %g5 will have the trap type (with 0x200 set if we're at TL > 0).
 983  *
 984  * Steps: 1. Get AFSR 2. Get AFAR <40:4> 3. If not UE error skip UDP registers.
 985  *        4. Else get and clear datapath error bit(s) 4. Clear AFSR error bits
 986  *        6. package data in %g2 and %g3 7. disable all cpu errors, because
 987  *        trap is likely to be fatal 8. call cpu_async_error vis sys_trap
 988  *
 989  * %g3: [ 63:53 tt | 52:43 UDB_L | 42:33 UDB_U | 32:0 afsr ] - arg #3/arg #1
 990  * %g2: [ 40:4 afar ] - sys_trap->have_win: arg #4/arg #2
 991  */
 992 void
 993 async_err(void)
 994 {}
 995 
 996 /*
 997  * The clr_datapath function clears any error bits set in the UDB regs.
 998  */
 999 void
1000 clr_datapath(void)
1001 {}
1002 
1003 /*
1004  * The get_udb_errors() function gets the current value of the
1005  * Datapath Error Registers.
1006  */
1007 /*ARGSUSED*/
1008 void
1009 get_udb_errors(uint64_t *udbh, uint64_t *udbl)
1010 {
1011         *udbh = 0;
1012         *udbl = 0;
1013 }
1014 
1015 #else   /* lint */
1016 
1017         ENTRY_NP(ce_err)
1018         ldxa    [%g0]ASI_AFSR, %g3      ! save afsr in g3
1019 
1020         !
1021         ! Check for a UE... From Kevin.Normoyle:
1022         ! We try to switch to the trap for the UE, but since that's
1023         ! a hardware pipeline, we might get to the CE trap before we
1024         ! can switch. The UDB and AFSR registers will have both the
1025         ! UE and CE bits set but the UDB syndrome and the AFAR will be
1026         ! for the UE.
1027         !
1028         or      %g0, 1, %g1             ! put 1 in g1
1029         sllx    %g1, 21, %g1            ! shift left to <21> afsr UE
1030         andcc   %g1, %g3, %g0           ! check for UE in afsr
1031         bnz     async_err               ! handle the UE, not the CE
1032           or    %g0, 0x63, %g5          ! pass along the CE ttype
1033         !
1034         ! Disable further CE traps to avoid recursion (stack overflow)
1035         ! and staying above XCALL_PIL for extended periods.
1036         !
1037         ldxa    [%g0]ASI_ESTATE_ERR, %g2
1038         andn    %g2, 0x1, %g2           ! clear bit 0 - CEEN
1039         stxa    %g2, [%g0]ASI_ESTATE_ERR
1040         membar  #Sync                   ! required
1041         !
1042         ! handle the CE
1043         ldxa    [%g0]ASI_AFAR, %g2      ! save afar in g2
1044 
1045         set     P_DER_H, %g4            ! put P_DER_H in g4
1046         ldxa    [%g4]ASI_SDB_INTR_R, %g5 ! read sdb upper half into g5
1047         or      %g0, 1, %g6             ! put 1 in g6
1048         sllx    %g6, 8, %g6             ! shift g6 to <8> sdb CE
1049         andcc   %g5, %g6, %g1           ! check for CE in upper half
1050         sllx    %g5, 33, %g5            ! shift upper bits to <42:33>
1051         or      %g3, %g5, %g3           ! or with afsr bits
1052         bz,a    1f                      ! no error, goto 1f
1053           nop
1054         stxa    %g1, [%g4]ASI_SDB_INTR_W ! clear sdb reg error bit
1055         membar  #Sync                   ! membar sync required
1056 1:
1057         set     P_DER_L, %g4            ! put P_DER_L in g4
1058         ldxa    [%g4]ASI_SDB_INTR_R, %g5 ! read sdb lower half into g6
1059         andcc   %g5, %g6, %g1           ! check for CE in lower half
1060         sllx    %g5, 43, %g5            ! shift upper bits to <52:43>
1061         or      %g3, %g5, %g3           ! or with afsr bits
1062         bz,a    2f                      ! no error, goto 2f
1063           nop
1064         stxa    %g1, [%g4]ASI_SDB_INTR_W ! clear sdb reg error bit
1065         membar  #Sync                   ! membar sync required
1066 2:
1067         or      %g0, 1, %g4             ! put 1 in g4
1068         sllx    %g4, 20, %g4            ! shift left to <20> afsr CE
1069         stxa    %g4, [%g0]ASI_AFSR      ! use g4 to clear afsr CE error
1070         membar  #Sync                   ! membar sync required
1071 
1072         set     cpu_ce_error, %g1       ! put *cpu_ce_error() in g1
1073         rdpr    %pil, %g6               ! read pil into %g6
1074         subcc   %g6, PIL_15, %g0
1075           movneg        %icc, PIL_14, %g4 ! run at pil 14 unless already at 15
1076         sethi   %hi(sys_trap), %g5
1077         jmp     %g5 + %lo(sys_trap)     ! goto sys_trap
1078           movge %icc, PIL_15, %g4       ! already at pil 15
1079         SET_SIZE(ce_err)
1080 
1081         ENTRY_NP(ce_err_tl1)
1082 #ifndef TRAPTRACE
1083         ldxa    [%g0]ASI_AFSR, %g7
1084         stxa    %g7, [%g0]ASI_AFSR
1085         membar  #Sync
1086         retry
1087 #else
1088         set     ce_trap_tl1, %g1
1089         sethi   %hi(dis_err_panic1), %g4
1090         jmp     %g4 + %lo(dis_err_panic1)
1091         nop
1092 #endif
1093         SET_SIZE(ce_err_tl1)
1094 
1095 #ifdef  TRAPTRACE
1096 .celevel1msg:
1097         .asciz  "Softerror with trap tracing at tl1: AFAR 0x%08x.%08x AFSR 0x%08x.%08x";
1098 
1099         ENTRY_NP(ce_trap_tl1)
1100         ! upper 32 bits of AFSR already in o3
1101         mov     %o4, %o0                ! save AFAR upper 32 bits
1102         mov     %o2, %o4                ! lower 32 bits of AFSR
1103         mov     %o1, %o2                ! lower 32 bits of AFAR
1104         mov     %o0, %o1                ! upper 32 bits of AFAR
1105         set     .celevel1msg, %o0
1106         call    panic
1107         nop
1108         SET_SIZE(ce_trap_tl1)
1109 #endif
1110 
1111         !
1112         ! async_err is the assembly glue code to get us from the actual trap
1113         ! into the CPU module's C error handler.  Note that we also branch
1114         ! here from ce_err() above.
1115         !
1116         ENTRY_NP(async_err)
1117         stxa    %g0, [%g0]ASI_ESTATE_ERR ! disable ecc and other cpu errors
1118         membar  #Sync                   ! membar sync required
1119 
1120         ldxa    [%g0]ASI_AFSR, %g3      ! save afsr in g3
1121         ldxa    [%g0]ASI_AFAR, %g2      ! save afar in g2
1122 
1123         sllx    %g5, 53, %g5            ! move ttype to <63:53>
1124         or      %g3, %g5, %g3           ! or to afsr in g3
1125 
1126         or      %g0, 1, %g1             ! put 1 in g1
1127         sllx    %g1, 21, %g1            ! shift left to <21> afsr UE
1128         andcc   %g1, %g3, %g0           ! check for UE in afsr
1129         bz,a,pn %icc, 2f                ! if !UE skip sdb read/clear
1130           nop
1131 
1132         set     P_DER_H, %g4            ! put P_DER_H in g4
1133         ldxa    [%g4]ASI_SDB_INTR_R, %g5 ! read sdb upper half into 56
1134         or      %g0, 1, %g6             ! put 1 in g6
1135         sllx    %g6, 9, %g6             ! shift g6 to <9> sdb UE
1136         andcc   %g5, %g6, %g1           ! check for UE in upper half
1137         sllx    %g5, 33, %g5            ! shift upper bits to <42:33>
1138         or      %g3, %g5, %g3           ! or with afsr bits
1139         bz,a    1f                      ! no error, goto 1f
1140           nop
1141         stxa    %g1, [%g4]ASI_SDB_INTR_W ! clear sdb reg UE error bit
1142         membar  #Sync                   ! membar sync required
1143 1:
1144         set     P_DER_L, %g4            ! put P_DER_L in g4
1145         ldxa    [%g4]ASI_SDB_INTR_R, %g5 ! read sdb lower half into g5
1146         andcc   %g5, %g6, %g1           ! check for UE in lower half
1147         sllx    %g5, 43, %g5            ! shift upper bits to <52:43>
1148         or      %g3, %g5, %g3           ! or with afsr bits
1149         bz,a    2f                      ! no error, goto 2f
1150           nop
1151         stxa    %g1, [%g4]ASI_SDB_INTR_W ! clear sdb reg UE error bit
1152         membar  #Sync                   ! membar sync required
1153 2:
1154         stxa    %g3, [%g0]ASI_AFSR      ! clear all the sticky bits
1155         membar  #Sync                   ! membar sync required
1156 
1157         RESET_USER_RTT_REGS(%g4, %g5, async_err_resetskip)
1158 async_err_resetskip:
1159 
1160         set     cpu_async_error, %g1    ! put cpu_async_error in g1
1161         sethi   %hi(sys_trap), %g5
1162         jmp     %g5 + %lo(sys_trap)     ! goto sys_trap
1163           or    %g0, PIL_15, %g4        ! run at pil 15
1164         SET_SIZE(async_err)
1165 
1166         ENTRY_NP(dis_err_panic1)
1167         stxa    %g0, [%g0]ASI_ESTATE_ERR ! disable all error traps
1168         membar  #Sync
1169         ! save destination routine is in g1
1170         ldxa    [%g0]ASI_AFAR, %g2      ! read afar
1171         ldxa    [%g0]ASI_AFSR, %g3      ! read afsr
1172         set     P_DER_H, %g4            ! put P_DER_H in g4
1173         ldxa    [%g4]ASI_SDB_INTR_R, %g5 ! read sdb upper half into g5
1174         sllx    %g5, 33, %g5            ! shift upper bits to <42:33>
1175         or      %g3, %g5, %g3           ! or with afsr bits
1176         set     P_DER_L, %g4            ! put P_DER_L in g4
1177         ldxa    [%g4]ASI_SDB_INTR_R, %g5 ! read sdb lower half into g5
1178         sllx    %g5, 43, %g5            ! shift upper bits to <52:43>
1179         or      %g3, %g5, %g3           ! or with afsr bits
1180 
1181         RESET_USER_RTT_REGS(%g4, %g5, dis_err_panic1_resetskip)
1182 dis_err_panic1_resetskip:
1183 
1184         sethi   %hi(sys_trap), %g5
1185         jmp     %g5 + %lo(sys_trap)     ! goto sys_trap
1186           sub   %g0, 1, %g4
1187         SET_SIZE(dis_err_panic1)
1188 
1189         ENTRY(clr_datapath)
1190         set     P_DER_H, %o4                    ! put P_DER_H in o4
1191         ldxa    [%o4]ASI_SDB_INTR_R, %o5        ! read sdb upper half into o3
1192         or      %g0, 0x3, %o2                   ! put 0x3 in o2
1193         sllx    %o2, 8, %o2                     ! shift o2 to <9:8> sdb
1194         andcc   %o5, %o2, %o1                   ! check for UE,CE in upper half
1195         bz,a    1f                              ! no error, goto 1f
1196           nop
1197         stxa    %o1, [%o4]ASI_SDB_INTR_W        ! clear sdb reg UE,CE error bits
1198         membar  #Sync                           ! membar sync required
1199 1:
1200         set     P_DER_L, %o4                    ! put P_DER_L in o4
1201         ldxa    [%o4]ASI_SDB_INTR_R, %o5        ! read sdb lower half into o5
1202         andcc   %o5, %o2, %o1                   ! check for UE,CE in lower half
1203         bz,a    2f                              ! no error, goto 2f
1204           nop
1205         stxa    %o1, [%o4]ASI_SDB_INTR_W        ! clear sdb reg UE,CE error bits
1206         membar  #Sync
1207 2:
1208         retl
1209           nop
1210         SET_SIZE(clr_datapath)
1211 
1212         ENTRY(get_udb_errors)
1213         set     P_DER_H, %o3
1214         ldxa    [%o3]ASI_SDB_INTR_R, %o2
1215         stx     %o2, [%o0]
1216         set     P_DER_L, %o3
1217         ldxa    [%o3]ASI_SDB_INTR_R, %o2
1218         retl
1219           stx   %o2, [%o1]
1220         SET_SIZE(get_udb_errors)
1221 
1222 #endif /* lint */
1223 
1224 #if defined(lint)
1225 /*
1226  * The itlb_rd_entry and dtlb_rd_entry functions return the tag portion of the
1227  * tte, the virtual address, and the ctxnum of the specified tlb entry.  They
1228  * should only be used in places where you have no choice but to look at the
1229  * tlb itself.
1230  *
1231  * Note: These two routines are required by the Estar "cpr" loadable module.
1232  */
1233 /*ARGSUSED*/
1234 void
1235 itlb_rd_entry(uint_t entry, tte_t *tte, uint64_t *va_tag)
1236 {}
1237 
1238 /*ARGSUSED*/
1239 void
1240 dtlb_rd_entry(uint_t entry, tte_t *tte, uint64_t *va_tag)
1241 {}
1242 #else   /* lint */
1243 /*
1244  * NB - In Spitfire cpus, when reading a tte from the hardware, we
1245  * need to clear [42-41] because the general definitions in pte.h
1246  * define the PA to be [42-13] whereas Spitfire really uses [40-13].
1247  * When cloning these routines for other cpus the "andn" below is not
1248  * necessary.
1249  */
1250         ENTRY_NP(itlb_rd_entry)
1251         sllx    %o0, 3, %o0
1252 #if defined(SF_ERRATA_32)
1253         sethi   %hi(FLUSH_ADDR), %g2
1254         set     MMU_PCONTEXT, %g1
1255         stxa    %g0, [%g1]ASI_DMMU                      ! KCONTEXT
1256         flush   %g2
1257 #endif
1258         ldxa    [%o0]ASI_ITLB_ACCESS, %g1
1259         set     TTE_SPITFIRE_PFNHI_CLEAR, %g2           ! spitfire only
1260         sllx    %g2, TTE_SPITFIRE_PFNHI_SHIFT, %g2      ! see comment above
1261         andn    %g1, %g2, %g1                           ! for details
1262         stx     %g1, [%o1]
1263         ldxa    [%o0]ASI_ITLB_TAGREAD, %g2
1264         set     TAGREAD_CTX_MASK, %o4
1265         andn    %g2, %o4, %o5
1266         retl
1267           stx   %o5, [%o2]
1268         SET_SIZE(itlb_rd_entry)
1269 
1270         ENTRY_NP(dtlb_rd_entry)
1271         sllx    %o0, 3, %o0
1272 #if defined(SF_ERRATA_32)
1273         sethi   %hi(FLUSH_ADDR), %g2
1274         set     MMU_PCONTEXT, %g1
1275         stxa    %g0, [%g1]ASI_DMMU                      ! KCONTEXT
1276         flush   %g2
1277 #endif
1278         ldxa    [%o0]ASI_DTLB_ACCESS, %g1
1279         set     TTE_SPITFIRE_PFNHI_CLEAR, %g2           ! spitfire only
1280         sllx    %g2, TTE_SPITFIRE_PFNHI_SHIFT, %g2      ! see comment above
1281         andn    %g1, %g2, %g1                           ! itlb_rd_entry
1282         stx     %g1, [%o1]
1283         ldxa    [%o0]ASI_DTLB_TAGREAD, %g2
1284         set     TAGREAD_CTX_MASK, %o4
1285         andn    %g2, %o4, %o5
1286         retl
1287           stx   %o5, [%o2]
1288         SET_SIZE(dtlb_rd_entry)
1289 #endif /* lint */
1290 
1291 #if defined(lint)
1292 
1293 /*
1294  * routines to get and set the LSU register
1295  */
1296 uint64_t
1297 get_lsu(void)
1298 {
1299         return ((uint64_t)0);
1300 }
1301 
1302 /*ARGSUSED*/
1303 void
1304 set_lsu(uint64_t lsu)
1305 {}
1306 
1307 #else /* lint */
1308 
1309         ENTRY(set_lsu)
1310         stxa    %o0, [%g0]ASI_LSU               ! store to LSU
1311         retl
1312         membar  #Sync
1313         SET_SIZE(set_lsu)
1314 
1315         ENTRY(get_lsu)
1316         retl
1317         ldxa    [%g0]ASI_LSU, %o0               ! load LSU
1318         SET_SIZE(get_lsu)
1319 
1320 #endif /* lint */
1321 
1322 #ifndef lint
1323         /*
1324          * Clear the NPT (non-privileged trap) bit in the %tick
1325          * registers. In an effort to make the change in the
1326          * tick counter as consistent as possible, we disable
1327          * all interrupts while we're changing the registers. We also
1328          * ensure that the read and write instructions are in the same
1329          * line in the instruction cache.
1330          */
1331         ENTRY_NP(cpu_clearticknpt)
1332         rdpr    %pstate, %g1            /* save processor state */
1333         andn    %g1, PSTATE_IE, %g3     /* turn off */
1334         wrpr    %g0, %g3, %pstate       /*   interrupts */
1335         rdpr    %tick, %g2              /* get tick register */
1336         brgez,pn %g2, 1f                /* if NPT bit off, we're done */
1337         mov     1, %g3                  /* create mask */
1338         sllx    %g3, 63, %g3            /*   for NPT bit */
1339         ba,a,pt %xcc, 2f
1340         .align  64                      /* Align to I$ boundary */
1341 2:
1342         rdpr    %tick, %g2              /* get tick register */
1343         wrpr    %g3, %g2, %tick         /* write tick register, */
1344                                         /*   clearing NPT bit   */
1345 #if defined(BB_ERRATA_1)
1346         rdpr    %tick, %g0              /* read (s)tick (BB_ERRATA_1) */
1347 #endif
1348 1:
1349         jmp     %g4 + 4
1350         wrpr    %g0, %g1, %pstate       /* restore processor state */
1351         SET_SIZE(cpu_clearticknpt)
1352 
1353         /*
1354          * get_ecache_tag()
1355          * Register Usage:
1356          * %o0: In: 32-bit E$ index
1357          *      Out: 64-bit E$ tag value
1358          * %o1: In: 64-bit AFSR value after clearing sticky bits
1359          * %o2: In: address of cpu private afsr storage
1360          */
1361         ENTRY(get_ecache_tag)
1362         or      %g0, 1, %o4
1363         sllx    %o4, 40, %o4                    ! set bit 40 for e$ tag access
1364         or      %o0, %o4, %o4                   ! %o4 = e$ addr for tag read
1365         rdpr    %pstate, %o5
1366         andn    %o5, PSTATE_IE | PSTATE_AM, %o0
1367         wrpr    %o0, %g0, %pstate               ! clear IE, AM bits
1368 
1369         ldxa    [%g0]ASI_ESTATE_ERR, %g1
1370         stxa    %g0, [%g0]ASI_ESTATE_ERR        ! Turn off Error enable
1371         membar  #Sync
1372 
1373         ldxa    [%g0]ASI_AFSR, %o0
1374         srlx    %o0, P_AFSR_CP_SHIFT, %o3
1375         btst    1, %o3
1376         bz      1f
1377           nop
1378         ldx     [%o2], %g4
1379         or      %g4, %o0, %g4                   ! aggregate AFSR in cpu private
1380         stx     %g4, [%o2]
1381 1:
1382         stxa    %o0, [%g0]ASI_AFSR              ! clear AFSR
1383         membar  #Sync
1384 
1385         ldxa    [%o4]ASI_EC_R, %g0
1386         ldxa    [%g0]ASI_EC_DIAG, %o0           ! read tag from e$ tag reg
1387 
1388         ldxa    [%g0]ASI_AFSR, %o3
1389         srlx    %o3, P_AFSR_CP_SHIFT, %o4
1390         btst    1, %o4
1391         bz      2f
1392           stx   %o3, [%o1]                      ! AFSR after sticky clear
1393         ldx     [%o2], %g4
1394         or      %g4, %o3, %g4                   ! aggregate AFSR in cpu private
1395         stx     %g4, [%o2]
1396 2:
1397         membar  #Sync
1398 
1399         stxa    %g1, [%g0]ASI_ESTATE_ERR        ! Turn error enable back on
1400         membar  #Sync
1401         retl
1402         wrpr    %g0, %o5, %pstate
1403         SET_SIZE(get_ecache_tag)
1404 
1405         /*
1406          * check_ecache_line()
1407          * Register Usage:
1408          * %o0: In: 32-bit E$ index
1409          *      Out: 64-bit accumulated AFSR
1410          * %o1: In: address of cpu private afsr storage
1411          */
1412         ENTRY(check_ecache_line)
1413         or      %g0, 1, %o4
1414         sllx    %o4, 39, %o4                    ! set bit 39 for e$ data access
1415         or      %o0, %o4, %o4                   ! %o4 = e$ addr for data read
1416 
1417         rdpr    %pstate, %o5
1418         andn    %o5, PSTATE_IE | PSTATE_AM, %o0
1419         wrpr    %o0, %g0, %pstate               ! clear IE, AM bits
1420 
1421         ldxa    [%g0]ASI_ESTATE_ERR, %g1
1422         stxa    %g0, [%g0]ASI_ESTATE_ERR        ! Turn off Error enable
1423         membar  #Sync
1424 
1425         ldxa    [%g0]ASI_AFSR, %o0
1426         srlx    %o0, P_AFSR_CP_SHIFT, %o2
1427         btst    1, %o2
1428         bz      1f
1429           clr   %o2                             ! loop count
1430         ldx     [%o1], %o3
1431         or      %o3, %o0, %o3                   ! aggregate AFSR in cpu private
1432         stx     %o3, [%o1]
1433 1: 
1434         stxa    %o0, [%g0]ASI_AFSR              ! clear AFSR
1435         membar  #Sync
1436 
1437 2:
1438         ldxa    [%o4]ASI_EC_R, %g0              ! Read the E$ data 8bytes each
1439         add     %o2, 1, %o2
1440         cmp     %o2, 8
1441         bl,a    2b
1442           add   %o4, 8, %o4
1443 
1444         membar  #Sync
1445         ldxa    [%g0]ASI_AFSR, %o0              ! read accumulated AFSR
1446         srlx    %o0, P_AFSR_CP_SHIFT, %o2
1447         btst    1, %o2
1448         bz      3f
1449           nop
1450         ldx     [%o1], %o3
1451         or      %o3, %o0, %o3                   ! aggregate AFSR in cpu private
1452         stx     %o3, [%o1]
1453 3:
1454         stxa    %o0, [%g0]ASI_AFSR              ! clear AFSR
1455         membar  #Sync
1456         stxa    %g1, [%g0]ASI_ESTATE_ERR        ! Turn error enable back on
1457         membar  #Sync
1458         retl
1459         wrpr    %g0, %o5, %pstate
1460         SET_SIZE(check_ecache_line)
1461 #endif /* lint */
1462 
1463 #if defined(lint)
1464 uint64_t
1465 read_and_clear_afsr()
1466 {
1467         return ((uint64_t)0);
1468 }
1469 #else   /* lint */
1470         ENTRY(read_and_clear_afsr)
1471         ldxa    [%g0]ASI_AFSR, %o0
1472         retl
1473           stxa  %o0, [%g0]ASI_AFSR              ! clear AFSR
1474         SET_SIZE(read_and_clear_afsr)
1475 #endif  /* lint */
1476 
1477 #if defined(lint)
1478 /* ARGSUSED */
1479 void
1480 scrubphys(uint64_t paddr, int ecache_size)
1481 {
1482 }
1483 
1484 #else   /* lint */
1485 
1486 /*
1487  * scrubphys - Pass in the aligned physical memory address that you want
1488  * to scrub, along with the ecache size.
1489  *
1490  *      1) Displacement flush the E$ line corresponding to %addr.
1491  *         The first ldxa guarantees that the %addr is no longer in
1492  *         M, O, or E (goes to I or S (if instruction fetch also happens).
1493  *      2) "Write" the data using a CAS %addr,%g0,%g0.
1494  *         The casxa guarantees a transition from I to M or S to M.
1495  *      3) Displacement flush the E$ line corresponding to %addr.
1496  *         The second ldxa pushes the M line out of the ecache, into the
1497  *         writeback buffers, on the way to memory.
1498  *      4) The "membar #Sync" pushes the cache line out of the writeback
1499  *         buffers onto the bus, on the way to dram finally.
1500  *
1501  * This is a modified version of the algorithm suggested by Gary Lauterbach.
1502  * In theory the CAS %addr,%g0,%g0 is supposed to mark the addr's cache line
1503  * as modified, but then we found out that for spitfire, if it misses in the
1504  * E$ it will probably install as an M, but if it hits in the E$, then it
1505  * will stay E, if the store doesn't happen. So the first displacement flush
1506  * should ensure that the CAS will miss in the E$.  Arrgh.
1507  */
1508 
1509         ENTRY(scrubphys)
1510         or      %o1, %g0, %o2   ! put ecache size in %o2
1511 #ifndef HUMMINGBIRD
1512         xor     %o0, %o2, %o1   ! calculate alias address
1513         add     %o2, %o2, %o3   ! 2 * ecachesize in case
1514                                 ! addr == ecache_flushaddr
1515         sub     %o3, 1, %o3     ! -1 == mask
1516         and     %o1, %o3, %o1   ! and with xor'd address
1517         set     ecache_flushaddr, %o3
1518         ldx     [%o3], %o3
1519 
1520         rdpr    %pstate, %o4
1521         andn    %o4, PSTATE_IE | PSTATE_AM, %o5
1522         wrpr    %o5, %g0, %pstate       ! clear IE, AM bits
1523 
1524         ldxa    [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias
1525         casxa   [%o0]ASI_MEM, %g0, %g0
1526         ldxa    [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias
1527 
1528 #else /* HUMMINGBIRD */
1529         /*
1530          * UltraSPARC-IIe processor supports both 4-way set associative
1531          * and direct map E$. We need to reconfigure E$ to direct map
1532          * mode for data load/store before displacement flush. Also, we
1533          * need to flush all 4 sets of the E$ to ensure that the physaddr
1534          * has been flushed. Keep the interrupts disabled while flushing
1535          * E$ in this manner.
1536          *
1537          * For flushing a specific physical address, we start at the
1538          * aliased address and load at set-size stride, wrapping around
1539          * at 2*ecache-size boundary and skipping fault physical address.
1540          * It takes 10 loads to guarantee that the physical address has
1541          * been flushed.
1542          *
1543          * Usage:
1544          *      %o0     physaddr
1545          *      %o5     physaddr - ecache_flushaddr
1546          *      %g1     UPA config (restored later)
1547          *      %g2     E$ set size
1548          *      %g3     E$ flush address range mask (i.e. 2 * E$ -1)
1549          *      %g4     #loads to flush phys address
1550          *      %g5     temp 
1551          */
1552 
1553         sethi   %hi(ecache_associativity), %g5
1554         ld      [%g5 + %lo(ecache_associativity)], %g5
1555         udivx   %o2, %g5, %g2   ! set size (i.e. ecache_size/#sets)
1556         xor     %o0, %o2, %o1   ! calculate alias address
1557         add     %o2, %o2, %g3   ! 2 * ecachesize in case
1558                                 ! addr == ecache_flushaddr
1559         sub     %g3, 1, %g3     ! 2 * ecachesize -1 == mask
1560         and     %o1, %g3, %o1   ! and with xor'd address
1561         sethi   %hi(ecache_flushaddr), %o3
1562         ldx     [%o3 + %lo(ecache_flushaddr)], %o3
1563 
1564         rdpr    %pstate, %o4
1565         andn    %o4, PSTATE_IE | PSTATE_AM, %o5
1566         wrpr    %o5, %g0, %pstate       ! clear IE, AM bits
1567 
1568         ! Place E$ in direct map mode for data access
1569         or      %g0, 1, %g5
1570         sllx    %g5, HB_UPA_DMAP_DATA_BIT, %g5
1571         ldxa    [%g0]ASI_UPA_CONFIG, %g1 ! current UPA config (restored later)
1572         or      %g1, %g5, %g5
1573         membar  #Sync
1574         stxa    %g5, [%g0]ASI_UPA_CONFIG ! enable direct map for data access
1575         membar  #Sync
1576 
1577         ! Displace cache line from each set of E$ starting at the
1578         ! aliased address. at set-size stride, wrapping at 2*ecache_size
1579         ! and skipping load from physaddr. We need 10 loads to flush the
1580         ! physaddr from E$.
1581         mov     HB_PHYS_FLUSH_CNT-1, %g4 ! #loads to flush phys addr
1582         sub     %o0, %o3, %o5           ! physaddr - ecache_flushaddr
1583         or      %o1, %g0, %g5           ! starting aliased offset
1584 2:
1585         ldxa    [%g5 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias
1586 1:
1587         add     %g5, %g2, %g5           ! calculate offset in next set
1588         and     %g5, %g3, %g5           ! force offset within aliased range
1589         cmp     %g5, %o5                ! skip loads from physaddr
1590         be,pn %ncc, 1b
1591           nop
1592         brgz,pt %g4, 2b
1593           dec   %g4
1594 
1595         casxa   [%o0]ASI_MEM, %g0, %g0
1596 
1597         ! Flush %o0 from ecahe again.
1598         ! Need single displacement flush at offset %o1 this time as
1599         ! the E$ is already in direct map mode.
1600         ldxa    [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias
1601 
1602         membar  #Sync
1603         stxa    %g1, [%g0]ASI_UPA_CONFIG ! restore UPA config (DM bits)
1604         membar  #Sync
1605 #endif /* HUMMINGBIRD */
1606         wrpr    %g0, %o4, %pstate       ! restore earlier pstate register value
1607 
1608         retl
1609         membar  #Sync                   ! move the data out of the load buffer
1610         SET_SIZE(scrubphys)
1611 
1612 #endif  /* lint */
1613 
1614 #if defined(lint)
1615 
1616 /*
1617  * clearphys - Pass in the aligned physical memory address that you want
1618  * to push out, as a 64 byte block of zeros, from the ecache zero-filled.
1619  * Since this routine does not bypass the ecache, it is possible that
1620  * it could generate a UE error while trying to clear the a bad line.
1621  * This routine clears and restores the error enable flag.
1622  * TBD - Hummingbird may need similar protection
1623  */
1624 /* ARGSUSED */
1625 void
1626 clearphys(uint64_t paddr, int ecache_size, int ecache_linesize)
1627 {
1628 }
1629 
1630 #else   /* lint */
1631 
1632         ENTRY(clearphys)
1633         or      %o2, %g0, %o3   ! ecache linesize
1634         or      %o1, %g0, %o2   ! ecache size
1635 #ifndef HUMMINGBIRD
1636         or      %o3, %g0, %o4   ! save ecache linesize
1637         xor     %o0, %o2, %o1   ! calculate alias address
1638         add     %o2, %o2, %o3   ! 2 * ecachesize
1639         sub     %o3, 1, %o3     ! -1 == mask
1640         and     %o1, %o3, %o1   ! and with xor'd address
1641         set     ecache_flushaddr, %o3
1642         ldx     [%o3], %o3
1643         or      %o4, %g0, %o2   ! saved ecache linesize
1644 
1645         rdpr    %pstate, %o4
1646         andn    %o4, PSTATE_IE | PSTATE_AM, %o5
1647         wrpr    %o5, %g0, %pstate       ! clear IE, AM bits
1648 
1649         ldxa    [%g0]ASI_ESTATE_ERR, %g1
1650         stxa    %g0, [%g0]ASI_ESTATE_ERR        ! disable errors
1651         membar  #Sync
1652 
1653         ! need to put zeros in the cache line before displacing it
1654 
1655         sub     %o2, 8, %o2     ! get offset of last double word in ecache line
1656 1:
1657         stxa    %g0, [%o0 + %o2]ASI_MEM ! put zeros in the ecache line
1658         sub     %o2, 8, %o2
1659         brgez,a,pt %o2, 1b
1660         nop
1661         ldxa    [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias
1662         casxa   [%o0]ASI_MEM, %g0, %g0
1663         ldxa    [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias
1664 
1665         stxa    %g1, [%g0]ASI_ESTATE_ERR        ! restore error enable
1666         membar  #Sync
1667 
1668 #else /* HUMMINGBIRD... */
1669         /*
1670          * UltraSPARC-IIe processor supports both 4-way set associative
1671          * and direct map E$. We need to reconfigure E$ to direct map
1672          * mode for data load/store before displacement flush. Also, we
1673          * need to flush all 4 sets of the E$ to ensure that the physaddr
1674          * has been flushed. Keep the interrupts disabled while flushing
1675          * E$ in this manner.
1676          *
1677          * For flushing a specific physical address, we start at the
1678          * aliased address and load at set-size stride, wrapping around
1679          * at 2*ecache-size boundary and skipping fault physical address.
1680          * It takes 10 loads to guarantee that the physical address has
1681          * been flushed.
1682          *
1683          * Usage:
1684          *      %o0     physaddr
1685          *      %o5     physaddr - ecache_flushaddr
1686          *      %g1     UPA config (restored later)
1687          *      %g2     E$ set size
1688          *      %g3     E$ flush address range mask (i.e. 2 * E$ -1)
1689          *      %g4     #loads to flush phys address
1690          *      %g5     temp 
1691          */
1692 
1693         or      %o3, %g0, %o4   ! save ecache linesize
1694         sethi   %hi(ecache_associativity), %g5
1695         ld      [%g5 + %lo(ecache_associativity)], %g5
1696         udivx   %o2, %g5, %g2   ! set size (i.e. ecache_size/#sets)
1697 
1698         xor     %o0, %o2, %o1   ! calculate alias address
1699         add     %o2, %o2, %g3   ! 2 * ecachesize
1700         sub     %g3, 1, %g3     ! 2 * ecachesize -1 == mask
1701         and     %o1, %g3, %o1   ! and with xor'd address
1702         sethi   %hi(ecache_flushaddr), %o3
1703         ldx     [%o3 +%lo(ecache_flushaddr)], %o3
1704         or      %o4, %g0, %o2   ! saved ecache linesize
1705 
1706         rdpr    %pstate, %o4
1707         andn    %o4, PSTATE_IE | PSTATE_AM, %o5
1708         wrpr    %o5, %g0, %pstate       ! clear IE, AM bits
1709 
1710         ! Place E$ in direct map mode for data access
1711         or      %g0, 1, %g5
1712         sllx    %g5, HB_UPA_DMAP_DATA_BIT, %g5
1713         ldxa    [%g0]ASI_UPA_CONFIG, %g1 ! current UPA config (restored later)
1714         or      %g1, %g5, %g5
1715         membar  #Sync
1716         stxa    %g5, [%g0]ASI_UPA_CONFIG ! enable direct map for data access
1717         membar  #Sync
1718 
1719         ! need to put zeros in the cache line before displacing it
1720 
1721         sub     %o2, 8, %o2     ! get offset of last double word in ecache line
1722 1:
1723         stxa    %g0, [%o0 + %o2]ASI_MEM ! put zeros in the ecache line
1724         sub     %o2, 8, %o2
1725         brgez,a,pt %o2, 1b
1726         nop
1727 
1728         ! Displace cache line from each set of E$ starting at the
1729         ! aliased address. at set-size stride, wrapping at 2*ecache_size
1730         ! and skipping load from physaddr. We need 10 loads to flush the
1731         ! physaddr from E$.
1732         mov     HB_PHYS_FLUSH_CNT-1, %g4 ! #loads to flush phys addr
1733         sub     %o0, %o3, %o5           ! physaddr - ecache_flushaddr
1734         or      %o1, %g0, %g5           ! starting offset
1735 2:
1736         ldxa    [%g5 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias
1737 3:
1738         add     %g5, %g2, %g5           ! calculate offset in next set
1739         and     %g5, %g3, %g5           ! force offset within aliased range
1740         cmp     %g5, %o5                ! skip loads from physaddr
1741         be,pn %ncc, 3b
1742           nop
1743         brgz,pt %g4, 2b
1744           dec   %g4
1745 
1746         casxa   [%o0]ASI_MEM, %g0, %g0
1747 
1748         ! Flush %o0 from ecahe again.
1749         ! Need single displacement flush at offset %o1 this time as
1750         ! the E$ is already in direct map mode.
1751         ldxa    [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias
1752 
1753         membar  #Sync
1754         stxa    %g1, [%g0]ASI_UPA_CONFIG ! restore UPA config (DM bits)
1755         membar  #Sync
1756 #endif /* HUMMINGBIRD... */
1757 
1758         retl
1759         wrpr    %g0, %o4, %pstate       ! restore earlier pstate register value
1760         SET_SIZE(clearphys)
1761 
1762 #endif  /* lint */
1763 
1764 #if defined(lint)
1765 /* ARGSUSED */
1766 void
1767 flushecacheline(uint64_t paddr, int ecache_size)
1768 {
1769 }
1770 
1771 #else   /* lint */
1772 /*
1773  * flushecacheline - This is a simpler version of scrubphys
1774  * which simply does a displacement flush of the line in
1775  * question. This routine is mainly used in handling async
1776  * errors where we want to get rid of a bad line in ecache.
1777  * Note that if the line is modified and it has suffered
1778  * data corruption - we are guarantee that the hw will write
1779  * a UE back to mark the page poisoned.
1780  */
1781         ENTRY(flushecacheline)
1782         or      %o1, %g0, %o2   ! put ecache size in %o2
1783 #ifndef HUMMINGBIRD
1784         xor     %o0, %o2, %o1   ! calculate alias address
1785         add     %o2, %o2, %o3   ! 2 * ecachesize in case
1786                                 ! addr == ecache_flushaddr
1787         sub     %o3, 1, %o3     ! -1 == mask
1788         and     %o1, %o3, %o1   ! and with xor'd address
1789         set     ecache_flushaddr, %o3
1790         ldx     [%o3], %o3
1791 
1792         rdpr    %pstate, %o4
1793         andn    %o4, PSTATE_IE | PSTATE_AM, %o5
1794         wrpr    %o5, %g0, %pstate       ! clear IE, AM bits
1795 
1796         ldxa    [%g0]ASI_ESTATE_ERR, %g1
1797         stxa    %g0, [%g0]ASI_ESTATE_ERR        ! disable errors
1798         membar  #Sync
1799 
1800         ldxa    [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias
1801         membar  #Sync
1802         stxa    %g1, [%g0]ASI_ESTATE_ERR        ! restore error enable
1803         membar  #Sync                   
1804 #else /* HUMMINGBIRD */
1805         /*
1806          * UltraSPARC-IIe processor supports both 4-way set associative
1807          * and direct map E$. We need to reconfigure E$ to direct map
1808          * mode for data load/store before displacement flush. Also, we
1809          * need to flush all 4 sets of the E$ to ensure that the physaddr
1810          * has been flushed. Keep the interrupts disabled while flushing
1811          * E$ in this manner.
1812          *
1813          * For flushing a specific physical address, we start at the
1814          * aliased address and load at set-size stride, wrapping around
1815          * at 2*ecache-size boundary and skipping fault physical address.
1816          * It takes 10 loads to guarantee that the physical address has
1817          * been flushed.
1818          *
1819          * Usage:
1820          *      %o0     physaddr
1821          *      %o5     physaddr - ecache_flushaddr
1822          *      %g1     error enable register
1823          *      %g2     E$ set size
1824          *      %g3     E$ flush address range mask (i.e. 2 * E$ -1)
1825          *      %g4     UPA config (restored later)
1826          *      %g5     temp 
1827          */
1828 
1829         sethi   %hi(ecache_associativity), %g5
1830         ld      [%g5 + %lo(ecache_associativity)], %g5
1831         udivx   %o2, %g5, %g2   ! set size (i.e. ecache_size/#sets)
1832         xor     %o0, %o2, %o1   ! calculate alias address
1833         add     %o2, %o2, %g3   ! 2 * ecachesize in case
1834                                 ! addr == ecache_flushaddr
1835         sub     %g3, 1, %g3     ! 2 * ecachesize -1 == mask
1836         and     %o1, %g3, %o1   ! and with xor'd address
1837         sethi   %hi(ecache_flushaddr), %o3
1838         ldx     [%o3 + %lo(ecache_flushaddr)], %o3
1839 
1840         rdpr    %pstate, %o4
1841         andn    %o4, PSTATE_IE | PSTATE_AM, %o5
1842         wrpr    %o5, %g0, %pstate       ! clear IE, AM bits
1843 
1844         ! Place E$ in direct map mode for data access
1845         or      %g0, 1, %g5
1846         sllx    %g5, HB_UPA_DMAP_DATA_BIT, %g5
1847         ldxa    [%g0]ASI_UPA_CONFIG, %g4 ! current UPA config (restored later)
1848         or      %g4, %g5, %g5
1849         membar  #Sync
1850         stxa    %g5, [%g0]ASI_UPA_CONFIG ! enable direct map for data access
1851         membar  #Sync
1852 
1853         ldxa    [%g0]ASI_ESTATE_ERR, %g1
1854         stxa    %g0, [%g0]ASI_ESTATE_ERR        ! disable errors
1855         membar  #Sync
1856 
1857         ! Displace cache line from each set of E$ starting at the
1858         ! aliased address. at set-size stride, wrapping at 2*ecache_size
1859         ! and skipping load from physaddr. We need 10 loads to flush the
1860         ! physaddr from E$.
1861         mov     HB_PHYS_FLUSH_CNT-1, %g5 ! #loads to flush physaddr
1862         sub     %o0, %o3, %o5           ! physaddr - ecache_flushaddr
1863 2:
1864         ldxa    [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias
1865 3:
1866         add     %o1, %g2, %o1           ! calculate offset in next set
1867         and     %o1, %g3, %o1           ! force offset within aliased range
1868         cmp     %o1, %o5                ! skip loads from physaddr
1869         be,pn %ncc, 3b
1870           nop
1871         brgz,pt %g5, 2b
1872           dec   %g5
1873         
1874         membar  #Sync
1875         stxa    %g1, [%g0]ASI_ESTATE_ERR        ! restore error enable
1876         membar  #Sync                   
1877 
1878         stxa    %g4, [%g0]ASI_UPA_CONFIG ! restore UPA config (DM bits)
1879         membar  #Sync
1880 #endif /* HUMMINGBIRD */
1881         retl
1882         wrpr    %g0, %o4, %pstate       
1883         SET_SIZE(flushecacheline)
1884 
1885 #endif  /* lint */
1886 
1887 #if defined(lint)
1888 /* ARGSUSED */
1889 void
1890 ecache_scrubreq_tl1(uint64_t inum, uint64_t dummy)
1891 {
1892 }
1893 
1894 #else   /* lint */
1895 /*
1896  * ecache_scrubreq_tl1 is the crosstrap handler called at ecache_calls_a_sec Hz
1897  * from the clock CPU.  It atomically increments the outstanding request
1898  * counter and, if there was not already an outstanding request,
1899  * branches to setsoftint_tl1 to enqueue an intr_vec for the given inum.
1900  */
1901 
1902         ! Register usage:
1903         !
1904         ! Arguments:
1905         ! %g1 - inum
1906         !
1907         ! Internal:
1908         ! %g2, %g3, %g5 - scratch
1909         ! %g4 - ptr. to spitfire_scrub_misc ec_scrub_outstanding.
1910         ! %g6 - setsoftint_tl1 address
1911 
1912         ENTRY_NP(ecache_scrubreq_tl1)
1913         set     SFPR_SCRUB_MISC + EC_SCRUB_OUTSTANDING, %g2
1914         GET_CPU_PRIVATE_PTR(%g2, %g4, %g5, 1f);
1915         ld      [%g4], %g2              ! cpu's ec_scrub_outstanding.
1916         set     setsoftint_tl1, %g6
1917         !
1918         ! no need to use atomic instructions for the following
1919         ! increment - we're at tl1
1920         !
1921         add     %g2, 0x1, %g3
1922         brnz,pn %g2, 1f                 ! no need to enqueue more intr_vec
1923           st    %g3, [%g4]              ! delay - store incremented counter
1924         jmp     %g6                     ! setsoftint_tl1(%g1) - queue intr_vec
1925           nop
1926         ! not reached
1927 1:
1928         retry
1929         SET_SIZE(ecache_scrubreq_tl1)
1930 
1931 #endif  /* lint */
1932 
1933 #if defined(lint)
1934 /*ARGSUSED*/
1935 void
1936 write_ec_tag_parity(uint32_t id)
1937 {}
1938 #else /* lint */
1939 
1940         /*
1941          * write_ec_tag_parity(), which zero's the ecache tag,
1942          * marks the state as invalid and writes good parity to the tag.
1943          * Input %o1= 32 bit E$ index
1944          */
1945         ENTRY(write_ec_tag_parity)
1946         or      %g0, 1, %o4
1947         sllx    %o4, 39, %o4                    ! set bit 40 for e$ tag access
1948         or      %o0, %o4, %o4                 ! %o4 = ecache addr for tag write
1949 
1950         rdpr    %pstate, %o5
1951         andn    %o5, PSTATE_IE | PSTATE_AM, %o1
1952         wrpr    %o1, %g0, %pstate               ! clear IE, AM bits
1953 
1954         ldxa    [%g0]ASI_ESTATE_ERR, %g1
1955         stxa    %g0, [%g0]ASI_ESTATE_ERR        ! Turn off Error enable
1956         membar  #Sync
1957 
1958         ba      1f
1959          nop
1960         /*
1961          * Align on the ecache boundary in order to force
1962          * ciritical code section onto the same ecache line.
1963          */
1964          .align 64
1965 
1966 1:
1967         set     S_EC_PARITY, %o3                ! clear tag, state invalid
1968         sllx    %o3, S_ECPAR_SHIFT, %o3         ! and with good tag parity
1969         stxa    %o3, [%g0]ASI_EC_DIAG           ! update with the above info
1970         stxa    %g0, [%o4]ASI_EC_W
1971         membar  #Sync
1972 
1973         stxa    %g1, [%g0]ASI_ESTATE_ERR        ! Turn error enable back on
1974         membar  #Sync
1975         retl
1976         wrpr    %g0, %o5, %pstate
1977         SET_SIZE(write_ec_tag_parity)
1978 
1979 #endif /* lint */
1980 
1981 #if defined(lint)
1982 /*ARGSUSED*/
1983 void
1984 write_hb_ec_tag_parity(uint32_t id)
1985 {}
1986 #else /* lint */
1987 
1988         /*
1989          * write_hb_ec_tag_parity(), which zero's the ecache tag,
1990          * marks the state as invalid and writes good parity to the tag.
1991          * Input %o1= 32 bit E$ index
1992          */
1993         ENTRY(write_hb_ec_tag_parity)
1994         or      %g0, 1, %o4
1995         sllx    %o4, 39, %o4                    ! set bit 40 for e$ tag access
1996         or      %o0, %o4, %o4               ! %o4 = ecache addr for tag write
1997 
1998         rdpr    %pstate, %o5
1999         andn    %o5, PSTATE_IE | PSTATE_AM, %o1
2000         wrpr    %o1, %g0, %pstate               ! clear IE, AM bits
2001 
2002         ldxa    [%g0]ASI_ESTATE_ERR, %g1
2003         stxa    %g0, [%g0]ASI_ESTATE_ERR        ! Turn off Error enable
2004         membar  #Sync
2005 
2006         ba      1f
2007          nop
2008         /*
2009          * Align on the ecache boundary in order to force
2010          * ciritical code section onto the same ecache line.
2011          */
2012          .align 64
2013 1: 
2014 #ifdef HUMMINGBIRD
2015         set     HB_EC_PARITY, %o3               ! clear tag, state invalid
2016         sllx    %o3, HB_ECPAR_SHIFT, %o3        ! and with good tag parity
2017 #else /* !HUMMINGBIRD */
2018         set     SB_EC_PARITY, %o3               ! clear tag, state invalid
2019         sllx    %o3, SB_ECPAR_SHIFT, %o3        ! and with good tag parity
2020 #endif /* !HUMMINGBIRD */
2021 
2022         stxa    %o3, [%g0]ASI_EC_DIAG           ! update with the above info
2023         stxa    %g0, [%o4]ASI_EC_W
2024         membar  #Sync
2025 
2026         stxa    %g1, [%g0]ASI_ESTATE_ERR        ! Turn error enable back on
2027         membar  #Sync
2028         retl
2029         wrpr    %g0, %o5, %pstate
2030         SET_SIZE(write_hb_ec_tag_parity)
2031 
2032 #endif /* lint */
2033 
2034 #define VIS_BLOCKSIZE           64
2035 
2036 #if defined(lint)
2037 
2038 /*ARGSUSED*/
2039 int
2040 dtrace_blksuword32(uintptr_t addr, uint32_t *data, int tryagain)
2041 { return (0); }
2042 
2043 #else
2044 
2045         ENTRY(dtrace_blksuword32)
2046         save    %sp, -SA(MINFRAME + 4), %sp
2047 
2048         rdpr    %pstate, %l1
2049         andn    %l1, PSTATE_IE, %l2             ! disable interrupts to
2050         wrpr    %g0, %l2, %pstate               ! protect our FPU diddling
2051 
2052         rd      %fprs, %l0
2053         andcc   %l0, FPRS_FEF, %g0
2054         bz,a,pt %xcc, 1f                        ! if the fpu is disabled
2055         wr      %g0, FPRS_FEF, %fprs            ! ... enable the fpu
2056 
2057         st      %f0, [%fp + STACK_BIAS - 4]     ! save %f0 to the stack
2058 1:
2059         set     0f, %l5
2060         /*
2061          * We're about to write a block full or either total garbage
2062          * (not kernel data, don't worry) or user floating-point data
2063          * (so it only _looks_ like garbage).
2064          */
2065         ld      [%i1], %f0                      ! modify the block
2066         membar  #Sync
2067         stn     %l5, [THREAD_REG + T_LOFAULT]   ! set up the lofault handler
2068         stda    %d0, [%i0]ASI_BLK_COMMIT_S      ! store the modified block
2069         membar  #Sync
2070         stn     %g0, [THREAD_REG + T_LOFAULT]   ! remove the lofault handler
2071 
2072         bz,a,pt %xcc, 1f
2073         wr      %g0, %l0, %fprs                 ! restore %fprs
2074 
2075         ld      [%fp + STACK_BIAS - 4], %f0     ! restore %f0
2076 1:
2077 
2078         wrpr    %g0, %l1, %pstate               ! restore interrupts
2079 
2080         ret
2081         restore %g0, %g0, %o0
2082 
2083 0:
2084         membar  #Sync
2085         stn     %g0, [THREAD_REG + T_LOFAULT]   ! remove the lofault handler
2086 
2087         bz,a,pt %xcc, 1f
2088         wr      %g0, %l0, %fprs                 ! restore %fprs
2089 
2090         ld      [%fp + STACK_BIAS - 4], %f0     ! restore %f0
2091 1:
2092 
2093         wrpr    %g0, %l1, %pstate               ! restore interrupts
2094 
2095         /*
2096          * If tryagain is set (%i2) we tail-call dtrace_blksuword32_err()
2097          * which deals with watchpoints. Otherwise, just return -1.
2098          */
2099         brnz,pt %i2, 1f
2100         nop
2101         ret
2102         restore %g0, -1, %o0
2103 1:
2104         call    dtrace_blksuword32_err
2105         restore
2106 
2107         SET_SIZE(dtrace_blksuword32)
2108 
2109 #endif /* lint */