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