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 /*
  27  * SFMMU primitives.  These primitives should only be used by sfmmu
  28  * routines.
  29  */
  30 
  31 #include "assym.h"
  32 
  33 #include <sys/asm_linkage.h>
  34 #include <sys/machtrap.h>
  35 #include <sys/machasi.h>
  36 #include <sys/sun4asi.h>
  37 #include <sys/pte.h>
  38 #include <sys/mmu.h>
  39 #include <vm/hat_sfmmu.h>
  40 #include <vm/seg_spt.h>
  41 #include <sys/machparam.h>
  42 #include <sys/privregs.h>
  43 #include <sys/scb.h>
  44 #include <sys/intreg.h>
  45 #include <sys/machthread.h>
  46 #include <sys/clock.h>
  47 #include <sys/trapstat.h>
  48 
  49 /*
  50  * sfmmu related subroutines
  51  */
  52 
  53 /*
  54  * Invalidate either the context of a specific victim or any process
  55  * currently running on this CPU. 
  56  *
  57  * %g1 = sfmmup whose ctx is being invalidated
  58  *       when called from sfmmu_wrap_around, %g1 == INVALID_CONTEXT
  59  * Note %g1 is the only input argument used by this xcall handler.
  60  */
  61         ENTRY(sfmmu_raise_tsb_exception)
  62         !
  63         ! if (victim == INVALID_CONTEXT ||
  64         !     current CPU tsbmiss->usfmmup == victim sfmmup) {
  65         !       if (shctx_on) {
  66         !               shctx = INVALID;
  67         !       }
  68         !       if (sec-ctx > INVALID_CONTEXT) {
  69         !               write INVALID_CONTEXT to sec-ctx
  70         !       }
  71         !       if (pri-ctx > INVALID_CONTEXT) {
  72         !               write INVALID_CONTEXT to pri-ctx
  73         !       }
  74         ! }
  75 
  76         sethi   %hi(ksfmmup), %g3
  77         ldx     [%g3 + %lo(ksfmmup)], %g3
  78         cmp     %g1, %g3
  79         be,a,pn %xcc, ptl1_panic                /* can't invalidate kernel ctx */
  80           mov   PTL1_BAD_RAISE_TSBEXCP, %g1
  81 
  82         set     INVALID_CONTEXT, %g2
  83         cmp     %g1, INVALID_CONTEXT
  84         be,pn   %xcc, 0f                        /* called from wrap_around? */
  85           mov   MMU_SCONTEXT, %g3
  86 
  87         CPU_TSBMISS_AREA(%g5, %g6)              /* load cpu tsbmiss area */
  88         ldx     [%g5 + TSBMISS_UHATID], %g5     /* load usfmmup */
  89         cmp     %g5, %g1                        /* hat toBe-invalid running? */
  90         bne,pt  %xcc, 3f
  91           nop
  92 
  93 0:
  94         sethi   %hi(shctx_on), %g5
  95         ld      [%g5 + %lo(shctx_on)], %g5
  96         brz     %g5, 1f
  97           mov     MMU_SHARED_CONTEXT, %g5
  98         sethi   %hi(FLUSH_ADDR), %g4
  99         stxa    %g0, [%g5]ASI_MMU_CTX
 100         flush   %g4
 101 
 102 1:
 103         ldxa    [%g3]ASI_MMU_CTX, %g5           /* %g5 = pgsz | sec-ctx */
 104         set     CTXREG_CTX_MASK, %g4
 105         and     %g5, %g4, %g5                   /* %g5 = sec-ctx */
 106         cmp     %g5, INVALID_CONTEXT            /* kernel ctx or invald ctx? */
 107         ble,pn  %xcc, 2f                        /* yes, no need to change */
 108           mov   MMU_PCONTEXT, %g7
 109 
 110         stxa    %g2, [%g3]ASI_MMU_CTX           /* set invalid ctx */
 111         membar  #Sync
 112         
 113 2:
 114         ldxa    [%g7]ASI_MMU_CTX, %g3           /* get pgz | pri-ctx */
 115         and     %g3, %g4, %g5                   /* %g5 = pri-ctx */
 116         cmp     %g5, INVALID_CONTEXT            /* kernel ctx or invald ctx? */
 117         ble,pn  %xcc, 3f                        /* yes, no need to change */
 118           srlx  %g3, CTXREG_NEXT_SHIFT, %g3     /* %g3 = nucleus pgsz */
 119         sllx    %g3, CTXREG_NEXT_SHIFT, %g3     /* need to preserve nucleus pgsz */
 120         or      %g3, %g2, %g2                   /* %g2 = nucleus pgsz | INVALID_CONTEXT */
 121         
 122         stxa    %g2, [%g7]ASI_MMU_CTX           /* set pri-ctx to invalid */
 123 3:
 124         retry
 125         SET_SIZE(sfmmu_raise_tsb_exception)
 126         
 127 
 128 
 129         /*
 130          * %o0 = virtual address
 131          * %o1 = address of TTE to be loaded
 132          */
 133         ENTRY_NP(sfmmu_itlb_ld_kva)
 134         rdpr    %pstate, %o3
 135 #ifdef DEBUG
 136         PANIC_IF_INTR_DISABLED_PSTR(%o3, msfmmu_di_l1, %g1)
 137 #endif /* DEBUG */
 138         wrpr    %o3, PSTATE_IE, %pstate         ! Disable interrupts
 139         srln    %o0, MMU_PAGESHIFT, %o0
 140         slln    %o0, MMU_PAGESHIFT, %o0         ! Clear page offset
 141 
 142         ldx     [%o1], %g1
 143         set     MMU_TAG_ACCESS, %o5
 144 #ifdef  CHEETAHPLUS_ERRATUM_34
 145         !
 146         ! If this is Cheetah or derivative and the specified TTE is locked
 147         ! and hence to be loaded into the T16, fully-associative TLB, we
 148         ! must avoid Cheetah+ erratum 34.  In Cheetah+ erratum 34, under
 149         ! certain conditions an ITLB locked index 0 TTE will erroneously be
 150         ! displaced when a new TTE is loaded via ASI_ITLB_IN.  To avoid
 151         ! this erratum, we scan the T16 top down for an unlocked TTE and
 152         ! explicitly load the specified TTE into that index.
 153         !
 154         GET_CPU_IMPL(%g2)
 155         cmp     %g2, CHEETAH_IMPL
 156         bl,pn   %icc, 0f
 157           nop
 158 
 159         andcc   %g1, TTE_LCK_INT, %g0
 160         bz      %icc, 0f                        ! Lock bit is not set;
 161                                                 !   load normally.
 162           or    %g0, (15 << 3), %g3               ! Start searching from the
 163                                                 !   top down.
 164 
 165 1:
 166         ldxa    [%g3]ASI_ITLB_ACCESS, %g4       ! Load TTE from t16
 167 
 168         !
 169         ! If this entry isn't valid, we'll choose to displace it (regardless
 170         ! of the lock bit).
 171         !
 172         cmp     %g4, %g0
 173         bge     %xcc, 2f                        ! TTE is > 0 iff not valid
 174           andcc %g4, TTE_LCK_INT, %g0           ! Check for lock bit
 175         bz      %icc, 2f                        ! If unlocked, go displace
 176           nop
 177         sub     %g3, (1 << 3), %g3
 178         brgz    %g3, 1b                         ! Still more TLB entries
 179           nop                                   ! to search
 180 
 181         sethi   %hi(sfmmu_panic5), %o0          ! We searched all entries and
 182         call    panic                           ! found no unlocked TTE so
 183           or    %o0, %lo(sfmmu_panic5), %o0     ! give up.
 184 
 185 
 186 2:
 187         !
 188         ! We have found an unlocked or non-valid entry; we'll explicitly load
 189         ! our locked entry here.
 190         !
 191         sethi   %hi(FLUSH_ADDR), %o1            ! Flush addr doesn't matter
 192         stxa    %o0, [%o5]ASI_IMMU
 193         stxa    %g1, [%g3]ASI_ITLB_ACCESS
 194         flush   %o1                             ! Flush required for I-MMU
 195         ba      3f                              ! Delay slot of ba is empty
 196           nop                                   !   per Erratum 64
 197 
 198 0:
 199 #endif  /* CHEETAHPLUS_ERRATUM_34 */
 200         sethi   %hi(FLUSH_ADDR), %o1            ! Flush addr doesn't matter
 201         stxa    %o0, [%o5]ASI_IMMU
 202         stxa    %g1, [%g0]ASI_ITLB_IN
 203         flush   %o1                             ! Flush required for I-MMU
 204 3:
 205         retl
 206           wrpr  %g0, %o3, %pstate               ! Enable interrupts
 207         SET_SIZE(sfmmu_itlb_ld_kva)
 208 
 209         /*
 210          * Load an entry into the DTLB.
 211          *
 212          * Special handling is required for locked entries since there
 213          * are some TLB slots that are reserved for the kernel but not
 214          * always held locked.  We want to avoid loading locked TTEs
 215          * into those slots since they could be displaced.
 216          *
 217          * %o0 = virtual address
 218          * %o1 = address of TTE to be loaded
 219          */
 220         ENTRY_NP(sfmmu_dtlb_ld_kva)
 221         rdpr    %pstate, %o3
 222 #ifdef DEBUG
 223         PANIC_IF_INTR_DISABLED_PSTR(%o3, msfmmu_di_l2, %g1)
 224 #endif /* DEBUG */
 225         wrpr    %o3, PSTATE_IE, %pstate         ! disable interrupts
 226         srln    %o0, MMU_PAGESHIFT, %o0
 227         slln    %o0, MMU_PAGESHIFT, %o0         ! clear page offset
 228 
 229         ldx     [%o1], %g1
 230 
 231         set     MMU_TAG_ACCESS, %o5
 232         
 233         set     cpu_impl_dual_pgsz, %o2
 234         ld      [%o2], %o2
 235         brz     %o2, 1f
 236           nop
 237 
 238         sethi   %hi(ksfmmup), %o2
 239         ldx     [%o2 + %lo(ksfmmup)], %o2
 240         ldub    [%o2 + SFMMU_CEXT], %o2
 241         sll     %o2, TAGACCEXT_SHIFT, %o2
 242 
 243         set     MMU_TAG_ACCESS_EXT, %o4         ! can go into T8 if unlocked
 244         stxa    %o2,[%o4]ASI_DMMU
 245         membar  #Sync
 246 1:
 247         andcc   %g1, TTE_LCK_INT, %g0           ! Locked entries require
 248         bnz,pn  %icc, 2f                        ! special handling
 249           sethi %hi(dtlb_resv_ttenum), %g3
 250         stxa    %o0,[%o5]ASI_DMMU               ! Load unlocked TTE
 251         stxa    %g1,[%g0]ASI_DTLB_IN            ! via DTLB_IN
 252         membar  #Sync
 253         retl
 254           wrpr  %g0, %o3, %pstate               ! enable interrupts
 255 2:
 256 #ifdef  CHEETAHPLUS_ERRATUM_34
 257         GET_CPU_IMPL(%g2)
 258 #endif
 259         ld      [%g3 + %lo(dtlb_resv_ttenum)], %g3
 260         sll     %g3, 3, %g3                     ! First reserved idx in TLB 0
 261         sub     %g3, (1 << 3), %g3                ! Decrement idx
 262         ! Erratum 15 workaround due to ld [%g3 + %lo(dtlb_resv_ttenum)], %g3
 263         ldxa    [%g3]ASI_DTLB_ACCESS, %g4       ! Load TTE from TLB 0
 264 3:
 265         ldxa    [%g3]ASI_DTLB_ACCESS, %g4       ! Load TTE from TLB 0
 266         !
 267         ! If this entry isn't valid, we'll choose to displace it (regardless
 268         ! of the lock bit).
 269         !
 270         brgez,pn %g4, 4f                        ! TTE is > 0 iff not valid
 271           nop
 272         andcc   %g4, TTE_LCK_INT, %g0           ! Check for lock bit
 273         bz,pn   %icc, 4f                        ! If unlocked, go displace
 274           nop
 275         sub     %g3, (1 << 3), %g3                ! Decrement idx
 276 #ifdef  CHEETAHPLUS_ERRATUM_34
 277         !
 278         ! If this is a Cheetah or derivative, we must work around Erratum 34
 279         ! for the DTLB.  Erratum 34 states that under certain conditions, 
 280         ! a locked entry 0 TTE may be improperly displaced.  To avoid this,
 281         ! we do not place a locked TTE in entry 0.
 282         !
 283         brgz    %g3, 3b
 284           nop
 285         cmp     %g2, CHEETAH_IMPL
 286         bge,pt  %icc, 5f
 287           nop
 288         brz     %g3, 3b
 289          nop
 290 #else   /* CHEETAHPLUS_ERRATUM_34 */
 291         brgez   %g3, 3b
 292           nop
 293 #endif  /* CHEETAHPLUS_ERRATUM_34 */
 294 5:
 295         sethi   %hi(sfmmu_panic5), %o0          ! We searched all entries and
 296         call    panic                           ! found no unlocked TTE so
 297           or    %o0, %lo(sfmmu_panic5), %o0     ! give up.
 298 4:
 299         stxa    %o0,[%o5]ASI_DMMU               ! Setup tag access
 300 #ifdef  OLYMPUS_SHARED_FTLB
 301         stxa    %g1,[%g0]ASI_DTLB_IN
 302 #else
 303         stxa    %g1,[%g3]ASI_DTLB_ACCESS        ! Displace entry at idx
 304 #endif
 305         membar  #Sync
 306         retl
 307           wrpr  %g0, %o3, %pstate               ! enable interrupts
 308         SET_SIZE(sfmmu_dtlb_ld_kva)
 309 
 310         ENTRY_NP(sfmmu_getctx_pri)
 311         set     MMU_PCONTEXT, %o0
 312         retl
 313           ldxa  [%o0]ASI_MMU_CTX, %o0
 314         SET_SIZE(sfmmu_getctx_pri)
 315 
 316         ENTRY_NP(sfmmu_getctx_sec)
 317         set     MMU_SCONTEXT, %o0
 318         set     CTXREG_CTX_MASK, %o1
 319         ldxa    [%o0]ASI_MMU_CTX, %o0
 320         retl
 321           and   %o0, %o1, %o0
 322         SET_SIZE(sfmmu_getctx_sec)
 323 
 324         /*
 325          * Set the secondary context register for this process.
 326          * %o0 = page_size | context number for this process.
 327          */
 328         ENTRY_NP(sfmmu_setctx_sec)
 329         /*
 330          * From resume we call sfmmu_setctx_sec with interrupts disabled.
 331          * But we can also get called from C with interrupts enabled. So,
 332          * we need to check first.
 333          */
 334 
 335         /* If interrupts are not disabled, then disable them */
 336         rdpr    %pstate, %g1
 337         btst    PSTATE_IE, %g1
 338         bnz,a,pt %icc, 1f
 339           wrpr  %g1, PSTATE_IE, %pstate         /* disable interrupts */
 340 
 341 1:
 342         mov     MMU_SCONTEXT, %o1
 343 
 344         sethi   %hi(FLUSH_ADDR), %o4
 345         stxa    %o0, [%o1]ASI_MMU_CTX           /* set 2nd context reg. */
 346         flush   %o4
 347         sethi   %hi(shctx_on), %g3
 348         ld      [%g3 + %lo(shctx_on)], %g3
 349         brz     %g3, 2f
 350           nop
 351         set     CTXREG_CTX_MASK, %o4
 352         and     %o0,%o4,%o1
 353         cmp     %o1, INVALID_CONTEXT
 354         bne,pn %icc, 2f
 355           mov     MMU_SHARED_CONTEXT, %o1
 356         sethi   %hi(FLUSH_ADDR), %o4
 357         stxa    %g0, [%o1]ASI_MMU_CTX           /* set 2nd context reg. */
 358         flush   %o4
 359 
 360         /*
 361          * if the routine was entered with intr enabled, then enable intr now.
 362          * otherwise, keep intr disabled, return without enabing intr.
 363          * %g1 - old intr state
 364          */
 365 2:      btst    PSTATE_IE, %g1
 366         bnz,a,pt %icc, 3f
 367           wrpr  %g0, %g1, %pstate               /* enable interrupts */
 368 3:      retl
 369           nop
 370         SET_SIZE(sfmmu_setctx_sec)
 371 
 372         /*
 373          * set ktsb_phys to 1 if the processor supports ASI_QUAD_LDD_PHYS.
 374          * returns the detection value in %o0.
 375          *
 376          * Currently ASI_QUAD_LDD_PHYS is supported in processors as follows
 377          *  - cheetah+ and later (greater or equal to CHEETAH_PLUS_IMPL)
 378          *  - FJ OPL Olympus-C and later  (less than SPITFIRE_IMPL)
 379          *
 380          */
 381         ENTRY_NP(sfmmu_setup_4lp)
 382         GET_CPU_IMPL(%o0);
 383         cmp     %o0, CHEETAH_PLUS_IMPL
 384         bge,pt  %icc, 4f
 385           mov   1, %o1
 386         cmp     %o0, SPITFIRE_IMPL
 387         bge,a,pn %icc, 3f
 388           clr   %o1
 389 4:
 390         set     ktsb_phys, %o2
 391         st      %o1, [%o2]
 392 3:      retl
 393         mov     %o1, %o0
 394         SET_SIZE(sfmmu_setup_4lp)
 395 
 396 
 397         /*
 398          * Called to load MMU registers and tsbmiss area
 399          * for the active process.  This function should
 400          * only be called from TL=0.
 401          *
 402          * %o0 - hat pointer
 403          *
 404          */
 405         ENTRY_NP(sfmmu_load_mmustate)
 406 
 407 #ifdef DEBUG
 408         PANIC_IF_INTR_ENABLED_PSTR(msfmmu_ei_l3, %g1)
 409 #endif /* DEBUG */
 410 
 411         sethi   %hi(ksfmmup), %o3
 412         ldx     [%o3 + %lo(ksfmmup)], %o3
 413         cmp     %o3, %o0
 414         be,pn   %xcc, 8f                        ! if kernel as, do nothing
 415           nop      
 416         /*
 417          * We need to set up the TSB base register, tsbmiss
 418          * area, and load locked TTE(s) for the TSB.
 419          */
 420         ldx     [%o0 + SFMMU_TSB], %o1          ! %o1 = first tsbinfo
 421         ldx     [%o1 + TSBINFO_NEXTPTR], %g2    ! %g2 = second tsbinfo
 422 
 423 #ifdef UTSB_PHYS
 424         /*
 425          * UTSB_PHYS accesses user TSBs via physical addresses.  The first
 426          * TSB is in the MMU I/D TSB Base registers.  The 2nd, 3rd and 
 427          * 4th TSBs use designated ASI_SCRATCHPAD regs as pseudo TSB base regs.
 428          */
 429          
 430         /* create/set first UTSBREG actually loaded into MMU_TSB  */
 431         MAKE_UTSBREG(%o1, %o2, %o3)             ! %o2 = first utsbreg
 432         LOAD_TSBREG(%o2, %o3, %o4)              ! write TSB base register
 433 
 434         brz,a,pt  %g2, 2f
 435           mov   -1, %o2                         ! use -1 if no second TSB
 436 
 437         MAKE_UTSBREG(%g2, %o2, %o3)             ! %o2 = second utsbreg
 438 2:
 439         SET_UTSBREG(SCRATCHPAD_UTSBREG2, %o2, %o3)
 440 
 441         /* make 3rd and 4th TSB */
 442         CPU_TSBMISS_AREA(%o4, %o3)              ! %o4 = tsbmiss area
 443 
 444         ldx     [%o0 + SFMMU_SCDP], %g2         ! %g2 = sfmmu_scd
 445         brz,pt  %g2, 3f
 446           mov   -1, %o2                         ! use -1 if no third TSB
 447 
 448         ldx     [%g2 + SCD_SFMMUP], %g3         ! %g3 = scdp->scd_sfmmup
 449         ldx     [%g3 + SFMMU_TSB], %o1          ! %o1 = first scd tsbinfo
 450         brz,pn %o1, 5f
 451           nop                                   ! panic if no third TSB
 452 
 453         /* make 3rd UTSBREG */
 454         MAKE_UTSBREG(%o1, %o2, %o3)             ! %o2 = third utsbreg
 455 3:
 456         SET_UTSBREG(SCRATCHPAD_UTSBREG3, %o2, %o3)
 457         stn     %o2, [%o4 + TSBMISS_TSBSCDPTR]
 458 
 459         brz,pt  %g2, 4f
 460           mov   -1, %o2                         ! use -1 if no 3rd or 4th TSB
 461 
 462         ldx     [%o1 + TSBINFO_NEXTPTR], %g2    ! %g2 = second scd tsbinfo
 463         brz,pt  %g2, 4f
 464           mov   -1, %o2                         ! use -1 if no 4th TSB
 465 
 466         /* make 4th UTSBREG */
 467         MAKE_UTSBREG(%g2, %o2, %o3)             ! %o2 = fourth utsbreg
 468 4:
 469         SET_UTSBREG(SCRATCHPAD_UTSBREG4, %o2, %o3)
 470         stn     %o2, [%o4 + TSBMISS_TSBSCDPTR4M]
 471         ba,pt   %icc, 6f
 472           mov   %o4, %o2                        ! %o2 = tsbmiss area
 473 5:
 474         sethi   %hi(panicstr), %g1              ! panic if no 3rd TSB
 475         ldx     [%g1 + %lo(panicstr)], %g1
 476         tst     %g1
 477 
 478         bnz,pn  %xcc, 8f
 479           nop    
 480 
 481         sethi   %hi(sfmmu_panic10), %o0
 482         call    panic
 483           or     %o0, %lo(sfmmu_panic10), %o0
 484           
 485 #else /* UTSBREG_PHYS */
 486 
 487         brz,pt  %g2, 4f 
 488           nop
 489         /*
 490          * We have a second TSB for this process, so we need to
 491          * encode data for both the first and second TSB in our single
 492          * TSB base register.  See hat_sfmmu.h for details on what bits
 493          * correspond to which TSB.
 494          * We also need to load a locked TTE into the TLB for the second TSB
 495          * in this case.
 496          */
 497         MAKE_TSBREG_SECTSB(%o2, %o1, %g2, %o3, %o4, %g3, sfmmu_tsb_2nd)
 498         ! %o2 = tsbreg
 499         sethi   %hi(utsb4m_dtlb_ttenum), %o3
 500         sethi   %hi(utsb4m_vabase), %o4
 501         ld      [%o3 + %lo(utsb4m_dtlb_ttenum)], %o3
 502         ldx     [%o4 + %lo(utsb4m_vabase)], %o4 ! %o4 = TLB tag for sec TSB
 503         sll     %o3, DTACC_SHIFT, %o3           ! %o3 = sec TSB TLB index
 504         RESV_OFFSET(%g2, %o4, %g3, sfmmu_tsb_2nd)       ! or-in bits of TSB VA
 505         LOAD_TSBTTE(%g2, %o3, %o4, %g3)         ! load sec TSB locked TTE
 506         sethi   %hi(utsb_vabase), %g3
 507         ldx     [%g3 + %lo(utsb_vabase)], %g3   ! %g3 = TLB tag for first TSB
 508         ba,pt   %xcc, 5f
 509           nop
 510 
 511 4:      sethi   %hi(utsb_vabase), %g3
 512         ldx     [%g3 + %lo(utsb_vabase)], %g3   ! %g3 = TLB tag for first TSB
 513         MAKE_TSBREG(%o2, %o1, %g3, %o3, %o4, sfmmu_tsb_1st)     ! %o2 = tsbreg
 514 
 515 5:      LOAD_TSBREG(%o2, %o3, %o4)              ! write TSB base register
 516 
 517         /*
 518          * Load the TTE for the first TSB at the appropriate location in
 519          * the TLB
 520          */
 521         sethi   %hi(utsb_dtlb_ttenum), %o2
 522         ld      [%o2 + %lo(utsb_dtlb_ttenum)], %o2
 523         sll     %o2, DTACC_SHIFT, %o2           ! %o1 = first TSB TLB index
 524         RESV_OFFSET(%o1, %g3, %o3, sfmmu_tsb_1st)       ! or-in bits of TSB VA
 525         LOAD_TSBTTE(%o1, %o2, %g3, %o4)         ! load first TSB locked TTE
 526         CPU_TSBMISS_AREA(%o2, %o3)
 527 #endif /* UTSB_PHYS */
 528 6:
 529         ldx     [%o0 + SFMMU_ISMBLKPA], %o1     ! copy members of sfmmu
 530                                                 ! we need to access from
 531         stx     %o1, [%o2 + TSBMISS_ISMBLKPA]   ! sfmmu_tsb_miss into the
 532         ldub    [%o0 + SFMMU_TTEFLAGS], %o3     ! per-CPU tsbmiss area.
 533         stx     %o0, [%o2 + TSBMISS_UHATID]
 534         stub    %o3, [%o2 + TSBMISS_UTTEFLAGS]
 535 #ifdef UTSB_PHYS
 536         ldx     [%o0 + SFMMU_SRDP], %o1
 537         ldub    [%o0 + SFMMU_RTTEFLAGS], %o4
 538         stub    %o4,  [%o2 + TSBMISS_URTTEFLAGS]
 539         stx     %o1, [%o2 +  TSBMISS_SHARED_UHATID]
 540         brz,pn  %o1, 8f                         ! check for sfmmu_srdp
 541           add   %o0, SFMMU_HMERMAP, %o1
 542         add     %o2, TSBMISS_SHMERMAP, %o2
 543         mov     SFMMU_HMERGNMAP_WORDS, %o3
 544                                                 ! set tsbmiss shmermap
 545         SET_REGION_MAP(%o1, %o2, %o3, %o4, load_shme_mmustate)
 546 
 547         ldx     [%o0 + SFMMU_SCDP], %o4         ! %o4 = sfmmu_scd
 548         CPU_TSBMISS_AREA(%o2, %o3)              ! %o2 = tsbmiss area
 549         mov     SFMMU_HMERGNMAP_WORDS, %o3
 550         brnz,pt %o4, 7f                       ! check for sfmmu_scdp else
 551           add   %o2, TSBMISS_SCDSHMERMAP, %o2 ! zero tsbmiss scd_shmermap
 552         ZERO_REGION_MAP(%o2, %o3, zero_scd_mmustate)
 553         ba 8f
 554           nop
 555 7:
 556         add     %o4, SCD_HMERMAP, %o1
 557         SET_REGION_MAP(%o1, %o2, %o3, %o4, load_scd_mmustate)
 558 #endif /* UTSB_PHYS */
 559 
 560 8:
 561         retl
 562           nop
 563         SET_SIZE(sfmmu_load_mmustate)
 564 
 565 /*
 566  * Invalidate all of the entries within the TSB, by setting the inv bit
 567  * in the tte_tag field of each tsbe.
 568  *
 569  * We take advantage of the fact that the TSBs are page aligned and a
 570  * multiple of PAGESIZE to use ASI_BLK_INIT_xxx ASI.
 571  *
 572  * See TSB_LOCK_ENTRY and the miss handlers for how this works in practice
 573  * (in short, we set all bits in the upper word of the tag, and we give the
 574  * invalid bit precedence over other tag bits in both places).
 575  */
 576 
 577 #define VIS_BLOCKSIZE   64
 578 
 579         ENTRY(sfmmu_inv_tsb_fast)
 580 
 581         ! Get space for aligned block of saved fp regs.
 582         save    %sp, -SA(MINFRAME + 2*VIS_BLOCKSIZE), %sp
 583 
 584         ! kpreempt_disable();
 585         ldsb    [THREAD_REG + T_PREEMPT], %l3
 586         inc     %l3
 587         stb     %l3, [THREAD_REG + T_PREEMPT]
 588 
 589         ! See if fpu was in use.  If it was, we need to save off the
 590         ! floating point registers to the stack.
 591         rd      %fprs, %l0                      ! %l0 = cached copy of fprs
 592         btst    FPRS_FEF, %l0
 593         bz,pt   %icc, 4f
 594           nop
 595 
 596         ! save in-use fpregs on stack
 597         membar  #Sync                           ! make sure tranx to fp regs
 598                                                 ! have completed
 599         add     %fp, STACK_BIAS - 65, %l1       ! get stack frame for fp regs
 600         and     %l1, -VIS_BLOCKSIZE, %l1        ! block align frame
 601         stda    %d0, [%l1]ASI_BLK_P             ! %l1 = addr of saved fp regs
 602 
 603         ! enable fp
 604 4:      membar  #StoreStore|#StoreLoad|#LoadStore
 605         wr      %g0, FPRS_FEF, %fprs
 606         wr      %g0, ASI_BLK_P, %asi
 607 
 608         ! load up FP registers with invalid TSB tag.
 609         fone    %d0                     ! ones in tag
 610         fzero   %d2                     ! zeros in TTE
 611         fone    %d4                     ! ones in tag
 612         fzero   %d6                     ! zeros in TTE
 613         fone    %d8                     ! ones in tag
 614         fzero   %d10                    ! zeros in TTE
 615         fone    %d12                    ! ones in tag
 616         fzero   %d14                    ! zeros in TTE
 617         ba,pt   %xcc, .sfmmu_inv_doblock
 618           mov   (4*VIS_BLOCKSIZE), %i4  ! we do 4 stda's each loop below
 619 
 620 .sfmmu_inv_blkstart:
 621       ! stda    %d0, [%i0+192]%asi  ! in dly slot of branch that got us here
 622         stda    %d0, [%i0+128]%asi
 623         stda    %d0, [%i0+64]%asi
 624         stda    %d0, [%i0]%asi
 625 
 626         add     %i0, %i4, %i0
 627         sub     %i1, %i4, %i1
 628 
 629 .sfmmu_inv_doblock:
 630         cmp     %i1, (4*VIS_BLOCKSIZE)  ! check for completion
 631         bgeu,a  %icc, .sfmmu_inv_blkstart
 632           stda  %d0, [%i0+192]%asi
 633 
 634 .sfmmu_inv_finish:
 635         membar  #Sync
 636         btst    FPRS_FEF, %l0           ! saved from above
 637         bz,a    .sfmmu_inv_finished
 638           wr    %l0, 0, %fprs           ! restore fprs
 639 
 640         ! restore fpregs from stack
 641         ldda    [%l1]ASI_BLK_P, %d0
 642         membar  #Sync
 643         wr      %l0, 0, %fprs           ! restore fprs
 644 
 645 .sfmmu_inv_finished:
 646         ! kpreempt_enable();
 647         ldsb    [THREAD_REG + T_PREEMPT], %l3
 648         dec     %l3
 649         stb     %l3, [THREAD_REG + T_PREEMPT]
 650         ret
 651           restore
 652         SET_SIZE(sfmmu_inv_tsb_fast)
 653 
 654 /*
 655  * Prefetch "struct tsbe" while walking TSBs.
 656  * prefetch 7 cache lines ahead of where we are at now.
 657  * #n_reads is being used since #one_read only applies to
 658  * floating point reads, and we are not doing floating point
 659  * reads.  However, this has the negative side effect of polluting
 660  * the ecache.
 661  * The 448 comes from (7 * 64) which is how far ahead of our current
 662  * address, we want to prefetch.
 663  */
 664         ENTRY(prefetch_tsbe_read)
 665         retl
 666           prefetch      [%o0+448], #n_reads
 667         SET_SIZE(prefetch_tsbe_read)
 668 
 669 /* Prefetch the tsbe that we are about to write */
 670         ENTRY(prefetch_tsbe_write)
 671         retl
 672           prefetch      [%o0], #n_writes
 673         SET_SIZE(prefetch_tsbe_write)
 674