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 2006 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 65/* ARGSUSED */ 66void 67sfmmu_ctx_steal_tl1(uint64_t sctx, uint64_t rctx) 68{} 69 70/* ARGSUSED */ 71void 72sfmmu_raise_tsb_exception(uint64_t sctx, uint64_t rctx) 73{} 74 75/* ARGSUSED */ 76void 77sfmmu_itlb_ld(caddr_t vaddr, int ctxnum, tte_t *tte) 78{} 79 80/* ARGSUSED */ 81void 82sfmmu_dtlb_ld(caddr_t vaddr, int ctxnum, tte_t *tte) 83{} 84 85int 86sfmmu_getctx_pri() 87{ return(0); } 88 89int 90sfmmu_getctx_sec() 91{ return(0); } 92 93/* ARGSUSED */ 94void 95sfmmu_setctx_sec(int ctx) 96{} 97 98/* ARGSUSED */ 99void 100sfmmu_load_mmustate(sfmmu_t *sfmmup) 101{ 102} 103 104#else /* lint */ 105 106/* 107 * 1. If stealing ctx, flush all TLB entries whose ctx is ctx-being-stolen. 108 * 2. If processor is running in the ctx-being-stolen, set the 109 * context to the resv context. That is 110 * If processor in User-mode - pri/sec-ctx both set to ctx-being-stolen, 111 * change both pri/sec-ctx registers to resv ctx. 112 * If processor in Kernel-mode - pri-ctx is 0, sec-ctx is ctx-being-stolen, 113 * just change sec-ctx register to resv ctx. When it returns to 114 * kernel-mode, user_rtt will change pri-ctx. 115 * 116 * Note: For multiple page size TLB, no need to set page sizes for 117 * DEMAP context. 118 * 119 * %g1 = ctx being stolen (victim) 120 * %g2 = invalid ctx to replace victim with 121 */ 122 ENTRY(sfmmu_ctx_steal_tl1) 123 /* 124 * Flush TLBs. 125 */ 126 set MMU_PCONTEXT, %g3 127 set DEMAP_CTX_TYPE | DEMAP_PRIMARY, %g4 128 ldxa [%g3]ASI_MMU_CTX, %g5 /* get pri-ctx */ 129 sethi %hi(FLUSH_ADDR), %g6 130 stxa %g1, [%g3]ASI_MMU_CTX /* temporarily set our */ 131 /* pri-ctx to victim */ 132 stxa %g0, [%g4]ASI_DTLB_DEMAP /* flush DTLB */ 133 stxa %g0, [%g4]ASI_ITLB_DEMAP /* flush ITLB */ 134 stxa %g5, [%g3]ASI_MMU_CTX /* restore original pri-ctx */ 135 flush %g6 /* ensure stxa's committed */ 136 /* fall through to the code below */ 137 138 /* 139 * We enter here if we're just raising a TSB miss 140 * exception, without switching MMU contexts. In 141 * this case, there is no need to flush the TLB. 142 */ 143 ALTENTRY(sfmmu_raise_tsb_exception) 144 ! 145 ! if (sec-ctx != victim) { 146 ! return 147 ! } else { 148 ! if (pri-ctx == victim) { 149 ! write INVALID_CONTEXT to sec-ctx 150 ! write INVALID_CONTEXT to pri-ctx 151 ! } else { 152 ! write INVALID_CONTEXT to sec-ctx 153 ! } 154 ! } 155 ! 156 cmp %g1, NUM_LOCKED_CTXS 157 blt,a,pn %icc, ptl1_panic /* can't steal locked ctx */ 158 mov PTL1_BAD_CTX_STEAL, %g1 159 set CTXREG_CTX_MASK, %g6 160 set MMU_SCONTEXT, %g3 161 ldxa [%g3]ASI_MMU_CTX, %g5 /* get sec-ctx */ 162 and %g5, %g6, %g5 163 cmp %g5, %g1 /* is it the victim? */ 164 bne,pn %icc, 2f /* was our sec-ctx a victim? */ 165 mov MMU_PCONTEXT, %g7 166 ldxa [%g7]ASI_MMU_CTX, %g4 /* get pri-ctx */ 167 and %g4, %g6, %g4 168 stxa %g2, [%g3]ASI_MMU_CTX /* set sec-ctx to invalid ctx */ 169 membar #Sync 170 cmp %g1, %g4 /* is it the victim? */ 171 bne %icc, 2f /* nope, no need to change it */ 172 nop 173 stxa %g2, [%g7]ASI_MMU_CTX /* set pri-ctx to invalid ctx */ 174 /* next instruction is retry so no membar sync */ 1752: 176 retry 177 SET_SIZE(sfmmu_ctx_steal_tl1) 178 179 ENTRY_NP(sfmmu_itlb_ld) 180 rdpr %pstate, %o3 181#ifdef DEBUG 182 andcc %o3, PSTATE_IE, %g0 ! If interrupts already 183 bnz,pt %icc, 1f ! disabled, panic 184 nop 185 186 sethi %hi(panicstr), %g1 187 ldx [%g1 + %lo(panicstr)], %g1 188 tst %g1 189 bnz,pt %icc, 1f 190 nop 191 192 sethi %hi(sfmmu_panic1), %o0 193 call panic 194 or %o0, %lo(sfmmu_panic1), %o0 1951: 196#endif /* DEBUG */ 197 wrpr %o3, PSTATE_IE, %pstate ! Disable interrupts 198 srln %o0, MMU_PAGESHIFT, %o0 199 slln %o0, MMU_PAGESHIFT, %o0 ! Clear page offset 200 or %o0, %o1, %o0 201 ldx [%o2], %g1 202 set MMU_TAG_ACCESS, %o5 203#ifdef CHEETAHPLUS_ERRATUM_34 204 ! 205 ! If this is Cheetah or derivative and the specified TTE is locked 206 ! and hence to be loaded into the T16, fully-associative TLB, we 207 ! must avoid Cheetah+ erratum 34. In Cheetah+ erratum 34, under 208 ! certain conditions an ITLB locked index 0 TTE will erroneously be 209 ! displaced when a new TTE is loaded via ASI_ITLB_IN. To avoid 210 ! this erratum, we scan the T16 top down for an unlocked TTE and 211 ! explicitly load the specified TTE into that index. 212 ! 213 GET_CPU_IMPL(%g2) 214 cmp %g2, CHEETAH_IMPL 215 bl,pn %icc, 0f 216 nop 217 218 andcc %g1, TTE_LCK_INT, %g0 219 bz %icc, 0f ! Lock bit is not set; 220 ! load normally. 221 or %g0, (15 << 3), %g3 ! Start searching from the 222 ! top down. 223 2241: 225 ldxa [%g3]ASI_ITLB_ACCESS, %g4 ! Load TTE from t16 226 227 ! 228 ! If this entry isn't valid, we'll choose to displace it (regardless 229 ! of the lock bit). 230 ! 231 cmp %g4, %g0 232 bge %xcc, 2f ! TTE is > 0 iff not valid 233 andcc %g4, TTE_LCK_INT, %g0 ! Check for lock bit 234 bz %icc, 2f ! If unlocked, go displace 235 nop 236 sub %g3, (1 << 3), %g3 237 brgz %g3, 1b ! Still more TLB entries 238 nop ! to search 239 240 sethi %hi(sfmmu_panic5), %o0 ! We searched all entries and 241 call panic ! found no unlocked TTE so 242 or %o0, %lo(sfmmu_panic5), %o0 ! give up. 243 244 2452: 246 ! 247 ! We have found an unlocked or non-valid entry; we'll explicitly load 248 ! our locked entry here. 249 ! 250 sethi %hi(FLUSH_ADDR), %o1 ! Flush addr doesn't matter 251 stxa %o0, [%o5]ASI_IMMU 252 stxa %g1, [%g3]ASI_ITLB_ACCESS 253 flush %o1 ! Flush required for I-MMU 254 ba 3f ! Delay slot of ba is empty 255 nop ! per Erratum 64 256 2570: 258#endif /* CHEETAHPLUS_ERRATUM_34 */ 259 sethi %hi(FLUSH_ADDR), %o1 ! Flush addr doesn't matter 260 stxa %o0, [%o5]ASI_IMMU 261 stxa %g1, [%g0]ASI_ITLB_IN 262 flush %o1 ! Flush required for I-MMU 2633: 264 retl 265 wrpr %g0, %o3, %pstate ! Enable interrupts 266 SET_SIZE(sfmmu_itlb_ld) 267 268 /* 269 * Load an entry into the DTLB. 270 * 271 * Special handling is required for locked entries since there 272 * are some TLB slots that are reserved for the kernel but not 273 * always held locked. We want to avoid loading locked TTEs 274 * into those slots since they could be displaced. 275 */ 276 ENTRY_NP(sfmmu_dtlb_ld) 277 rdpr %pstate, %o3 278#ifdef DEBUG 279 andcc %o3, PSTATE_IE, %g0 ! if interrupts already 280 bnz,pt %icc, 1f ! disabled, panic 281 nop 282 283 sethi %hi(panicstr), %g1 284 ldx [%g1 + %lo(panicstr)], %g1 285 tst %g1 286 bnz,pt %icc, 1f 287 nop 288 289 sethi %hi(sfmmu_panic1), %o0 290 call panic 291 or %o0, %lo(sfmmu_panic1), %o0 2921: 293#endif /* DEBUG */ 294 wrpr %o3, PSTATE_IE, %pstate ! disable interrupts 295 srln %o0, MMU_PAGESHIFT, %o0 296 slln %o0, MMU_PAGESHIFT, %o0 ! clear page offset 297 or %o0, %o1, %o0 ! or in ctx to form tagacc 298 ldx [%o2], %g1 299 sethi %hi(ctx_pgsz_array), %o2 ! Check for T8s 300 ldn [%o2 + %lo(ctx_pgsz_array)], %o2 301 brz %o2, 1f 302 set MMU_TAG_ACCESS, %o5 303 ldub [%o2 + %o1], %o2 ! Cheetah+: set up tag access 304 sll %o2, TAGACCEXT_SHIFT, %o2 ! extension register so entry 305 set MMU_TAG_ACCESS_EXT, %o4 ! can go into T8 if unlocked 306 stxa %o2,[%o4]ASI_DMMU 307 membar #Sync 3081: 309 andcc %g1, TTE_LCK_INT, %g0 ! Locked entries require 310 bnz,pn %icc, 2f ! special handling 311 sethi %hi(dtlb_resv_ttenum), %g3 312 stxa %o0,[%o5]ASI_DMMU ! Load unlocked TTE 313 stxa %g1,[%g0]ASI_DTLB_IN ! via DTLB_IN 314 membar #Sync 315 retl 316 wrpr %g0, %o3, %pstate ! enable interrupts 3172: 318 ld [%g3 + %lo(dtlb_resv_ttenum)], %g3 319 sll %g3, 3, %g3 ! First reserved idx in TLB 0 320 sub %g3, (1 << 3), %g3 ! Decrement idx 3213: 322 ldxa [%g3]ASI_DTLB_ACCESS, %g4 ! Load TTE from TLB 0 323 ! 324 ! If this entry isn't valid, we'll choose to displace it (regardless 325 ! of the lock bit). 326 ! 327 brgez,pn %g4, 4f ! TTE is > 0 iff not valid 328 nop 329 andcc %g4, TTE_LCK_INT, %g0 ! Check for lock bit 330 bz,pn %icc, 4f ! If unlocked, go displace 331 nop 332 sub %g3, (1 << 3), %g3 ! Decrement idx 333 brgez %g3, 3b 334 nop 335 sethi %hi(sfmmu_panic5), %o0 ! We searched all entries and 336 call panic ! found no unlocked TTE so 337 or %o0, %lo(sfmmu_panic5), %o0 ! give up. 3384: 339 stxa %o0,[%o5]ASI_DMMU ! Setup tag access 340#ifdef OLYMPUS_SHARED_FTLB 341 stxa %g1,[%g0]ASI_DTLB_IN 342#else 343 stxa %g1,[%g3]ASI_DTLB_ACCESS ! Displace entry at idx 344#endif 345 membar #Sync 346 retl 347 wrpr %g0, %o3, %pstate ! enable interrupts 348 SET_SIZE(sfmmu_dtlb_ld) 349 350 ENTRY_NP(sfmmu_getctx_pri) 351 set MMU_PCONTEXT, %o0 352 retl 353 ldxa [%o0]ASI_MMU_CTX, %o0 354 SET_SIZE(sfmmu_getctx_pri) 355 356 ENTRY_NP(sfmmu_getctx_sec) 357 set MMU_SCONTEXT, %o0 358 set CTXREG_CTX_MASK, %o1 359 ldxa [%o0]ASI_MMU_CTX, %o0 360 retl 361 and %o0, %o1, %o0 362 SET_SIZE(sfmmu_getctx_sec) 363 364 /* 365 * Set the secondary context register for this process. 366 * %o0 = context number for this process. 367 */ 368 ENTRY_NP(sfmmu_setctx_sec) 369 /* 370 * From resume we call sfmmu_setctx_sec with interrupts disabled. 371 * But we can also get called from C with interrupts enabled. So, 372 * we need to check first. Also, resume saves state in %o3 and %o5 373 * so we can't use those registers here. 374 */ 375 376 /* If interrupts are not disabled, then disable them */ 377 rdpr %pstate, %g1 378 btst PSTATE_IE, %g1 379 bnz,a,pt %icc, 1f 380 wrpr %g1, PSTATE_IE, %pstate /* disable interrupts */ 3811: 382 mov MMU_SCONTEXT, %o1 383 sethi %hi(ctx_pgsz_array), %g2 384 ldn [%g2 + %lo(ctx_pgsz_array)], %g2 385 brz %g2, 2f 386 nop 387 ldub [%g2 + %o0], %g2 388 sll %g2, CTXREG_EXT_SHIFT, %g2 389 or %g2, %o0, %o0 3902: 391 sethi %hi(FLUSH_ADDR), %o4 392 stxa %o0, [%o1]ASI_MMU_CTX /* set 2nd context reg. */ 393 flush %o4 394 395 btst PSTATE_IE, %g1 396 bnz,a,pt %icc, 1f 397 wrpr %g0, %g1, %pstate /* enable interrupts */ 3981: retl 399 nop 400 SET_SIZE(sfmmu_setctx_sec) 401 402 /* 403 * set ktsb_phys to 1 if the processor supports ASI_QUAD_LDD_PHYS. 404 * returns the detection value in %o0. 405 * 406 * Currently ASI_QUAD_LDD_PHYS is supported in processors as follows 407 * - cheetah+ and later (greater or equal to CHEETAH_PLUS_IMPL) 408 * - FJ OPL Olympus-C and later (less than SPITFIRE_IMPL) 409 * 410 */ 411 ENTRY_NP(sfmmu_setup_4lp) 412 GET_CPU_IMPL(%o0); 413 cmp %o0, CHEETAH_PLUS_IMPL 414 bge,pt %icc, 4f 415 mov 1, %o1 416 cmp %o0, SPITFIRE_IMPL 417 bge,a,pn %icc, 3f 418 clr %o1 4194: 420 set ktsb_phys, %o2 421 st %o1, [%o2] 4223: retl 423 mov %o1, %o0 424 SET_SIZE(sfmmu_setup_4lp) 425 426 427 /* 428 * Called to load MMU registers and tsbmiss area 429 * for the active process. This function should 430 * only be called from TL=0. 431 * 432 * %o0 - hat pointer 433 */ 434 ENTRY_NP(sfmmu_load_mmustate) 435 /* 436 * From resume we call sfmmu_load_mmustate with interrupts disabled. 437 * But we can also get called from C with interrupts enabled. So, 438 * we need to check first. Also, resume saves state in %o5 and we 439 * can't use this register here. 440 */ 441 442 sethi %hi(ksfmmup), %o3 443 ldx [%o3 + %lo(ksfmmup)], %o3 444 cmp %o3, %o0 445 be,pn %xcc, 3f ! if kernel as, do nothing 446 nop 447 448 /* If interrupts are not disabled, then disable them */ 449 rdpr %pstate, %g1 450 btst PSTATE_IE, %g1 451 bnz,a,pt %icc, 1f 452 wrpr %g1, PSTATE_IE, %pstate ! disable interrupts 4531: 454 /* 455 * We need to set up the TSB base register, tsbmiss 456 * area, and load locked TTE(s) for the TSB. 457 */ 458 ldx [%o0 + SFMMU_TSB], %o1 ! %o1 = first tsbinfo 459 ldx [%o1 + TSBINFO_NEXTPTR], %g2 ! %g2 = second tsbinfo 460 461#ifdef UTSB_PHYS 462 /* 463 * UTSB_PHYS accesses user TSBs via physical addresses. The first 464 * TSB is in the MMU I/D TSB Base registers. The second TSB uses a 465 * designated ASI_SCRATCHPAD register as a pseudo TSB base register. 466 */ 467 MAKE_UTSBREG_PHYS(%o1, %o2, %o3) ! %o2 = first utsbreg 468 LOAD_TSBREG(%o2, %o3, %o4) ! write TSB base register 469 470 brz,a,pt %g2, 2f 471 mov -1, %o2 ! use -1 if no second TSB 472 473 MAKE_UTSBREG_PHYS(%g2, %o2, %o3) ! %o2 = second utsbreg 4742: 475 LOAD_2ND_TSBREG(%o2, %o3) ! write 2nd pseudo TSB base register 476#else /* UTSB_PHYS */ 477 brz,pt %g2, 4f 478 nop 479 /* 480 * We have a second TSB for this process, so we need to 481 * encode data for both the first and second TSB in our single 482 * TSB base register. See hat_sfmmu.h for details on what bits 483 * correspond to which TSB. 484 * We also need to load a locked TTE into the TLB for the second TSB 485 * in this case. 486 */ 487 MAKE_TSBREG_SECTSB(%o2, %o1, %g2, %o3, %o4, %g3, sfmmu_tsb_2nd) 488 ! %o2 = tsbreg 489 sethi %hi(utsb4m_dtlb_ttenum), %o3 490 sethi %hi(utsb4m_vabase), %o4 491 ld [%o3 + %lo(utsb4m_dtlb_ttenum)], %o3 492 ldx [%o4 + %lo(utsb4m_vabase)], %o4 ! %o4 = TLB tag for sec TSB 493 sll %o3, DTACC_SHIFT, %o3 ! %o3 = sec TSB TLB index 494 RESV_OFFSET(%g2, %o4, %g3, sfmmu_tsb_2nd) ! or-in bits of TSB VA 495 LOAD_TSBTTE(%g2, %o3, %o4, %g3) ! load sec TSB locked TTE 496 sethi %hi(utsb_vabase), %g3 497 ldx [%g3 + %lo(utsb_vabase)], %g3 ! %g3 = TLB tag for first TSB 498 ba,pt %xcc, 5f 499 nop 500 5014: sethi %hi(utsb_vabase), %g3 502 ldx [%g3 + %lo(utsb_vabase)], %g3 ! %g3 = TLB tag for first TSB 503 MAKE_TSBREG(%o2, %o1, %g3, %o3, %o4, sfmmu_tsb_1st) ! %o2 = tsbreg 504 5055: LOAD_TSBREG(%o2, %o3, %o4) ! write TSB base register 506 507 /* 508 * Load the TTE for the first TSB at the appropriate location in 509 * the TLB 510 */ 511 sethi %hi(utsb_dtlb_ttenum), %o2 512 ld [%o2 + %lo(utsb_dtlb_ttenum)], %o2 513 sll %o2, DTACC_SHIFT, %o2 ! %o1 = first TSB TLB index 514 RESV_OFFSET(%o1, %g3, %o3, sfmmu_tsb_1st) ! or-in bits of TSB VA 515 LOAD_TSBTTE(%o1, %o2, %g3, %o4) ! load first TSB locked TTE 516#endif /* UTSB_PHYS */ 517 5186: ldx [%o0 + SFMMU_ISMBLKPA], %o1 ! copy members of sfmmu 519 CPU_TSBMISS_AREA(%o2, %o3) ! we need to access from 520 stx %o1, [%o2 + TSBMISS_ISMBLKPA] ! sfmmu_tsb_miss into the 521 lduh [%o0 + SFMMU_FLAGS], %o3 ! per-CPU tsbmiss area. 522 stx %o0, [%o2 + TSBMISS_UHATID] 523 stuh %o3, [%o2 + TSBMISS_HATFLAGS] 524 525 btst PSTATE_IE, %g1 526 bnz,a,pt %icc, 3f 527 wrpr %g0, %g1, %pstate ! enable interrupts 5283: retl 529 nop 530 SET_SIZE(sfmmu_load_mmustate) 531 532#endif /* lint */ 533 534#if defined (lint) 535/* 536 * Invalidate all of the entries within the tsb, by setting the inv bit 537 * in the tte_tag field of each tsbe. 538 * 539 * We take advantage of the fact TSBs are page aligned and a multiple of 540 * PAGESIZE to use block stores. 541 * 542 * See TSB_LOCK_ENTRY and the miss handlers for how this works in practice 543 * (in short, we set all bits in the upper word of the tag, and we give the 544 * invalid bit precedence over other tag bits in both places). 545 */ 546/* ARGSUSED */ 547void 548sfmmu_inv_tsb_fast(caddr_t tsb_base, uint_t tsb_bytes) 549{} 550 551#else /* lint */ 552 553#define VIS_BLOCKSIZE 64 554 555 ENTRY(sfmmu_inv_tsb_fast) 556 557 ! Get space for aligned block of saved fp regs. 558 save %sp, -SA(MINFRAME + 2*VIS_BLOCKSIZE), %sp 559 560 ! kpreempt_disable(); 561 ldsb [THREAD_REG + T_PREEMPT], %l3 562 inc %l3 563 stb %l3, [THREAD_REG + T_PREEMPT] 564 565 ! See if fpu was in use. If it was, we need to save off the 566 ! floating point registers to the stack. 567 rd %fprs, %l0 ! %l0 = cached copy of fprs 568 btst FPRS_FEF, %l0 569 bz,pt %icc, 4f 570 nop 571 572 ! save in-use fpregs on stack 573 membar #Sync ! make sure tranx to fp regs 574 ! have completed 575 add %fp, STACK_BIAS - 65, %l1 ! get stack frame for fp regs 576 and %l1, -VIS_BLOCKSIZE, %l1 ! block align frame 577 stda %d0, [%l1]ASI_BLK_P ! %l1 = addr of saved fp regs 578 579 ! enable fp 5804: membar #StoreStore|#StoreLoad|#LoadStore 581 wr %g0, FPRS_FEF, %fprs 582 wr %g0, ASI_BLK_P, %asi 583 584 ! load up FP registers with invalid TSB tag. 585 fone %d0 ! ones in tag 586 fzero %d2 ! zeros in TTE 587 fone %d4 ! ones in tag 588 fzero %d6 ! zeros in TTE 589 fone %d8 ! ones in tag 590 fzero %d10 ! zeros in TTE 591 fone %d12 ! ones in tag 592 fzero %d14 ! zeros in TTE 593 ba,pt %xcc, .sfmmu_inv_doblock 594 mov (4*VIS_BLOCKSIZE), %i4 ! we do 4 stda's each loop below 595 596.sfmmu_inv_blkstart: 597 ! stda %d0, [%i0+192]%asi ! in dly slot of branch that got us here 598 stda %d0, [%i0+128]%asi 599 stda %d0, [%i0+64]%asi 600 stda %d0, [%i0]%asi 601 602 add %i0, %i4, %i0 603 sub %i1, %i4, %i1 604 605.sfmmu_inv_doblock: 606 cmp %i1, (4*VIS_BLOCKSIZE) ! check for completion 607 bgeu,a %icc, .sfmmu_inv_blkstart 608 stda %d0, [%i0+192]%asi 609 610.sfmmu_inv_finish: 611 membar #Sync 612 btst FPRS_FEF, %l0 ! saved from above 613 bz,a .sfmmu_inv_finished 614 wr %l0, 0, %fprs ! restore fprs 615 616 ! restore fpregs from stack 617 ldda [%l1]ASI_BLK_P, %d0 618 membar #Sync 619 wr %l0, 0, %fprs ! restore fprs 620 621.sfmmu_inv_finished: 622 ! kpreempt_enable(); 623 ldsb [THREAD_REG + T_PREEMPT], %l3 624 dec %l3 625 stb %l3, [THREAD_REG + T_PREEMPT] 626 ret 627 restore 628 SET_SIZE(sfmmu_inv_tsb_fast) 629 630#endif /* lint */ 631 632#if defined(lint) 633 634/* 635 * Prefetch "struct tsbe" while walking TSBs. 636 * prefetch 7 cache lines ahead of where we are at now. 637 * #n_reads is being used since #one_read only applies to 638 * floating point reads, and we are not doing floating point 639 * reads. However, this has the negative side effect of polluting 640 * the ecache. 641 * The 448 comes from (7 * 64) which is how far ahead of our current 642 * address, we want to prefetch. 643 */ 644/*ARGSUSED*/ 645void 646prefetch_tsbe_read(struct tsbe *tsbep) 647{} 648 649/* Prefetch the tsbe that we are about to write */ 650/*ARGSUSED*/ 651void 652prefetch_tsbe_write(struct tsbe *tsbep) 653{} 654 655#else /* lint */ 656 657 ENTRY(prefetch_tsbe_read) 658 retl 659 prefetch [%o0+448], #n_reads 660 SET_SIZE(prefetch_tsbe_read) 661 662 ENTRY(prefetch_tsbe_write) 663 retl 664 prefetch [%o0], #n_writes 665 SET_SIZE(prefetch_tsbe_write) 666#endif /* lint */ 667 668 669#ifndef lint 670#endif /* lint */ 671