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 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright (c) 2016 by Delphix. All rights reserved.
  25  */
  26 
  27 /*
  28  * SFMMU primitives.  These primitives should only be used by sfmmu
  29  * routines.
  30  */
  31 
  32 #if defined(lint)
  33 #include <sys/types.h>
  34 #else   /* lint */
  35 #include "assym.h"
  36 #endif  /* lint */
  37 
  38 #include <sys/asm_linkage.h>
  39 #include <sys/machtrap.h>
  40 #include <sys/machasi.h>
  41 #include <sys/sun4asi.h>
  42 #include <sys/pte.h>
  43 #include <sys/mmu.h>
  44 #include <vm/hat_sfmmu.h>
  45 #include <vm/seg_spt.h>
  46 #include <sys/machparam.h>
  47 #include <sys/privregs.h>
  48 #include <sys/scb.h>
  49 #include <sys/intreg.h>
  50 #include <sys/machthread.h>
  51 #include <sys/intr.h>
  52 #include <sys/clock.h>
  53 #include <sys/trapstat.h>
  54 
  55 #ifdef TRAPTRACE
  56 #include <sys/traptrace.h>
  57 
  58 /*
  59  * Tracing macro. Adds two instructions if TRAPTRACE is defined.
  60  */
  61 #define TT_TRACE(label)         \
  62         ba      label           ;\
  63         rd      %pc, %g7
  64 #else
  65 
  66 #define TT_TRACE(label)
  67 
  68 #endif /* TRAPTRACE */
  69 
  70 #ifndef lint
  71 
  72 #if (TTE_SUSPEND_SHIFT > 0)
  73 #define TTE_SUSPEND_INT_SHIFT(reg)                              \
  74         sllx    reg, TTE_SUSPEND_SHIFT, reg
  75 #else
  76 #define TTE_SUSPEND_INT_SHIFT(reg)
  77 #endif
  78 
  79 #endif /* lint */
  80 
  81 #ifndef lint
  82 
  83 /*
  84  * Assumes TSBE_TAG is 0
  85  * Assumes TSBE_INTHI is 0
  86  * Assumes TSBREG.split is 0
  87  */
  88 
  89 #if TSBE_TAG != 0
  90 #error "TSB_UPDATE and TSB_INVALIDATE assume TSBE_TAG = 0"
  91 #endif
  92 
  93 #if TSBTAG_INTHI != 0
  94 #error "TSB_UPDATE and TSB_INVALIDATE assume TSBTAG_INTHI = 0"
  95 #endif
  96 
  97 /*
  98  * The following code assumes the tsb is not split.
  99  *
 100  * With TSBs no longer shared between processes, it's no longer
 101  * necessary to hash the context bits into the tsb index to get
 102  * tsb coloring; the new implementation treats the TSB as a
 103  * direct-mapped, virtually-addressed cache.
 104  *
 105  * In:
 106  *    vpshift = virtual page shift; e.g. 13 for 8K TTEs (constant or ro)
 107  *    tsbbase = base address of TSB (clobbered)
 108  *    tagacc = tag access register (clobbered)
 109  *    szc = size code of TSB (ro)
 110  *    tmp = scratch reg
 111  * Out:
 112  *    tsbbase = pointer to entry in TSB
 113  */
 114 #define GET_TSBE_POINTER(vpshift, tsbbase, tagacc, szc, tmp)            \
 115         mov     TSB_ENTRIES(0), tmp     /* nentries in TSB size 0 */    ;\
 116         srlx    tagacc, vpshift, tagacc                                 ;\
 117         sllx    tmp, szc, tmp           /* tmp = nentries in TSB */     ;\
 118         sub     tmp, 1, tmp             /* mask = nentries - 1 */       ;\
 119         and     tagacc, tmp, tmp        /* tsbent = virtpage & mask */      ;\
 120         sllx    tmp, TSB_ENTRY_SHIFT, tmp       /* entry num --> ptr */      ;\
 121         add     tsbbase, tmp, tsbbase   /* add entry offset to TSB base */
 122 
 123 /*
 124  * When the kpm TSB is used it is assumed that it is direct mapped
 125  * using (vaddr>>vpshift)%tsbsz as the index.
 126  *
 127  * Note that, for now, the kpm TSB and kernel TSB are the same for
 128  * each mapping size.  However that need not always be the case.  If
 129  * the trap handlers are updated to search a different TSB for kpm
 130  * addresses than for kernel addresses then kpm_tsbbase and kpm_tsbsz
 131  * (and/or kpmsm_tsbbase/kpmsm_tsbsz) may be entirely independent.
 132  *
 133  * In:
 134  *    vpshift = virtual page shift; e.g. 13 for 8K TTEs (constant or ro)
 135  *    vaddr = virtual address (clobbered)
 136  *    tsbp, szc, tmp = scratch
 137  * Out:
 138  *    tsbp = pointer to entry in TSB
 139  */
 140 #define GET_KPM_TSBE_POINTER(vpshift, tsbp, vaddr, szc, tmp)            \
 141         cmp     vpshift, MMU_PAGESHIFT                                  ;\
 142         bne,pn  %icc, 1f                /* branch if large case */      ;\
 143           sethi %hi(kpmsm_tsbsz), szc                                   ;\
 144         sethi   %hi(kpmsm_tsbbase), tsbp                                ;\
 145         ld      [szc + %lo(kpmsm_tsbsz)], szc                           ;\
 146         ldx     [tsbp + %lo(kpmsm_tsbbase)], tsbp                       ;\
 147         ba,pt   %icc, 2f                                                ;\
 148           nop                                                           ;\
 149 1:      sethi   %hi(kpm_tsbsz), szc                                     ;\
 150         sethi   %hi(kpm_tsbbase), tsbp                                  ;\
 151         ld      [szc + %lo(kpm_tsbsz)], szc                             ;\
 152         ldx     [tsbp + %lo(kpm_tsbbase)], tsbp                         ;\
 153 2:      GET_TSBE_POINTER(vpshift, tsbp, vaddr, szc, tmp)
 154 
 155 /*
 156  * Lock the TSBE at virtual address tsbep.
 157  *
 158  * tsbep = TSBE va (ro)
 159  * tmp1, tmp2 = scratch registers (clobbered)
 160  * label = label to jump to if we fail to lock the tsb entry
 161  * %asi = ASI to use for TSB access
 162  *
 163  * NOTE that we flush the TSB using fast VIS instructions that
 164  * set all 1's in the TSB tag, so TSBTAG_LOCKED|TSBTAG_INVALID must
 165  * not be treated as a locked entry or we'll get stuck spinning on
 166  * an entry that isn't locked but really invalid.
 167  */
 168 
 169 #if defined(UTSB_PHYS)
 170 
 171 #define TSB_LOCK_ENTRY(tsbep, tmp1, tmp2, label)                        \
 172         lda     [tsbep]ASI_MEM, tmp1                                    ;\
 173         sethi   %hi(TSBTAG_LOCKED), tmp2                                ;\
 174         cmp     tmp1, tmp2                                              ;\
 175         be,a,pn %icc, label             /* if locked ignore */          ;\
 176           nop                                                           ;\
 177         casa    [tsbep]ASI_MEM, tmp1, tmp2                              ;\
 178         cmp     tmp1, tmp2                                              ;\
 179         bne,a,pn %icc, label            /* didn't lock so ignore */     ;\
 180           nop                                                           ;\
 181         /* tsbe lock acquired */                                        ;\
 182         membar #StoreStore
 183 
 184 #else /* UTSB_PHYS */
 185 
 186 #define TSB_LOCK_ENTRY(tsbep, tmp1, tmp2, label)                        \
 187         lda     [tsbep]%asi, tmp1                                       ;\
 188         sethi   %hi(TSBTAG_LOCKED), tmp2                                ;\
 189         cmp     tmp1, tmp2                                              ;\
 190         be,a,pn %icc, label             /* if locked ignore */          ;\
 191           nop                                                           ;\
 192         casa    [tsbep]%asi, tmp1, tmp2                                 ;\
 193         cmp     tmp1, tmp2                                              ;\
 194         bne,a,pn %icc, label            /* didn't lock so ignore */     ;\
 195           nop                                                           ;\
 196         /* tsbe lock acquired */                                        ;\
 197         membar #StoreStore
 198 
 199 #endif /* UTSB_PHYS */
 200 
 201 /*
 202  * Atomically write TSBE at virtual address tsbep.
 203  *
 204  * tsbep = TSBE va (ro)
 205  * tte = TSBE TTE (ro)
 206  * tagtarget = TSBE tag (ro)
 207  * %asi = ASI to use for TSB access
 208  */
 209 
 210 #if defined(UTSB_PHYS)
 211 
 212 #define TSB_INSERT_UNLOCK_ENTRY(tsbep, tte, tagtarget, tmp1)            \
 213         add     tsbep, TSBE_TTE, tmp1                                   ;\
 214         stxa    tte, [tmp1]ASI_MEM              /* write tte data */    ;\
 215         membar #StoreStore                                              ;\
 216         add     tsbep, TSBE_TAG, tmp1                                   ;\
 217         stxa    tagtarget, [tmp1]ASI_MEM        /* write tte tag & unlock */
 218 
 219 #else /* UTSB_PHYS */
 220 
 221 #define TSB_INSERT_UNLOCK_ENTRY(tsbep, tte, tagtarget,tmp1)             \
 222         stxa    tte, [tsbep + TSBE_TTE]%asi     /* write tte data */    ;\
 223         membar #StoreStore                                              ;\
 224         stxa    tagtarget, [tsbep + TSBE_TAG]%asi /* write tte tag & unlock */
 225 
 226 #endif /* UTSB_PHYS */
 227 
 228 /*
 229  * Load an entry into the TSB at TL > 0.
 230  *
 231  * tsbep = pointer to the TSBE to load as va (ro)
 232  * tte = value of the TTE retrieved and loaded (wo)
 233  * tagtarget = tag target register.  To get TSBE tag to load,
 234  *   we need to mask off the context and leave only the va (clobbered)
 235  * ttepa = pointer to the TTE to retrieve/load as pa (ro)
 236  * tmp1, tmp2 = scratch registers
 237  * label = label to jump to if we fail to lock the tsb entry
 238  * %asi = ASI to use for TSB access
 239  */
 240 
 241 #if defined(UTSB_PHYS)
 242 
 243 #define TSB_UPDATE_TL(tsbep, tte, tagtarget, ttepa, tmp1, tmp2, label) \
 244         TSB_LOCK_ENTRY(tsbep, tmp1, tmp2, label)                        ;\
 245         /*                                                              ;\
 246          * I don't need to update the TSB then check for the valid tte. ;\
 247          * TSB invalidate will spin till the entry is unlocked. Note,   ;\
 248          * we always invalidate the hash table before we unload the TSB.;\
 249          */                                                             ;\
 250         sllx    tagtarget, TTARGET_VA_SHIFT, tagtarget                  ;\
 251         ldxa    [ttepa]ASI_MEM, tte                                     ;\
 252         srlx    tagtarget, TTARGET_VA_SHIFT, tagtarget                  ;\
 253         sethi   %hi(TSBTAG_INVALID), tmp2                               ;\
 254         add     tsbep, TSBE_TAG, tmp1                                   ;\
 255         brgez,a,pn tte, label                                           ;\
 256          sta    tmp2, [tmp1]ASI_MEM                     /* unlock */    ;\
 257         TSB_INSERT_UNLOCK_ENTRY(tsbep, tte, tagtarget, tmp1)            ;\
 258 label:
 259 
 260 #else /* UTSB_PHYS */
 261 
 262 #define TSB_UPDATE_TL(tsbep, tte, tagtarget, ttepa, tmp1, tmp2, label) \
 263         TSB_LOCK_ENTRY(tsbep, tmp1, tmp2, label)                        ;\
 264         /*                                                              ;\
 265          * I don't need to update the TSB then check for the valid tte. ;\
 266          * TSB invalidate will spin till the entry is unlocked. Note,   ;\
 267          * we always invalidate the hash table before we unload the TSB.;\
 268          */                                                             ;\
 269         sllx    tagtarget, TTARGET_VA_SHIFT, tagtarget                  ;\
 270         ldxa    [ttepa]ASI_MEM, tte                                     ;\
 271         srlx    tagtarget, TTARGET_VA_SHIFT, tagtarget                  ;\
 272         sethi   %hi(TSBTAG_INVALID), tmp2                               ;\
 273         brgez,a,pn tte, label                                           ;\
 274          sta    tmp2, [tsbep + TSBE_TAG]%asi            /* unlock */    ;\
 275         TSB_INSERT_UNLOCK_ENTRY(tsbep, tte, tagtarget, tmp1)            ;\
 276 label:
 277 
 278 #endif /* UTSB_PHYS */
 279 
 280 /*
 281  * Load a 32M/256M Panther TSB entry into the TSB at TL > 0,
 282  *   for ITLB synthesis.
 283  *
 284  * tsbep = pointer to the TSBE to load as va (ro)
 285  * tte = 4M pfn offset (in), value of the TTE retrieved and loaded (out)
 286  *   with exec_perm turned off and exec_synth turned on
 287  * tagtarget = tag target register.  To get TSBE tag to load,
 288  *   we need to mask off the context and leave only the va (clobbered)
 289  * ttepa = pointer to the TTE to retrieve/load as pa (ro)
 290  * tmp1, tmp2 = scratch registers
 291  * label = label to use for branch (text)
 292  * %asi = ASI to use for TSB access
 293  */
 294 
 295 #define TSB_UPDATE_TL_PN(tsbep, tte, tagtarget, ttepa, tmp1, tmp2, label) \
 296         TSB_LOCK_ENTRY(tsbep, tmp1, tmp2, label)                        ;\
 297         /*                                                              ;\
 298          * I don't need to update the TSB then check for the valid tte. ;\
 299          * TSB invalidate will spin till the entry is unlocked. Note,   ;\
 300          * we always invalidate the hash table before we unload the TSB.;\
 301          * Or in 4M pfn offset to TTE and set the exec_perm bit to 0    ;\
 302          * and exec_synth bit to 1.                                     ;\
 303          */                                                             ;\
 304         sllx    tagtarget, TTARGET_VA_SHIFT, tagtarget                  ;\
 305         mov     tte, tmp1                                               ;\
 306         ldxa    [ttepa]ASI_MEM, tte                                     ;\
 307         srlx    tagtarget, TTARGET_VA_SHIFT, tagtarget                  ;\
 308         sethi   %hi(TSBTAG_INVALID), tmp2                               ;\
 309         brgez,a,pn tte, label                                           ;\
 310          sta    tmp2, [tsbep + TSBE_TAG]%asi            /* unlock */    ;\
 311         or      tte, tmp1, tte                                          ;\
 312         andn    tte, TTE_EXECPRM_INT, tte                               ;\
 313         or      tte, TTE_E_SYNTH_INT, tte                               ;\
 314         TSB_INSERT_UNLOCK_ENTRY(tsbep, tte, tagtarget, tmp1)            ;\
 315 label:
 316 
 317 /*
 318  * Build a 4M pfn offset for a Panther 32M/256M page, for ITLB synthesis.
 319  *
 320  * tte = value of the TTE, used to get tte_size bits (ro)
 321  * tagaccess = tag access register, used to get 4M pfn bits (ro)
 322  * pfn = 4M pfn bits shifted to offset for tte (out)
 323  * tmp1 = scratch register
 324  * label = label to use for branch (text)
 325  */
 326 
 327 #define GET_4M_PFN_OFF(tte, tagaccess, pfn, tmp, label)                 \
 328         /*                                                              ;\
 329          * Get 4M bits from tagaccess for 32M, 256M pagesizes.          ;\
 330          * Return them, shifted, in pfn.                                ;\
 331          */                                                             ;\
 332         srlx    tagaccess, MMU_PAGESHIFT4M, tagaccess                   ;\
 333         srlx    tte, TTE_SZ_SHFT, tmp           /* isolate the */       ;\
 334         andcc   tmp, TTE_SZ_BITS, %g0           /* tte_size bits */     ;\
 335         bz,a,pt %icc, label/**/f                /* if 0, is */          ;\
 336           and   tagaccess, 0x7, tagaccess       /* 32M page size */     ;\
 337         and     tagaccess, 0x3f, tagaccess /* else 256M page size */    ;\
 338 label:                                                                  ;\
 339         sllx    tagaccess, MMU_PAGESHIFT4M, pfn
 340 
 341 /*
 342  * Add 4M TTE size code to a tte for a Panther 32M/256M page,
 343  * for ITLB synthesis.
 344  *
 345  * tte = value of the TTE, used to get tte_size bits (rw)
 346  * tmp1 = scratch register
 347  */
 348 
 349 #define SET_TTE4M_PN(tte, tmp)                                          \
 350         /*                                                              ;\
 351          * Set 4M pagesize tte bits.                                    ;\
 352          */                                                             ;\
 353         set     TTE4M, tmp                                              ;\
 354         sllx    tmp, TTE_SZ_SHFT, tmp                                   ;\
 355         or      tte, tmp, tte
 356 
 357 /*
 358  * Load an entry into the TSB at TL=0.
 359  *
 360  * tsbep = pointer to the TSBE to load as va (ro)
 361  * tteva = pointer to the TTE to load as va (ro)
 362  * tagtarget = TSBE tag to load (which contains no context), synthesized
 363  * to match va of MMU tag target register only (ro)
 364  * tmp1, tmp2 = scratch registers (clobbered)
 365  * label = label to use for branches (text)
 366  * %asi = ASI to use for TSB access
 367  */
 368 
 369 #if defined(UTSB_PHYS)
 370 
 371 #define TSB_UPDATE(tsbep, tteva, tagtarget, tmp1, tmp2, label)          \
 372         /* can't rd tteva after locking tsb because it can tlb miss */  ;\
 373         ldx     [tteva], tteva                  /* load tte */          ;\
 374         TSB_LOCK_ENTRY(tsbep, tmp1, tmp2, label)                        ;\
 375         sethi   %hi(TSBTAG_INVALID), tmp2                               ;\
 376         add     tsbep, TSBE_TAG, tmp1                                   ;\
 377         brgez,a,pn tteva, label                                         ;\
 378          sta    tmp2, [tmp1]ASI_MEM                     /* unlock */    ;\
 379         TSB_INSERT_UNLOCK_ENTRY(tsbep, tteva, tagtarget, tmp1)          ;\
 380 label:
 381 
 382 #else /* UTSB_PHYS */
 383 
 384 #define TSB_UPDATE(tsbep, tteva, tagtarget, tmp1, tmp2, label)          \
 385         /* can't rd tteva after locking tsb because it can tlb miss */  ;\
 386         ldx     [tteva], tteva                  /* load tte */          ;\
 387         TSB_LOCK_ENTRY(tsbep, tmp1, tmp2, label)                        ;\
 388         sethi   %hi(TSBTAG_INVALID), tmp2                               ;\
 389         brgez,a,pn tteva, label                                         ;\
 390          sta    tmp2, [tsbep + TSBE_TAG]%asi            /* unlock */    ;\
 391         TSB_INSERT_UNLOCK_ENTRY(tsbep, tteva, tagtarget, tmp1)          ;\
 392 label:
 393 
 394 #endif /* UTSB_PHYS */
 395 
 396 /*
 397  * Invalidate a TSB entry in the TSB.
 398  *
 399  * NOTE: TSBE_TAG is assumed to be zero.  There is a compile time check
 400  *       about this earlier to ensure this is true.  Thus when we are
 401  *       directly referencing tsbep below, we are referencing the tte_tag
 402  *       field of the TSBE.  If this  offset ever changes, the code below
 403  *       will need to be modified.
 404  *
 405  * tsbep = pointer to TSBE as va (ro)
 406  * tag = invalidation is done if this matches the TSBE tag (ro)
 407  * tmp1 - tmp3 = scratch registers (clobbered)
 408  * label = label name to use for branches (text)
 409  * %asi = ASI to use for TSB access
 410  */
 411 
 412 #if defined(UTSB_PHYS)
 413 
 414 #define TSB_INVALIDATE(tsbep, tag, tmp1, tmp2, tmp3, label)             \
 415         lda     [tsbep]ASI_MEM, tmp1    /* tmp1 = tsbe tag */           ;\
 416         sethi   %hi(TSBTAG_LOCKED), tmp2                                ;\
 417 label/**/1:                                                             ;\
 418         cmp     tmp1, tmp2              /* see if tsbe is locked, if */ ;\
 419         be,a,pn %icc, label/**/1        /* so, loop until unlocked */   ;\
 420           lda   [tsbep]ASI_MEM, tmp1    /* reloading value each time */ ;\
 421         ldxa    [tsbep]ASI_MEM, tmp3    /* tmp3 = tsbe tag */           ;\
 422         cmp     tag, tmp3               /* compare tags */              ;\
 423         bne,pt  %xcc, label/**/2        /* if different, do nothing */  ;\
 424           sethi %hi(TSBTAG_INVALID), tmp3                               ;\
 425         casa    [tsbep]ASI_MEM, tmp1, tmp3 /* try to set tag invalid */ ;\
 426         cmp     tmp1, tmp3              /* if not successful */         ;\
 427         bne,a,pn %icc, label/**/1       /* start over from the top */   ;\
 428           lda   [tsbep]ASI_MEM, tmp1    /* reloading tsbe tag */        ;\
 429 label/**/2:
 430 
 431 #else /* UTSB_PHYS */
 432 
 433 #define TSB_INVALIDATE(tsbep, tag, tmp1, tmp2, tmp3, label)             \
 434         lda     [tsbep]%asi, tmp1       /* tmp1 = tsbe tag */           ;\
 435         sethi   %hi(TSBTAG_LOCKED), tmp2                                ;\
 436 label/**/1:                                                             ;\
 437         cmp     tmp1, tmp2              /* see if tsbe is locked, if */ ;\
 438         be,a,pn %icc, label/**/1        /* so, loop until unlocked */   ;\
 439           lda   [tsbep]%asi, tmp1       /* reloading value each time */ ;\
 440         ldxa    [tsbep]%asi, tmp3       /* tmp3 = tsbe tag */           ;\
 441         cmp     tag, tmp3               /* compare tags */              ;\
 442         bne,pt  %xcc, label/**/2        /* if different, do nothing */  ;\
 443           sethi %hi(TSBTAG_INVALID), tmp3                               ;\
 444         casa    [tsbep]%asi, tmp1, tmp3 /* try to set tag invalid */    ;\
 445         cmp     tmp1, tmp3              /* if not successful */         ;\
 446         bne,a,pn %icc, label/**/1       /* start over from the top */   ;\
 447           lda   [tsbep]%asi, tmp1       /* reloading tsbe tag */        ;\
 448 label/**/2:
 449 
 450 #endif /* UTSB_PHYS */
 451 
 452 #if TSB_SOFTSZ_MASK < TSB_SZ_MASK
 453 #error  - TSB_SOFTSZ_MASK too small
 454 #endif
 455 
 456 
 457 /*
 458  * An implementation of setx which will be hot patched at run time.
 459  * since it is being hot patched, there is no value passed in.
 460  * Thus, essentially we are implementing
 461  *      setx value, tmp, dest
 462  * where value is RUNTIME_PATCH (aka 0) in this case.
 463  */
 464 #define RUNTIME_PATCH_SETX(dest, tmp)                                   \
 465         sethi   %hh(RUNTIME_PATCH), tmp                                 ;\
 466         sethi   %lm(RUNTIME_PATCH), dest                                ;\
 467         or      tmp, %hm(RUNTIME_PATCH), tmp                            ;\
 468         or      dest, %lo(RUNTIME_PATCH), dest                          ;\
 469         sllx    tmp, 32, tmp                                            ;\
 470         nop                             /* for perf reasons */          ;\
 471         or      tmp, dest, dest         /* contents of patched value */
 472 
 473 #endif /* lint */
 474 
 475 
 476 #if defined (lint)
 477 
 478 /*
 479  * sfmmu related subroutines
 480  */
 481 uint_t
 482 sfmmu_disable_intrs()
 483 { return(0); }
 484 
 485 /* ARGSUSED */
 486 void
 487 sfmmu_enable_intrs(uint_t pstate_save)
 488 {}
 489 
 490 /* ARGSUSED */
 491 int
 492 sfmmu_alloc_ctx(sfmmu_t *sfmmup, int allocflag, struct cpu *cp, int shflag)
 493 { return(0); }
 494 
 495 /*
 496  * Use cas, if tte has changed underneath us then reread and try again.
 497  * In the case of a retry, it will update sttep with the new original.
 498  */
 499 /* ARGSUSED */
 500 int
 501 sfmmu_modifytte(tte_t *sttep, tte_t *stmodttep, tte_t *dttep)
 502 { return(0); }
 503 
 504 /*
 505  * Use cas, if tte has changed underneath us then return 1, else return 0
 506  */
 507 /* ARGSUSED */
 508 int
 509 sfmmu_modifytte_try(tte_t *sttep, tte_t *stmodttep, tte_t *dttep)
 510 { return(0); }
 511 
 512 /* ARGSUSED */
 513 void
 514 sfmmu_copytte(tte_t *sttep, tte_t *dttep)
 515 {}
 516 
 517 /*ARGSUSED*/
 518 struct tsbe *
 519 sfmmu_get_tsbe(uint64_t tsbeptr, caddr_t vaddr, int vpshift, int tsb_szc)
 520 { return(0); }
 521 
 522 /*ARGSUSED*/
 523 uint64_t
 524 sfmmu_make_tsbtag(caddr_t va)
 525 { return(0); }
 526 
 527 #else   /* lint */
 528 
 529         .seg    ".data"
 530         .global sfmmu_panic1
 531 sfmmu_panic1:
 532         .asciz  "sfmmu_asm: interrupts already disabled"
 533 
 534         .global sfmmu_panic3
 535 sfmmu_panic3:
 536         .asciz  "sfmmu_asm: sfmmu_vatopfn called for user"
 537 
 538         .global sfmmu_panic4
 539 sfmmu_panic4:
 540         .asciz  "sfmmu_asm: 4M tsb pointer mis-match"
 541 
 542         .global sfmmu_panic5
 543 sfmmu_panic5:
 544         .asciz  "sfmmu_asm: no unlocked TTEs in TLB 0"
 545 
 546         .global sfmmu_panic6
 547 sfmmu_panic6:
 548         .asciz  "sfmmu_asm: interrupts not disabled"
 549 
 550         .global sfmmu_panic7
 551 sfmmu_panic7:
 552         .asciz  "sfmmu_asm: kernel as"
 553 
 554         .global sfmmu_panic8
 555 sfmmu_panic8:
 556         .asciz  "sfmmu_asm: gnum is zero"
 557 
 558         .global sfmmu_panic9
 559 sfmmu_panic9:
 560         .asciz  "sfmmu_asm: cnum is greater than MAX_SFMMU_CTX_VAL"
 561 
 562         .global sfmmu_panic10
 563 sfmmu_panic10:
 564         .asciz  "sfmmu_asm: valid SCD with no 3rd scd TSB"
 565 
 566         .global sfmmu_panic11
 567 sfmmu_panic11:
 568         .asciz  "sfmmu_asm: ktsb_phys must not be 0 on a sun4v platform"
 569 
 570         ENTRY(sfmmu_disable_intrs)
 571         rdpr    %pstate, %o0
 572 #ifdef DEBUG
 573         PANIC_IF_INTR_DISABLED_PSTR(%o0, sfmmu_di_l0, %g1)
 574 #endif /* DEBUG */
 575         retl
 576           wrpr   %o0, PSTATE_IE, %pstate
 577         SET_SIZE(sfmmu_disable_intrs)
 578 
 579         ENTRY(sfmmu_enable_intrs)
 580         retl
 581           wrpr    %g0, %o0, %pstate
 582         SET_SIZE(sfmmu_enable_intrs)
 583 
 584 /*
 585  * This routine is called both by resume() and sfmmu_get_ctx() to
 586  * allocate a new context for the process on a MMU.
 587  * if allocflag == 1, then alloc ctx when HAT mmu cnum == INVALID .
 588  * if allocflag == 0, then do not alloc ctx if HAT mmu cnum == INVALID, which
 589  * is the case when sfmmu_alloc_ctx is called from resume().
 590  *
 591  * The caller must disable interrupts before entering this routine.
 592  * To reduce ctx switch overhead, the code contains both 'fast path' and
 593  * 'slow path' code. The fast path code covers the common case where only
 594  * a quick check is needed and the real ctx allocation is not required.
 595  * It can be done without holding the per-process (PP) lock.
 596  * The 'slow path' code must be protected by the PP Lock and performs ctx
 597  * allocation.
 598  * Hardware context register and HAT mmu cnum are updated accordingly.
 599  *
 600  * %o0 - sfmmup
 601  * %o1 - allocflag
 602  * %o2 - CPU
 603  * %o3 - sfmmu private/shared flag
 604  *
 605  * ret - 0: no ctx is allocated
 606  *       1: a ctx is allocated
 607  */
 608         ENTRY_NP(sfmmu_alloc_ctx)
 609 
 610 #ifdef DEBUG
 611         sethi   %hi(ksfmmup), %g1
 612         ldx     [%g1 + %lo(ksfmmup)], %g1
 613         cmp     %g1, %o0
 614         bne,pt   %xcc, 0f
 615           nop
 616 
 617         sethi   %hi(panicstr), %g1              ! if kernel as, panic
 618         ldx     [%g1 + %lo(panicstr)], %g1
 619         tst     %g1
 620         bnz,pn  %icc, 7f
 621           nop
 622 
 623         sethi   %hi(sfmmu_panic7), %o0
 624         call    panic
 625           or    %o0, %lo(sfmmu_panic7), %o0
 626 
 627 7:
 628         retl
 629           mov   %g0, %o0                        ! %o0 = ret = 0
 630 
 631 0:
 632         PANIC_IF_INTR_ENABLED_PSTR(sfmmu_ei_l1, %g1)
 633 #endif /* DEBUG */
 634 
 635         mov     %o3, %g1                        ! save sfmmu pri/sh flag in %g1
 636 
 637         ! load global mmu_ctxp info
 638         ldx     [%o2 + CPU_MMU_CTXP], %o3               ! %o3 = mmu_ctx_t ptr
 639 
 640 #ifdef sun4v
 641         /* During suspend on sun4v, context domains can be temporary removed */
 642         brz,a,pn       %o3, 0f
 643           nop
 644 #endif
 645 
 646         lduw    [%o2 + CPU_MMU_IDX], %g2                ! %g2 = mmu index
 647 
 648         ! load global mmu_ctxp gnum
 649         ldx     [%o3 + MMU_CTX_GNUM], %o4               ! %o4 = mmu_ctxp->gnum
 650 
 651 #ifdef DEBUG
 652         cmp     %o4, %g0                ! mmu_ctxp->gnum should never be 0
 653         bne,pt  %xcc, 3f
 654           nop
 655 
 656         sethi   %hi(panicstr), %g1      ! test if panicstr is already set
 657         ldx     [%g1 + %lo(panicstr)], %g1
 658         tst     %g1
 659         bnz,pn  %icc, 1f
 660           nop
 661 
 662         sethi   %hi(sfmmu_panic8), %o0
 663         call    panic
 664           or    %o0, %lo(sfmmu_panic8), %o0
 665 1:
 666         retl
 667           mov   %g0, %o0                        ! %o0 = ret = 0
 668 3:
 669 #endif
 670 
 671         ! load HAT sfmmu_ctxs[mmuid] gnum, cnum
 672 
 673         sllx    %g2, SFMMU_MMU_CTX_SHIFT, %g2
 674         add     %o0, %g2, %g2           ! %g2 = &sfmmu_ctxs[mmuid] - SFMMU_CTXS
 675 
 676         /*
 677          * %g5 = sfmmu gnum returned
 678          * %g6 = sfmmu cnum returned
 679          * %g2 = &sfmmu_ctxs[mmuid] - SFMMU_CTXS
 680          * %g4 = scratch
 681          *
 682          * Fast path code, do a quick check.
 683          */
 684         SFMMU_MMUID_GNUM_CNUM(%g2, %g5, %g6, %g4)
 685 
 686         cmp     %g6, INVALID_CONTEXT            ! hat cnum == INVALID ??
 687         bne,pt  %icc, 1f                        ! valid hat cnum, check gnum
 688           nop
 689 
 690         ! cnum == INVALID, check allocflag
 691         mov     %g0, %g4        ! %g4 = ret = 0
 692         brz,pt  %o1, 8f         ! allocflag == 0, skip ctx allocation, bail
 693           mov   %g6, %o1
 694 
 695         ! (invalid HAT cnum) && (allocflag == 1)
 696         ba,pt   %icc, 2f
 697           nop
 698 #ifdef sun4v
 699 0:
 700         set     INVALID_CONTEXT, %o1
 701         membar  #LoadStore|#StoreStore
 702         ba,pt   %icc, 8f
 703           mov   %g0, %g4                ! %g4 = ret = 0
 704 #endif
 705 1:
 706         ! valid HAT cnum, check gnum
 707         cmp     %g5, %o4
 708         mov     1, %g4                          !%g4 = ret = 1
 709         be,a,pt %icc, 8f                        ! gnum unchanged, go to done
 710           mov   %g6, %o1
 711 
 712 2:
 713         /*
 714          * Grab per process (PP) sfmmu_ctx_lock spinlock,
 715          * followed by the 'slow path' code.
 716          */
 717         ldstub  [%o0 + SFMMU_CTX_LOCK], %g3     ! %g3 = per process (PP) lock
 718 3:
 719         brz     %g3, 5f
 720           nop
 721 4:
 722         brnz,a,pt       %g3, 4b                         ! spin if lock is 1
 723           ldub  [%o0 + SFMMU_CTX_LOCK], %g3
 724         ba      %xcc, 3b                                ! retry the lock
 725           ldstub        [%o0 + SFMMU_CTX_LOCK], %g3    ! %g3 = PP lock
 726 
 727 5:
 728         membar  #LoadLoad
 729         /*
 730          * %g5 = sfmmu gnum returned
 731          * %g6 = sfmmu cnum returned
 732          * %g2 = &sfmmu_ctxs[mmuid] - SFMMU_CTXS
 733          * %g4 = scratch
 734          */
 735         SFMMU_MMUID_GNUM_CNUM(%g2, %g5, %g6, %g4)
 736 
 737         cmp     %g6, INVALID_CONTEXT            ! hat cnum == INVALID ??
 738         bne,pt  %icc, 1f                        ! valid hat cnum, check gnum
 739           nop
 740 
 741         ! cnum == INVALID, check allocflag
 742         mov     %g0, %g4        ! %g4 = ret = 0
 743         brz,pt  %o1, 2f         ! allocflag == 0, called from resume, set hw
 744           mov   %g6, %o1
 745 
 746         ! (invalid HAT cnum) && (allocflag == 1)
 747         ba,pt   %icc, 6f
 748           nop
 749 1:
 750         ! valid HAT cnum, check gnum
 751         cmp     %g5, %o4
 752         mov     1, %g4                          ! %g4 = ret  = 1
 753         be,a,pt %icc, 2f                        ! gnum unchanged, go to done
 754           mov   %g6, %o1
 755 
 756         ba,pt   %icc, 6f
 757           nop
 758 2:
 759         membar  #LoadStore|#StoreStore
 760         ba,pt %icc, 8f
 761           clrb  [%o0 + SFMMU_CTX_LOCK]
 762 6:
 763         /*
 764          * We get here if we do not have a valid context, or
 765          * the HAT gnum does not match global gnum. We hold
 766          * sfmmu_ctx_lock spinlock. Allocate that context.
 767          *
 768          * %o3 = mmu_ctxp
 769          */
 770         add     %o3, MMU_CTX_CNUM, %g3
 771         ld      [%o3 + MMU_CTX_NCTXS], %g4
 772 
 773         /*
 774          * %g2 = &sfmmu_ctx_t[mmuid] - SFMMU_CTXS;
 775          * %g3 = mmu cnum address
 776          * %g4 = mmu nctxs
 777          *
 778          * %o0 = sfmmup
 779          * %o1 = mmu current cnum value (used as new cnum)
 780          * %o4 = mmu gnum
 781          *
 782          * %o5 = scratch
 783          */
 784         ld      [%g3], %o1
 785 0:
 786         cmp     %o1, %g4
 787         bl,a,pt %icc, 1f
 788           add   %o1, 1, %o5             ! %o5 = mmu_ctxp->cnum + 1
 789 
 790         /*
 791          * cnum reachs max, bail, so wrap around can be performed later.
 792          */
 793         set     INVALID_CONTEXT, %o1
 794         mov     %g0, %g4                ! %g4 = ret = 0
 795 
 796         membar  #LoadStore|#StoreStore
 797         ba,pt   %icc, 8f
 798           clrb  [%o0 + SFMMU_CTX_LOCK]
 799 1:
 800         ! %g3 = addr of mmu_ctxp->cnum
 801         ! %o5 = mmu_ctxp->cnum + 1
 802         cas     [%g3], %o1, %o5
 803         cmp     %o1, %o5
 804         bne,a,pn %xcc, 0b       ! cas failed
 805           ld    [%g3], %o1
 806 
 807 #ifdef DEBUG
 808         set     MAX_SFMMU_CTX_VAL, %o5
 809         cmp     %o1, %o5
 810         ble,pt %icc, 2f
 811           nop
 812 
 813         sethi   %hi(sfmmu_panic9), %o0
 814         call    panic
 815           or    %o0, %lo(sfmmu_panic9), %o0
 816 2:
 817 #endif
 818         ! update hat gnum and cnum
 819         sllx    %o4, SFMMU_MMU_GNUM_RSHIFT, %o4
 820         or      %o4, %o1, %o4
 821         stx     %o4, [%g2 + SFMMU_CTXS]
 822 
 823         membar  #LoadStore|#StoreStore
 824         clrb    [%o0 + SFMMU_CTX_LOCK]
 825 
 826         mov     1, %g4                  ! %g4 = ret = 1
 827 8:
 828         /*
 829          * program the secondary context register
 830          *
 831          * %o1 = cnum
 832          * %g1 = sfmmu private/shared flag (0:private,  1:shared)
 833          */
 834 
 835         /*
 836          * When we come here and context is invalid, we want to set both
 837          * private and shared ctx regs to INVALID. In order to
 838          * do so, we set the sfmmu priv/shared flag to 'private' regardless
 839          * so that private ctx reg will be set to invalid.
 840          * Note that on sun4v values written to private context register are
 841          * automatically written to corresponding shared context register as
 842          * well. On sun4u SET_SECCTX() will invalidate shared context register
 843          * when it sets a private secondary context register.
 844          */
 845 
 846         cmp     %o1, INVALID_CONTEXT
 847         be,a,pn %icc, 9f
 848           clr   %g1
 849 9:
 850 
 851 #ifdef  sun4u
 852         ldub    [%o0 + SFMMU_CEXT], %o2
 853         sll     %o2, CTXREG_EXT_SHIFT, %o2
 854         or      %o1, %o2, %o1
 855 #endif /* sun4u */
 856 
 857         SET_SECCTX(%o1, %g1, %o4, %o5, alloc_ctx_lbl1)
 858 
 859         retl
 860           mov   %g4, %o0                        ! %o0 = ret
 861 
 862         SET_SIZE(sfmmu_alloc_ctx)
 863 
 864         ENTRY_NP(sfmmu_modifytte)
 865         ldx     [%o2], %g3                      /* current */
 866         ldx     [%o0], %g1                      /* original */
 867 2:
 868         ldx     [%o1], %g2                      /* modified */
 869         cmp     %g2, %g3                        /* is modified = current? */
 870         be,a,pt %xcc,1f                         /* yes, don't write */
 871         stx     %g3, [%o0]                      /* update new original */
 872         casx    [%o2], %g1, %g2
 873         cmp     %g1, %g2
 874         be,pt   %xcc, 1f                        /* cas succeeded - return */
 875           nop
 876         ldx     [%o2], %g3                      /* new current */
 877         stx     %g3, [%o0]                      /* save as new original */
 878         ba,pt   %xcc, 2b
 879           mov   %g3, %g1
 880 1:      retl
 881         membar  #StoreLoad
 882         SET_SIZE(sfmmu_modifytte)
 883 
 884         ENTRY_NP(sfmmu_modifytte_try)
 885         ldx     [%o1], %g2                      /* modified */
 886         ldx     [%o2], %g3                      /* current */
 887         ldx     [%o0], %g1                      /* original */
 888         cmp     %g3, %g2                        /* is modified = current? */
 889         be,a,pn %xcc,1f                         /* yes, don't write */
 890         mov     0, %o1                          /* as if cas failed. */
 891 
 892         casx    [%o2], %g1, %g2
 893         membar  #StoreLoad
 894         cmp     %g1, %g2
 895         movne   %xcc, -1, %o1                   /* cas failed. */
 896         move    %xcc, 1, %o1                    /* cas succeeded. */
 897 1:
 898         stx     %g2, [%o0]                      /* report "current" value */
 899         retl
 900         mov     %o1, %o0
 901         SET_SIZE(sfmmu_modifytte_try)
 902 
 903         ENTRY_NP(sfmmu_copytte)
 904         ldx     [%o0], %g1
 905         retl
 906         stx     %g1, [%o1]
 907         SET_SIZE(sfmmu_copytte)
 908 
 909 
 910         /*
 911          * Calculate a TSB entry pointer for the given TSB, va, pagesize.
 912          * %o0 = TSB base address (in), pointer to TSB entry (out)
 913          * %o1 = vaddr (in)
 914          * %o2 = vpshift (in)
 915          * %o3 = tsb size code (in)
 916          * %o4 = scratch register
 917          */
 918         ENTRY_NP(sfmmu_get_tsbe)
 919         GET_TSBE_POINTER(%o2, %o0, %o1, %o3, %o4)
 920         retl
 921         nop
 922         SET_SIZE(sfmmu_get_tsbe)
 923 
 924         /*
 925          * Return a TSB tag for the given va.
 926          * %o0 = va (in/clobbered)
 927          * %o0 = va shifted to be in tsb tag format (with no context) (out)
 928          */
 929         ENTRY_NP(sfmmu_make_tsbtag)
 930         retl
 931         srln    %o0, TTARGET_VA_SHIFT, %o0
 932         SET_SIZE(sfmmu_make_tsbtag)
 933 
 934 #endif /* lint */
 935 
 936 /*
 937  * Other sfmmu primitives
 938  */
 939 
 940 
 941 #if defined (lint)
 942 void
 943 sfmmu_patch_ktsb(void)
 944 {
 945 }
 946 
 947 void
 948 sfmmu_kpm_patch_tlbm(void)
 949 {
 950 }
 951 
 952 void
 953 sfmmu_kpm_patch_tsbm(void)
 954 {
 955 }
 956 
 957 void
 958 sfmmu_patch_shctx(void)
 959 {
 960 }
 961 
 962 /* ARGSUSED */
 963 void
 964 sfmmu_load_tsbe(struct tsbe *tsbep, uint64_t vaddr, tte_t *ttep, int phys)
 965 {
 966 }
 967 
 968 /* ARGSUSED */
 969 void
 970 sfmmu_unload_tsbe(struct tsbe *tsbep, uint64_t vaddr, int phys)
 971 {
 972 }
 973 
 974 /* ARGSUSED */
 975 void
 976 sfmmu_kpm_load_tsb(caddr_t addr, tte_t *ttep, int vpshift)
 977 {
 978 }
 979 
 980 /* ARGSUSED */
 981 void
 982 sfmmu_kpm_unload_tsb(caddr_t addr, int vpshift)
 983 {
 984 }
 985 
 986 #else /* lint */
 987 
 988 #define I_SIZE          4
 989 
 990         ENTRY_NP(sfmmu_fix_ktlb_traptable)
 991         /*
 992          * %o0 = start of patch area
 993          * %o1 = size code of TSB to patch
 994          * %o3 = scratch
 995          */
 996         /* fix sll */
 997         ld      [%o0], %o3                      /* get sll */
 998         sub     %o3, %o1, %o3                   /* decrease shift by tsb szc */
 999         st      %o3, [%o0]                      /* write sll */
