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