1000         flush   %o0
1001         /* fix srl */
1002         add     %o0, I_SIZE, %o0                /* goto next instr. */
1003         ld      [%o0], %o3                      /* get srl */
1004         sub     %o3, %o1, %o3                   /* decrease shift by tsb szc */
1005         st      %o3, [%o0]                      /* write srl */
1006         retl
1007         flush   %o0
1008         SET_SIZE(sfmmu_fix_ktlb_traptable)
1009 
1010         ENTRY_NP(sfmmu_fixup_ktsbbase)
1011         /*
1012          * %o0 = start of patch area
1013          * %o5 = kernel virtual or physical tsb base address
1014          * %o2, %o3 are used as scratch registers.
1015          */
1016         /* fixup sethi instruction */
1017         ld      [%o0], %o3
1018         srl     %o5, 10, %o2                    ! offset is bits 32:10
1019         or      %o3, %o2, %o3                   ! set imm22
1020         st      %o3, [%o0]
1021         /* fixup offset of lduw/ldx */
1022         add     %o0, I_SIZE, %o0                ! next instr
1023         ld      [%o0], %o3
1024         and     %o5, 0x3ff, %o2                 ! set imm13 to bits 9:0
1025         or      %o3, %o2, %o3
1026         st      %o3, [%o0]
1027         retl
1028         flush   %o0
1029         SET_SIZE(sfmmu_fixup_ktsbbase)
1030 
1031         ENTRY_NP(sfmmu_fixup_setx)
1032         /*
1033          * %o0 = start of patch area
1034          * %o4 = 64 bit value to patch
1035          * %o2, %o3 are used as scratch registers.
1036          *
1037          * Note: Assuming that all parts of the instructions which need to be
1038          *       patched correspond to RUNTIME_PATCH (aka 0)
1039          *
1040          * Note the implementation of setx which is being patched is as follows:
1041          *
1042          * sethi   %hh(RUNTIME_PATCH), tmp
1043          * sethi   %lm(RUNTIME_PATCH), dest
1044          * or      tmp, %hm(RUNTIME_PATCH), tmp
1045          * or      dest, %lo(RUNTIME_PATCH), dest
1046          * sllx    tmp, 32, tmp
1047          * nop
1048          * or      tmp, dest, dest
1049          *
1050          * which differs from the implementation in the
1051          * "SPARC Architecture Manual"
1052          */
1053         /* fixup sethi instruction */
1054         ld      [%o0], %o3
1055         srlx    %o4, 42, %o2                    ! bits [63:42]
1056         or      %o3, %o2, %o3                   ! set imm22
1057         st      %o3, [%o0]
1058         /* fixup sethi instruction */
1059         add     %o0, I_SIZE, %o0                ! next instr
1060         ld      [%o0], %o3
1061         sllx    %o4, 32, %o2                    ! clear upper bits
1062         srlx    %o2, 42, %o2                    ! bits [31:10]
1063         or      %o3, %o2, %o3                   ! set imm22
1064         st      %o3, [%o0]
1065         /* fixup or instruction */
1066         add     %o0, I_SIZE, %o0                ! next instr
1067         ld      [%o0], %o3
1068         srlx    %o4, 32, %o2                    ! bits [63:32]
1069         and     %o2, 0x3ff, %o2                 ! bits [41:32]
1070         or      %o3, %o2, %o3                   ! set imm
1071         st      %o3, [%o0]
1072         /* fixup or instruction */
1073         add     %o0, I_SIZE, %o0                ! next instr
1074         ld      [%o0], %o3
1075         and     %o4, 0x3ff, %o2                 ! bits [9:0]
1076         or      %o3, %o2, %o3                   ! set imm
1077         st      %o3, [%o0]
1078         retl
1079         flush   %o0
1080         SET_SIZE(sfmmu_fixup_setx)
1081 
1082         ENTRY_NP(sfmmu_fixup_or)
1083         /*
1084          * %o0 = start of patch area
1085          * %o4 = 32 bit value to patch
1086          * %o2, %o3 are used as scratch registers.
1087          * Note: Assuming that all parts of the instructions which need to be
1088          *       patched correspond to RUNTIME_PATCH (aka 0)
1089          */
1090         ld      [%o0], %o3
1091         and     %o4, 0x3ff, %o2                 ! bits [9:0]
1092         or      %o3, %o2, %o3                   ! set imm
1093         st      %o3, [%o0]
1094         retl
1095         flush   %o0
1096         SET_SIZE(sfmmu_fixup_or)
1097 
1098         ENTRY_NP(sfmmu_fixup_shiftx)
1099         /*
1100          * %o0 = start of patch area
1101          * %o4 = signed int immediate value to add to sllx/srlx imm field
1102          * %o2, %o3 are used as scratch registers.
1103          *
1104          * sllx/srlx store the 6 bit immediate value in the lowest order bits
1105          * so we do a simple add.  The caller must be careful to prevent
1106          * overflow, which could easily occur if the initial value is nonzero!
1107          */
1108         ld      [%o0], %o3                      ! %o3 = instruction to patch
1109         and     %o3, 0x3f, %o2                  ! %o2 = existing imm value
1110         add     %o2, %o4, %o2                   ! %o2 = new imm value
1111         andn    %o3, 0x3f, %o3                  ! clear old imm value
1112         and     %o2, 0x3f, %o2                  ! truncate new imm value
1113         or      %o3, %o2, %o3                   ! set new imm value
1114         st      %o3, [%o0]                      ! store updated instruction
1115         retl
1116         flush   %o0
1117         SET_SIZE(sfmmu_fixup_shiftx)
1118 
1119         ENTRY_NP(sfmmu_fixup_mmu_asi)
1120         /*
1121          * Patch imm_asi of all ldda instructions in the MMU
1122          * trap handlers.  We search MMU_PATCH_INSTR instructions
1123          * starting from the itlb miss handler (trap 0x64).
1124          * %o0 = address of tt[0,1]_itlbmiss
1125          * %o1 = imm_asi to setup, shifted by appropriate offset.
1126          * %o3 = number of instructions to search
1127          * %o4 = reserved by caller: called from leaf routine
1128          */
1129 1:      ldsw    [%o0], %o2                      ! load instruction to %o2
1130         brgez,pt %o2, 2f
1131           srl   %o2, 30, %o5
1132         btst    1, %o5                          ! test bit 30; skip if not set
1133         bz,pt   %icc, 2f
1134           sllx  %o2, 39, %o5                    ! bit 24 -> bit 63
1135         srlx    %o5, 58, %o5                    ! isolate op3 part of opcode
1136         xor     %o5, 0x13, %o5                  ! 01 0011 binary == ldda
1137         brnz,pt %o5, 2f                         ! skip if not a match
1138           or    %o2, %o1, %o2                   ! or in imm_asi
1139         st      %o2, [%o0]                      ! write patched instruction
1140 2:      dec     %o3
1141         brnz,a,pt %o3, 1b                       ! loop until we're done
1142           add   %o0, I_SIZE, %o0
1143         retl
1144         flush   %o0
1145         SET_SIZE(sfmmu_fixup_mmu_asi)
1146 
1147         /*
1148          * Patch immediate ASI used to access the TSB in the
1149          * trap table.
1150          * inputs: %o0 = value of ktsb_phys
1151          */
1152         ENTRY_NP(sfmmu_patch_mmu_asi)
1153         mov     %o7, %o4                        ! save return pc in %o4
1154         mov     ASI_QUAD_LDD_PHYS, %o3          ! set QUAD_LDD_PHYS by default
1155 
1156 #ifdef sun4v
1157 
1158         /*
1159          * Check ktsb_phys. It must be non-zero for sun4v, panic if not.
1160          */
1161 
1162         brnz,pt %o0, do_patch
1163         nop
1164 
1165         sethi   %hi(sfmmu_panic11), %o0
1166         call    panic
1167           or    %o0, %lo(sfmmu_panic11), %o0
1168 do_patch:
1169 
1170 #else /* sun4v */
1171         /*
1172          * Some non-sun4v platforms deploy virtual ktsb (ktsb_phys==0).
1173          * Note that ASI_NQUAD_LD is not defined/used for sun4v
1174          */
1175         movrz   %o0, ASI_NQUAD_LD, %o3
1176 
1177 #endif /* sun4v */
1178 
1179         sll     %o3, 5, %o1                     ! imm_asi offset
1180         mov     6, %o3                          ! number of instructions
1181         sethi   %hi(dktsb), %o0                 ! to search
1182         call    sfmmu_fixup_mmu_asi             ! patch kdtlb miss
1183           or    %o0, %lo(dktsb), %o0
1184         mov     6, %o3                          ! number of instructions
1185         sethi   %hi(dktsb4m), %o0               ! to search
1186         call    sfmmu_fixup_mmu_asi             ! patch kdtlb4m miss
1187           or    %o0, %lo(dktsb4m), %o0
1188         mov     6, %o3                          ! number of instructions
1189         sethi   %hi(iktsb), %o0                 ! to search
1190         call    sfmmu_fixup_mmu_asi             ! patch kitlb miss
1191           or    %o0, %lo(iktsb), %o0
1192         mov     6, %o3                          ! number of instructions
1193         sethi   %hi(iktsb4m), %o0               ! to search
1194         call    sfmmu_fixup_mmu_asi             ! patch kitlb4m miss
1195           or    %o0, %lo(iktsb4m), %o0
1196         mov     %o4, %o7                        ! retore return pc -- leaf
1197         retl
1198         nop
1199         SET_SIZE(sfmmu_patch_mmu_asi)
1200 
1201 
1202         ENTRY_NP(sfmmu_patch_ktsb)
1203         /*
1204          * We need to fix iktsb, dktsb, et. al.
1205          */
1206         save    %sp, -SA(MINFRAME), %sp
1207         set     ktsb_phys, %o1
1208         ld      [%o1], %o4
1209         set     ktsb_base, %o5
1210         set     ktsb4m_base, %l1
1211         brz,pt  %o4, 1f
1212           nop
1213         set     ktsb_pbase, %o5
1214         set     ktsb4m_pbase, %l1
1215 1:
1216         sethi   %hi(ktsb_szcode), %o1
1217         ld      [%o1 + %lo(ktsb_szcode)], %o1   /* %o1 = ktsb size code */
1218 
1219         sethi   %hi(iktsb), %o0
1220         call    sfmmu_fix_ktlb_traptable
1221           or    %o0, %lo(iktsb), %o0
1222 
1223         sethi   %hi(dktsb), %o0
1224         call    sfmmu_fix_ktlb_traptable
1225           or    %o0, %lo(dktsb), %o0
1226 
1227         sethi   %hi(ktsb4m_szcode), %o1
1228         ld      [%o1 + %lo(ktsb4m_szcode)], %o1 /* %o1 = ktsb4m size code */
1229 
1230         sethi   %hi(iktsb4m), %o0
1231         call    sfmmu_fix_ktlb_traptable
1232           or    %o0, %lo(iktsb4m), %o0
1233 
1234         sethi   %hi(dktsb4m), %o0
1235         call    sfmmu_fix_ktlb_traptable
1236           or    %o0, %lo(dktsb4m), %o0
1237 
1238 #ifndef sun4v
1239         mov     ASI_N, %o2
1240         movrnz  %o4, ASI_MEM, %o2       ! setup kernel 32bit ASI to patch
1241         mov     %o2, %o4                ! sfmmu_fixup_or needs this in %o4
1242         sethi   %hi(tsb_kernel_patch_asi), %o0
1243         call    sfmmu_fixup_or
1244           or    %o0, %lo(tsb_kernel_patch_asi), %o0
1245 #endif /* !sun4v */
1246 
1247         ldx     [%o5], %o4              ! load ktsb base addr (VA or PA)
1248 
1249         sethi   %hi(dktsbbase), %o0
1250         call    sfmmu_fixup_setx        ! patch value of ktsb base addr
1251           or    %o0, %lo(dktsbbase), %o0
1252 
1253         sethi   %hi(iktsbbase), %o0
1254         call    sfmmu_fixup_setx        ! patch value of ktsb base addr
1255           or    %o0, %lo(iktsbbase), %o0
1256 
1257         sethi   %hi(sfmmu_kprot_patch_ktsb_base), %o0
1258         call    sfmmu_fixup_setx        ! patch value of ktsb base addr
1259           or    %o0, %lo(sfmmu_kprot_patch_ktsb_base), %o0
1260 
1261 #ifdef sun4v
1262         sethi   %hi(sfmmu_dslow_patch_ktsb_base), %o0
1263         call    sfmmu_fixup_setx        ! patch value of ktsb base addr
1264           or    %o0, %lo(sfmmu_dslow_patch_ktsb_base), %o0
1265 #endif /* sun4v */
1266 
1267         ldx     [%l1], %o4              ! load ktsb4m base addr (VA or PA)
1268 
1269         sethi   %hi(dktsb4mbase), %o0
1270         call    sfmmu_fixup_setx        ! patch value of ktsb4m base addr
1271           or    %o0, %lo(dktsb4mbase), %o0
1272 
1273         sethi   %hi(iktsb4mbase), %o0
1274         call    sfmmu_fixup_setx        ! patch value of ktsb4m base addr
1275           or    %o0, %lo(iktsb4mbase), %o0
1276 
1277         sethi   %hi(sfmmu_kprot_patch_ktsb4m_base), %o0
1278         call    sfmmu_fixup_setx        ! patch value of ktsb4m base addr
1279           or    %o0, %lo(sfmmu_kprot_patch_ktsb4m_base), %o0
1280 
1281 #ifdef sun4v
1282         sethi   %hi(sfmmu_dslow_patch_ktsb4m_base), %o0
1283         call    sfmmu_fixup_setx        ! patch value of ktsb4m base addr
1284           or    %o0, %lo(sfmmu_dslow_patch_ktsb4m_base), %o0
1285 #endif /* sun4v */
1286 
1287         set     ktsb_szcode, %o4
1288         ld      [%o4], %o4
1289         sethi   %hi(sfmmu_kprot_patch_ktsb_szcode), %o0
1290         call    sfmmu_fixup_or          ! patch value of ktsb_szcode
1291           or    %o0, %lo(sfmmu_kprot_patch_ktsb_szcode), %o0
1292 
1293 #ifdef sun4v
1294         sethi   %hi(sfmmu_dslow_patch_ktsb_szcode), %o0
1295         call    sfmmu_fixup_or          ! patch value of ktsb_szcode
1296           or    %o0, %lo(sfmmu_dslow_patch_ktsb_szcode), %o0
1297 #endif /* sun4v */
1298 
1299         set     ktsb4m_szcode, %o4
1300         ld      [%o4], %o4
1301         sethi   %hi(sfmmu_kprot_patch_ktsb4m_szcode), %o0
1302         call    sfmmu_fixup_or          ! patch value of ktsb4m_szcode
1303           or    %o0, %lo(sfmmu_kprot_patch_ktsb4m_szcode), %o0
1304 
1305 #ifdef sun4v
1306         sethi   %hi(sfmmu_dslow_patch_ktsb4m_szcode), %o0
1307         call    sfmmu_fixup_or          ! patch value of ktsb4m_szcode
1308           or    %o0, %lo(sfmmu_dslow_patch_ktsb4m_szcode), %o0
1309 #endif /* sun4v */
1310 
1311         ret
1312         restore
1313         SET_SIZE(sfmmu_patch_ktsb)
1314 
1315         ENTRY_NP(sfmmu_kpm_patch_tlbm)
1316         /*
1317          * Fixup trap handlers in common segkpm case.  This is reserved
1318          * for future use should kpm TSB be changed to be other than the
1319          * kernel TSB.
1320          */
1321         retl
1322         nop
1323         SET_SIZE(sfmmu_kpm_patch_tlbm)
1324 
1325         ENTRY_NP(sfmmu_kpm_patch_tsbm)
1326         /*
1327          * nop the branch to sfmmu_kpm_dtsb_miss_small
1328          * in the case where we are using large pages for
1329          * seg_kpm (and hence must probe the second TSB for
1330          * seg_kpm VAs)
1331          */
1332         set     dktsb4m_kpmcheck_small, %o0
1333         MAKE_NOP_INSTR(%o1)
1334         st      %o1, [%o0]
1335         flush   %o0
1336         retl
1337         nop
1338         SET_SIZE(sfmmu_kpm_patch_tsbm)
1339 
1340         ENTRY_NP(sfmmu_patch_utsb)
1341 #ifdef UTSB_PHYS
1342         retl
1343         nop
1344 #else /* UTSB_PHYS */
1345         /*
1346          * We need to hot patch utsb_vabase and utsb4m_vabase
1347          */
1348         save    %sp, -SA(MINFRAME), %sp
1349 
1350         /* patch value of utsb_vabase */
1351         set     utsb_vabase, %o1
1352         ldx     [%o1], %o4
1353         sethi   %hi(sfmmu_uprot_get_1st_tsbe_ptr), %o0
1354         call    sfmmu_fixup_setx
1355           or    %o0, %lo(sfmmu_uprot_get_1st_tsbe_ptr), %o0
1356         sethi   %hi(sfmmu_uitlb_get_1st_tsbe_ptr), %o0
1357         call    sfmmu_fixup_setx
1358           or    %o0, %lo(sfmmu_uitlb_get_1st_tsbe_ptr), %o0
1359         sethi   %hi(sfmmu_udtlb_get_1st_tsbe_ptr), %o0
1360         call    sfmmu_fixup_setx
1361           or    %o0, %lo(sfmmu_udtlb_get_1st_tsbe_ptr), %o0
1362 
1363         /* patch value of utsb4m_vabase */
1364         set     utsb4m_vabase, %o1
1365         ldx     [%o1], %o4
1366         sethi   %hi(sfmmu_uprot_get_2nd_tsb_base), %o0
1367         call    sfmmu_fixup_setx
1368           or    %o0, %lo(sfmmu_uprot_get_2nd_tsb_base), %o0
1369         sethi   %hi(sfmmu_uitlb_get_2nd_tsb_base), %o0
1370         call    sfmmu_fixup_setx
1371           or    %o0, %lo(sfmmu_uitlb_get_2nd_tsb_base), %o0
1372         sethi   %hi(sfmmu_udtlb_get_2nd_tsb_base), %o0
1373         call    sfmmu_fixup_setx
1374           or    %o0, %lo(sfmmu_udtlb_get_2nd_tsb_base), %o0
1375 
1376         /*
1377          * Patch TSB base register masks and shifts if needed.
1378          * By default the TSB base register contents are set up for 4M slab.
1379          * If we're using a smaller slab size and reserved VA range we need
1380          * to patch up those values here.
1381          */
1382         set     tsb_slab_shift, %o1
1383         set     MMU_PAGESHIFT4M, %o4
1384         lduw    [%o1], %o3
1385         subcc   %o4, %o3, %o4
1386         bz,pt   %icc, 1f
1387           /* delay slot safe */
1388 
1389         /* patch reserved VA range size if needed. */
1390         sethi   %hi(sfmmu_tsb_1st_resv_offset), %o0
1391         call    sfmmu_fixup_shiftx
1392           or    %o0, %lo(sfmmu_tsb_1st_resv_offset), %o0
1393         call    sfmmu_fixup_shiftx
1394           add   %o0, I_SIZE, %o0
1395         sethi   %hi(sfmmu_tsb_2nd_resv_offset), %o0
1396         call    sfmmu_fixup_shiftx
1397           or    %o0, %lo(sfmmu_tsb_2nd_resv_offset), %o0
1398         call    sfmmu_fixup_shiftx
1399           add   %o0, I_SIZE, %o0
1400 1:
1401         /* patch TSBREG_VAMASK used to set up TSB base register */
1402         set     tsb_slab_mask, %o1
1403         ldx     [%o1], %o4
1404         sethi   %hi(sfmmu_tsb_1st_tsbreg_vamask), %o0
1405         call    sfmmu_fixup_or
1406           or    %o0, %lo(sfmmu_tsb_1st_tsbreg_vamask), %o0
1407         sethi   %hi(sfmmu_tsb_2nd_tsbreg_vamask), %o0
1408         call    sfmmu_fixup_or
1409           or    %o0, %lo(sfmmu_tsb_2nd_tsbreg_vamask), %o0
1410 
1411         ret
1412         restore
1413 #endif /* UTSB_PHYS */
1414         SET_SIZE(sfmmu_patch_utsb)
1415 
1416         ENTRY_NP(sfmmu_patch_shctx)
1417 #ifdef sun4u
1418         retl
1419           nop
1420 #else /* sun4u */
1421         set     sfmmu_shctx_cpu_mondo_patch, %o0
1422         MAKE_JMP_INSTR(5, %o1, %o2)     ! jmp       %g5
1423         st      %o1, [%o0]
1424         flush   %o0
1425         MAKE_NOP_INSTR(%o1)
1426         add     %o0, I_SIZE, %o0        ! next instr
1427         st      %o1, [%o0]
1428         flush   %o0
1429 
1430         set     sfmmu_shctx_user_rtt_patch, %o0
1431         st      %o1, [%o0]              ! nop 1st instruction
1432         flush   %o0
1433         add     %o0, I_SIZE, %o0
1434         st      %o1, [%o0]              ! nop 2nd instruction
1435         flush   %o0
1436         add     %o0, I_SIZE, %o0
1437         st      %o1, [%o0]              ! nop 3rd instruction
1438         flush   %o0
1439         add     %o0, I_SIZE, %o0
1440         st      %o1, [%o0]              ! nop 4th instruction
1441         flush   %o0
1442         add     %o0, I_SIZE, %o0
1443         st      %o1, [%o0]              ! nop 5th instruction
1444         flush   %o0
1445         add     %o0, I_SIZE, %o0
1446         st      %o1, [%o0]              ! nop 6th instruction
1447         retl
1448         flush   %o0
1449 #endif /* sun4u */
1450         SET_SIZE(sfmmu_patch_shctx)
1451 
1452         /*
1453          * Routine that loads an entry into a tsb using virtual addresses.
1454          * Locking is required since all cpus can use the same TSB.
1455          * Note that it is no longer required to have a valid context
1456          * when calling this function.
1457          */
1458         ENTRY_NP(sfmmu_load_tsbe)
1459         /*
1460          * %o0 = pointer to tsbe to load
1461          * %o1 = tsb tag
1462          * %o2 = virtual pointer to TTE
1463          * %o3 = 1 if physical address in %o0 else 0
1464          */
1465         rdpr    %pstate, %o5
1466 #ifdef DEBUG
1467         PANIC_IF_INTR_DISABLED_PSTR(%o5, sfmmu_di_l2, %g1)
1468 #endif /* DEBUG */
1469 
1470         wrpr    %o5, PSTATE_IE, %pstate         /* disable interrupts */
1471 
1472         SETUP_TSB_ASI(%o3, %g3)
1473         TSB_UPDATE(%o0, %o2, %o1, %g1, %g2, locked_tsb_l8)
1474 
1475         wrpr    %g0, %o5, %pstate               /* enable interrupts */
1476 
1477         retl
1478         membar  #StoreStore|#StoreLoad
1479         SET_SIZE(sfmmu_load_tsbe)
1480 
1481         /*
1482          * Flush TSB of a given entry if the tag matches.
1483          */
1484         ENTRY(sfmmu_unload_tsbe)
1485         /*
1486          * %o0 = pointer to tsbe to be flushed
1487          * %o1 = tag to match
1488          * %o2 = 1 if physical address in %o0 else 0
1489          */
1490         SETUP_TSB_ASI(%o2, %g1)
1491         TSB_INVALIDATE(%o0, %o1, %g1, %o2, %o3, unload_tsbe)
1492         retl
1493         membar  #StoreStore|#StoreLoad
1494         SET_SIZE(sfmmu_unload_tsbe)
1495 
1496         /*
1497          * Routine that loads a TTE into the kpm TSB from C code.
1498          * Locking is required since kpm TSB is shared among all CPUs.
1499          */
1500         ENTRY_NP(sfmmu_kpm_load_tsb)
1501         /*
1502          * %o0 = vaddr
1503          * %o1 = ttep
1504          * %o2 = virtpg to TSB index shift (e.g. TTE pagesize shift)
1505          */
1506         rdpr    %pstate, %o5                    ! %o5 = saved pstate
1507 #ifdef DEBUG
1508         PANIC_IF_INTR_DISABLED_PSTR(%o5, sfmmu_di_l3, %g1)
1509 #endif /* DEBUG */
1510         wrpr    %o5, PSTATE_IE, %pstate         ! disable interrupts
1511 
1512 #ifndef sun4v
1513         sethi   %hi(ktsb_phys), %o4
1514         mov     ASI_N, %o3
1515         ld      [%o4 + %lo(ktsb_phys)], %o4
1516         movrnz  %o4, ASI_MEM, %o3
1517         mov     %o3, %asi
1518 #endif /* !sun4v */
1519         mov     %o0, %g1                        ! %g1 = vaddr
1520 
1521         /* GET_KPM_TSBE_POINTER(vpshift, tsbp, vaddr (clobbers), tmp1, tmp2) */
1522         GET_KPM_TSBE_POINTER(%o2, %g2, %g1, %o3, %o4)
1523         /* %g2 = tsbep, %g1 clobbered */
1524 
1525         srlx    %o0, TTARGET_VA_SHIFT, %g1;     ! %g1 = tag target
1526         /* TSB_UPDATE(tsbep, tteva, tagtarget, tmp1, tmp2, label) */
1527         TSB_UPDATE(%g2, %o1, %g1, %o3, %o4, locked_tsb_l9)
1528 
1529         wrpr    %g0, %o5, %pstate               ! enable interrupts
1530         retl
1531           membar #StoreStore|#StoreLoad
1532         SET_SIZE(sfmmu_kpm_load_tsb)
1533 
1534         /*
1535          * Routine that shoots down a TTE in the kpm TSB or in the
1536          * kernel TSB depending on virtpg. Locking is required since
1537          * kpm/kernel TSB is shared among all CPUs.
1538          */
1539         ENTRY_NP(sfmmu_kpm_unload_tsb)
1540         /*
1541          * %o0 = vaddr
1542          * %o1 = virtpg to TSB index shift (e.g. TTE page shift)
1543          */
1544 #ifndef sun4v
1545         sethi   %hi(ktsb_phys), %o4
1546         mov     ASI_N, %o3
1547         ld      [%o4 + %lo(ktsb_phys)], %o4
1548         movrnz  %o4, ASI_MEM, %o3
1549         mov     %o3, %asi
1550 #endif /* !sun4v */
1551         mov     %o0, %g1                        ! %g1 = vaddr
1552 
1553         /* GET_KPM_TSBE_POINTER(vpshift, tsbp, vaddr (clobbers), tmp1, tmp2) */
1554         GET_KPM_TSBE_POINTER(%o1, %g2, %g1, %o3, %o4)
1555         /* %g2 = tsbep, %g1 clobbered */
1556 
1557         srlx    %o0, TTARGET_VA_SHIFT, %g1;     ! %g1 = tag target
1558         /* TSB_INVALIDATE(tsbep, tag, tmp1, tmp2, tmp3, label) */
1559         TSB_INVALIDATE(%g2, %g1, %o3, %o4, %o1, kpm_tsbinval)
1560 
1561         retl
1562           membar        #StoreStore|#StoreLoad
1563         SET_SIZE(sfmmu_kpm_unload_tsb)
1564 
1565 #endif /* lint */
1566 
1567 
1568 #if defined (lint)
1569 
1570 /*ARGSUSED*/
1571 pfn_t
1572 sfmmu_ttetopfn(tte_t *tte, caddr_t vaddr)
1573 { return(0); }
1574 
1575 #else /* lint */
1576 
1577         ENTRY_NP(sfmmu_ttetopfn)
1578         ldx     [%o0], %g1                      /* read tte */
1579         TTETOPFN(%g1, %o1, sfmmu_ttetopfn_l1, %g2, %g3, %g4)
1580         /*
1581          * g1 = pfn
1582          */
1583         retl
1584         mov     %g1, %o0
1585         SET_SIZE(sfmmu_ttetopfn)
1586 
1587 #endif /* !lint */
1588 
1589 /*
1590  * These macros are used to update global sfmmu hme hash statistics
1591  * in perf critical paths. It is only enabled in debug kernels or
1592  * if SFMMU_STAT_GATHER is defined
1593  */
1594 #if defined(DEBUG) || defined(SFMMU_STAT_GATHER)
1595 #define HAT_HSEARCH_DBSTAT(hatid, tsbarea, tmp1, tmp2)                  \
1596         ldn     [tsbarea + TSBMISS_KHATID], tmp1                        ;\
1597         mov     HATSTAT_KHASH_SEARCH, tmp2                              ;\
1598         cmp     tmp1, hatid                                             ;\
1599         movne   %ncc, HATSTAT_UHASH_SEARCH, tmp2                        ;\
1600         set     sfmmu_global_stat, tmp1                                 ;\
1601         add     tmp1, tmp2, tmp1                                        ;\
1602         ld      [tmp1], tmp2                                            ;\
1603         inc     tmp2                                                    ;\
1604         st      tmp2, [tmp1]
1605 
1606 #define HAT_HLINK_DBSTAT(hatid, tsbarea, tmp1, tmp2)                    \
1607         ldn     [tsbarea + TSBMISS_KHATID], tmp1                        ;\
1608         mov     HATSTAT_KHASH_LINKS, tmp2                               ;\
1609         cmp     tmp1, hatid                                             ;\
1610         movne   %ncc, HATSTAT_UHASH_LINKS, tmp2                         ;\
1611         set     sfmmu_global_stat, tmp1                                 ;\
1612         add     tmp1, tmp2, tmp1                                        ;\
1613         ld      [tmp1], tmp2                                            ;\
1614         inc     tmp2                                                    ;\
1615         st      tmp2, [tmp1]
1616 
1617 
1618 #else /* DEBUG || SFMMU_STAT_GATHER */
1619 
1620 #define HAT_HSEARCH_DBSTAT(hatid, tsbarea, tmp1, tmp2)
1621 
1622 #define HAT_HLINK_DBSTAT(hatid, tsbarea, tmp1, tmp2)
1623 
1624 #endif  /* DEBUG || SFMMU_STAT_GATHER */
1625 
1626 /*
1627  * This macro is used to update global sfmmu kstas in non
1628  * perf critical areas so they are enabled all the time
1629  */
1630 #define HAT_GLOBAL_STAT(statname, tmp1, tmp2)                           \
1631         sethi   %hi(sfmmu_global_stat), tmp1                            ;\
1632         add     tmp1, statname, tmp1                                    ;\
1633         ld      [tmp1 + %lo(sfmmu_global_stat)], tmp2                   ;\
1634         inc     tmp2                                                    ;\
1635         st      tmp2, [tmp1 + %lo(sfmmu_global_stat)]
1636 
1637 /*
1638  * These macros are used to update per cpu stats in non perf
1639  * critical areas so they are enabled all the time
1640  */
1641 #define HAT_PERCPU_STAT32(tsbarea, stat, tmp1)                          \
1642         ld      [tsbarea + stat], tmp1                                  ;\
1643         inc     tmp1                                                    ;\
1644         st      tmp1, [tsbarea + stat]
1645 
1646 /*
1647  * These macros are used to update per cpu stats in non perf
1648  * critical areas so they are enabled all the time
1649  */
1650 #define HAT_PERCPU_STAT16(tsbarea, stat, tmp1)                          \
1651         lduh    [tsbarea + stat], tmp1                                  ;\
1652         inc     tmp1                                                    ;\
1653         stuh    tmp1, [tsbarea + stat]
1654 
1655 #if defined(KPM_TLBMISS_STATS_GATHER)
1656         /*
1657          * Count kpm dtlb misses separately to allow a different
1658          * evaluation of hme and kpm tlbmisses. kpm tsb hits can
1659          * be calculated by (kpm_dtlb_misses - kpm_tsb_misses).
1660          */
1661 #define KPM_TLBMISS_STAT_INCR(tagacc, val, tsbma, tmp1, label)          \
1662         brgez   tagacc, label   /* KPM VA? */                           ;\
1663         nop                                                             ;\
1664         CPU_INDEX(tmp1, tsbma)                                          ;\
1665         sethi   %hi(kpmtsbm_area), tsbma                                ;\
1666         sllx    tmp1, KPMTSBM_SHIFT, tmp1                               ;\
1667         or      tsbma, %lo(kpmtsbm_area), tsbma                         ;\
1668         add     tsbma, tmp1, tsbma              /* kpmtsbm area */      ;\
1669         /* VA range check */                                            ;\
1670         ldx     [tsbma + KPMTSBM_VBASE], val                            ;\
1671         cmp     tagacc, val                                             ;\
1672         blu,pn  %xcc, label                                             ;\
1673           ldx   [tsbma + KPMTSBM_VEND], tmp1                            ;\
1674         cmp     tagacc, tmp1                                            ;\
1675         bgeu,pn %xcc, label                                             ;\
1676           lduw  [tsbma + KPMTSBM_DTLBMISS], val                         ;\
1677         inc     val                                                     ;\
1678         st      val, [tsbma + KPMTSBM_DTLBMISS]                         ;\
1679 label:
1680 #else
1681 #define KPM_TLBMISS_STAT_INCR(tagacc, val, tsbma, tmp1, label)
1682 #endif  /* KPM_TLBMISS_STATS_GATHER */
1683 
1684 #if defined (lint)
1685 /*
1686  * The following routines are jumped to from the mmu trap handlers to do
1687  * the setting up to call systrap.  They are separate routines instead of
1688  * being part of the handlers because the handlers would exceed 32
1689  * instructions and since this is part of the slow path the jump
1690  * cost is irrelevant.
1691  */
1692 void
1693 sfmmu_pagefault(void)
1694 {
1695 }
1696 
1697 void
1698 sfmmu_mmu_trap(void)
1699 {
1700 }
1701 
1702 void
1703 sfmmu_window_trap(void)
1704 {
1705 }
1706 
1707 void
1708 sfmmu_kpm_exception(void)
1709 {
1710 }
1711 
1712 #else /* lint */
1713 
1714 #ifdef  PTL1_PANIC_DEBUG
1715         .seg    ".data"
1716         .global test_ptl1_panic
1717 test_ptl1_panic:
1718         .word   0
1719         .align  8
1720 
1721         .seg    ".text"
1722         .align  4
1723 #endif  /* PTL1_PANIC_DEBUG */
1724 
1725 
1726         ENTRY_NP(sfmmu_pagefault)
1727         SET_GL_REG(1)
1728         USE_ALTERNATE_GLOBALS(%g5)
1729         GET_MMU_BOTH_TAGACC(%g5 /*dtag*/, %g2 /*itag*/, %g6, %g4)
1730         rdpr    %tt, %g6
1731         cmp     %g6, FAST_IMMU_MISS_TT
1732         be,a,pn %icc, 1f
1733           mov   T_INSTR_MMU_MISS, %g3
1734         cmp     %g6, T_INSTR_MMU_MISS
1735         be,a,pn %icc, 1f
1736           mov   T_INSTR_MMU_MISS, %g3
1737         mov     %g5, %g2
1738         mov     T_DATA_PROT, %g3                /* arg2 = traptype */
1739         cmp     %g6, FAST_DMMU_MISS_TT
1740         move    %icc, T_DATA_MMU_MISS, %g3      /* arg2 = traptype */
1741         cmp     %g6, T_DATA_MMU_MISS
1742         move    %icc, T_DATA_MMU_MISS, %g3      /* arg2 = traptype */
1743 
1744 #ifdef  PTL1_PANIC_DEBUG
1745         /* check if we want to test the tl1 panic */
1746         sethi   %hi(test_ptl1_panic), %g4
1747         ld      [%g4 + %lo(test_ptl1_panic)], %g1
1748         st      %g0, [%g4 + %lo(test_ptl1_panic)]
1749         cmp     %g1, %g0
1750         bne,a,pn %icc, ptl1_panic
1751           or    %g0, PTL1_BAD_DEBUG, %g1
1752 #endif  /* PTL1_PANIC_DEBUG */
1753 1:
1754         HAT_GLOBAL_STAT(HATSTAT_PAGEFAULT, %g6, %g4)
1755         /*
1756          * g2 = tag access reg
1757          * g3.l = type
1758          * g3.h = 0
1759          */
1760         sethi   %hi(trap), %g1
1761         or      %g1, %lo(trap), %g1
1762 2:
1763         ba,pt   %xcc, sys_trap
1764           mov   -1, %g4
1765         SET_SIZE(sfmmu_pagefault)
1766 
1767         ENTRY_NP(sfmmu_mmu_trap)
1768         SET_GL_REG(1)
1769         USE_ALTERNATE_GLOBALS(%g5)
1770         GET_MMU_BOTH_TAGACC(%g5 /*dtag*/, %g2 /*itag*/, %g4, %g6)
1771         rdpr    %tt, %g6
1772         cmp     %g6, FAST_IMMU_MISS_TT
1773         be,a,pn %icc, 1f
1774           mov   T_INSTR_MMU_MISS, %g3
1775         cmp     %g6, T_INSTR_MMU_MISS
1776         be,a,pn %icc, 1f
1777           mov   T_INSTR_MMU_MISS, %g3
1778         mov     %g5, %g2
1779         mov     T_DATA_PROT, %g3                /* arg2 = traptype */
1780         cmp     %g6, FAST_DMMU_MISS_TT
1781         move    %icc, T_DATA_MMU_MISS, %g3      /* arg2 = traptype */
1782         cmp     %g6, T_DATA_MMU_MISS
1783         move    %icc, T_DATA_MMU_MISS, %g3      /* arg2 = traptype */
1784 1:
1785         /*
1786          * g2 = tag access reg
1787          * g3 = type
1788          */
1789         sethi   %hi(sfmmu_tsbmiss_exception), %g1
1790         or      %g1, %lo(sfmmu_tsbmiss_exception), %g1
1791         ba,pt   %xcc, sys_trap
1792           mov   -1, %g4
1793         /*NOTREACHED*/
1794         SET_SIZE(sfmmu_mmu_trap)
1795 
1796         ENTRY_NP(sfmmu_suspend_tl)
1797         SET_GL_REG(1)
1798         USE_ALTERNATE_GLOBALS(%g5)
1799         GET_MMU_BOTH_TAGACC(%g5 /*dtag*/, %g2 /*itag*/, %g4, %g3)
1800         rdpr    %tt, %g6
1801         cmp     %g6, FAST_IMMU_MISS_TT
1802         be,a,pn %icc, 1f
1803           mov   T_INSTR_MMU_MISS, %g3
1804         mov     %g5, %g2
1805         cmp     %g6, FAST_DMMU_MISS_TT
1806         move    %icc, T_DATA_MMU_MISS, %g3
1807         movne   %icc, T_DATA_PROT, %g3
1808 1:
1809         sethi   %hi(sfmmu_tsbmiss_suspended), %g1
1810         or      %g1, %lo(sfmmu_tsbmiss_suspended), %g1
1811         /* g1 = TL0 handler, g2 = tagacc, g3 = trap type */
1812         ba,pt   %xcc, sys_trap
1813           mov   PIL_15, %g4
1814         /*NOTREACHED*/
1815         SET_SIZE(sfmmu_suspend_tl)
1816 
1817         /*
1818          * No %g registers in use at this point.
1819          */
1820         ENTRY_NP(sfmmu_window_trap)
1821         rdpr    %tpc, %g1
1822 #ifdef sun4v
1823 #ifdef DEBUG
1824         /* We assume previous %gl was 1 */
1825         rdpr    %tstate, %g4
1826         srlx    %g4, TSTATE_GL_SHIFT, %g4
1827         and     %g4, TSTATE_GL_MASK, %g4
1828         cmp     %g4, 1
1829         bne,a,pn %icc, ptl1_panic
1830           mov   PTL1_BAD_WTRAP, %g1
1831 #endif /* DEBUG */
1832         /* user miss at tl>1. better be the window handler or user_rtt */
1833         /* in user_rtt? */
1834         set     rtt_fill_start, %g4
1835         cmp     %g1, %g4
1836         blu,pn %xcc, 6f
1837          .empty
1838         set     rtt_fill_end, %g4
1839         cmp     %g1, %g4
1840         bgeu,pn %xcc, 6f
1841          nop
1842         set     fault_rtt_fn1, %g1
1843         wrpr    %g0, %g1, %tnpc
1844         ba,a    7f
1845 6:
1846         ! must save this trap level before descending trap stack
1847         ! no need to save %tnpc, either overwritten or discarded
1848         ! already got it: rdpr  %tpc, %g1
1849         rdpr    %tstate, %g6
1850         rdpr    %tt, %g7
1851         ! trap level saved, go get underlying trap type
1852         rdpr    %tl, %g5
1853         sub     %g5, 1, %g3
1854         wrpr    %g3, %tl
1855         rdpr    %tt, %g2
1856         wrpr    %g5, %tl
1857         ! restore saved trap level
1858         wrpr    %g1, %tpc
1859         wrpr    %g6, %tstate
1860         wrpr    %g7, %tt
1861 #else /* sun4v */
1862         /* user miss at tl>1. better be the window handler */
1863         rdpr    %tl, %g5
1864         sub     %g5, 1, %g3
1865         wrpr    %g3, %tl
1866         rdpr    %tt, %g2
1867         wrpr    %g5, %tl
1868 #endif /* sun4v */
1869         and     %g2, WTRAP_TTMASK, %g4
1870         cmp     %g4, WTRAP_TYPE
1871         bne,pn  %xcc, 1f
1872          nop
1873         /* tpc should be in the trap table */
1874         set     trap_table, %g4
1875         cmp     %g1, %g4
1876         blt,pn %xcc, 1f
1877          .empty
1878         set     etrap_table, %g4
1879         cmp     %g1, %g4
1880         bge,pn %xcc, 1f
1881          .empty
1882         andn    %g1, WTRAP_ALIGN, %g1   /* 128 byte aligned */
1883         add     %g1, WTRAP_FAULTOFF, %g1
1884         wrpr    %g0, %g1, %tnpc
1885 7:
1886         /*
1887          * some wbuf handlers will call systrap to resolve the fault
1888          * we pass the trap type so they figure out the correct parameters.
1889          * g5 = trap type, g6 = tag access reg
1890          */
1891 
1892         /*
1893          * only use g5, g6, g7 registers after we have switched to alternate
1894          * globals.
1895          */
1896         SET_GL_REG(1)
1897         USE_ALTERNATE_GLOBALS(%g5)
1898         GET_MMU_D_TAGACC(%g6 /*dtag*/, %g5 /*scratch*/)
1899         rdpr    %tt, %g7
1900         cmp     %g7, FAST_IMMU_MISS_TT
1901         be,a,pn %icc, ptl1_panic
1902           mov   PTL1_BAD_WTRAP, %g1
1903         cmp     %g7, T_INSTR_MMU_MISS
1904         be,a,pn %icc, ptl1_panic
1905           mov   PTL1_BAD_WTRAP, %g1
1906         mov     T_DATA_PROT, %g5
1907         cmp     %g7, FAST_DMMU_MISS_TT
1908         move    %icc, T_DATA_MMU_MISS, %g5
1909         cmp     %g7, T_DATA_MMU_MISS
1910         move    %icc, T_DATA_MMU_MISS, %g5
1911         ! XXXQ AGS re-check out this one
1912         done
1913 1:
1914         CPU_PADDR(%g1, %g4)
1915         add     %g1, CPU_TL1_HDLR, %g1
1916         lda     [%g1]ASI_MEM, %g4
1917         brnz,a,pt %g4, sfmmu_mmu_trap
1918           sta   %g0, [%g1]ASI_MEM
1919         ba,pt   %icc, ptl1_panic
1920           mov   PTL1_BAD_TRAP, %g1
1921         SET_SIZE(sfmmu_window_trap)
1922 
1923         ENTRY_NP(sfmmu_kpm_exception)
1924         /*
1925          * We have accessed an unmapped segkpm address or a legal segkpm
1926          * address which is involved in a VAC alias conflict prevention.
1927          * Before we go to trap(), check to see if CPU_DTRACE_NOFAULT is
1928          * set. If it is, we will instead note that a fault has occurred
1929          * by setting CPU_DTRACE_BADADDR and issue a "done" (instead of
1930          * a "retry"). This will step over the faulting instruction.
1931          * Note that this means that a legal segkpm address involved in
1932          * a VAC alias conflict prevention (a rare case to begin with)
1933          * cannot be used in DTrace.
1934          */
1935         CPU_INDEX(%g1, %g2)
1936         set     cpu_core, %g2
1937         sllx    %g1, CPU_CORE_SHIFT, %g1
1938         add     %g1, %g2, %g1
1939         lduh    [%g1 + CPUC_DTRACE_FLAGS], %g2
1940         andcc   %g2, CPU_DTRACE_NOFAULT, %g0
1941         bz      0f
1942         or      %g2, CPU_DTRACE_BADADDR, %g2
1943         stuh    %g2, [%g1 + CPUC_DTRACE_FLAGS]
1944         GET_MMU_D_ADDR(%g3, /*scratch*/ %g4)
1945         stx     %g3, [%g1 + CPUC_DTRACE_ILLVAL]
1946         done
1947 0:
1948         TSTAT_CHECK_TL1(1f, %g1, %g2)
1949 1:
1950         SET_GL_REG(1)
1951         USE_ALTERNATE_GLOBALS(%g5)
1952         GET_MMU_D_TAGACC(%g2 /* tagacc */, %g4 /*scratch*/)
1953         mov     T_DATA_MMU_MISS, %g3    /* arg2 = traptype */
1954         /*
1955          * g2=tagacc g3.l=type g3.h=0
1956          */
1957         sethi   %hi(trap), %g1
1958         or      %g1, %lo(trap), %g1
1959         ba,pt   %xcc, sys_trap
1960         mov     -1, %g4
1961         SET_SIZE(sfmmu_kpm_exception)
1962 
1963 #endif /* lint */
1964 
1965 #if defined (lint)
1966 
1967 void
1968 sfmmu_tsb_miss(void)
1969 {
1970 }
1971 
1972 void
1973 sfmmu_kpm_dtsb_miss(void)
1974 {
1975 }
1976 
1977 void
1978 sfmmu_kpm_dtsb_miss_small(void)
1979 {
1980 }
1981 
1982 #else /* lint */
1983 
1984 #if (IMAP_SEG != 0)
1985 #error - ism_map->ism_seg offset is not zero
1986 #endif
1987 
1988 /*
1989  * Copies ism mapping for this ctx in param "ism" if this is a ISM
1990  * tlb miss and branches to label "ismhit". If this is not an ISM
1991  * process or an ISM tlb miss it falls thru.
1992  *
1993  * Checks to see if the vaddr passed in via tagacc is in an ISM segment for
1994  * this process.
1995  * If so, it will branch to label "ismhit".  If not, it will fall through.
1996  *
1997  * Also hat_unshare() will set the context for this process to INVALID_CONTEXT
1998  * so that any other threads of this process will not try and walk the ism
1999  * maps while they are being changed.
2000  *
2001  * NOTE: We will never have any holes in our ISM maps. sfmmu_share/unshare
2002  *       will make sure of that. This means we can terminate our search on
2003  *       the first zero mapping we find.
2004  *
2005  * Parameters:
2006  * tagacc       = (pseudo-)tag access register (vaddr + ctx) (in)
2007  * tsbmiss      = address of tsb miss area (in)
2008  * ismseg       = contents of ism_seg for this ism map (out)
2009  * ismhat       = physical address of imap_ismhat for this ism map (out)
2010  * tmp1         = scratch reg (CLOBBERED)
2011  * tmp2         = scratch reg (CLOBBERED)
2012  * tmp3         = scratch reg (CLOBBERED)
2013  * label:    temporary labels
2014  * ismhit:   label where to jump to if an ism dtlb miss
2015  * exitlabel:label where to jump if hat is busy due to hat_unshare.
2016  */
2017 #define ISM_CHECK(tagacc, tsbmiss, ismseg, ismhat, tmp1, tmp2, tmp3 \
2018         label, ismhit)                                                  \
2019         ldx     [tsbmiss + TSBMISS_ISMBLKPA], tmp1 /* tmp1 = &ismblk */     ;\
2020         brlz,pt  tmp1, label/**/3               /* exit if -1 */        ;\
2021           add   tmp1, IBLK_MAPS, ismhat /* ismhat = &ismblk.map[0] */       ;\
2022 label/**/1:                                                             ;\
2023         ldxa    [ismhat]ASI_MEM, ismseg /* ismblk.map[0].ism_seg */     ;\
2024         mov     tmp1, tmp3      /* update current ismblkpa head */      ;\
2025 label/**/2:                                                             ;\
2026         brz,pt  ismseg, label/**/3              /* no mapping */        ;\
2027           add   ismhat, IMAP_VB_SHIFT, tmp1 /* tmp1 = vb_shift addr */  ;\
2028         lduba   [tmp1]ASI_MEM, tmp1             /* tmp1 = vb shift*/    ;\
2029         srlx    ismseg, tmp1, tmp2              /* tmp2 = vbase */      ;\
2030         srlx    tagacc, tmp1, tmp1              /* tmp1 =  va seg*/     ;\
2031         sub     tmp1, tmp2, tmp2                /* tmp2 = va - vbase */ ;\
2032         add     ismhat, IMAP_SZ_MASK, tmp1 /* tmp1 = sz_mask addr */    ;\
2033         lda     [tmp1]ASI_MEM, tmp1             /* tmp1 = sz_mask */    ;\
2034         and     ismseg, tmp1, tmp1              /* tmp1 = size */       ;\
2035         cmp     tmp2, tmp1                      /* check va <= offset*/      ;\
2036         blu,a,pt  %xcc, ismhit                  /* ism hit */           ;\
2037           add   ismhat, IMAP_ISMHAT, ismhat     /* ismhat = &ism_sfmmu*/ ;\
2038                                                                         ;\
2039         add     ismhat, ISM_MAP_SZ, ismhat /* ismhat += sizeof(map) */  ;\
2040         add     tmp3, (IBLK_MAPS + ISM_MAP_SLOTS * ISM_MAP_SZ), tmp1    ;\
2041         cmp     ismhat, tmp1                                            ;\
2042         bl,pt   %xcc, label/**/2                /* keep looking  */     ;\
2043           ldxa  [ismhat]ASI_MEM, ismseg /* ismseg = map[ismhat] */      ;\
2044                                                                         ;\
2045         add     tmp3, IBLK_NEXTPA, tmp1                                 ;\
2046         ldxa    [tmp1]ASI_MEM, tmp1             /* check blk->nextpa */      ;\
2047         brgez,pt tmp1, label/**/1               /* continue if not -1*/ ;\
2048           add   tmp1, IBLK_MAPS, ismhat /* ismhat = &ismblk.map[0]*/        ;\
2049 label/**/3:
2050 
2051 /*
2052  * Returns the hme hash bucket (hmebp) given the vaddr, and the hatid
2053  * It also returns the virtual pg for vaddr (ie. vaddr << hmeshift)
2054  * Parameters:
2055  * tagacc = reg containing virtual address
2056  * hatid = reg containing sfmmu pointer
2057  * hmeshift = constant/register to shift vaddr to obtain vapg
2058  * hmebp = register where bucket pointer will be stored
2059  * vapg = register where virtual page will be stored
2060  * tmp1, tmp2 = tmp registers
2061  */
2062 
2063 
2064 #define HMEHASH_FUNC_ASM(tagacc, hatid, tsbarea, hmeshift, hmebp,       \
2065         vapg, label, tmp1, tmp2)                                        \
2066         sllx    tagacc, TAGACC_CTX_LSHIFT, tmp1                         ;\
2067         brnz,a,pt tmp1, label/**/1                                      ;\
2068           ld    [tsbarea + TSBMISS_UHASHSZ], hmebp                      ;\
2069         ld      [tsbarea + TSBMISS_KHASHSZ], hmebp                      ;\
2070         ba,pt   %xcc, label/**/2                                        ;\
2071           ldx   [tsbarea + TSBMISS_KHASHSTART], tmp1                    ;\
2072 label/**/1:                                                             ;\
2073         ldx     [tsbarea + TSBMISS_UHASHSTART], tmp1                    ;\
2074 label/**/2:                                                             ;\
2075         srlx    tagacc, hmeshift, vapg                                  ;\
2076         xor     vapg, hatid, tmp2       /* hatid ^ (vaddr >> shift) */    ;\
2077         and     tmp2, hmebp, hmebp      /* index into hme_hash */       ;\
2078         mulx    hmebp, HMEBUCK_SIZE, hmebp                              ;\
2079         add     hmebp, tmp1, hmebp
2080 
2081 /*
2082  * hashtag includes bspage + hashno (64 bits).
2083  */
2084 
2085 #define MAKE_HASHTAG(vapg, hatid, hmeshift, hashno, hblktag)            \
2086         sllx    vapg, hmeshift, vapg                                    ;\
2087         mov     hashno, hblktag                                         ;\
2088         sllx    hblktag, HTAG_REHASH_SHIFT, hblktag                     ;\
2089         or      vapg, hblktag, hblktag
2090 
2091 /*
2092  * Function to traverse hmeblk hash link list and find corresponding match.
2093  * The search is done using physical pointers. It returns the physical address
2094  * pointer to the hmeblk that matches with the tag provided.
2095  * Parameters:
2096  * hmebp        = register that points to hme hash bucket, also used as
2097  *                tmp reg (clobbered)
2098  * hmeblktag    = register with hmeblk tag match
2099  * hatid        = register with hatid
2100  * hmeblkpa     = register where physical ptr will be stored
2101  * tmp1         = tmp reg
2102  * label: temporary label
2103  */
2104 
2105 #define HMEHASH_SEARCH(hmebp, hmeblktag, hatid, hmeblkpa, tsbarea,      \
2106         tmp1, label)                                                    \
2107         add     hmebp, HMEBUCK_NEXTPA, hmeblkpa                         ;\
2108         ldxa    [hmeblkpa]ASI_MEM, hmeblkpa                             ;\
2109         HAT_HSEARCH_DBSTAT(hatid, tsbarea, hmebp, tmp1)                 ;\
2110 label/**/1:                                                             ;\
2111         cmp     hmeblkpa, HMEBLK_ENDPA                                  ;\
2112         be,pn   %xcc, label/**/2                                        ;\
2113         HAT_HLINK_DBSTAT(hatid, tsbarea, hmebp, tmp1)                   ;\
2114         add     hmeblkpa, HMEBLK_TAG, hmebp                             ;\
2115         ldxa    [hmebp]ASI_MEM, tmp1     /* read 1st part of tag */     ;\
2116         add     hmebp, CLONGSIZE, hmebp                                 ;\
2117         ldxa    [hmebp]ASI_MEM, hmebp   /* read 2nd part of tag */      ;\
2118         xor     tmp1, hmeblktag, tmp1                                   ;\
2119         xor     hmebp, hatid, hmebp                                     ;\
2120         or      hmebp, tmp1, hmebp                                      ;\
2121         brz,pn  hmebp, label/**/2       /* branch on hit */             ;\
2122           add   hmeblkpa, HMEBLK_NEXTPA, hmebp                          ;\
2123         ba,pt   %xcc, label/**/1                                        ;\
2124           ldxa  [hmebp]ASI_MEM, hmeblkpa        /* hmeblk ptr pa */     ;\
2125 label/**/2:
2126 
2127 /*
2128  * Function to traverse hmeblk hash link list and find corresponding match.
2129  * The search is done using physical pointers. It returns the physical address
2130  * pointer to the hmeblk that matches with the tag
2131  * provided.
2132  * Parameters:
2133  * hmeblktag    = register with hmeblk tag match (rid field is 0)
2134  * hatid        = register with hatid (pointer to SRD)
2135  * hmeblkpa     = register where physical ptr will be stored
2136  * tmp1         = tmp reg
2137  * tmp2         = tmp reg
2138  * label: temporary label
2139  */
2140 
2141 #define HMEHASH_SEARCH_SHME(hmeblktag, hatid, hmeblkpa, tsbarea,        \
2142         tmp1, tmp2, label)                                              \
2143 label/**/1:                                                             ;\
2144         cmp     hmeblkpa, HMEBLK_ENDPA                                  ;\
2145         be,pn   %xcc, label/**/4                                        ;\
2146         HAT_HLINK_DBSTAT(hatid, tsbarea, tmp1, tmp2)                    ;\
2147         add     hmeblkpa, HMEBLK_TAG, tmp2                              ;\
2148         ldxa    [tmp2]ASI_MEM, tmp1      /* read 1st part of tag */     ;\
2149         add     tmp2, CLONGSIZE, tmp2                                   ;\
2150         ldxa    [tmp2]ASI_MEM, tmp2     /* read 2nd part of tag */      ;\
2151         xor     tmp1, hmeblktag, tmp1                                   ;\
2152         xor     tmp2, hatid, tmp2                                       ;\
2153         brz,pn  tmp2, label/**/3        /* branch on hit */             ;\
2154           add   hmeblkpa, HMEBLK_NEXTPA, tmp2                           ;\
2155 label/**/2:                                                             ;\
2156         ba,pt   %xcc, label/**/1                                        ;\
2157           ldxa  [tmp2]ASI_MEM, hmeblkpa /* hmeblk ptr pa */             ;\
2158 label/**/3:                                                             ;\
2159         cmp     tmp1, SFMMU_MAX_HME_REGIONS                             ;\
2160         bgeu,pt %xcc, label/**/2                                        ;\
2161           add   hmeblkpa, HMEBLK_NEXTPA, tmp2                           ;\
2162         and     tmp1, BT_ULMASK, tmp2                                   ;\
2163         srlx    tmp1, BT_ULSHIFT, tmp1                                  ;\
2164         sllx    tmp1, CLONGSHIFT, tmp1                                  ;\
2165         add     tsbarea, tmp1, tmp1                                     ;\
2166         ldx     [tmp1 + TSBMISS_SHMERMAP], tmp1                         ;\
2167         srlx    tmp1, tmp2, tmp1                                        ;\
2168         btst    0x1, tmp1                                               ;\
2169         bz,pn   %xcc, label/**/2                                        ;\
2170           add   hmeblkpa, HMEBLK_NEXTPA, tmp2                           ;\
2171 label/**/4:
2172 
2173 #if ((1 << SFHME_SHIFT) != SFHME_SIZE)
2174 #error HMEBLK_TO_HMENT assumes sf_hment is power of 2 in size
2175 #endif
2176 
2177 /*
2178  * HMEBLK_TO_HMENT is a macro that given an hmeblk and a vaddr returns
2179  * the offset for the corresponding hment.
2180  * Parameters:
2181  * In:
2182  *      vaddr = register with virtual address
2183  *      hmeblkpa = physical pointer to hme_blk
2184  * Out:
2185  *      hmentoff = register where hment offset will be stored
2186  *      hmemisc = hblk_misc
2187  * Scratch:
2188  *      tmp1
2189  */
2190 #define HMEBLK_TO_HMENT(vaddr, hmeblkpa, hmentoff, hmemisc, tmp1, label1)\
2191         add     hmeblkpa, HMEBLK_MISC, hmentoff                         ;\
2192         lda     [hmentoff]ASI_MEM, hmemisc                              ;\
2193         andcc   hmemisc, HBLK_SZMASK, %g0                               ;\
2194         bnz,a,pn  %icc, label1          /* if sz != TTE8K branch */     ;\
2195           or    %g0, HMEBLK_HME1, hmentoff                              ;\
2196         srl     vaddr, MMU_PAGESHIFT, tmp1                              ;\
2197         and     tmp1, NHMENTS - 1, tmp1         /* tmp1 = index */      ;\
2198         sllx    tmp1, SFHME_SHIFT, tmp1                                 ;\
2199         add     tmp1, HMEBLK_HME1, hmentoff                             ;\
2200 label1:
2201 
2202 /*
2203  * GET_TTE is a macro that returns a TTE given a tag and hatid.
2204  *
2205  * tagacc       = (pseudo-)tag access register (in)
2206  * hatid        = sfmmu pointer for TSB miss (in)
2207  * tte          = tte for TLB miss if found, otherwise clobbered (out)
2208  * hmeblkpa     = PA of hment if found, otherwise clobbered (out)
2209  * tsbarea      = pointer to the tsbmiss area for this cpu. (in)
2210  * hmemisc      = hblk_misc if TTE is found (out), otherwise clobbered
2211  * hmeshift     = constant/register to shift VA to obtain the virtual pfn
2212  *                for this page size.
2213  * hashno       = constant/register hash number
2214  * tmp          = temp value - clobbered
2215  * label        = temporary label for branching within macro.
2216  * foundlabel   = label to jump to when tte is found.
2217  * suspendlabel= label to jump to when tte is suspended.
2218  * exitlabel    = label to jump to when tte is not found.
2219  *
2220  */
2221 #define GET_TTE(tagacc, hatid, tte, hmeblkpa, tsbarea, hmemisc, hmeshift, \
2222                  hashno, tmp, label, foundlabel, suspendlabel, exitlabel) \
2223                                                                         ;\
2224         stn     tagacc, [tsbarea + (TSBMISS_SCRATCH + TSB_TAGACC)]      ;\
2225         stn     hatid, [tsbarea + (TSBMISS_SCRATCH + TSBMISS_HATID)]    ;\
2226         HMEHASH_FUNC_ASM(tagacc, hatid, tsbarea, hmeshift, tte,         \
2227                 hmeblkpa, label/**/5, hmemisc, tmp)                     ;\
2228                                                                         ;\
2229         /*                                                              ;\
2230          * tagacc = tagacc                                              ;\
2231          * hatid = hatid                                                ;\
2232          * tsbarea = tsbarea                                            ;\
2233          * tte   = hmebp (hme bucket pointer)                           ;\
2234          * hmeblkpa  = vapg  (virtual page)                             ;\
2235          * hmemisc, tmp = scratch                                       ;\
2236          */                                                             ;\
2237         MAKE_HASHTAG(hmeblkpa, hatid, hmeshift, hashno, hmemisc)        ;\
2238         or      hmemisc, SFMMU_INVALID_SHMERID, hmemisc                 ;\
2239                                                                         ;\
2240         /*                                                              ;\
2241          * tagacc = tagacc                                              ;\
2242          * hatid = hatid                                                ;\
2243          * tte   = hmebp                                                ;\
2244          * hmeblkpa  = CLOBBERED                                        ;\
2245          * hmemisc  = htag_bspage+hashno+invalid_rid                    ;\
2246          * tmp  = scratch                                               ;\
2247          */                                                             ;\
2248         stn     tte, [tsbarea + (TSBMISS_SCRATCH + TSBMISS_HMEBP)]      ;\
2249         HMEHASH_SEARCH(tte, hmemisc, hatid, hmeblkpa,                   \
2250                 tsbarea, tagacc, label/**/1)                            ;\
2251         /*                                                              ;\
2252          * tagacc = CLOBBERED                                           ;\
2253          * tte = CLOBBERED                                              ;\
2254          * hmeblkpa = hmeblkpa                                          ;\
2255          * tmp = scratch                                                ;\
2256          */                                                             ;\
2257         cmp     hmeblkpa, HMEBLK_ENDPA                                  ;\
2258         bne,pn   %xcc, label/**/4       /* branch if hmeblk found */    ;\
2259           ldn   [tsbarea + (TSBMISS_SCRATCH + TSB_TAGACC)], tagacc      ;\
2260         ba,pt   %xcc, exitlabel         /* exit if hblk not found */    ;\
2261           nop                                                           ;\
2262 label/**/4:                                                             ;\
2263         /*                                                              ;\
2264          * We have found the hmeblk containing the hment.               ;\
2265          * Now we calculate the corresponding tte.                      ;\
2266          *                                                              ;\
2267          * tagacc = tagacc                                              ;\
2268          * hatid = hatid                                                ;\
2269          * tte   = clobbered                                            ;\
2270          * hmeblkpa  = hmeblkpa                                         ;\
2271          * hmemisc  = hblktag                                           ;\
2272          * tmp = scratch                                                ;\
2273          */                                                             ;\
2274         HMEBLK_TO_HMENT(tagacc, hmeblkpa, hatid, hmemisc, tte,          \
2275                 label/**/2)                                             ;\
2276                                                                         ;\
2277         /*                                                              ;\
2278          * tagacc = tagacc                                              ;\
2279          * hatid = hmentoff                                             ;\
2280          * tte   = clobbered                                            ;\
2281          * hmeblkpa  = hmeblkpa                                         ;\
2282          * hmemisc  = hblk_misc                                         ;\
2283          * tmp = scratch                                                ;\
2284          */                                                             ;\
2285                                                                         ;\
2286         add     hatid, SFHME_TTE, hatid                                 ;\
2287         add     hmeblkpa, hatid, hmeblkpa                               ;\
2288         ldxa    [hmeblkpa]ASI_MEM, tte  /* MMU_READTTE through pa */    ;\
2289         ldn     [tsbarea + (TSBMISS_SCRATCH + TSBMISS_HMEBP)], hatid    ;\
2290         set     TTE_SUSPEND, hatid                                      ;\
2291         TTE_SUSPEND_INT_SHIFT(hatid)                                    ;\
2292         btst    tte, hatid                                              ;\
2293         bz,pt   %xcc, foundlabel                                        ;\
2294         ldn     [tsbarea + (TSBMISS_SCRATCH + TSBMISS_HATID)], hatid    ;\
2295                                                                         ;\
2296         /*                                                              ;\
2297          * Mapping is suspended, so goto suspend label.                 ;\
2298          */                                                             ;\
2299         ba,pt   %xcc, suspendlabel                                      ;\
2300           nop
2301 
2302 /*
2303  * GET_SHME_TTE is similar to GET_TTE() except it searches
2304  * shared hmeblks via HMEHASH_SEARCH_SHME() macro.
2305  * If valid tte is found, hmemisc = shctx flag, i.e., shme is
2306  * either 0 (not part of scd) or 1 (part of scd).
2307  */
2308 #define GET_SHME_TTE(tagacc, hatid, tte, hmeblkpa, tsbarea, hmemisc,    \
2309                 hmeshift, hashno, tmp, label, foundlabel,               \
2310                 suspendlabel, exitlabel)                                \
2311                                                                         ;\
2312         stn     tagacc, [tsbarea + (TSBMISS_SCRATCH + TSB_TAGACC)]      ;\
2313         stn     hatid, [tsbarea + (TSBMISS_SCRATCH + TSBMISS_HATID)]    ;\
2314         HMEHASH_FUNC_ASM(tagacc, hatid, tsbarea, hmeshift, tte,         \
2315                 hmeblkpa, label/**/5, hmemisc, tmp)                     ;\
2316                                                                         ;\
2317         /*                                                              ;\
2318          * tagacc = tagacc                                              ;\
2319          * hatid = hatid                                                ;\
2320          * tsbarea = tsbarea                                            ;\
2321          * tte   = hmebp (hme bucket pointer)                           ;\
2322          * hmeblkpa  = vapg  (virtual page)                             ;\
2323          * hmemisc, tmp = scratch                                       ;\
2324          */                                                             ;\
2325         MAKE_HASHTAG(hmeblkpa, hatid, hmeshift, hashno, hmemisc)        ;\
2326                                                                         ;\
2327         /*                                                              ;\
2328          * tagacc = tagacc                                              ;\
2329          * hatid = hatid                                                ;\
2330          * tsbarea = tsbarea                                            ;\
2331          * tte   = hmebp                                                ;\
2332          * hmemisc  = htag_bspage + hashno + 0 (for rid)                ;\
2333          * hmeblkpa  = CLOBBERED                                        ;\
2334          * tmp = scratch                                                ;\
2335          */                                                             ;\
2336         stn     tte, [tsbarea + (TSBMISS_SCRATCH + TSBMISS_HMEBP)]      ;\
2337                                                                         ;\
2338         add     tte, HMEBUCK_NEXTPA, hmeblkpa                           ;\
2339         ldxa    [hmeblkpa]ASI_MEM, hmeblkpa                             ;\
2340         HAT_HSEARCH_DBSTAT(hatid, tsbarea, tagacc, tte)                 ;\
2341                                                                         ;\
2342 label/**/8:                                                             ;\
2343         HMEHASH_SEARCH_SHME(hmemisc, hatid, hmeblkpa,                   \
2344                 tsbarea, tagacc, tte, label/**/1)                       ;\
2345         /*                                                              ;\
2346          * tagacc = CLOBBERED                                           ;\
2347          * tte = CLOBBERED                                              ;\
2348          * hmeblkpa = hmeblkpa                                          ;\
2349          * tmp = scratch                                                ;\
2350          */                                                             ;\
2351         cmp     hmeblkpa, HMEBLK_ENDPA                                  ;\
2352         bne,pn   %xcc, label/**/4       /* branch if hmeblk found */    ;\
2353           ldn   [tsbarea + (TSBMISS_SCRATCH + TSB_TAGACC)], tagacc      ;\
2354         ba,pt   %xcc, exitlabel         /* exit if hblk not found */    ;\
2355           nop                                                           ;\
2356 label/**/4:                                                             ;\
2357         /*                                                              ;\
2358          * We have found the hmeblk containing the hment.               ;\
2359          * Now we calculate the corresponding tte.                      ;\
2360          *                                                              ;\
2361          * tagacc = tagacc                                              ;\
2362          * hatid = hatid                                                ;\
2363          * tte   = clobbered                                            ;\
2364          * hmeblkpa  = hmeblkpa                                         ;\
2365          * hmemisc  = hblktag                                           ;\
2366          * tsbarea = tsbmiss area                                       ;\
2367          * tmp = scratch                                                ;\
2368          */                                                             ;\
2369         HMEBLK_TO_HMENT(tagacc, hmeblkpa, hatid, hmemisc, tte,          \
2370                 label/**/2)                                             ;\
2371                                                                         ;\
2372         /*                                                              ;\
2373          * tagacc = tagacc                                              ;\
2374          * hatid = hmentoff                                             ;\
2375          * tte = clobbered                                              ;\
2376          * hmeblkpa  = hmeblkpa                                         ;\
2377          * hmemisc  = hblk_misc                                         ;\
2378          * tsbarea = tsbmiss area                                       ;\
2379          * tmp = scratch                                                ;\
2380          */                                                             ;\
2381                                                                         ;\
2382         add     hatid, SFHME_TTE, hatid                                 ;\
2383         add     hmeblkpa, hatid, hmeblkpa                               ;\
2384         ldxa    [hmeblkpa]ASI_MEM, tte  /* MMU_READTTE through pa */    ;\
2385         brlz,pt tte, label/**/6                                         ;\
2386           nop                                                           ;\
2387         btst    HBLK_SZMASK, hmemisc                                    ;\
2388         bnz,a,pt %icc, label/**/7                                       ;\
2389           ldn   [tsbarea + (TSBMISS_SCRATCH + TSBMISS_HMEBP)], hatid    ;\
2390                                                                         ;\
2391         /*                                                              ;\
2392          * We found an invalid 8K tte in shme.                          ;\
2393          * it may not belong to shme's region since                     ;\
2394          * region size/alignment granularity is 8K but different        ;\
2395          * regions don't share hmeblks. Continue the search.            ;\
2396          */                                                             ;\
2397         sub     hmeblkpa, hatid, hmeblkpa                               ;\
2398         ldn     [tsbarea + (TSBMISS_SCRATCH + TSBMISS_HATID)], hatid    ;\
2399         srlx    tagacc, hmeshift, tte                                   ;\
2400         add     hmeblkpa, HMEBLK_NEXTPA, hmeblkpa                       ;\
2401         ldxa    [hmeblkpa]ASI_MEM, hmeblkpa                             ;\
2402         MAKE_HASHTAG(tte, hatid, hmeshift, hashno, hmemisc)             ;\
2403         ba,a,pt %xcc, label/**/8                                        ;\
2404 label/**/6:                                                             ;\
2405         GET_SCDSHMERMAP(tsbarea, hmeblkpa, hatid, hmemisc)              ;\
2406         ldn     [tsbarea + (TSBMISS_SCRATCH + TSBMISS_HMEBP)], hatid    ;\
2407 label/**/7:                                                             ;\
2408         set     TTE_SUSPEND, hatid                                      ;\
2409         TTE_SUSPEND_INT_SHIFT(hatid)                                    ;\
2410         btst    tte, hatid                                              ;\
2411         bz,pt   %xcc, foundlabel                                        ;\
2412         ldn     [tsbarea + (TSBMISS_SCRATCH + TSBMISS_HATID)], hatid    ;\
2413                                                                         ;\
2414         /*                                                              ;\
2415          * Mapping is suspended, so goto suspend label.                 ;\
2416          */                                                             ;\
2417         ba,pt   %xcc, suspendlabel                                      ;\
2418           nop
2419 
2420         /*
2421          * KERNEL PROTECTION HANDLER
2422          *
2423          * g1 = tsb8k pointer register (clobbered)
2424          * g2 = tag access register (ro)
2425          * g3 - g7 = scratch registers
2426          *
2427          * Note: This function is patched at runtime for performance reasons.
2428          *       Any changes here require sfmmu_patch_ktsb fixed.
2429          */
2430         ENTRY_NP(sfmmu_kprot_trap)
2431         mov     %g2, %g7                ! TSB pointer macro clobbers tagacc
2432 sfmmu_kprot_patch_ktsb_base:
2433         RUNTIME_PATCH_SETX(%g1, %g6)
2434         /* %g1 = contents of ktsb_base or ktsb_pbase */
2435 sfmmu_kprot_patch_ktsb_szcode:
2436         or      %g0, RUNTIME_PATCH, %g3 ! ktsb_szcode (hot patched)
2437 
2438         GET_TSBE_POINTER(MMU_PAGESHIFT, %g1, %g7, %g3, %g5)
2439         ! %g1 = First TSB entry pointer, as TSB miss handler expects
2440 
2441         mov     %g2, %g7                ! TSB pointer macro clobbers tagacc
2442 sfmmu_kprot_patch_ktsb4m_base:
2443         RUNTIME_PATCH_SETX(%g3, %g6)
2444         /* %g3 = contents of ktsb4m_base or ktsb4m_pbase */
2445 sfmmu_kprot_patch_ktsb4m_szcode:
2446         or      %g0, RUNTIME_PATCH, %g6 ! ktsb4m_szcode (hot patched)
2447 
2448         GET_TSBE_POINTER(MMU_PAGESHIFT4M, %g3, %g7, %g6, %g5)
2449         ! %g3 = 4M tsb entry pointer, as TSB miss handler expects
2450 
2451         CPU_TSBMISS_AREA(%g6, %g7)
2452         HAT_PERCPU_STAT16(%g6, TSBMISS_KPROTS, %g7)
2453         ba,pt   %xcc, sfmmu_tsb_miss_tt
2454           nop
2455 
2456         /*
2457          * USER PROTECTION HANDLER
2458          *
2459          * g1 = tsb8k pointer register (ro)
2460          * g2 = tag access register (ro)
2461          * g3 = faulting context (clobbered, currently not used)
2462          * g4 - g7 = scratch registers
2463          */
2464         ALTENTRY(sfmmu_uprot_trap)
2465 #ifdef sun4v
2466         GET_1ST_TSBE_PTR(%g2, %g1, %g4, %g5)
2467         /* %g1 = first TSB entry ptr now, %g2 preserved */
2468 
2469         GET_UTSBREG(SCRATCHPAD_UTSBREG2, %g3)   /* get 2nd utsbreg */
2470         brlz,pt %g3, 9f                         /* check for 2nd TSB */
2471           nop
2472 
2473         GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5)
2474         /* %g3 = second TSB entry ptr now, %g2 preserved */
2475 
2476 #else /* sun4v */
2477 #ifdef UTSB_PHYS
2478         /* g1 = first TSB entry ptr */
2479         GET_UTSBREG(SCRATCHPAD_UTSBREG2, %g3)
2480         brlz,pt %g3, 9f                 /* check for 2nd TSB */
2481           nop
2482 
2483         GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5)
2484         /* %g3 = second TSB entry ptr now, %g2 preserved */
2485 #else /* UTSB_PHYS */
2486         brgez,pt %g1, 9f                /* check for 2nd TSB */
2487           mov   -1, %g3                 /* set second tsbe ptr to -1 */
2488 
2489         mov     %g2, %g7
2490         GET_2ND_TSBE_PTR(%g7, %g1, %g3, %g4, %g5, sfmmu_uprot)
2491         /* %g3 = second TSB entry ptr now, %g7 clobbered */
2492         mov     %g1, %g7
2493         GET_1ST_TSBE_PTR(%g7, %g1, %g5, sfmmu_uprot)
2494 #endif /* UTSB_PHYS */
2495 #endif /* sun4v */
2496 9:
2497         CPU_TSBMISS_AREA(%g6, %g7)
2498         HAT_PERCPU_STAT16(%g6, TSBMISS_UPROTS, %g7)
2499         ba,pt   %xcc, sfmmu_tsb_miss_tt         /* branch TSB miss handler */
2500           nop
2501 
2502         /*
2503          * Kernel 8K page iTLB miss.  We also get here if we took a
2504          * fast instruction access mmu miss trap while running in
2505          * invalid context.
2506          *
2507          * %g1 = 8K TSB pointer register (not used, clobbered)
2508          * %g2 = tag access register (used)
2509          * %g3 = faulting context id (used)
2510          * %g7 = TSB tag to match (used)
2511          */
2512         .align  64
2513         ALTENTRY(sfmmu_kitlb_miss)
2514         brnz,pn %g3, tsb_tl0_noctxt
2515           nop
2516 
2517         /* kernel miss */
2518         /* get kernel tsb pointer */
2519         /* we patch the next set of instructions at run time */
2520         /* NOTE: any changes here require sfmmu_patch_ktsb fixed */
2521 iktsbbase:
2522         RUNTIME_PATCH_SETX(%g4, %g5)
2523         /* %g4 = contents of ktsb_base or ktsb_pbase */
2524 
2525 iktsb:  sllx    %g2, 64-(TAGACC_SHIFT + TSB_START_SIZE + RUNTIME_PATCH), %g1
2526         srlx    %g1, 64-(TSB_START_SIZE + TSB_ENTRY_SHIFT + RUNTIME_PATCH), %g1
2527         or      %g4, %g1, %g1                   ! form tsb ptr
2528         ldda    [%g1]RUNTIME_PATCH, %g4         ! %g4 = tag, %g5 = data
2529         cmp     %g4, %g7
2530         bne,pn  %xcc, iktsb4mbase               ! check 4m ktsb
2531           srlx    %g2, MMU_PAGESHIFT4M, %g3     ! use 4m virt-page as TSB index
2532 
2533         andcc %g5, TTE_EXECPRM_INT, %g0         ! check exec bit
2534         bz,pn   %icc, exec_fault
2535           nop
2536         TT_TRACE(trace_tsbhit)                  ! 2 instr traptrace
2537         ITLB_STUFF(%g5, %g1, %g2, %g3, %g4)
2538         retry
2539 
2540 iktsb4mbase:
2541         RUNTIME_PATCH_SETX(%g4, %g6)
2542         /* %g4 = contents of ktsb4m_base or ktsb4m_pbase */
2543 iktsb4m:
2544         sllx    %g3, 64-(TSB_START_SIZE + RUNTIME_PATCH), %g3
2545         srlx    %g3, 64-(TSB_START_SIZE + TSB_ENTRY_SHIFT + RUNTIME_PATCH), %g3
2546         add     %g4, %g3, %g3                   ! %g3 = 4m tsbe ptr
2547         ldda    [%g3]RUNTIME_PATCH, %g4         ! %g4 = tag, %g5 = data
2548         cmp     %g4, %g7
2549         bne,pn  %xcc, sfmmu_tsb_miss_tt         ! branch on miss
2550           andcc %g5, TTE_EXECPRM_INT, %g0               ! check exec bit
2551         bz,pn   %icc, exec_fault
2552           nop
2553         TT_TRACE(trace_tsbhit)                  ! 2 instr traptrace
2554         ITLB_STUFF(%g5, %g1, %g2, %g3, %g4)
2555         retry
2556 
2557         /*
2558          * Kernel dTLB miss.  We also get here if we took a fast data
2559          * access mmu miss trap while running in invalid context.
2560          *
2561          * Note: for now we store kpm TTEs in the kernel TSB as usual.
2562          *      We select the TSB miss handler to branch to depending on
2563          *      the virtual address of the access.  In the future it may
2564          *      be desirable to separate kpm TTEs into their own TSB,
2565          *      in which case all that needs to be done is to set
2566          *      kpm_tsbbase/kpm_tsbsz to point to the new TSB and branch
2567          *      early in the miss if we detect a kpm VA to a new handler.
2568          *
2569          * %g1 = 8K TSB pointer register (not used, clobbered)
2570          * %g2 = tag access register (used)
2571          * %g3 = faulting context id (used)
2572          */
2573         .align  64
2574         ALTENTRY(sfmmu_kdtlb_miss)
2575         brnz,pn %g3, tsb_tl0_noctxt             /* invalid context? */
2576           nop
2577 
2578         /* Gather some stats for kpm misses in the TLB. */
2579         /* KPM_TLBMISS_STAT_INCR(tagacc, val, tsbma, tmp1, label) */
2580         KPM_TLBMISS_STAT_INCR(%g2, %g4, %g5, %g6, kpmtlbm_stat_out)
2581 
2582         /*
2583          * Get first TSB offset and look for 8K/64K/512K mapping
2584          * using the 8K virtual page as the index.
2585          *
2586          * We patch the next set of instructions at run time;
2587          * any changes here require sfmmu_patch_ktsb changes too.
2588          */
2589 dktsbbase:
2590         RUNTIME_PATCH_SETX(%g7, %g6)
2591         /* %g7 = contents of ktsb_base or ktsb_pbase */
2592 
2593 dktsb:  sllx    %g2, 64-(TAGACC_SHIFT + TSB_START_SIZE + RUNTIME_PATCH), %g1
2594         srlx    %g1, 64-(TSB_START_SIZE + TSB_ENTRY_SHIFT + RUNTIME_PATCH), %g1
2595 
2596         /*
2597          * At this point %g1 is our index into the TSB.
2598          * We just masked off enough bits of the VA depending
2599          * on our TSB size code.
2600          */
2601         ldda    [%g7 + %g1]RUNTIME_PATCH, %g4   ! %g4 = tag, %g5 = data
2602         srlx    %g2, TAG_VALO_SHIFT, %g6        ! make tag to compare
2603         cmp     %g6, %g4                        ! compare tag
2604         bne,pn  %xcc, dktsb4m_kpmcheck_small
2605           add   %g7, %g1, %g1                   /* form tsb ptr */
2606         TT_TRACE(trace_tsbhit)
2607         DTLB_STUFF(%g5, %g1, %g2, %g3, %g4)
2608         /* trapstat expects tte in %g5 */
2609         retry
2610 
2611         /*
2612          * If kpm is using large pages, the following instruction needs
2613          * to be patched to a nop at boot time (by sfmmu_kpm_patch_tsbm)
2614          * so that we will probe the 4M TSB regardless of the VA.  In
2615          * the case kpm is using small pages, we know no large kernel
2616          * mappings are located above 0x80000000.00000000 so we skip the
2617          * probe as an optimization.
2618          */
2619 dktsb4m_kpmcheck_small:
2620         brlz,pn %g2, sfmmu_kpm_dtsb_miss_small
2621           /* delay slot safe, below */
2622 
2623         /*
2624          * Get second TSB offset and look for 4M mapping
2625          * using 4M virtual page as the TSB index.
2626          *
2627          * Here:
2628          * %g1 = 8K TSB pointer.  Don't squash it.
2629          * %g2 = tag access register (we still need it)
2630          */
2631         srlx    %g2, MMU_PAGESHIFT4M, %g3
2632 
2633         /*
2634          * We patch the next set of instructions at run time;
2635          * any changes here require sfmmu_patch_ktsb changes too.
2636          */
2637 dktsb4mbase:
2638         RUNTIME_PATCH_SETX(%g7, %g6)
2639         /* %g7 = contents of ktsb4m_base or ktsb4m_pbase */
2640 dktsb4m:
2641         sllx    %g3, 64-(TSB_START_SIZE + RUNTIME_PATCH), %g3
2642         srlx    %g3, 64-(TSB_START_SIZE + TSB_ENTRY_SHIFT + RUNTIME_PATCH), %g3
2643 
2644         /*
2645          * At this point %g3 is our index into the TSB.
2646          * We just masked off enough bits of the VA depending
2647          * on our TSB size code.
2648          */
2649         ldda    [%g7 + %g3]RUNTIME_PATCH, %g4   ! %g4 = tag, %g5 = data
2650         srlx    %g2, TAG_VALO_SHIFT, %g6        ! make tag to compare
2651         cmp     %g6, %g4                        ! compare tag
2652 
2653 dktsb4m_tsbmiss:
2654         bne,pn  %xcc, dktsb4m_kpmcheck
2655           add   %g7, %g3, %g3                   ! %g3 = kernel second TSB ptr
2656         TT_TRACE(trace_tsbhit)
2657         /* we don't check TTE size here since we assume 4M TSB is separate */
2658         DTLB_STUFF(%g5, %g1, %g2, %g3, %g4)
2659         /* trapstat expects tte in %g5 */
2660         retry
2661 
2662         /*
2663          * So, we failed to find a valid TTE to match the faulting
2664          * address in either TSB.  There are a few cases that could land
2665          * us here:
2666          *
2667          * 1) This is a kernel VA below 0x80000000.00000000.  We branch
2668          *    to sfmmu_tsb_miss_tt to handle the miss.
2669          * 2) We missed on a kpm VA, and we didn't find the mapping in the
2670          *    4M TSB.  Let segkpm handle it.
2671          *
2672          * Note that we shouldn't land here in the case of a kpm VA when
2673          * kpm_smallpages is active -- we handled that case earlier at
2674          * dktsb4m_kpmcheck_small.
2675          *
2676          * At this point:
2677          *  g1 = 8K-indexed primary TSB pointer
2678          *  g2 = tag access register
2679          *  g3 = 4M-indexed secondary TSB pointer
2680          */
2681 dktsb4m_kpmcheck:
2682         cmp     %g2, %g0
2683         bl,pn   %xcc, sfmmu_kpm_dtsb_miss
2684           nop
2685         ba,a,pt %icc, sfmmu_tsb_miss_tt
2686           nop
2687 
2688 #ifdef sun4v
2689         /*
2690          * User instruction miss w/ single TSB.
2691          * The first probe covers 8K, 64K, and 512K page sizes,
2692          * because 64K and 512K mappings are replicated off 8K
2693          * pointer.
2694          *
2695          * g1 = tsb8k pointer register
2696          * g2 = tag access register
2697          * g3 - g6 = scratch registers
2698          * g7 = TSB tag to match
2699          */
2700         .align  64
2701         ALTENTRY(sfmmu_uitlb_fastpath)
2702 
2703         PROBE_1ST_ITSB(%g1, %g7, uitlb_fast_8k_probefail)
2704         /* g4 - g5 = clobbered by PROBE_1ST_ITSB */
2705         ba,pn   %xcc, sfmmu_tsb_miss_tt
2706           mov   -1, %g3
2707 
2708         /*
2709          * User data miss w/ single TSB.
2710          * The first probe covers 8K, 64K, and 512K page sizes,
2711          * because 64K and 512K mappings are replicated off 8K
2712          * pointer.
2713          *
2714          * g1 = tsb8k pointer register
2715          * g2 = tag access register
2716          * g3 - g6 = scratch registers
2717          * g7 = TSB tag to match
2718          */
2719         .align 64
2720         ALTENTRY(sfmmu_udtlb_fastpath)
2721 
2722         PROBE_1ST_DTSB(%g1, %g7, udtlb_fast_8k_probefail)
2723         /* g4 - g5 = clobbered by PROBE_1ST_DTSB */
2724         ba,pn   %xcc, sfmmu_tsb_miss_tt
2725           mov   -1, %g3
2726 
2727         /*
2728          * User instruction miss w/ multiple TSBs (sun4v).
2729          * The first probe covers 8K, 64K, and 512K page sizes,
2730          * because 64K and 512K mappings are replicated off 8K
2731          * pointer.  Second probe covers 4M page size only.
2732          *
2733          * Just like sfmmu_udtlb_slowpath, except:
2734          *   o Uses ASI_ITLB_IN
2735          *   o checks for execute permission
2736          *   o No ISM prediction.
2737          *
2738          * g1 = tsb8k pointer register
2739          * g2 = tag access register
2740          * g3 - g6 = scratch registers
2741          * g7 = TSB tag to match
2742          */
2743         .align  64
2744         ALTENTRY(sfmmu_uitlb_slowpath)
2745 
2746         GET_1ST_TSBE_PTR(%g2, %g1, %g4, %g5)
2747         PROBE_1ST_ITSB(%g1, %g7, uitlb_8k_probefail)
2748         /* g4 - g5 = clobbered here */
2749 
2750         GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5)
2751         /* g1 = first TSB pointer, g3 = second TSB pointer */
2752         srlx    %g2, TAG_VALO_SHIFT, %g7
2753         PROBE_2ND_ITSB(%g3, %g7)
2754         /* NOT REACHED */
2755 
2756 #else /* sun4v */
2757 
2758         /*
2759          * User instruction miss w/ multiple TSBs (sun4u).
2760          * The first probe covers 8K, 64K, and 512K page sizes,
2761          * because 64K and 512K mappings are replicated off 8K
2762          * pointer.  Probe of 1st TSB has already been done prior to entry
2763          * into this routine. For the UTSB_PHYS case we probe up to 3
2764          * valid other TSBs in the following order:
2765          * 1) shared TSB for 4M-256M pages
2766          * 2) private TSB for 4M-256M pages
2767          * 3) shared TSB for 8K-512K pages
2768          *
2769          * For the non UTSB_PHYS case we probe the 2nd TSB here that backs
2770          * 4M-256M pages.
2771          *
2772          * Just like sfmmu_udtlb_slowpath, except:
2773          *   o Uses ASI_ITLB_IN
2774          *   o checks for execute permission
2775          *   o No ISM prediction.
2776          *
2777          * g1 = tsb8k pointer register
2778          * g2 = tag access register
2779          * g4 - g6 = scratch registers
2780          * g7 = TSB tag to match
2781          */
2782         .align  64
2783         ALTENTRY(sfmmu_uitlb_slowpath)
2784 
2785 #ifdef UTSB_PHYS
2786 
2787        GET_UTSBREG(SCRATCHPAD_UTSBREG4, %g6)
2788         brlz,pt %g6, 1f
2789           nop
2790         GET_4TH_TSBE_PTR(%g2, %g6, %g4, %g5)
2791         PROBE_4TH_ITSB(%g6, %g7, uitlb_4m_scd_probefail)
2792 1:
2793         GET_UTSBREG(SCRATCHPAD_UTSBREG2, %g3)
2794         brlz,pt %g3, 2f
2795           nop
2796         GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5)
2797         PROBE_2ND_ITSB(%g3, %g7, uitlb_4m_probefail)
2798 2:
2799         GET_UTSBREG(SCRATCHPAD_UTSBREG3, %g6)
2800         brlz,pt %g6, sfmmu_tsb_miss_tt
2801           nop
2802         GET_3RD_TSBE_PTR(%g2, %g6, %g4, %g5)
2803         PROBE_3RD_ITSB(%g6, %g7, uitlb_8K_scd_probefail)
2804         ba,pn   %xcc, sfmmu_tsb_miss_tt
2805           nop
2806 
2807 #else /* UTSB_PHYS */
2808         mov     %g1, %g3        /* save tsb8k reg in %g3 */
2809         GET_1ST_TSBE_PTR(%g3, %g1, %g5, sfmmu_uitlb)
2810         PROBE_1ST_ITSB(%g1, %g7, uitlb_8k_probefail)
2811         mov     %g2, %g6        /* GET_2ND_TSBE_PTR clobbers tagacc */
2812         mov     %g3, %g7        /* copy tsb8k reg in %g7 */
2813         GET_2ND_TSBE_PTR(%g6, %g7, %g3, %g4, %g5, sfmmu_uitlb)
2814        /* g1 = first TSB pointer, g3 = second TSB pointer */
2815         srlx    %g2, TAG_VALO_SHIFT, %g7
2816         PROBE_2ND_ITSB(%g3, %g7, isynth)
2817         ba,pn   %xcc, sfmmu_tsb_miss_tt
2818           nop
2819 
2820 #endif /* UTSB_PHYS */
2821 #endif /* sun4v */
2822 
2823 #if defined(sun4u) && defined(UTSB_PHYS)
2824 
2825         /*
2826          * We come here for ism predict DTLB_MISS case or if
2827          * if probe in first TSB failed.
2828          */
2829 
2830         .align 64
2831         ALTENTRY(sfmmu_udtlb_slowpath_noismpred)
2832 
2833         /*
2834          * g1 = tsb8k pointer register
2835          * g2 = tag access register
2836          * g4 - %g6 = scratch registers
2837          * g7 = TSB tag to match
2838          */
2839 
2840         /*
2841          * ISM non-predict probe order
2842          * probe 1ST_TSB (8K index)
2843          * probe 2ND_TSB (4M index)
2844          * probe 4TH_TSB (4M index)
2845          * probe 3RD_TSB (8K index)
2846          *
2847          * We already probed first TSB in DTLB_MISS handler.
2848          */
2849 
2850         /*
2851          * Private 2ND TSB 4M-256 pages
2852          */
2853         GET_UTSBREG(SCRATCHPAD_UTSBREG2, %g3)
2854         brlz,pt %g3, 1f
2855           nop
2856         GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5)
2857         PROBE_2ND_DTSB(%g3, %g7, udtlb_4m_probefail)
2858 
2859         /*
2860          * Shared Context 4TH TSB 4M-256 pages
2861          */
2862 1:
2863         GET_UTSBREG(SCRATCHPAD_UTSBREG4, %g6)
2864         brlz,pt %g6, 2f
2865           nop
2866         GET_4TH_TSBE_PTR(%g2, %g6, %g4, %g5)
2867         PROBE_4TH_DTSB(%g6, %g7, udtlb_4m_shctx_probefail)
2868 
2869         /*
2870          * Shared Context 3RD TSB 8K-512K pages
2871          */
2872 2:
2873         GET_UTSBREG(SCRATCHPAD_UTSBREG3, %g6)
2874         brlz,pt %g6, sfmmu_tsb_miss_tt
2875           nop
2876         GET_3RD_TSBE_PTR(%g2, %g6, %g4, %g5)
2877         PROBE_3RD_DTSB(%g6, %g7, udtlb_8k_shctx_probefail)
2878         ba,pn   %xcc, sfmmu_tsb_miss_tt
2879           nop
2880 
2881         .align 64
2882         ALTENTRY(sfmmu_udtlb_slowpath_ismpred)
2883 
2884         /*
2885          * g1 = tsb8k pointer register
2886          * g2 = tag access register
2887          * g4 - g6 = scratch registers
2888          * g7 = TSB tag to match
2889          */
2890 
2891         /*
2892          * ISM predict probe order
2893          * probe 4TH_TSB (4M index)
2894          * probe 2ND_TSB (4M index)
2895          * probe 1ST_TSB (8K index)
2896          * probe 3RD_TSB (8K index)
2897 
2898         /*
2899          * Shared Context 4TH TSB 4M-256 pages
2900          */
2901         GET_UTSBREG(SCRATCHPAD_UTSBREG4, %g6)
2902         brlz,pt %g6, 4f
2903           nop
2904         GET_4TH_TSBE_PTR(%g2, %g6, %g4, %g5)
2905         PROBE_4TH_DTSB(%g6, %g7, udtlb_4m_shctx_probefail2)
2906 
2907         /*
2908          * Private 2ND TSB 4M-256 pages
2909          */
2910 4:
2911         GET_UTSBREG(SCRATCHPAD_UTSBREG2, %g3)
2912         brlz,pt %g3, 5f
2913           nop
2914         GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5)
2915         PROBE_2ND_DTSB(%g3, %g7, udtlb_4m_probefail2)
2916 
2917 5:
2918         PROBE_1ST_DTSB(%g1, %g7, udtlb_8k_first_probefail2)
2919 
2920         /*
2921          * Shared Context 3RD TSB 8K-512K pages
2922          */
2923         GET_UTSBREG(SCRATCHPAD_UTSBREG3, %g6)
2924         brlz,pt %g6, 6f
2925           nop
2926         GET_3RD_TSBE_PTR(%g2, %g6, %g4, %g5)
2927         PROBE_3RD_DTSB(%g6, %g7, udtlb_8k_shctx_probefail2)
2928 6:
2929         ba,pn   %xcc, sfmmu_tsb_miss_tt /* ISM Predict and ISM non-predict path */
2930           nop
2931 
2932 #else /* sun4u && UTSB_PHYS */
2933 
2934        .align 64
2935         ALTENTRY(sfmmu_udtlb_slowpath)
2936 
2937         srax    %g2, PREDISM_BASESHIFT, %g6     /* g6 > 0 : ISM predicted */
2938         brgz,pn %g6, udtlb_miss_probesecond     /* check for ISM */
2939           mov   %g1, %g3
2940 
2941 udtlb_miss_probefirst:
2942         /*
2943          * g1 = 8K TSB pointer register
2944          * g2 = tag access register
2945          * g3 = (potentially) second TSB entry ptr
2946          * g6 = ism pred.
2947          * g7 = vpg_4m
2948          */
2949 #ifdef sun4v
2950         GET_1ST_TSBE_PTR(%g2, %g1, %g4, %g5)
2951         PROBE_1ST_DTSB(%g1, %g7, udtlb_first_probefail)
2952 
2953         /*
2954          * Here:
2955          *   g1 = first TSB pointer
2956          *   g2 = tag access reg
2957          *   g3 = second TSB ptr IFF ISM pred. (else don't care)
2958          */
2959         brgz,pn %g6, sfmmu_tsb_miss_tt
2960           nop
2961 #else /* sun4v */
2962         mov     %g1, %g4
2963         GET_1ST_TSBE_PTR(%g4, %g1, %g5, sfmmu_udtlb)
2964         PROBE_1ST_DTSB(%g1, %g7, udtlb_first_probefail)
2965 
2966         /*
2967          * Here:
2968          *   g1 = first TSB pointer
2969          *   g2 = tag access reg
2970          *   g3 = second TSB ptr IFF ISM pred. (else don't care)
2971          */
2972         brgz,pn %g6, sfmmu_tsb_miss_tt
2973           nop
2974         ldxa    [%g0]ASI_DMMU_TSB_8K, %g3
2975         /* fall through in 8K->4M probe order */
2976 #endif /* sun4v */
2977 
2978 udtlb_miss_probesecond:
2979         /*
2980          * Look in the second TSB for the TTE
2981          * g1 = First TSB entry ptr if !ISM pred, TSB8K ptr reg if ISM pred.
2982          * g2 = tag access reg
2983          * g3 = 8K TSB pointer register
2984          * g6 = ism pred.
2985          * g7 = vpg_4m
2986          */
2987 #ifdef sun4v
2988         /* GET_2ND_TSBE_PTR(tagacc, tsbe_ptr, tmp1, tmp2) */
2989         GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5)
2990         /* %g2 is okay, no need to reload, %g3 = second tsbe ptr */
2991 #else /* sun4v */
2992         mov     %g3, %g7
2993         GET_2ND_TSBE_PTR(%g2, %g7, %g3, %g4, %g5, sfmmu_udtlb)
2994         /* %g2 clobbered, %g3 =second tsbe ptr */
2995         mov     MMU_TAG_ACCESS, %g2
2996         ldxa    [%g2]ASI_DMMU, %g2
2997 #endif /* sun4v */
2998 
2999         srlx    %g2, TAG_VALO_SHIFT, %g7
3000         PROBE_2ND_DTSB(%g3, %g7, udtlb_4m_probefail)
3001         /* g4 - g5 = clobbered here; %g7 still vpg_4m at this point */
3002         brgz,pn %g6, udtlb_miss_probefirst
3003           nop
3004 
3005         /* fall through to sfmmu_tsb_miss_tt */
3006 #endif /* sun4u && UTSB_PHYS */
3007 
3008 
3009         ALTENTRY(sfmmu_tsb_miss_tt)
3010         TT_TRACE(trace_tsbmiss)
3011         /*
3012          * We get here if there is a TSB miss OR a write protect trap.
3013          *
3014          * g1 = First TSB entry pointer
3015          * g2 = tag access register
3016          * g3 = 4M TSB entry pointer; -1 if no 2nd TSB
3017          * g4 - g7 = scratch registers
3018          */
3019 
3020         ALTENTRY(sfmmu_tsb_miss)
3021 
3022         /*
3023          * If trapstat is running, we need to shift the %tpc and %tnpc to
3024          * point to trapstat's TSB miss return code (note that trapstat
3025          * itself will patch the correct offset to add).
3026          */
3027         rdpr    %tl, %g7
3028         cmp     %g7, 1
3029         ble,pt  %xcc, 0f
3030           sethi %hi(KERNELBASE), %g6
3031         rdpr    %tpc, %g7
3032         or      %g6, %lo(KERNELBASE), %g6
3033         cmp     %g7, %g6
3034         bgeu,pt %xcc, 0f
3035         /* delay slot safe */
3036 
3037         ALTENTRY(tsbmiss_trapstat_patch_point)
3038         add     %g7, RUNTIME_PATCH, %g7 /* must match TSTAT_TSBMISS_INSTR */
3039         wrpr    %g7, %tpc
3040         add     %g7, 4, %g7
3041         wrpr    %g7, %tnpc
3042 0:
3043         CPU_TSBMISS_AREA(%g6, %g7)
3044         stn     %g1, [%g6 + TSBMISS_TSBPTR]     /* save 1ST tsb pointer */
3045         stn     %g3, [%g6 + TSBMISS_TSBPTR4M]   /* save 2ND tsb pointer */
3046 
3047         sllx    %g2, TAGACC_CTX_LSHIFT, %g3
3048         brz,a,pn %g3, 1f                        /* skip ahead if kernel */
3049           ldn   [%g6 + TSBMISS_KHATID], %g7
3050         srlx    %g3, TAGACC_CTX_LSHIFT, %g3     /* g3 = ctxnum */
3051         ldn     [%g6 + TSBMISS_UHATID], %g7     /* g7 = hatid */
3052 
3053         HAT_PERCPU_STAT32(%g6, TSBMISS_UTSBMISS, %g5)
3054 
3055         cmp     %g3, INVALID_CONTEXT
3056         be,pn   %icc, tsb_tl0_noctxt            /* no ctx miss exception */
3057           stn   %g7, [%g6 + (TSBMISS_SCRATCH + TSBMISS_HATID)]
3058 
3059 #if defined(sun4v) || defined(UTSB_PHYS)
3060         ldub    [%g6 + TSBMISS_URTTEFLAGS], %g7 /* clear ctx1 flag set from */
3061         andn    %g7, HAT_CHKCTX1_FLAG, %g7      /* the previous tsb miss    */
3062         stub    %g7, [%g6 + TSBMISS_URTTEFLAGS]
3063 #endif /* sun4v || UTSB_PHYS */
3064 
3065         ISM_CHECK(%g2, %g6, %g3, %g4, %g5, %g7, %g1, tsb_l1, tsb_ism)
3066         /*
3067          * The miss wasn't in an ISM segment.
3068          *
3069          * %g1 %g3, %g4, %g5, %g7 all clobbered
3070          * %g2 = (pseudo) tag access
3071          */
3072 
3073         ba,pt   %icc, 2f
3074           ldn   [%g6 + (TSBMISS_SCRATCH + TSBMISS_HATID)], %g7
3075 
3076 1:
3077         HAT_PERCPU_STAT32(%g6, TSBMISS_KTSBMISS, %g5)
3078         /*
3079          * 8K and 64K hash.
3080          */
3081 2:
3082 
3083         GET_TTE(%g2, %g7, %g3, %g4, %g6, %g1,
3084                 MMU_PAGESHIFT64K, TTE64K, %g5, tsb_l8K, tsb_checktte,
3085                 sfmmu_suspend_tl, tsb_512K)
3086         /* NOT REACHED */
3087 
3088 tsb_512K:
3089         sllx    %g2, TAGACC_CTX_LSHIFT, %g5
3090         brz,pn  %g5, 3f
3091           ldub  [%g6 + TSBMISS_UTTEFLAGS], %g4
3092         and     %g4, HAT_512K_FLAG, %g5
3093 
3094         /*
3095          * Note that there is a small window here where we may have
3096          * a 512k page in the hash list but have not set the HAT_512K_FLAG
3097          * flag yet, so we will skip searching the 512k hash list.
3098          * In this case we will end up in pagefault which will find
3099          * the mapping and return.  So, in this instance we will end up
3100          * spending a bit more time resolving this TSB miss, but it can
3101          * only happen once per process and even then, the chances of that
3102          * are very small, so it's not worth the extra overhead it would
3103          * take to close this window.
3104          */
3105         brz,pn  %g5, tsb_4M
3106           nop
3107 3:
3108         /*
3109          * 512K hash
3110          */
3111 
3112         GET_TTE(%g2, %g7, %g3, %g4, %g6, %g1,
3113                 MMU_PAGESHIFT512K, TTE512K, %g5, tsb_l512K, tsb_checktte,
3114                 sfmmu_suspend_tl, tsb_4M)
3115         /* NOT REACHED */
3116 
3117 tsb_4M:
3118         sllx    %g2, TAGACC_CTX_LSHIFT, %g5
3119         brz,pn  %g5, 4f
3120           ldub  [%g6 + TSBMISS_UTTEFLAGS], %g4
3121         and     %g4, HAT_4M_FLAG, %g5
3122         brz,pn  %g5, tsb_32M
3123           nop
3124 4:
3125         /*
3126          * 4M hash
3127          */
3128 
3129         GET_TTE(%g2, %g7, %g3, %g4, %g6, %g1,
3130                 MMU_PAGESHIFT4M, TTE4M, %g5, tsb_l4M, tsb_checktte,
3131                 sfmmu_suspend_tl, tsb_32M)
3132         /* NOT REACHED */
3133 
3134 tsb_32M:
3135         sllx    %g2, TAGACC_CTX_LSHIFT, %g5
3136 #ifdef  sun4v
3137         brz,pn  %g5, 6f
3138 #else
3139         brz,pn  %g5, tsb_pagefault
3140 #endif
3141           ldub  [%g6 + TSBMISS_UTTEFLAGS], %g4
3142         and     %g4, HAT_32M_FLAG, %g5
3143         brz,pn  %g5, tsb_256M
3144           nop
3145 5:
3146         /*
3147          * 32M hash
3148          */
3149 
3150         GET_TTE(%g2, %g7, %g3, %g4, %g6, %g1,
3151                 MMU_PAGESHIFT32M, TTE32M, %g5, tsb_l32M, tsb_checktte,
3152                 sfmmu_suspend_tl, tsb_256M)
3153         /* NOT REACHED */
3154 
3155 #if defined(sun4u) && !defined(UTSB_PHYS)
3156 #define tsb_shme        tsb_pagefault
3157 #endif
3158 tsb_256M:
3159         ldub    [%g6 + TSBMISS_UTTEFLAGS], %g4
3160         and     %g4, HAT_256M_FLAG, %g5
3161         brz,pn  %g5, tsb_shme
3162           nop
3163 6:
3164         /*
3165          * 256M hash
3166          */
3167 
3168         GET_TTE(%g2, %g7, %g3, %g4, %g6, %g1,
3169             MMU_PAGESHIFT256M, TTE256M, %g5, tsb_l256M, tsb_checktte,
3170             sfmmu_suspend_tl, tsb_shme)
3171         /* NOT REACHED */
3172 
3173 tsb_checktte:
3174         /*
3175          * g1 = hblk_misc
3176          * g2 = tagacc
3177          * g3 = tte
3178          * g4 = tte pa
3179          * g6 = tsbmiss area
3180          * g7 = hatid
3181          */
3182         brlz,a,pt %g3, tsb_validtte
3183           rdpr  %tt, %g7
3184 
3185 #if defined(sun4u) && !defined(UTSB_PHYS)
3186 #undef tsb_shme
3187         ba      tsb_pagefault
3188           nop
3189 #else /* sun4u && !UTSB_PHYS */
3190 
3191 tsb_shme:
3192         /*
3193          * g2 = tagacc
3194          * g6 = tsbmiss area
3195          */
3196         sllx    %g2, TAGACC_CTX_LSHIFT, %g5
3197         brz,pn  %g5, tsb_pagefault
3198           nop
3199         ldx     [%g6 + TSBMISS_SHARED_UHATID], %g7      /* g7 = srdp */
3200         brz,pn  %g7, tsb_pagefault
3201           nop
3202 
3203         GET_SHME_TTE(%g2, %g7, %g3, %g4, %g6, %g1,
3204                 MMU_PAGESHIFT64K, TTE64K, %g5, tsb_shme_l8K, tsb_shme_checktte,
3205                 sfmmu_suspend_tl, tsb_shme_512K)
3206         /* NOT REACHED */
3207 
3208 tsb_shme_512K:
3209         ldub    [%g6 + TSBMISS_URTTEFLAGS], %g4
3210         and     %g4, HAT_512K_FLAG, %g5
3211         brz,pn  %g5, tsb_shme_4M
3212           nop
3213 
3214         /*
3215          * 512K hash
3216          */
3217 
3218         GET_SHME_TTE(%g2, %g7, %g3, %g4, %g6, %g1,
3219                 MMU_PAGESHIFT512K, TTE512K, %g5, tsb_shme_l512K, tsb_shme_checktte,
3220                 sfmmu_suspend_tl, tsb_shme_4M)
3221         /* NOT REACHED */
3222 
3223 tsb_shme_4M:
3224         ldub    [%g6 + TSBMISS_URTTEFLAGS], %g4
3225         and     %g4, HAT_4M_FLAG, %g5
3226         brz,pn  %g5, tsb_shme_32M
3227           nop
3228 4:
3229         /*
3230          * 4M hash
3231          */
3232         GET_SHME_TTE(%g2, %g7, %g3, %g4, %g6, %g1,
3233                 MMU_PAGESHIFT4M, TTE4M, %g5, tsb_shme_l4M, tsb_shme_checktte,
3234                 sfmmu_suspend_tl, tsb_shme_32M)
3235         /* NOT REACHED */
3236 
3237 tsb_shme_32M:
3238         ldub    [%g6 + TSBMISS_URTTEFLAGS], %g4
3239         and     %g4, HAT_32M_FLAG, %g5
3240         brz,pn  %g5, tsb_shme_256M
3241           nop
3242 
3243         /*
3244          * 32M hash
3245          */
3246 
3247         GET_SHME_TTE(%g2, %g7, %g3, %g4, %g6, %g1,
3248                 MMU_PAGESHIFT32M, TTE32M, %g5, tsb_shme_l32M, tsb_shme_checktte,
3249                 sfmmu_suspend_tl, tsb_shme_256M)
3250         /* NOT REACHED */
3251 
3252 tsb_shme_256M:
3253         ldub    [%g6 + TSBMISS_URTTEFLAGS], %g4
3254         and     %g4, HAT_256M_FLAG, %g5
3255         brz,pn  %g5, tsb_pagefault
3256           nop
3257 
3258         /*
3259          * 256M hash
3260          */
3261 
3262         GET_SHME_TTE(%g2, %g7, %g3, %g4, %g6, %g1,
3263             MMU_PAGESHIFT256M, TTE256M, %g5, tsb_shme_l256M, tsb_shme_checktte,
3264             sfmmu_suspend_tl, tsb_pagefault)
3265         /* NOT REACHED */
3266 
3267 tsb_shme_checktte:
3268 
3269         brgez,pn %g3, tsb_pagefault
3270           rdpr  %tt, %g7
3271         /*
3272          * g1 = ctx1 flag
3273          * g3 = tte
3274          * g4 = tte pa
3275          * g6 = tsbmiss area
3276          * g7 = tt
3277          */
3278 
3279         brz,pt  %g1, tsb_validtte
3280           nop
3281         ldub    [%g6 + TSBMISS_URTTEFLAGS], %g1
3282           or    %g1, HAT_CHKCTX1_FLAG, %g1
3283         stub    %g1, [%g6 + TSBMISS_URTTEFLAGS]
3284 
3285         SAVE_CTX1(%g7, %g2, %g1, tsb_shmel)
3286 #endif /* sun4u && !UTSB_PHYS */
3287 
3288 tsb_validtte:
3289         /*
3290          * g3 = tte
3291          * g4 = tte pa
3292          * g6 = tsbmiss area
3293          * g7 = tt
3294          */
3295 
3296         /*
3297          * Set ref/mod bits if this is a prot trap.  Usually, it isn't.
3298          */
3299         cmp     %g7, FAST_PROT_TT
3300         bne,pt  %icc, 4f
3301           nop
3302 
3303         TTE_SET_REFMOD_ML(%g3, %g4, %g6, %g7, %g5, tsb_lset_refmod,
3304             tsb_protfault)
3305 
3306         GET_MMU_D_TTARGET(%g2, %g7)             /* %g2 = ttarget */
3307 #ifdef sun4v
3308         MMU_FAULT_STATUS_AREA(%g7)
3309         ldx     [%g7 + MMFSA_D_ADDR], %g5       /* load fault addr for later */
3310 #else /* sun4v */
3311         mov     MMU_TAG_ACCESS, %g5
3312         ldxa    [%g5]ASI_DMMU, %g5
3313 #endif /* sun4v */
3314         ba,pt   %xcc, tsb_update_tl1
3315           nop
3316 4:
3317         /*
3318          * If ITLB miss check exec bit.
3319          * If not set treat as invalid TTE.
3320          */
3321         cmp     %g7, T_INSTR_MMU_MISS
3322         be,pn   %icc, 5f
3323           andcc   %g3, TTE_EXECPRM_INT, %g0     /* check execute bit is set */
3324         cmp     %g7, FAST_IMMU_MISS_TT
3325         bne,pt %icc, 3f
3326           andcc   %g3, TTE_EXECPRM_INT, %g0     /* check execute bit is set */
3327 5:
3328         bz,pn %icc, tsb_protfault
3329           nop
3330 
3331 3:
3332         /*
3333          * Set reference bit if not already set
3334          */
3335         TTE_SET_REF_ML(%g3, %g4, %g6, %g7, %g5, tsb_lset_ref)
3336 
3337         /*
3338          * Now, load into TSB/TLB.  At this point:
3339          * g3 = tte
3340          * g4 = patte
3341          * g6 = tsbmiss area
3342          */
3343         rdpr    %tt, %g7
3344 #ifdef sun4v
3345         MMU_FAULT_STATUS_AREA(%g2)
3346         cmp     %g7, T_INSTR_MMU_MISS
3347         be,a,pt %icc, 9f
3348           nop
3349         cmp     %g7, FAST_IMMU_MISS_TT
3350         be,a,pt %icc, 9f
3351           nop
3352         add     %g2, MMFSA_D_, %g2
3353 9:
3354         ldx     [%g2 + MMFSA_CTX_], %g7
3355         sllx    %g7, TTARGET_CTX_SHIFT, %g7
3356         ldx     [%g2 + MMFSA_ADDR_], %g2
3357         mov     %g2, %g5                ! load the fault addr for later use
3358         srlx    %g2, TTARGET_VA_SHIFT, %g2
3359         or      %g2, %g7, %g2
3360 #else /* sun4v */
3361         mov     MMU_TAG_ACCESS, %g5
3362         cmp     %g7, FAST_IMMU_MISS_TT
3363         be,a,pt %icc, 9f
3364            ldxa  [%g0]ASI_IMMU, %g2
3365         ldxa    [%g0]ASI_DMMU, %g2
3366         ba,pt   %icc, tsb_update_tl1
3367            ldxa  [%g5]ASI_DMMU, %g5
3368 9:
3369         ldxa    [%g5]ASI_IMMU, %g5
3370 #endif /* sun4v */
3371 
3372 tsb_update_tl1:
3373         srlx    %g2, TTARGET_CTX_SHIFT, %g7
3374         brz,pn  %g7, tsb_kernel
3375 #ifdef sun4v
3376           and   %g3, TTE_SZ_BITS, %g7   ! assumes TTE_SZ_SHFT is 0
3377 #else  /* sun4v */
3378           srlx  %g3, TTE_SZ_SHFT, %g7
3379 #endif /* sun4v */
3380 
3381 tsb_user:
3382 #ifdef sun4v
3383         cmp     %g7, TTE4M
3384         bge,pn  %icc, tsb_user4m
3385           nop
3386 #else /* sun4v */
3387         cmp     %g7, TTESZ_VALID | TTE4M
3388         be,pn   %icc, tsb_user4m
3389           srlx  %g3, TTE_SZ2_SHFT, %g7
3390         andcc   %g7, TTE_SZ2_BITS, %g7          ! check 32/256MB
3391 #ifdef ITLB_32M_256M_SUPPORT
3392         bnz,pn  %icc, tsb_user4m
3393           nop
3394 #else /* ITLB_32M_256M_SUPPORT */
3395         bnz,a,pn %icc, tsb_user_pn_synth
3396          nop
3397 #endif /* ITLB_32M_256M_SUPPORT */
3398 #endif /* sun4v */
3399 
3400 tsb_user8k:
3401 #if defined(sun4v) || defined(UTSB_PHYS)
3402         ldub    [%g6 + TSBMISS_URTTEFLAGS], %g7
3403         and     %g7, HAT_CHKCTX1_FLAG, %g1
3404         brz,a,pn %g1, 1f
3405           ldn   [%g6 + TSBMISS_TSBPTR], %g1             ! g1 = 1ST TSB ptr
3406         GET_UTSBREG_SHCTX(%g6, TSBMISS_TSBSCDPTR, %g1)
3407         brlz,a,pn %g1, ptl1_panic                       ! if no shared 3RD tsb
3408           mov PTL1_NO_SCDTSB8K, %g1                     ! panic
3409         GET_3RD_TSBE_PTR(%g5, %g1, %g6, %g7)
3410 1:
3411 #else /* defined(sun4v) || defined(UTSB_PHYS) */
3412         ldn   [%g6 + TSBMISS_TSBPTR], %g1             ! g1 = 1ST TSB ptr
3413 #endif /* defined(sun4v) || defined(UTSB_PHYS) */
3414 
3415 #ifndef UTSB_PHYS
3416         mov     ASI_N, %g7      ! user TSBs accessed by VA
3417         mov     %g7, %asi
3418 #endif /* !UTSB_PHYS */
3419 
3420         TSB_UPDATE_TL(%g1, %g3, %g2, %g4, %g7, %g6, locked_tsb_l3)
3421 
3422         rdpr    %tt, %g5
3423 #ifdef sun4v
3424         cmp     %g5, T_INSTR_MMU_MISS
3425         be,a,pn %xcc, 9f
3426           mov   %g3, %g5
3427 #endif /* sun4v */
3428         cmp     %g5, FAST_IMMU_MISS_TT
3429         be,pn   %xcc, 9f
3430           mov   %g3, %g5
3431 
3432         DTLB_STUFF(%g5, %g1, %g2, %g3, %g4)
3433         ! trapstat wants TTE in %g5
3434         retry
3435 9:
3436         ITLB_STUFF(%g5, %g1, %g2, %g3, %g4)
3437         ! trapstat wants TTE in %g5
3438         retry
3439 
3440 tsb_user4m:
3441 #if defined(sun4v) || defined(UTSB_PHYS)
3442         ldub    [%g6 + TSBMISS_URTTEFLAGS], %g7
3443         and     %g7, HAT_CHKCTX1_FLAG, %g1
3444         brz,a,pn %g1, 4f
3445           ldn   [%g6 + TSBMISS_TSBPTR4M], %g1           ! g1 = 2ND TSB ptr
3446         GET_UTSBREG_SHCTX(%g6, TSBMISS_TSBSCDPTR4M, %g1)! g1 = 4TH TSB ptr
3447         brlz,a,pn %g1, 5f                               ! if no shared 4TH TSB
3448           nop
3449         GET_4TH_TSBE_PTR(%g5, %g1, %g6, %g7)
3450 
3451 #else /* defined(sun4v) || defined(UTSB_PHYS) */
3452         ldn   [%g6 + TSBMISS_TSBPTR4M], %g1             ! g1 = 2ND TSB ptr
3453 #endif /* defined(sun4v) || defined(UTSB_PHYS) */
3454 4:
3455         brlz,pn %g1, 5f /* Check to see if we have 2nd TSB programmed */
3456           nop
3457 
3458 #ifndef UTSB_PHYS
3459         mov     ASI_N, %g7      ! user TSBs accessed by VA
3460         mov     %g7, %asi
3461 #endif /* UTSB_PHYS */
3462 
3463         TSB_UPDATE_TL(%g1, %g3, %g2, %g4, %g7, %g6, locked_tsb_l4)
3464 
3465 5:
3466         rdpr    %tt, %g5
3467 #ifdef sun4v
3468         cmp     %g5, T_INSTR_MMU_MISS
3469         be,a,pn %xcc, 9f
3470           mov   %g3, %g5
3471 #endif /* sun4v */
3472         cmp     %g5, FAST_IMMU_MISS_TT
3473         be,pn   %xcc, 9f
3474         mov     %g3, %g5
3475 
3476         DTLB_STUFF(%g5, %g1, %g2, %g3, %g4)
3477         ! trapstat wants TTE in %g5
3478         retry
3479 9:
3480         ITLB_STUFF(%g5, %g1, %g2, %g3, %g4)
3481         ! trapstat wants TTE in %g5
3482         retry
3483 
3484 #if !defined(sun4v) && !defined(ITLB_32M_256M_SUPPORT)
3485         /*
3486          * Panther ITLB synthesis.
3487          * The Panther 32M and 256M ITLB code simulates these two large page
3488          * sizes with 4M pages, to provide support for programs, for example
3489          * Java, that may copy instructions into a 32M or 256M data page and
3490          * then execute them. The code below generates the 4M pfn bits and
3491          * saves them in the modified 32M/256M ttes in the TSB. If the tte is
3492          * stored in the DTLB to map a 32M/256M page, the 4M pfn offset bits
3493          * are ignored by the hardware.
3494          *
3495          * Now, load into TSB/TLB.  At this point:
3496          * g2 = tagtarget
3497          * g3 = tte
3498          * g4 = patte
3499          * g5 = tt
3500          * g6 = tsbmiss area
3501          */
3502 tsb_user_pn_synth:
3503         rdpr %tt, %g5
3504         cmp    %g5, FAST_IMMU_MISS_TT
3505         be,pt   %xcc, tsb_user_itlb_synth       /* ITLB miss */
3506           andcc %g3, TTE_EXECPRM_INT, %g0       /* is execprm bit set */
3507         bz,pn %icc, 4b                          /* if not, been here before */
3508           ldn   [%g6 + TSBMISS_TSBPTR4M], %g1   /* g1 = tsbp */
3509         brlz,a,pn %g1, 5f                       /* no 2nd tsb */
3510           mov   %g3, %g5
3511 
3512         mov     MMU_TAG_ACCESS, %g7
3513         ldxa    [%g7]ASI_DMMU, %g6              /* get tag access va */
3514         GET_4M_PFN_OFF(%g3, %g6, %g5, %g7, 1)   /* make 4M pfn offset */
3515 
3516         mov     ASI_N, %g7      /* user TSBs always accessed by VA */
3517         mov     %g7, %asi
3518         TSB_UPDATE_TL_PN(%g1, %g5, %g2, %g4, %g7, %g3, locked_tsb_l5) /* update TSB */
3519 5:
3520         DTLB_STUFF(%g5, %g1, %g2, %g3, %g4)
3521         retry
3522 
3523 tsb_user_itlb_synth:
3524         ldn     [%g6 + TSBMISS_TSBPTR4M], %g1           /* g1 =  2ND TSB */
3525 
3526         mov     MMU_TAG_ACCESS, %g7
3527         ldxa    [%g7]ASI_IMMU, %g6              /* get tag access va */
3528         GET_4M_PFN_OFF(%g3, %g6, %g5, %g7, 2)   /* make 4M pfn offset */
3529         brlz,a,pn %g1, 7f       /* Check to see if we have 2nd TSB programmed */
3530           or    %g5, %g3, %g5                   /* add 4M bits to TTE */
3531 
3532         mov     ASI_N, %g7      /* user TSBs always accessed by VA */
3533         mov     %g7, %asi
3534         TSB_UPDATE_TL_PN(%g1, %g5, %g2, %g4, %g7, %g3, locked_tsb_l6) /* update TSB */
3535 7:
3536         SET_TTE4M_PN(%g5, %g7)                  /* add TTE4M pagesize to TTE */
3537         ITLB_STUFF(%g5, %g1, %g2, %g3, %g4)
3538         retry
3539 #endif /* sun4v && ITLB_32M_256M_SUPPORT */
3540 
3541 tsb_kernel:
3542         rdpr    %tt, %g5
3543 #ifdef sun4v
3544         cmp     %g7, TTE4M
3545         bge,pn  %icc, 5f
3546 #else
3547         cmp     %g7, TTESZ_VALID | TTE4M        ! no 32M or 256M support
3548         be,pn   %icc, 5f
3549 #endif /* sun4v */
3550           nop
3551         ldn     [%g6 + TSBMISS_TSBPTR], %g1     ! g1 = 8K TSB ptr
3552         ba,pt   %xcc, 6f
3553           nop
3554 5:
3555         ldn     [%g6 + TSBMISS_TSBPTR4M], %g1   ! g1 = 4M TSB ptr
3556         brlz,pn %g1, 3f         /* skip programming if 4M TSB ptr is -1 */
3557           nop
3558 6:
3559 #ifndef sun4v
3560 tsb_kernel_patch_asi:
3561         or      %g0, RUNTIME_PATCH, %g6
3562         mov     %g6, %asi       ! XXX avoid writing to %asi !!
3563 #endif
3564         TSB_UPDATE_TL(%g1, %g3, %g2, %g4, %g7, %g6, locked_tsb_l7)
3565 3:
3566 #ifdef sun4v
3567         cmp     %g5, T_INSTR_MMU_MISS
3568         be,a,pn %icc, 1f
3569           mov   %g3, %g5                        ! trapstat wants TTE in %g5
3570 #endif /* sun4v */
3571         cmp     %g5, FAST_IMMU_MISS_TT
3572         be,pn   %icc, 1f
3573           mov   %g3, %g5                        ! trapstat wants TTE in %g5
3574         DTLB_STUFF(%g5, %g1, %g2, %g3, %g4)
3575         ! trapstat wants TTE in %g5
3576         retry
3577 1:
3578         ITLB_STUFF(%g5, %g1, %g2, %g3, %g4)
3579         ! trapstat wants TTE in %g5
3580         retry
3581 
3582 tsb_ism:
3583         /*
3584          * This is an ISM [i|d]tlb miss.  We optimize for largest
3585          * page size down to smallest.
3586          *
3587          * g2 = vaddr + ctx(or ctxtype (sun4v)) aka (pseudo-)tag access
3588          *      register
3589          * g3 = ismmap->ism_seg
3590          * g4 = physical address of ismmap->ism_sfmmu
3591          * g6 = tsbmiss area
3592          */
3593         ldna    [%g4]ASI_MEM, %g7               /* g7 = ism hatid */
3594         brz,a,pn %g7, ptl1_panic                /* if zero jmp ahead */
3595           mov   PTL1_BAD_ISM, %g1
3596                                                 /* g5 = pa of imap_vb_shift */
3597         sub     %g4, (IMAP_ISMHAT - IMAP_VB_SHIFT), %g5
3598         lduba   [%g5]ASI_MEM, %g4               /* g4 = imap_vb_shift */
3599         srlx    %g3, %g4, %g3                   /* clr size field */
3600         set     TAGACC_CTX_MASK, %g1            /* mask off ctx number */
3601         sllx    %g3, %g4, %g3                   /* g3 = ism vbase */
3602         and     %g2, %g1, %g4                   /* g4 = ctx number */
3603         andn    %g2, %g1, %g1                   /* g1 = tlb miss vaddr */
3604         sub     %g1, %g3, %g2                   /* g2 = offset in ISM seg */
3605         or      %g2, %g4, %g2                   /* g2 = (pseudo-)tagacc */
3606         sub     %g5, (IMAP_VB_SHIFT - IMAP_HATFLAGS), %g5
3607         lduha   [%g5]ASI_MEM, %g4               /* g5 = pa of imap_hatflags */
3608 #if defined(sun4v) || defined(UTSB_PHYS)
3609         and     %g4, HAT_CTX1_FLAG, %g5         /* g5 = imap_hatflags */
3610         brz,pt %g5, tsb_chk4M_ism
3611           nop
3612         ldub    [%g6 + TSBMISS_URTTEFLAGS], %g5
3613         or      %g5, HAT_CHKCTX1_FLAG, %g5
3614         stub    %g5, [%g6 + TSBMISS_URTTEFLAGS]
3615         rdpr    %tt, %g5
3616         SAVE_CTX1(%g5, %g3, %g1, tsb_shctxl)
3617 #endif /* defined(sun4v) || defined(UTSB_PHYS) */
3618 
3619         /*
3620          * ISM pages are always locked down.
3621          * If we can't find the tte then pagefault
3622          * and let the spt segment driver resolve it.
3623          *
3624          * g2 = tagacc w/ISM vaddr (offset in ISM seg)
3625          * g4 = imap_hatflags
3626          * g6 = tsb miss area
3627          * g7 = ISM hatid
3628          */
3629 
3630 tsb_chk4M_ism:
3631         and     %g4, HAT_4M_FLAG, %g5           /* g4 = imap_hatflags */
3632         brnz,pt %g5, tsb_ism_4M                 /* branch if 4M pages */
3633           nop
3634 
3635 tsb_ism_32M:
3636         and     %g4, HAT_32M_FLAG, %g5          /* check default 32M next */
3637         brz,pn  %g5, tsb_ism_256M
3638           nop
3639 
3640         /*
3641          * 32M hash.
3642          */
3643 
3644         GET_TTE(%g2, %g7, %g3, %g4, %g6, %g1, MMU_PAGESHIFT32M,
3645             TTE32M, %g5, tsb_ism_l32M, tsb_ism_32M_found, sfmmu_suspend_tl,
3646             tsb_ism_4M)
3647         /* NOT REACHED */
3648 
3649 tsb_ism_32M_found:
3650         brlz,a,pt %g3, tsb_validtte
3651           rdpr  %tt, %g7
3652         ba,pt   %xcc, tsb_ism_4M
3653           nop
3654 
3655 tsb_ism_256M:
3656         and     %g4, HAT_256M_FLAG, %g5         /* 256M is last resort */
3657         brz,a,pn %g5, ptl1_panic
3658           mov   PTL1_BAD_ISM, %g1
3659 
3660         /*
3661          * 256M hash.
3662          */
3663         GET_TTE(%g2, %g7, %g3, %g4, %g6, %g1, MMU_PAGESHIFT256M,
3664             TTE256M, %g5, tsb_ism_l256M, tsb_ism_256M_found, sfmmu_suspend_tl,
3665             tsb_ism_4M)
3666 
3667 tsb_ism_256M_found:
3668         brlz,a,pt %g3, tsb_validtte
3669           rdpr  %tt, %g7
3670 
3671 tsb_ism_4M:
3672         /*
3673          * 4M hash.
3674          */
3675         GET_TTE(%g2, %g7, %g3, %g4, %g6, %g1, MMU_PAGESHIFT4M,
3676             TTE4M, %g5, tsb_ism_l4M, tsb_ism_4M_found, sfmmu_suspend_tl,
3677             tsb_ism_8K)
3678         /* NOT REACHED */
3679 
3680 tsb_ism_4M_found:
3681         brlz,a,pt %g3, tsb_validtte
3682           rdpr  %tt, %g7
3683 
3684 tsb_ism_8K:
3685         /*
3686          * 8K and 64K hash.
3687          */
3688 
3689         GET_TTE(%g2, %g7, %g3, %g4, %g6, %g1, MMU_PAGESHIFT64K,
3690             TTE64K, %g5, tsb_ism_l8K, tsb_ism_8K_found, sfmmu_suspend_tl,
3691             tsb_pagefault)
3692         /* NOT REACHED */
3693 
3694 tsb_ism_8K_found:
3695         brlz,a,pt %g3, tsb_validtte
3696           rdpr  %tt, %g7
3697 
3698 tsb_pagefault:
3699         rdpr    %tt, %g7
3700         cmp     %g7, FAST_PROT_TT
3701         be,a,pn %icc, tsb_protfault
3702           wrpr  %g0, FAST_DMMU_MISS_TT, %tt
3703 
3704 tsb_protfault:
3705         /*
3706          * we get here if we couldn't find a valid tte in the hash.
3707          *
3708          * If user and we are at tl>1 we go to window handling code.
3709          *
3710          * If kernel and the fault is on the same page as our stack
3711          * pointer, then we know the stack is bad and the trap handler
3712          * will fail, so we call ptl1_panic with PTL1_BAD_STACK.
3713          *
3714          * If this is a kernel trap and tl>1, panic.
3715          *
3716          * Otherwise we call pagefault.
3717          */
3718         cmp     %g7, FAST_IMMU_MISS_TT
3719 #ifdef sun4v
3720         MMU_FAULT_STATUS_AREA(%g4)
3721         ldx     [%g4 + MMFSA_I_CTX], %g5
3722         ldx     [%g4 + MMFSA_D_CTX], %g4
3723         move    %icc, %g5, %g4
3724         cmp     %g7, T_INSTR_MMU_MISS
3725         move    %icc, %g5, %g4
3726 #else
3727         mov     MMU_TAG_ACCESS, %g4
3728         ldxa    [%g4]ASI_DMMU, %g2
3729         ldxa    [%g4]ASI_IMMU, %g5
3730         move    %icc, %g5, %g2
3731         cmp     %g7, T_INSTR_MMU_MISS
3732         move    %icc, %g5, %g2
3733         sllx    %g2, TAGACC_CTX_LSHIFT, %g4
3734 #endif /* sun4v */
3735         brnz,pn %g4, 3f                         /* skip if not kernel */
3736           rdpr  %tl, %g5
3737 
3738         add     %sp, STACK_BIAS, %g3
3739         srlx    %g3, MMU_PAGESHIFT, %g3
3740         srlx    %g2, MMU_PAGESHIFT, %g4
3741         cmp     %g3, %g4
3742         be,a,pn %icc, ptl1_panic                /* panic if bad %sp */
3743           mov   PTL1_BAD_STACK, %g1
3744 
3745         cmp     %g5, 1
3746         ble,pt  %icc, 2f
3747           nop
3748         TSTAT_CHECK_TL1(2f, %g1, %g2)
3749         rdpr    %tt, %g2
3750         cmp     %g2, FAST_PROT_TT
3751         mov     PTL1_BAD_KPROT_FAULT, %g1
3752         movne   %icc, PTL1_BAD_KMISS, %g1
3753         ba,pt   %icc, ptl1_panic
3754           nop
3755 
3756 2:
3757         /*
3758          * We are taking a pagefault in the kernel on a kernel address.  If
3759          * CPU_DTRACE_NOFAULT is set in the cpuc_dtrace_flags, we don't actually
3760          * want to call sfmmu_pagefault -- we will instead note that a fault
3761          * has occurred by setting CPU_DTRACE_BADADDR and issue a "done"
3762          * (instead of a "retry").  This will step over the faulting
3763          * instruction.
3764          */
3765         CPU_INDEX(%g1, %g2)
3766         set     cpu_core, %g2
3767         sllx    %g1, CPU_CORE_SHIFT, %g1
3768         add     %g1, %g2, %g1
3769         lduh    [%g1 + CPUC_DTRACE_FLAGS], %g2
3770         andcc   %g2, CPU_DTRACE_NOFAULT, %g0
3771         bz      sfmmu_pagefault
3772         or      %g2, CPU_DTRACE_BADADDR, %g2
3773         stuh    %g2, [%g1 + CPUC_DTRACE_FLAGS]
3774         GET_MMU_D_ADDR(%g3, %g4)
3775         stx     %g3, [%g1 + CPUC_DTRACE_ILLVAL]
3776         done
3777 
3778 3:
3779         cmp     %g5, 1
3780         ble,pt  %icc, 4f
3781           nop
3782         TSTAT_CHECK_TL1(4f, %g1, %g2)
3783         ba,pt   %icc, sfmmu_window_trap
3784           nop
3785 
3786 4:
3787         /*
3788          * We are taking a pagefault on a non-kernel address.  If we are in
3789          * the kernel (e.g., due to a copyin()), we will check cpuc_dtrace_flags
3790          * and (if CPU_DTRACE_NOFAULT is set) will proceed as outlined above.
3791          */
3792         CPU_INDEX(%g1, %g2)
3793         set     cpu_core, %g2
3794         sllx    %g1, CPU_CORE_SHIFT, %g1
3795         add     %g1, %g2, %g1
3796         lduh    [%g1 + CPUC_DTRACE_FLAGS], %g2
3797         andcc   %g2, CPU_DTRACE_NOFAULT, %g0
3798         bz      sfmmu_mmu_trap
3799         or      %g2, CPU_DTRACE_BADADDR, %g2
3800         stuh    %g2, [%g1 + CPUC_DTRACE_FLAGS]
3801         GET_MMU_D_ADDR(%g3, %g4)
3802         stx     %g3, [%g1 + CPUC_DTRACE_ILLVAL]
3803 
3804         /*
3805          * Be sure that we're actually taking this miss from the kernel --
3806          * otherwise we have managed to return to user-level with
3807          * CPU_DTRACE_NOFAULT set in cpuc_dtrace_flags.
3808          */
3809         rdpr    %tstate, %g2
3810         btst    TSTATE_PRIV, %g2
3811         bz,a    ptl1_panic
3812           mov   PTL1_BAD_DTRACE_FLAGS, %g1
3813         done
3814 
3815         ALTENTRY(tsb_tl0_noctxt)
3816         /*
3817          * If we have no context, check to see if CPU_DTRACE_NOFAULT is set;
3818          * if it is, indicated that we have faulted and issue a done.
3819          */
3820         CPU_INDEX(%g5, %g6)
3821         set     cpu_core, %g6
3822         sllx    %g5, CPU_CORE_SHIFT, %g5
3823         add     %g5, %g6, %g5
3824         lduh    [%g5 + CPUC_DTRACE_FLAGS], %g6
3825         andcc   %g6, CPU_DTRACE_NOFAULT, %g0
3826         bz      1f
3827         or      %g6, CPU_DTRACE_BADADDR, %g6
3828         stuh    %g6, [%g5 + CPUC_DTRACE_FLAGS]
3829         GET_MMU_D_ADDR(%g3, %g4)
3830         stx     %g3, [%g5 + CPUC_DTRACE_ILLVAL]
3831 
3832         /*
3833          * Be sure that we're actually taking this miss from the kernel --
3834          * otherwise we have managed to return to user-level with
3835          * CPU_DTRACE_NOFAULT set in cpuc_dtrace_flags.
3836          */
3837         rdpr    %tstate, %g5
3838         btst    TSTATE_PRIV, %g5
3839         bz,a    ptl1_panic
3840           mov   PTL1_BAD_DTRACE_FLAGS, %g1
3841         TSTAT_CHECK_TL1(2f, %g1, %g2);
3842 2:
3843         done
3844 
3845 1:
3846         rdpr    %tt, %g5
3847         cmp     %g5, FAST_IMMU_MISS_TT
3848 #ifdef sun4v
3849         MMU_FAULT_STATUS_AREA(%g2)
3850         be,a,pt %icc, 2f
3851           ldx   [%g2 + MMFSA_I_CTX], %g3
3852         cmp     %g5, T_INSTR_MMU_MISS
3853         be,a,pt %icc, 2f
3854           ldx   [%g2 + MMFSA_I_CTX], %g3
3855         ldx     [%g2 + MMFSA_D_CTX], %g3
3856 2:
3857 #else
3858         mov     MMU_TAG_ACCESS, %g2
3859         be,a,pt %icc, 2f
3860           ldxa  [%g2]ASI_IMMU, %g3
3861         ldxa    [%g2]ASI_DMMU, %g3
3862 2:      sllx    %g3, TAGACC_CTX_LSHIFT, %g3
3863 #endif /* sun4v */
3864         brz,a,pn %g3, ptl1_panic                ! panic if called for kernel
3865           mov   PTL1_BAD_CTX_STEAL, %g1         ! since kernel ctx was stolen
3866         rdpr    %tl, %g5
3867         cmp     %g5, 1
3868         ble,pt  %icc, sfmmu_mmu_trap
3869           nop
3870         TSTAT_CHECK_TL1(sfmmu_mmu_trap, %g1, %g2)
3871         ba,pt   %icc, sfmmu_window_trap
3872           nop
3873         SET_SIZE(sfmmu_tsb_miss)
3874 #endif  /* lint */
3875 
3876 #if defined (lint)
3877 /*
3878  * This routine will look for a user or kernel vaddr in the hash
3879  * structure.  It returns a valid pfn or PFN_INVALID.  It doesn't
3880  * grab any locks.  It should only be used by other sfmmu routines.
3881  */
3882 /* ARGSUSED */
3883 pfn_t
3884 sfmmu_vatopfn(caddr_t vaddr, sfmmu_t *sfmmup, tte_t *ttep)
3885 {
3886         return(0);
3887 }
3888 
3889 /* ARGSUSED */
3890 pfn_t
3891 sfmmu_kvaszc2pfn(caddr_t vaddr, int hashno)
3892 {
3893         return(0);
3894 }
3895 
3896 #else /* lint */
3897 
3898         ENTRY_NP(sfmmu_vatopfn)
3899         /*
3900          * disable interrupts
3901          */
3902         rdpr    %pstate, %o3
3903 #ifdef DEBUG
3904         PANIC_IF_INTR_DISABLED_PSTR(%o3, sfmmu_di_l5, %g1)
3905 #endif
3906         /*
3907          * disable interrupts to protect the TSBMISS area
3908          */
3909         andn    %o3, PSTATE_IE, %o5
3910         wrpr    %o5, 0, %pstate
3911 
3912         /*
3913          * o0 = vaddr
3914          * o1 = sfmmup
3915          * o2 = ttep
3916          */
3917         CPU_TSBMISS_AREA(%g1, %o5)
3918         ldn     [%g1 + TSBMISS_KHATID], %o4
3919         cmp     %o4, %o1
3920         bne,pn  %ncc, vatopfn_nokernel
3921           mov   TTE64K, %g5                     /* g5 = rehash # */
3922         mov %g1,%o5                             /* o5 = tsbmiss_area */
3923         /*
3924          * o0 = vaddr
3925          * o1 & o4 = hatid
3926          * o2 = ttep
3927          * o5 = tsbmiss area
3928          */
3929         mov     HBLK_RANGE_SHIFT, %g6
3930 1:
3931 
3932         /*
3933          * o0 = vaddr
3934          * o1 = sfmmup
3935          * o2 = ttep
3936          * o3 = old %pstate
3937          * o4 = hatid
3938          * o5 = tsbmiss
3939          * g5 = rehash #
3940          * g6 = hmeshift
3941          *
3942          * The first arg to GET_TTE is actually tagaccess register
3943          * not just vaddr. Since this call is for kernel we need to clear
3944          * any lower vaddr bits that would be interpreted as ctx bits.
3945          */
3946         set     TAGACC_CTX_MASK, %g1
3947         andn    %o0, %g1, %o0
3948         GET_TTE(%o0, %o4, %g1, %g2, %o5, %g4, %g6, %g5, %g3,
3949                 vatopfn_l1, kvtop_hblk_found, tsb_suspend, kvtop_nohblk)
3950 
3951 kvtop_hblk_found:
3952         /*
3953          * o0 = vaddr
3954          * o1 = sfmmup
3955          * o2 = ttep
3956          * g1 = tte
3957          * g2 = tte pa
3958          * g3 = scratch
3959          * o2 = tsbmiss area
3960          * o1 = hat id
3961          */
3962         brgez,a,pn %g1, 6f                      /* if tte invalid goto tl0 */
3963           mov   -1, %o0                         /* output = -1 (PFN_INVALID) */
3964         stx %g1,[%o2]                           /* put tte into *ttep */
3965         TTETOPFN(%g1, %o0, vatopfn_l2, %g2, %g3, %g4)
3966         /*
3967          * o0 = vaddr
3968          * o1 = sfmmup
3969          * o2 = ttep
3970          * g1 = pfn
3971          */
3972         ba,pt   %xcc, 6f
3973           mov   %g1, %o0
3974 
3975 kvtop_nohblk:
3976         /*
3977          * we get here if we couldn't find valid hblk in hash.  We rehash
3978          * if neccesary.
3979          */
3980         ldn     [%o5 + (TSBMISS_SCRATCH + TSB_TAGACC)], %o0
3981 #ifdef sun4v
3982         cmp     %g5, MAX_HASHCNT
3983 #else
3984         cmp     %g5, DEFAULT_MAX_HASHCNT        /* no 32/256M kernel pages */
3985 #endif /* sun4v */
3986         be,a,pn %icc, 6f
3987           mov   -1, %o0                         /* output = -1 (PFN_INVALID) */
3988         mov     %o1, %o4                        /* restore hatid */
3989 #ifdef sun4v
3990         add     %g5, 2, %g5
3991         cmp     %g5, 3
3992         move    %icc, MMU_PAGESHIFT4M, %g6
3993         ba,pt   %icc, 1b
3994         movne   %icc, MMU_PAGESHIFT256M, %g6
3995 #else
3996         inc     %g5
3997         cmp     %g5, 2
3998         move    %icc, MMU_PAGESHIFT512K, %g6
3999         ba,pt   %icc, 1b
4000         movne   %icc, MMU_PAGESHIFT4M, %g6
4001 #endif /* sun4v */
4002 6:
4003         retl
4004           wrpr  %g0, %o3, %pstate               /* re-enable interrupts */
4005 
4006 tsb_suspend:
4007         /*
4008          * o0 = vaddr
4009          * o1 = sfmmup
4010          * o2 = ttep
4011          * g1 = tte
4012          * g2 = tte pa
4013          * g3 = tte va
4014          * o2 = tsbmiss area  use o5 instead of o2 for tsbmiss
4015          */
4016         stx %g1,[%o2]                           /* put tte into *ttep */
4017         brgez,a,pn %g1, 8f                      /* if tte invalid goto 8: */
4018           sub   %g0, 1, %o0                     /* output = PFN_INVALID */
4019         sub     %g0, 2, %o0                     /* output = PFN_SUSPENDED */
4020 8:
4021         retl
4022          wrpr   %g0, %o3, %pstate               /* enable interrupts */
4023 
4024 vatopfn_nokernel:
4025         /*
4026          * This routine does NOT support user addresses
4027          * There is a routine in C that supports this.
4028          * The only reason why we don't have the C routine
4029          * support kernel addresses as well is because
4030          * we do va_to_pa while holding the hashlock.
4031          */
4032         wrpr    %g0, %o3, %pstate               /* re-enable interrupts */
4033         save    %sp, -SA(MINFRAME), %sp
4034         sethi   %hi(sfmmu_panic3), %o0
4035         call    panic
4036          or     %o0, %lo(sfmmu_panic3), %o0
4037 
4038         SET_SIZE(sfmmu_vatopfn)
4039 
4040         /*
4041          * %o0 = vaddr
4042          * %o1 = hashno (aka szc)
4043          *
4044          *
4045          * This routine is similar to sfmmu_vatopfn() but will only look for
4046          * a kernel vaddr in the hash structure for the specified rehash value.
4047          * It's just an optimization for the case when pagesize for a given
4048          * va range is already known (e.g. large page heap) and we don't want
4049          * to start the search with rehash value 1 as sfmmu_vatopfn() does.
4050          *
4051          * Returns valid pfn or PFN_INVALID if
4052          * tte for specified rehash # is not found, invalid or suspended.
4053          */
4054         ENTRY_NP(sfmmu_kvaszc2pfn)
4055         /*
4056          * disable interrupts
4057          */
4058         rdpr    %pstate, %o3
4059 #ifdef DEBUG
4060         PANIC_IF_INTR_DISABLED_PSTR(%o3, sfmmu_di_l6, %g1)
4061 #endif
4062         /*
4063          * disable interrupts to protect the TSBMISS area
4064          */
4065         andn    %o3, PSTATE_IE, %o5
4066         wrpr    %o5, 0, %pstate
4067 
4068         CPU_TSBMISS_AREA(%g1, %o5)
4069         ldn     [%g1 + TSBMISS_KHATID], %o4
4070         sll     %o1, 1, %g6
4071         add     %g6, %o1, %g6
4072         add     %g6, MMU_PAGESHIFT, %g6
4073         /*
4074          * %o0 = vaddr
4075          * %o1 = hashno
4076          * %o3 = old %pstate
4077          * %o4 = ksfmmup
4078          * %g1 = tsbmiss area
4079          * %g6 = hmeshift
4080          */
4081 
4082         /*
4083          * The first arg to GET_TTE is actually tagaccess register
4084          * not just vaddr. Since this call is for kernel we need to clear
4085          * any lower vaddr bits that would be interpreted as ctx bits.
4086          */
4087         srlx    %o0, MMU_PAGESHIFT, %o0
4088         sllx    %o0, MMU_PAGESHIFT, %o0
4089         GET_TTE(%o0, %o4, %g3, %g4, %g1, %o5, %g6, %o1, %g5,
4090                 kvaszc2pfn_l1, kvaszc2pfn_hblk_found, kvaszc2pfn_nohblk,
4091                 kvaszc2pfn_nohblk)
4092 
4093 kvaszc2pfn_hblk_found:
4094         /*
4095          * %g3 = tte
4096          * %o0 = vaddr
4097          */
4098         brgez,a,pn %g3, 1f                      /* check if tte is invalid */
4099           mov   -1, %o0                         /* output = -1 (PFN_INVALID) */
4100         TTETOPFN(%g3, %o0, kvaszc2pfn_l2, %g2, %g4, %g5)
4101         /*
4102          * g3 = pfn
4103          */
4104         ba,pt   %xcc, 1f
4105           mov   %g3, %o0
4106 
4107 kvaszc2pfn_nohblk:
4108         mov     -1, %o0
4109 
4110 1:
4111         retl
4112           wrpr  %g0, %o3, %pstate               /* re-enable interrupts */
4113 
4114         SET_SIZE(sfmmu_kvaszc2pfn)
4115 
4116 #endif /* lint */
4117 
4118 
4119 
4120 #if !defined(lint)
4121 
4122 /*
4123  * kpm lock used between trap level tsbmiss handler and kpm C level.
4124  */
4125 #define KPMLOCK_ENTER(kpmlckp, tmp1, label1, asi)                       \
4126         mov     0xff, tmp1                                              ;\
4127 label1:                                                                 ;\
4128         casa    [kpmlckp]asi, %g0, tmp1                                 ;\
4129         brnz,pn tmp1, label1                                            ;\
4130         mov     0xff, tmp1                                              ;\
4131         membar  #LoadLoad
4132 
4133 #define KPMLOCK_EXIT(kpmlckp, asi)                                      \
4134         membar  #LoadStore|#StoreStore                                  ;\
4135         sta     %g0, [kpmlckp]asi
4136 
4137 /*
4138  * Lookup a memseg for a given pfn and if found, return the physical
4139  * address of the corresponding struct memseg in mseg, otherwise
4140  * return MSEG_NULLPTR_PA. The kpmtsbm pointer must be provided in
4141  * tsbmp, %asi is assumed to be ASI_MEM.
4142  * This lookup is done by strictly traversing only the physical memseg
4143  * linkage. The more generic approach, to check the virtual linkage
4144  * before using the physical (used e.g. with hmehash buckets), cannot
4145  * be used here. Memory DR operations can run in parallel to this
4146  * lookup w/o any locks and updates of the physical and virtual linkage
4147  * cannot be done atomically wrt. to each other. Because physical
4148  * address zero can be valid physical address, MSEG_NULLPTR_PA acts
4149  * as "physical NULL" pointer.
4150  */
4151 #define PAGE_NUM2MEMSEG_NOLOCK_PA(pfn, mseg, tsbmp, tmp1, tmp2, tmp3, label) \
4152         sethi   %hi(mhash_per_slot), tmp3 /* no tsbmp use due to DR */  ;\
4153         ldx     [tmp3 + %lo(mhash_per_slot)], mseg                      ;\
4154         udivx   pfn, mseg, mseg                                         ;\
4155         ldx     [tsbmp + KPMTSBM_MSEGPHASHPA], tmp1                     ;\
4156         and     mseg, SFMMU_N_MEM_SLOTS - 1, mseg                       ;\
4157         sllx    mseg, SFMMU_MEM_HASH_ENTRY_SHIFT, mseg                  ;\
4158         add     tmp1, mseg, tmp1                                        ;\
4159         ldxa    [tmp1]%asi, mseg                                        ;\
4160         cmp     mseg, MSEG_NULLPTR_PA                                   ;\
4161         be,pn   %xcc, label/**/1                /* if not found */      ;\
4162           nop                                                           ;\
4163         ldxa    [mseg + MEMSEG_PAGES_BASE]%asi, tmp1                    ;\
4164         cmp     pfn, tmp1                       /* pfn - pages_base */  ;\
4165         blu,pn  %xcc, label/**/1                                        ;\
4166           ldxa  [mseg + MEMSEG_PAGES_END]%asi, tmp2                     ;\
4167         cmp     pfn, tmp2                       /* pfn - pages_end */   ;\
4168         bgeu,pn %xcc, label/**/1                                        ;\
4169           sub   pfn, tmp1, tmp1                 /* pfn - pages_base */  ;\
4170         mulx    tmp1, PAGE_SIZE, tmp1                                   ;\
4171         ldxa    [mseg + MEMSEG_PAGESPA]%asi, tmp2       /* pages */     ;\
4172         add     tmp2, tmp1, tmp1                        /* pp */        ;\
4173         lduwa   [tmp1 + PAGE_PAGENUM]%asi, tmp2                         ;\
4174         cmp     tmp2, pfn                                               ;\
4175         be,pt   %xcc, label/**/_ok                      /* found */     ;\
4176 label/**/1:                                                             ;\
4177         /* brute force lookup */                                        ;\
4178         sethi   %hi(memsegspa), tmp3 /* no tsbmp use due to DR */       ;\
4179         ldx     [tmp3 + %lo(memsegspa)], mseg                           ;\
4180 label/**/2:                                                             ;\
4181         cmp     mseg, MSEG_NULLPTR_PA                                   ;\
4182         be,pn   %xcc, label/**/_ok              /* if not found */      ;\
4183           nop                                                           ;\
4184         ldxa    [mseg + MEMSEG_PAGES_BASE]%asi, tmp1                    ;\
4185         cmp     pfn, tmp1                       /* pfn - pages_base */  ;\
4186         blu,a,pt %xcc, label/**/2                                       ;\
4187           ldxa  [mseg + MEMSEG_NEXTPA]%asi, mseg                        ;\
4188         ldxa    [mseg + MEMSEG_PAGES_END]%asi, tmp2                     ;\
4189         cmp     pfn, tmp2                       /* pfn - pages_end */   ;\
4190         bgeu,a,pt %xcc, label/**/2                                      ;\
4191           ldxa  [mseg + MEMSEG_NEXTPA]%asi, mseg                        ;\
4192 label/**/_ok:
4193 
4194         /*
4195          * kpm tsb miss handler large pages
4196          * g1 = 8K kpm TSB entry pointer
4197          * g2 = tag access register
4198          * g3 = 4M kpm TSB entry pointer
4199          */
4200         ALTENTRY(sfmmu_kpm_dtsb_miss)
4201         TT_TRACE(trace_tsbmiss)
4202 
4203         CPU_INDEX(%g7, %g6)
4204         sethi   %hi(kpmtsbm_area), %g6
4205         sllx    %g7, KPMTSBM_SHIFT, %g7
4206         or      %g6, %lo(kpmtsbm_area), %g6
4207         add     %g6, %g7, %g6                   /* g6 = kpmtsbm ptr */
4208 
4209         /* check enable flag */
4210         ldub    [%g6 + KPMTSBM_FLAGS], %g4
4211         and     %g4, KPMTSBM_ENABLE_FLAG, %g5
4212         brz,pn  %g5, sfmmu_tsb_miss             /* if kpm not enabled */
4213           nop
4214 
4215         /* VA range check */
4216         ldx     [%g6 + KPMTSBM_VBASE], %g7
4217         cmp     %g2, %g7
4218         blu,pn  %xcc, sfmmu_tsb_miss
4219           ldx   [%g6 + KPMTSBM_VEND], %g5
4220         cmp     %g2, %g5
4221         bgeu,pn %xcc, sfmmu_tsb_miss
4222           stx   %g3, [%g6 + KPMTSBM_TSBPTR]
4223 
4224         /*
4225          * check TL tsbmiss handling flag
4226          * bump tsbmiss counter
4227          */
4228         lduw    [%g6 + KPMTSBM_TSBMISS], %g5
4229 #ifdef  DEBUG
4230         and     %g4, KPMTSBM_TLTSBM_FLAG, %g3
4231         inc     %g5
4232         brz,pn  %g3, sfmmu_kpm_exception
4233           st    %g5, [%g6 + KPMTSBM_TSBMISS]
4234 #else
4235         inc     %g5
4236         st      %g5, [%g6 + KPMTSBM_TSBMISS]
4237 #endif
4238         /*
4239          * At this point:
4240          *  g1 = 8K kpm TSB pointer (not used)
4241          *  g2 = tag access register
4242          *  g3 = clobbered
4243          *  g6 = per-CPU kpm tsbmiss area
4244          *  g7 = kpm_vbase
4245          */
4246 
4247         /* vaddr2pfn */
4248         ldub    [%g6 + KPMTSBM_SZSHIFT], %g3
4249         sub     %g2, %g7, %g4                   /* paddr = vaddr-kpm_vbase */
4250         srax    %g4, %g3, %g2                   /* which alias range (r) */
4251         brnz,pn %g2, sfmmu_kpm_exception        /* if (r != 0) goto C handler */
4252           srlx  %g4, MMU_PAGESHIFT, %g2         /* %g2 = pfn */
4253 
4254         /*
4255          * Setup %asi
4256          * mseg_pa = page_numtomemseg_nolock(pfn)
4257          * if (mseg_pa == NULL) sfmmu_kpm_exception
4258          * g2=pfn
4259          */
4260         mov     ASI_MEM, %asi
4261         PAGE_NUM2MEMSEG_NOLOCK_PA(%g2, %g3, %g6, %g4, %g5, %g7, kpmtsbmp2m)
4262         cmp     %g3, MSEG_NULLPTR_PA
4263         be,pn   %xcc, sfmmu_kpm_exception       /* if mseg not found */
4264           nop
4265 
4266         /*
4267          * inx = ptokpmp((kpmptop((ptopkpmp(pfn))) - mseg_pa->kpm_pbase));
4268          * g2=pfn g3=mseg_pa
4269          */
4270         ldub    [%g6 + KPMTSBM_KPMP2PSHFT], %g5
4271         ldxa    [%g3 + MEMSEG_KPM_PBASE]%asi, %g7
4272         srlx    %g2, %g5, %g4
4273         sllx    %g4, %g5, %g4
4274         sub     %g4, %g7, %g4
4275         srlx    %g4, %g5, %g4
4276 
4277         /*
4278          * Validate inx value
4279          * g2=pfn g3=mseg_pa g4=inx
4280          */
4281 #ifdef  DEBUG
4282         ldxa    [%g3 + MEMSEG_KPM_NKPMPGS]%asi, %g5
4283         cmp     %g4, %g5                        /* inx - nkpmpgs */
4284         bgeu,pn %xcc, sfmmu_kpm_exception       /* if out of range */
4285           ld    [%g6 + KPMTSBM_KPMPTABLESZ], %g7
4286 #else
4287         ld      [%g6 + KPMTSBM_KPMPTABLESZ], %g7
4288 #endif
4289         /*
4290          * kp = &mseg_pa->kpm_pages[inx]
4291          */
4292         sllx    %g4, KPMPAGE_SHIFT, %g4         /* kpm_pages offset */
4293         ldxa    [%g3 + MEMSEG_KPM_PAGES]%asi, %g5 /* kpm_pages */
4294         add     %g5, %g4, %g5                   /* kp */
4295 
4296         /*
4297          * KPMP_HASH(kp)
4298          * g2=pfn g3=mseg_pa g4=offset g5=kp g7=kpmp_table_sz
4299          */
4300         ldub    [%g6 + KPMTSBM_KPMPSHIFT], %g1  /* kpmp_shift */
4301         sub     %g7, 1, %g7                     /* mask */
4302         srlx    %g5, %g1, %g1                   /* x = ksp >> kpmp_shift */
4303         add     %g5, %g1, %g5                   /* y = ksp + x */
4304         and     %g5, %g7, %g5                   /* hashinx = y & mask */
4305 
4306         /*
4307          * Calculate physical kpm_page pointer
4308          * g2=pfn g3=mseg_pa g4=offset g5=hashinx
4309          */
4310         ldxa    [%g3 + MEMSEG_KPM_PAGESPA]%asi, %g1 /* kpm_pagespa */
4311         add     %g1, %g4, %g1                   /* kp_pa */
4312 
4313         /*
4314          * Calculate physical hash lock address
4315          * g1=kp_refcntc_pa g2=pfn g5=hashinx
4316          */
4317         ldx     [%g6 + KPMTSBM_KPMPTABLEPA], %g4 /* kpmp_tablepa */
4318         sllx    %g5, KPMHLK_SHIFT, %g5
4319         add     %g4, %g5, %g3
4320         add     %g3, KPMHLK_LOCK, %g3           /* hlck_pa */
4321 
4322         /*
4323          * Assemble tte
4324          * g1=kp_pa g2=pfn g3=hlck_pa
4325          */
4326 #ifdef sun4v
4327         sethi   %hi(TTE_VALID_INT), %g5         /* upper part */
4328         sllx    %g5, 32, %g5
4329         mov     (TTE_CP_INT|TTE_CV_INT|TTE_PRIV_INT|TTE_HWWR_INT), %g4
4330         or      %g4, TTE4M, %g4
4331         or      %g5, %g4, %g5
4332 #else
4333         sethi   %hi(TTE_VALID_INT), %g4
4334         mov     TTE4M, %g5
4335         sllx    %g5, TTE_SZ_SHFT_INT, %g5
4336         or      %g5, %g4, %g5                   /* upper part */
4337         sllx    %g5, 32, %g5
4338         mov     (TTE_CP_INT|TTE_CV_INT|TTE_PRIV_INT|TTE_HWWR_INT), %g4
4339         or      %g5, %g4, %g5
4340 #endif
4341         sllx    %g2, MMU_PAGESHIFT, %g4
4342         or      %g5, %g4, %g5                   /* tte */
4343         ldx     [%g6 + KPMTSBM_TSBPTR], %g4
4344         GET_MMU_D_TTARGET(%g2, %g7)             /* %g2 = ttarget */
4345 
4346         /*
4347          * tsb dropin
4348          * g1=kp_pa g2=ttarget g3=hlck_pa g4=kpmtsbp4m g5=tte g6=kpmtsbm_area
4349          */
4350 
4351         /* KPMLOCK_ENTER(kpmlckp, tmp1, label1, asi) */
4352         KPMLOCK_ENTER(%g3, %g7, kpmtsbmhdlr1, ASI_MEM)
4353 
4354         /* use C-handler if there's no go for dropin */
4355         ldsha   [%g1 + KPMPAGE_REFCNTC]%asi, %g7 /* kp_refcntc */
4356         cmp     %g7, -1
4357         bne,pn  %xcc, 5f        /* use C-handler if there's no go for dropin */
4358           nop
4359 
4360 #ifdef  DEBUG
4361         /* double check refcnt */
4362         ldsha   [%g1 + KPMPAGE_REFCNT]%asi, %g7
4363         brz,pn  %g7, 5f                 /* let C-handler deal with this */
4364           nop
4365 #endif
4366 
4367 #ifndef sun4v
4368         ldub    [%g6 + KPMTSBM_FLAGS], %g7
4369         mov     ASI_N, %g1
4370         andcc   %g7, KPMTSBM_TSBPHYS_FLAG, %g0
4371         movnz   %icc, ASI_MEM, %g1
4372         mov     %g1, %asi
4373 #endif
4374 
4375         /*
4376          * TSB_LOCK_ENTRY(tsbp, tmp1, tmp2, label) (needs %asi set)
4377          * If we fail to lock the TSB entry then just load the tte into the
4378          * TLB.
4379          */
4380         TSB_LOCK_ENTRY(%g4, %g1, %g7, locked_tsb_l1)
4381 
4382         /* TSB_INSERT_UNLOCK_ENTRY(tsbp, tte, tagtarget, tmp) */
4383         TSB_INSERT_UNLOCK_ENTRY(%g4, %g5, %g2, %g7)
4384 locked_tsb_l1:
4385         DTLB_STUFF(%g5, %g1, %g2, %g4, %g6)
4386 
4387         /* KPMLOCK_EXIT(kpmlckp, asi) */
4388         KPMLOCK_EXIT(%g3, ASI_MEM)
4389 
4390         /*
4391          * If trapstat is running, we need to shift the %tpc and %tnpc to
4392          * point to trapstat's TSB miss return code (note that trapstat
4393          * itself will patch the correct offset to add).
4394          * Note: TTE is expected in %g5 (allows per pagesize reporting).
4395          */
4396         rdpr    %tl, %g7
4397         cmp     %g7, 1
4398         ble     %icc, 0f
4399         sethi   %hi(KERNELBASE), %g6
4400         rdpr    %tpc, %g7
4401         or      %g6, %lo(KERNELBASE), %g6
4402         cmp     %g7, %g6
4403         bgeu    %xcc, 0f
4404         ALTENTRY(tsbmiss_trapstat_patch_point_kpm)
4405         add     %g7, RUNTIME_PATCH, %g7 /* must match TSTAT_TSBMISS_INSTR */
4406         wrpr    %g7, %tpc
4407         add     %g7, 4, %g7
4408         wrpr    %g7, %tnpc
4409 0:
4410         retry
4411 5:
4412         /* g3=hlck_pa */
4413         KPMLOCK_EXIT(%g3, ASI_MEM)
4414         ba,pt   %icc, sfmmu_kpm_exception
4415           nop
4416         SET_SIZE(sfmmu_kpm_dtsb_miss)
4417 
4418         /*
4419          * kpm tsbmiss handler for smallpages
4420          * g1 = 8K kpm TSB pointer
4421          * g2 = tag access register
4422          * g3 = 4M kpm TSB pointer
4423          */
4424         ALTENTRY(sfmmu_kpm_dtsb_miss_small)
4425         TT_TRACE(trace_tsbmiss)
4426         CPU_INDEX(%g7, %g6)
4427         sethi   %hi(kpmtsbm_area), %g6
4428         sllx    %g7, KPMTSBM_SHIFT, %g7
4429         or      %g6, %lo(kpmtsbm_area), %g6
4430         add     %g6, %g7, %g6                   /* g6 = kpmtsbm ptr */
4431 
4432         /* check enable flag */
4433         ldub    [%g6 + KPMTSBM_FLAGS], %g4
4434         and     %g4, KPMTSBM_ENABLE_FLAG, %g5
4435         brz,pn  %g5, sfmmu_tsb_miss             /* if kpm not enabled */
4436           nop
4437 
4438         /*
4439          * VA range check
4440          * On fail: goto sfmmu_tsb_miss
4441          */
4442         ldx     [%g6 + KPMTSBM_VBASE], %g7
4443         cmp     %g2, %g7
4444         blu,pn  %xcc, sfmmu_tsb_miss
4445           ldx   [%g6 + KPMTSBM_VEND], %g5
4446         cmp     %g2, %g5
4447         bgeu,pn %xcc, sfmmu_tsb_miss
4448           stx   %g1, [%g6 + KPMTSBM_TSBPTR]     /* save 8K kpm TSB pointer */
4449 
4450         /*
4451          * check TL tsbmiss handling flag
4452          * bump tsbmiss counter
4453          */
4454         lduw    [%g6 + KPMTSBM_TSBMISS], %g5
4455 #ifdef  DEBUG
4456         and     %g4, KPMTSBM_TLTSBM_FLAG, %g1
4457         inc     %g5
4458         brz,pn  %g1, sfmmu_kpm_exception
4459           st    %g5, [%g6 + KPMTSBM_TSBMISS]
4460 #else
4461         inc     %g5
4462         st      %g5, [%g6 + KPMTSBM_TSBMISS]
4463 #endif
4464         /*
4465          * At this point:
4466          *  g1 = clobbered
4467          *  g2 = tag access register
4468          *  g3 = 4M kpm TSB pointer (not used)
4469          *  g6 = per-CPU kpm tsbmiss area
4470          *  g7 = kpm_vbase
4471          */
4472 
4473         /*
4474          * Assembly implementation of SFMMU_KPM_VTOP(vaddr, paddr)
4475          * which is defined in mach_kpm.h. Any changes in that macro
4476          * should also be ported back to this assembly code.
4477          */
4478         ldub    [%g6 + KPMTSBM_SZSHIFT], %g3    /* g3 = kpm_size_shift */
4479         sub     %g2, %g7, %g4                   /* paddr = vaddr-kpm_vbase */
4480         srax    %g4, %g3, %g7                   /* which alias range (r) */
4481         brz,pt  %g7, 2f
4482           sethi   %hi(vac_colors_mask), %g5
4483         ld      [%g5 + %lo(vac_colors_mask)], %g5
4484 
4485         srlx    %g2, MMU_PAGESHIFT, %g1         /* vaddr >> MMU_PAGESHIFT */
4486         and     %g1, %g5, %g1                   /* g1 = v */
4487         sllx    %g7, %g3, %g5                   /* g5 = r << kpm_size_shift */
4488         cmp     %g7, %g1                        /* if (r > v) */
4489         bleu,pn %xcc, 1f
4490           sub   %g4, %g5, %g4                   /* paddr -= r << kpm_size_shift */
4491         sub     %g7, %g1, %g5                   /* g5 = r - v */
4492         sllx    %g5, MMU_PAGESHIFT, %g7         /* (r-v) << MMU_PAGESHIFT */
4493         add     %g4, %g7, %g4                   /* paddr += (r-v)<<MMU_PAGESHIFT */
4494         ba      2f
4495           nop
4496 1:
4497         sllx    %g7, MMU_PAGESHIFT, %g5         /* else */
4498         sub     %g4, %g5, %g4                   /* paddr -= r << MMU_PAGESHIFT */
4499 
4500         /*
4501          * paddr2pfn
4502          *  g1 = vcolor (not used)
4503          *  g2 = tag access register
4504          *  g3 = clobbered
4505          *  g4 = paddr
4506          *  g5 = clobbered
4507          *  g6 = per-CPU kpm tsbmiss area
4508          *  g7 = clobbered
4509          */
4510 2:
4511         srlx    %g4, MMU_PAGESHIFT, %g2         /* g2 = pfn */
4512 
4513         /*
4514          * Setup %asi
4515          * mseg_pa = page_numtomemseg_nolock_pa(pfn)
4516          * if (mseg not found) sfmmu_kpm_exception
4517          * g2=pfn g6=per-CPU kpm tsbmiss area
4518          * g4 g5 g7 for scratch use.
4519          */
4520         mov     ASI_MEM, %asi
4521         PAGE_NUM2MEMSEG_NOLOCK_PA(%g2, %g3, %g6, %g4, %g5, %g7, kpmtsbmsp2m)
4522         cmp     %g3, MSEG_NULLPTR_PA
4523         be,pn   %xcc, sfmmu_kpm_exception       /* if mseg not found */
4524           nop
4525 
4526         /*
4527          * inx = pfn - mseg_pa->kpm_pbase
4528          * g2=pfn  g3=mseg_pa  g6=per-CPU kpm tsbmiss area
4529          */
4530         ldxa    [%g3 + MEMSEG_KPM_PBASE]%asi, %g7
4531         sub     %g2, %g7, %g4
4532 
4533 #ifdef  DEBUG
4534         /*
4535          * Validate inx value
4536          * g2=pfn g3=mseg_pa g4=inx g6=per-CPU tsbmiss area
4537          */
4538         ldxa    [%g3 + MEMSEG_KPM_NKPMPGS]%asi, %g5
4539         cmp     %g4, %g5                        /* inx - nkpmpgs */
4540         bgeu,pn %xcc, sfmmu_kpm_exception       /* if out of range */
4541           ld    [%g6 + KPMTSBM_KPMPTABLESZ], %g7
4542 #else
4543         ld      [%g6 + KPMTSBM_KPMPTABLESZ], %g7
4544 #endif
4545         /* ksp = &mseg_pa->kpm_spages[inx] */
4546         ldxa    [%g3 + MEMSEG_KPM_SPAGES]%asi, %g5
4547         add     %g5, %g4, %g5                   /* ksp */
4548 
4549         /*
4550          * KPMP_SHASH(kp)
4551          * g2=pfn g3=mseg_pa g4=inx g5=ksp
4552          * g6=per-CPU kpm tsbmiss area  g7=kpmp_stable_sz
4553          */
4554         ldub    [%g6 + KPMTSBM_KPMPSHIFT], %g1  /* kpmp_shift */
4555         sub     %g7, 1, %g7                     /* mask */
4556         sllx    %g5, %g1, %g1                   /* x = ksp << kpmp_shift */
4557         add     %g5, %g1, %g5                   /* y = ksp + x */
4558         and     %g5, %g7, %g5                   /* hashinx = y & mask */
4559 
4560         /*
4561          * Calculate physical kpm_spage pointer
4562          * g2=pfn g3=mseg_pa g4=offset g5=hashinx
4563          * g6=per-CPU kpm tsbmiss area
4564          */
4565         ldxa    [%g3 + MEMSEG_KPM_PAGESPA]%asi, %g1 /* kpm_spagespa */
4566         add     %g1, %g4, %g1                   /* ksp_pa */
4567 
4568         /*
4569          * Calculate physical hash lock address.
4570          * Note: Changes in kpm_shlk_t must be reflected here.
4571          * g1=ksp_pa g2=pfn g5=hashinx
4572          * g6=per-CPU kpm tsbmiss area
4573          */
4574         ldx     [%g6 + KPMTSBM_KPMPTABLEPA], %g4 /* kpmp_stablepa */
4575         sllx    %g5, KPMSHLK_SHIFT, %g5
4576         add     %g4, %g5, %g3                   /* hlck_pa */
4577 
4578         /*
4579          * Assemble non-cacheable tte initially
4580          * g1=ksp_pa g2=pfn g3=hlck_pa
4581          * g6=per-CPU kpm tsbmiss area
4582          */
4583         sethi   %hi(TTE_VALID_INT), %g5         /* upper part */
4584         sllx    %g5, 32, %g5
4585         mov     (TTE_CP_INT|TTE_PRIV_INT|TTE_HWWR_INT), %g4
4586         or      %g5, %g4, %g5
4587         sllx    %g2, MMU_PAGESHIFT, %g4
4588         or      %g5, %g4, %g5                   /* tte */
4589         ldx     [%g6 + KPMTSBM_TSBPTR], %g4
4590         GET_MMU_D_TTARGET(%g2, %g7)             /* %g2 = ttarget */
4591 
4592         /*
4593          * tsb dropin
4594          * g1=ksp_pa g2=ttarget g3=hlck_pa g4=ktsbp g5=tte (non-cacheable)
4595          * g6=per-CPU kpm tsbmiss area  g7=scratch register
4596          */
4597 
4598         /* KPMLOCK_ENTER(kpmlckp, tmp1, label1, asi) */
4599         KPMLOCK_ENTER(%g3, %g7, kpmtsbsmlock, ASI_MEM)
4600 
4601         /* use C-handler if there's no go for dropin */
4602         ldsba   [%g1 + KPMSPAGE_MAPPED]%asi, %g7        /* kp_mapped */
4603         andcc   %g7, KPM_MAPPED_GO, %g0                 /* go or no go ? */
4604         bz,pt   %icc, 5f                                /* no go */
4605           nop
4606         and     %g7, KPM_MAPPED_MASK, %g7               /* go */
4607         cmp     %g7, KPM_MAPPEDS                        /* cacheable ? */
4608         be,a,pn %xcc, 3f
4609           or    %g5, TTE_CV_INT, %g5                    /* cacheable */
4610 3:
4611 #ifndef sun4v
4612         ldub    [%g6 + KPMTSBM_FLAGS], %g7
4613         mov     ASI_N, %g1
4614         andcc   %g7, KPMTSBM_TSBPHYS_FLAG, %g0
4615         movnz   %icc, ASI_MEM, %g1
4616         mov     %g1, %asi
4617 #endif
4618 
4619         /*
4620          * TSB_LOCK_ENTRY(tsbp, tmp1, tmp2, label) (needs %asi set)
4621          * If we fail to lock the TSB entry then just load the tte into the
4622          * TLB.
4623          */
4624         TSB_LOCK_ENTRY(%g4, %g1, %g7, locked_tsb_l2)
4625 
4626         /* TSB_INSERT_UNLOCK_ENTRY(tsbp, tte, tagtarget, tmp) */
4627         TSB_INSERT_UNLOCK_ENTRY(%g4, %g5, %g2, %g7)
4628 locked_tsb_l2:
4629         DTLB_STUFF(%g5, %g2, %g4, %g5, %g6)
4630 
4631         /* KPMLOCK_EXIT(kpmlckp, asi) */
4632         KPMLOCK_EXIT(%g3, ASI_MEM)
4633 
4634         /*
4635          * If trapstat is running, we need to shift the %tpc and %tnpc to
4636          * point to trapstat's TSB miss return code (note that trapstat
4637          * itself will patch the correct offset to add).
4638          * Note: TTE is expected in %g5 (allows per pagesize reporting).
4639          */
4640         rdpr    %tl, %g7
4641         cmp     %g7, 1
4642         ble     %icc, 0f
4643         sethi   %hi(KERNELBASE), %g6
4644         rdpr    %tpc, %g7
4645         or      %g6, %lo(KERNELBASE), %g6
4646         cmp     %g7, %g6
4647         bgeu    %xcc, 0f
4648         ALTENTRY(tsbmiss_trapstat_patch_point_kpm_small)
4649         add     %g7, RUNTIME_PATCH, %g7 /* must match TSTAT_TSBMISS_INSTR */
4650         wrpr    %g7, %tpc
4651         add     %g7, 4, %g7
4652         wrpr    %g7, %tnpc
4653 0:
4654         retry
4655 5:
4656         /* g3=hlck_pa */
4657         KPMLOCK_EXIT(%g3, ASI_MEM)
4658         ba,pt   %icc, sfmmu_kpm_exception
4659           nop
4660         SET_SIZE(sfmmu_kpm_dtsb_miss_small)
4661 
4662 #if (1<< KPMTSBM_SHIFT) != KPMTSBM_SIZE
4663 #error - KPMTSBM_SHIFT does not correspond to size of kpmtsbm struct
4664 #endif
4665 
4666 #endif /* lint */
4667 
4668 #ifdef  lint
4669 /*
4670  * Enable/disable tsbmiss handling at trap level for a kpm (large) page.
4671  * Called from C-level, sets/clears "go" indication for trap level handler.
4672  * khl_lock is a low level spin lock to protect the kp_tsbmtl field.
4673  * Assumed that &kp->kp_refcntc is checked for zero or -1 at C-level.
4674  * Assumes khl_mutex is held when called from C-level.
4675  */
4676 /* ARGSUSED */
4677 void
4678 sfmmu_kpm_tsbmtl(short *kp_refcntc, uint_t *khl_lock, int cmd)
4679 {
4680 }
4681 
4682 /*
4683  * kpm_smallpages: stores val to byte at address mapped within
4684  * low level lock brackets. The old value is returned.
4685  * Called from C-level.
4686  */
4687 /* ARGSUSED */
4688 int
4689 sfmmu_kpm_stsbmtl(uchar_t *mapped, uint_t *kshl_lock, int val)
4690 {
4691         return (0);
4692 }
4693 
4694 #else /* lint */
4695 
4696         .seg    ".data"
4697 sfmmu_kpm_tsbmtl_panic:
4698         .ascii  "sfmmu_kpm_tsbmtl: interrupts disabled"
4699         .byte   0
4700 sfmmu_kpm_stsbmtl_panic:
4701         .ascii  "sfmmu_kpm_stsbmtl: interrupts disabled"
4702         .byte   0
4703         .align  4
4704         .seg    ".text"
4705 
4706         ENTRY_NP(sfmmu_kpm_tsbmtl)
4707         rdpr    %pstate, %o3
4708         /*
4709          * %o0 = &kp_refcntc
4710          * %o1 = &khl_lock
4711          * %o2 = 0/1 (off/on)
4712          * %o3 = pstate save
4713          */
4714 #ifdef DEBUG
4715         andcc   %o3, PSTATE_IE, %g0             /* if interrupts already */
4716         bnz,pt %icc, 1f                         /* disabled, panic       */
4717           nop
4718         save    %sp, -SA(MINFRAME), %sp
4719         sethi   %hi(sfmmu_kpm_tsbmtl_panic), %o0
4720         call    panic
4721          or     %o0, %lo(sfmmu_kpm_tsbmtl_panic), %o0
4722         ret
4723         restore
4724 1:
4725 #endif /* DEBUG */
4726         wrpr    %o3, PSTATE_IE, %pstate         /* disable interrupts */
4727 
4728         KPMLOCK_ENTER(%o1, %o4, kpmtsbmtl1, ASI_N)
4729         mov     -1, %o5
4730         brz,a   %o2, 2f
4731           mov   0, %o5
4732 2:
4733         sth     %o5, [%o0]
4734         KPMLOCK_EXIT(%o1, ASI_N)
4735 
4736         retl
4737           wrpr  %g0, %o3, %pstate               /* enable interrupts */
4738         SET_SIZE(sfmmu_kpm_tsbmtl)
4739 
4740         ENTRY_NP(sfmmu_kpm_stsbmtl)
4741         rdpr    %pstate, %o3
4742         /*
4743          * %o0 = &mapped
4744          * %o1 = &kshl_lock
4745          * %o2 = val
4746          * %o3 = pstate save
4747          */
4748 #ifdef DEBUG
4749         andcc   %o3, PSTATE_IE, %g0             /* if interrupts already */
4750         bnz,pt %icc, 1f                         /* disabled, panic       */
4751           nop
4752         save    %sp, -SA(MINFRAME), %sp
4753         sethi   %hi(sfmmu_kpm_stsbmtl_panic), %o0
4754         call    panic
4755           or    %o0, %lo(sfmmu_kpm_stsbmtl_panic), %o0
4756         ret
4757         restore
4758 1:
4759 #endif /* DEBUG */
4760         wrpr    %o3, PSTATE_IE, %pstate         /* disable interrupts */
4761 
4762         KPMLOCK_ENTER(%o1, %o4, kpmstsbmtl1, ASI_N)
4763         ldsb    [%o0], %o5
4764         stb     %o2, [%o0]
4765         KPMLOCK_EXIT(%o1, ASI_N)
4766 
4767         and     %o5, KPM_MAPPED_MASK, %o0       /* return old val */
4768         retl
4769           wrpr  %g0, %o3, %pstate               /* enable interrupts */
4770         SET_SIZE(sfmmu_kpm_stsbmtl)
4771 
4772 #endif /* lint */
4773 
4774 #ifndef lint
4775 #ifdef sun4v
4776         /*
4777          * User/kernel data miss w// multiple TSBs
4778          * The first probe covers 8K, 64K, and 512K page sizes,
4779          * because 64K and 512K mappings are replicated off 8K
4780          * pointer.  Second probe covers 4M page size only.
4781          *
4782          * MMU fault area contains miss address and context.
4783          */
4784         ALTENTRY(sfmmu_slow_dmmu_miss)
4785         GET_MMU_D_PTAGACC_CTXTYPE(%g2, %g3)     ! %g2 = ptagacc, %g3 = ctx type
4786 
4787 slow_miss_common:
4788         /*
4789          *  %g2 = tagacc register (needed for sfmmu_tsb_miss_tt)
4790          *  %g3 = ctx (cannot be INVALID_CONTEXT)
4791          */
4792         brnz,pt %g3, 8f                 ! check for user context
4793           nop
4794 
4795         /*
4796          * Kernel miss
4797          * Get 8K and 4M TSB pointers in %g1 and %g3 and
4798          * branch to sfmmu_tsb_miss_tt to handle it.
4799          */
4800         mov     %g2, %g7                ! TSB pointer macro clobbers tagacc
4801 sfmmu_dslow_patch_ktsb_base:
4802         RUNTIME_PATCH_SETX(%g1, %g6)    ! %g1 = contents of ktsb_pbase
4803 sfmmu_dslow_patch_ktsb_szcode:
4804         or      %g0, RUNTIME_PATCH, %g3 ! ktsb_szcode (hot patched)
4805 
4806         GET_TSBE_POINTER(MMU_PAGESHIFT, %g1, %g7, %g3, %g5)
4807         ! %g1 = First TSB entry pointer, as TSB miss handler expects
4808 
4809         mov     %g2, %g7                ! TSB pointer macro clobbers tagacc
4810 sfmmu_dslow_patch_ktsb4m_base:
4811         RUNTIME_PATCH_SETX(%g3, %g6)    ! %g3 = contents of ktsb4m_pbase
4812 sfmmu_dslow_patch_ktsb4m_szcode:
4813         or      %g0, RUNTIME_PATCH, %g6 ! ktsb4m_szcode (hot patched)
4814 
4815         GET_TSBE_POINTER(MMU_PAGESHIFT4M, %g3, %g7, %g6, %g5)
4816         ! %g3 = 4M tsb entry pointer, as TSB miss handler expects
4817         ba,a,pt %xcc, sfmmu_tsb_miss_tt
4818         .empty
4819 
4820 8:
4821         /*
4822          * User miss
4823          * Get first TSB pointer in %g1
4824          * Get second TSB pointer (or NULL if no second TSB) in %g3
4825          * Branch to sfmmu_tsb_miss_tt to handle it
4826          */
4827         GET_1ST_TSBE_PTR(%g2, %g1, %g4, %g5)
4828         /* %g1 = first TSB entry ptr now, %g2 preserved */
4829 
4830         GET_UTSBREG(SCRATCHPAD_UTSBREG2, %g3)   /* get 2nd utsbreg */
4831         brlz,pt %g3, sfmmu_tsb_miss_tt          /* done if no 2nd TSB */
4832           nop
4833 
4834         GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5)
4835         /* %g3 = second TSB entry ptr now, %g2 preserved */
4836 9:
4837         ba,a,pt %xcc, sfmmu_tsb_miss_tt
4838         .empty
4839         SET_SIZE(sfmmu_slow_dmmu_miss)
4840 
4841 
4842         /*
4843          * User/kernel instruction miss w/ multiple TSBs
4844          * The first probe covers 8K, 64K, and 512K page sizes,
4845          * because 64K and 512K mappings are replicated off 8K
4846          * pointer.  Second probe covers 4M page size only.
4847          *
4848          * MMU fault area contains miss address and context.
4849          */
4850         ALTENTRY(sfmmu_slow_immu_miss)
4851         GET_MMU_I_PTAGACC_CTXTYPE(%g2, %g3)
4852         ba,a,pt %xcc, slow_miss_common
4853         SET_SIZE(sfmmu_slow_immu_miss)
4854 
4855 #endif /* sun4v */
4856 #endif  /* lint */
4857 
4858 #ifndef lint
4859 
4860 /*
4861  * Per-CPU tsbmiss areas to avoid cache misses in TSB miss handlers.
4862  */
4863         .seg    ".data"
4864         .align  64
4865         .global tsbmiss_area
4866 tsbmiss_area:
4867         .skip   (TSBMISS_SIZE * NCPU)
4868 
4869         .align  64
4870         .global kpmtsbm_area
4871 kpmtsbm_area:
4872         .skip   (KPMTSBM_SIZE * NCPU)
4873 #endif  /* lint */