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 /* 27 * VM - Hardware Address Translation management. 28 * 29 * This file describes the contents of the sun reference mmu (sfmmu) 30 * specific hat data structures and the sfmmu specific hat procedures. 31 * The machine independent interface is described in <vm/hat.h>. 32 */ 33 34 #ifndef _VM_MACH_SFMMU_H 35 #define _VM_MACH_SFMMU_H 36 37 #pragma ident "%Z%%M% %I% %E% SMI" 38 39 #include <sys/x_call.h> 40 #include <sys/hypervisor_api.h> 41 42 #ifdef __cplusplus 43 extern "C" { 44 #endif 45 46 /* 47 * Define UTSB_PHYS if user TSB is always accessed via physical address. 48 * On sun4v platform, user TSB is accessed via physical address. 49 */ 50 #define UTSB_PHYS 1 51 52 /* 53 * Hypervisor TSB info 54 */ 55 #define NHV_TSB_INFO 2 56 57 #ifndef _ASM 58 59 struct hv_tsb_block { 60 uint64_t hv_tsb_info_pa; /* hypervisor TSB info PA */ 61 uint64_t hv_tsb_info_cnt; /* hypervisor TSB info count */ 62 hv_tsb_info_t hv_tsb_info[NHV_TSB_INFO]; /* hypervisor TSB info */ 63 }; 64 65 #endif /* _ASM */ 66 67 #ifdef _ASM 68 69 /* 70 * This macro is used in the MMU code to check if TL should be lowered from 71 * 2 to 1 to pop trapstat's state. See the block comment in trapstat.c 72 * for details. 73 */ 74 75 #define TSTAT_CHECK_TL1(label, scr1, scr2) \ 76 rdpr %tpc, scr1; \ 77 sethi %hi(KERNELBASE), scr2; \ 78 or scr2, %lo(KERNELBASE), scr2; \ 79 cmp scr1, scr2; \ 80 bgeu %xcc, 9f; \ 81 nop; \ 82 wrpr %g0, 1, %gl; \ 83 ba label; \ 84 wrpr %g0, 1, %tl; \ 85 9: 86 87 /* 88 * The following macros allow us to share majority of the 89 * SFMMU code between sun4u and sun4v platforms. 90 */ 91 92 #define SETUP_TSB_ASI(qlp, tmp) 93 94 #define SETUP_UTSB_ATOMIC_ASI(tmp1, tmp2) 95 96 /* 97 * Macro to swtich to alternate global register on sun4u platforms 98 * (not applicable to sun4v platforms) 99 */ 100 #define USE_ALTERNATE_GLOBALS(scr) 101 102 /* 103 * Macro to set %gl register value on sun4v platforms 104 * (not applicable to sun4u platforms) 105 */ 106 #define SET_GL_REG(val) \ 107 wrpr %g0, val, %gl 108 109 /* 110 * Get pseudo-tagacc value and context from the MMU fault area. Pseudo-tagacc 111 * is the faulting virtual address OR'd with 0 for KCONTEXT, INVALID_CONTEXT 112 * (1) for invalid context, and USER_CONTEXT (2) for user context. 113 * 114 * In: 115 * tagacc, ctxtype = scratch registers 116 * Out: 117 * tagacc = MMU data tag access register value 118 * ctx = context type (KCONTEXT, INVALID_CONTEXT or USER_CONTEXT) 119 */ 120 #define GET_MMU_D_PTAGACC_CTXTYPE(ptagacc, ctxtype) \ 121 MMU_FAULT_STATUS_AREA(ctxtype); \ 122 ldx [ctxtype + MMFSA_D_ADDR], ptagacc; \ 123 ldx [ctxtype + MMFSA_D_CTX], ctxtype; \ 124 srlx ptagacc, MMU_PAGESHIFT, ptagacc; /* align to page boundary */ \ 125 cmp ctxtype, USER_CONTEXT_TYPE; \ 126 sllx ptagacc, MMU_PAGESHIFT, ptagacc; \ 127 movgu %icc, USER_CONTEXT_TYPE, ctxtype; \ 128 or ptagacc, ctxtype, ptagacc 129 130 /* 131 * Synthesize/get data tag access register value from the MMU fault area 132 * 133 * In: 134 * tagacc, scr1 = scratch registers 135 * Out: 136 * tagacc = MMU data tag access register value 137 */ 138 #define GET_MMU_D_TAGACC(tagacc, scr1) \ 139 GET_MMU_D_PTAGACC_CTXTYPE(tagacc, scr1) 140 141 /* 142 * Synthesize/get data tag target register value from the MMU fault area 143 * 144 * In: 145 * ttarget, scr1 = scratch registers 146 * Out: 147 * ttarget = MMU data tag target register value 148 */ 149 #define GET_MMU_D_TTARGET(ttarget, scr1) \ 150 MMU_FAULT_STATUS_AREA(ttarget); \ 151 ldx [ttarget + MMFSA_D_CTX], scr1; \ 152 sllx scr1, TTARGET_CTX_SHIFT, scr1; \ 153 ldx [ttarget + MMFSA_D_ADDR], ttarget; \ 154 srlx ttarget, TTARGET_VA_SHIFT, ttarget; \ 155 or ttarget, scr1, ttarget 156 157 /* 158 * Synthesize/get data/instruction psuedo tag access register values 159 * from the MMU fault area (context is 0 for kernel, 1 for invalid, 2 for user) 160 * 161 * In: 162 * dtagacc, itagacc, scr1, scr2 = scratch registers 163 * Out: 164 * dtagacc = MMU data tag access register value w/psuedo-context 165 * itagacc = MMU instruction tag access register value w/pseudo-context 166 */ 167 #define GET_MMU_BOTH_TAGACC(dtagacc, itagacc, scr1, scr2) \ 168 MMU_FAULT_STATUS_AREA(scr1); \ 169 ldx [scr1 + MMFSA_D_ADDR], scr2; \ 170 ldx [scr1 + MMFSA_D_CTX], dtagacc; \ 171 srlx scr2, MMU_PAGESHIFT, scr2; /* align to page boundary */ \ 172 cmp dtagacc, USER_CONTEXT_TYPE; \ 173 sllx scr2, MMU_PAGESHIFT, scr2; \ 174 movgu %icc, USER_CONTEXT_TYPE, dtagacc; \ 175 or scr2, dtagacc, dtagacc; \ 176 ldx [scr1 + MMFSA_I_ADDR], scr2; \ 177 ldx [scr1 + MMFSA_I_CTX], itagacc; \ 178 srlx scr2, MMU_PAGESHIFT, scr2; /* align to page boundry */ \ 179 cmp itagacc, USER_CONTEXT_TYPE; \ 180 sllx scr2, MMU_PAGESHIFT, scr2; \ 181 movgu %icc, USER_CONTEXT_TYPE, itagacc; \ 182 or scr2, itagacc, itagacc 183 184 /* 185 * Synthesize/get MMU data fault address from the MMU fault area 186 * 187 * In: 188 * daddr, scr1 = scratch registers 189 * Out: 190 * daddr = MMU data fault address 191 */ 192 #define GET_MMU_D_ADDR(daddr, scr1) \ 193 MMU_FAULT_STATUS_AREA(scr1); \ 194 ldx [scr1 + MMFSA_D_ADDR], daddr 195 196 /* 197 * Get pseudo-tagacc value and context from the MMU fault area. Pseudo-tagacc 198 * is the faulting virtual address OR'd with 0 for KCONTEXT, INVALID_CONTEXT 199 * (1) for invalid context, and USER_CONTEXT (2) for user context. 200 * 201 * In: 202 * tagacc, ctxtype = scratch registers 203 * Out: 204 * tagacc = MMU instruction tag access register value 205 * ctxtype = context type (KCONTEXT, INVALID_CONTEXT or USER_CONTEXT) 206 */ 207 #define GET_MMU_I_PTAGACC_CTXTYPE(ptagacc, ctxtype) \ 208 MMU_FAULT_STATUS_AREA(ctxtype); \ 209 ldx [ctxtype + MMFSA_I_ADDR], ptagacc; \ 210 ldx [ctxtype + MMFSA_I_CTX], ctxtype; \ 211 srlx ptagacc, MMU_PAGESHIFT, ptagacc; /* align to page boundary */ \ 212 cmp ctxtype, USER_CONTEXT_TYPE; \ 213 sllx ptagacc, MMU_PAGESHIFT, ptagacc; \ 214 movgu %icc, USER_CONTEXT_TYPE, ctxtype; \ 215 or ptagacc, ctxtype, ptagacc 216 217 /* 218 * Load ITLB entry 219 * 220 * In: 221 * tte = reg containing tte 222 * scr1, scr2, scr3, scr4 = scratch registers 223 */ 224 #define ITLB_STUFF(tte, scr1, scr2, scr3, scr4) \ 225 mov %o0, scr1; \ 226 mov %o1, scr2; \ 227 mov %o2, scr3; \ 228 mov %o3, scr4; \ 229 MMU_FAULT_STATUS_AREA(%o2); \ 230 ldx [%o2 + MMFSA_I_ADDR], %o0; \ 231 ldx [%o2 + MMFSA_I_CTX], %o1; \ 232 mov tte, %o2; \ 233 mov MAP_ITLB, %o3; \ 234 ta MMU_MAP_ADDR; \ 235 /* BEGIN CSTYLED */ \ 236 brnz,a,pn %o0, ptl1_panic; \ 237 mov PTL1_BAD_HCALL, %g1; \ 238 /* END CSTYLED */ \ 239 mov scr1, %o0; \ 240 mov scr2, %o1; \ 241 mov scr3, %o2; \ 242 mov scr4, %o3 243 244 /* 245 * Load DTLB entry 246 * 247 * In: 248 * tte = reg containing tte 249 * scr1, scr2, scr3, scr4 = scratch registers 250 */ 251 #define DTLB_STUFF(tte, scr1, scr2, scr3, scr4) \ 252 mov %o0, scr1; \ 253 mov %o1, scr2; \ 254 mov %o2, scr3; \ 255 mov %o3, scr4; \ 256 MMU_FAULT_STATUS_AREA(%o2); \ 257 ldx [%o2 + MMFSA_D_ADDR], %o0; \ 258 ldx [%o2 + MMFSA_D_CTX], %o1; \ 259 mov tte, %o2; \ 260 mov MAP_DTLB, %o3; \ 261 ta MMU_MAP_ADDR; \ 262 /* BEGIN CSTYLED */ \ 263 brnz,a,pn %o0, ptl1_panic; \ 264 mov PTL1_BAD_HCALL, %g1; \ 265 /* END CSTYLED */ \ 266 mov scr1, %o0; \ 267 mov scr2, %o1; \ 268 mov scr3, %o2; \ 269 mov scr4, %o3 270 271 /* 272 * Returns PFN given the TTE and vaddr 273 * 274 * In: 275 * tte = reg containing tte 276 * vaddr = reg containing vaddr 277 * scr1, scr2, scr3 = scratch registers 278 * Out: 279 * tte = PFN value 280 */ 281 #define TTETOPFN(tte, vaddr, label, scr1, scr2, scr3) \ 282 and tte, TTE_SZ_BITS, scr1; /* scr1 = ttesz */ \ 283 sllx tte, TTE_PA_LSHIFT, tte; \ 284 sllx scr1, 1, scr2; \ 285 add scr2, scr1, scr2; /* mulx 3 */ \ 286 add scr2, MMU_PAGESHIFT + TTE_PA_LSHIFT, scr3; \ 287 /* CSTYLED */ \ 288 brz,pt scr2, label/**/1; \ 289 srlx tte, scr3, tte; \ 290 sllx tte, scr2, tte; \ 291 set 1, scr1; \ 292 add scr2, MMU_PAGESHIFT, scr3; \ 293 sllx scr1, scr3, scr1; \ 294 sub scr1, 1, scr1; /* scr1=TTE_PAGE_OFFSET(ttesz) */ \ 295 and vaddr, scr1, scr2; \ 296 srln scr2, MMU_PAGESHIFT, scr2; \ 297 or tte, scr2, tte; \ 298 /* CSTYLED */ \ 299 label/**/1: 300 301 /* 302 * TTE_SET_REF_ML is a macro that updates the reference bit if it is 303 * not already set. 304 * 305 * Parameters: 306 * tte = reg containing tte 307 * ttepa = physical pointer to tte 308 * tteva = virtual ptr to tte 309 * tsbarea = tsb miss area 310 * tmp1 = tmp reg 311 * label = temporary label 312 */ 313 314 #define TTE_SET_REF_ML(tte, ttepa, tteva, tsbarea, tmp1, label) \ 315 /* BEGIN CSTYLED */ \ 316 /* check reference bit */ \ 317 btst TTE_REF_INT, tte; \ 318 bnz,pt %xcc, label/**/2; /* if ref bit set-skip ahead */ \ 319 nop; \ 320 /* update reference bit */ \ 321 label/**/1: \ 322 or tte, TTE_REF_INT, tmp1; \ 323 casxa [ttepa]ASI_MEM, tte, tmp1; /* update ref bit */ \ 324 cmp tte, tmp1; \ 325 bne,a,pn %xcc, label/**/1; \ 326 ldxa [ttepa]ASI_MEM, tte; /* MMU_READTTE through pa */ \ 327 or tte, TTE_REF_INT, tte; \ 328 label/**/2: \ 329 /* END CSTYLED */ 330 331 332 /* 333 * TTE_SET_REFMOD_ML is a macro that updates the reference and modify bits 334 * if not already set. 335 * 336 * Parameters: 337 * tte = reg containing tte 338 * ttepa = physical pointer to tte 339 * tteva = virtual ptr to tte 340 * tsbarea = tsb miss area 341 * tmp1 = tmp reg 342 * label = temporary label 343 * exitlabel = label where to jump to if write perm bit not set. 344 */ 345 346 #define TTE_SET_REFMOD_ML(tte, ttepa, tteva, tsbarea, tmp1, label, \ 347 exitlabel) \ 348 /* BEGIN CSTYLED */ \ 349 /* check reference bit */ \ 350 btst TTE_WRPRM_INT, tte; \ 351 bz,pn %xcc, exitlabel; /* exit if wr_perm no set */ \ 352 btst TTE_HWWR_INT, tte; \ 353 bnz,pn %xcc, label/**/2; /* nothing to do */ \ 354 nop; \ 355 /* update reference bit */ \ 356 label/**/1: \ 357 or tte, TTE_HWWR_INT | TTE_REF_INT, tmp1; \ 358 casxa [ttepa]ASI_MEM, tte, tmp1; /* update ref/mod bit */ \ 359 cmp tte, tmp1; \ 360 bne,a,pn %xcc, label/**/1; \ 361 ldxa [ttepa]ASI_MEM, tte; /* MMU_READTTE through pa */ \ 362 or tte, TTE_HWWR_INT | TTE_REF_INT, tte; \ 363 label/**/2: \ 364 /* END CSTYLED */ 365 366 367 /* 368 * Synthesize a TSB base register contents for a process. 369 * 370 * In: 371 * tsbinfo = TSB info pointer (ro) 372 * tsbreg, tmp1 = scratch registers 373 * Out: 374 * tsbreg = value to program into TSB base register 375 */ 376 377 #define MAKE_UTSBREG(tsbinfo, tsbreg, tmp1) \ 378 ldx [tsbinfo + TSBINFO_PADDR], tsbreg; \ 379 lduh [tsbinfo + TSBINFO_SZCODE], tmp1; \ 380 and tmp1, TSB_SOFTSZ_MASK, tmp1; \ 381 or tsbreg, tmp1, tsbreg; 382 383 384 /* 385 * Load TSB base register into a dedicated scratchpad register. 386 * This register contains utsb_pabase in bits 63:13, and TSB size 387 * code in bits 2:0. 388 * 389 * In: 390 * tsbreg = value to load (ro) 391 * regnum = constant or register 392 * tmp1 = scratch register 393 * Out: 394 * Specified scratchpad register updated 395 * 396 */ 397 #define SET_UTSBREG(regnum, tsbreg, tmp1) \ 398 mov regnum, tmp1; \ 399 stxa tsbreg, [tmp1]ASI_SCRATCHPAD /* save tsbreg */ 400 401 /* 402 * Get TSB base register from the scratchpad 403 * 404 * In: 405 * regnum = constant or register 406 * tsbreg = scratch 407 * Out: 408 * tsbreg = tsbreg from the specified scratchpad register 409 */ 410 #define GET_UTSBREG(regnum, tsbreg) \ 411 mov regnum, tsbreg; \ 412 ldxa [tsbreg]ASI_SCRATCHPAD, tsbreg 413 414 415 /* 416 * Get the location of the TSB entry in the first TSB to probe 417 * 418 * In: 419 * tagacc = tag access register (not clobbered) 420 * tsbe, tmp1, tmp2 = scratch registers 421 * Out: 422 * tsbe = pointer to the tsbe in the 1st TSB 423 */ 424 425 #define GET_1ST_TSBE_PTR(tagacc, tsbe, tmp1, tmp2) \ 426 /* BEGIN CSTYLED */ \ 427 mov SCRATCHPAD_UTSBREG1, tmp1 ;\ 428 ldxa [tmp1]ASI_SCRATCHPAD, tsbe /* get tsbreg */ ;\ 429 and tsbe, TSB_SOFTSZ_MASK, tmp2 /* tmp2=szc */ ;\ 430 andn tsbe, TSB_SOFTSZ_MASK, tsbe /* tsbbase */ ;\ 431 mov TSB_ENTRIES(0), tmp1 /* nentries in TSB size 0 */ ;\ 432 sllx tmp1, tmp2, tmp1 /* tmp1 = nentries in TSB */ ;\ 433 sub tmp1, 1, tmp1 /* mask = nentries - 1 */ ;\ 434 srlx tagacc, MMU_PAGESHIFT, tmp2 ;\ 435 and tmp2, tmp1, tmp1 /* tsbent = virtpage & mask */ ;\ 436 sllx tmp1, TSB_ENTRY_SHIFT, tmp1 /* entry num --> ptr */ ;\ 437 add tsbe, tmp1, tsbe /* add entry offset to TSB base */ ;\ 438 /* END CSTYLED */ 439 440 441 /* 442 * Will probe the first TSB, and if it finds a match, will insert it 443 * into the TLB and retry. 444 * 445 * tsbe_ptr = precomputed first TSB entry pointer (in, ro) 446 * vpg_4m = 4M virtual page number for tag matching (in, ro) 447 * label = where to branch to if this is a miss (text) 448 * %asi = atomic ASI to use for the TSB access 449 * 450 * For trapstat, we have to explicily use these registers. 451 * g4 = location tag will be retrieved into from TSB (out) 452 * g5 = location data(tte) will be retrieved into from TSB (out) 453 */ 454 #define PROBE_1ST_DTSB(tsbe_ptr, vpg_4m, label) /* g4/g5 clobbered */ \ 455 /* BEGIN CSTYLED */ \ 456 ldda [tsbe_ptr]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, g5 = data */ ;\ 457 cmp %g4, vpg_4m /* compare tag w/ TSB */ ;\ 458 bne,pn %xcc, label/**/1 /* branch if !match */ ;\ 459 nop ;\ 460 brgez,pn %g5, label/**/1 ;\ 461 nop ;\ 462 TT_TRACE(trace_tsbhit) ;\ 463 DTLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ 464 /* trapstat expects tte in %g5 */ ;\ 465 retry /* retry faulted instruction */ ;\ 466 label/**/1: \ 467 /* END CSTYLED */ 468 469 470 /* 471 * Same as above, only if the TTE doesn't have the execute 472 * bit set, will branch to exec_fault directly. 473 */ 474 #define PROBE_1ST_ITSB(tsbe_ptr, vpg_4m, label) \ 475 /* BEGIN CSTYLED */ \ 476 ldda [tsbe_ptr]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, g5 = data */ ;\ 477 cmp %g4, vpg_4m /* compare tag w/ TSB */ ;\ 478 bne,pn %xcc, label/**/1 /* branch if !match */ ;\ 479 nop ;\ 480 brgez,pn %g5, label/**/1 ;\ 481 nop ;\ 482 andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ 483 bz,pn %icc, exec_fault ;\ 484 nop ;\ 485 TT_TRACE(trace_tsbhit) ;\ 486 ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ 487 retry /* retry faulted instruction */ ;\ 488 label/**/1: \ 489 /* END CSTYLED */ 490 491 492 /* 493 * Get the location in the 2nd TSB of the tsbe for this fault. 494 * Assumes that the second TSB only contains 4M mappings. 495 * 496 * In: 497 * tagacc = tag access register (not clobbered) 498 * tsbe, tmp1, tmp2 = scratch registers 499 * Out: 500 * tsbe = pointer to the tsbe in the 2nd TSB 501 */ 502 503 #define GET_2ND_TSBE_PTR(tagacc, tsbe, tmp1, tmp2) \ 504 mov SCRATCHPAD_UTSBREG2, tmp1; \ 505 ldxa [tmp1]ASI_SCRATCHPAD, tsbe; /* get tsbreg */ \ 506 and tsbe, TSB_SOFTSZ_MASK, tmp2; /* tmp2=szc */ \ 507 andn tsbe, TSB_SOFTSZ_MASK, tsbe; /* tsbbase */ \ 508 mov TSB_ENTRIES(0), tmp1; /* nentries in TSB size 0 */ \ 509 sllx tmp1, tmp2, tmp1; /* tmp1 = nentries in TSB */ \ 510 sub tmp1, 1, tmp1; /* mask = nentries - 1 */ \ 511 srlx tagacc, MMU_PAGESHIFT4M, tmp2; \ 512 and tmp2, tmp1, tmp1; /* tsbent = virtpage & mask */ \ 513 sllx tmp1, TSB_ENTRY_SHIFT, tmp1; /* entry num --> ptr */ \ 514 add tsbe, tmp1, tsbe /* add entry offset to TSB base */ 515 516 517 /* 518 * vpg_4m = 4M virtual page number for tag matching (in) 519 * tsbe_ptr = precomputed second TSB entry pointer (in) 520 * label = label to use to make branch targets unique (text) 521 * 522 * For trapstat, we have to explicity use these registers. 523 * g4 = tag portion of TSBE (out) 524 * g5 = data portion of TSBE (out) 525 */ 526 #define PROBE_2ND_DTSB(tsbe_ptr, vpg_4m, label) \ 527 /* BEGIN CSTYLED */ \ 528 ldda [tsbe_ptr]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, g5 = data */ ;\ 529 /* since we are looking at 2nd tsb, if it's valid, it must be 4M */ ;\ 530 cmp %g4, vpg_4m ;\ 531 bne,pn %xcc, label/**/1 ;\ 532 nop ;\ 533 brgez,pn %g5, label/**/1 ;\ 534 nop ;\ 535 mov tsbe_ptr, %g1 /* trace_tsbhit wants ptr in %g1 */ ;\ 536 TT_TRACE(trace_tsbhit) ;\ 537 DTLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ 538 /* trapstat expects tte in %g5 */ ;\ 539 retry /* retry faulted instruction */ ;\ 540 label/**/1: \ 541 /* END CSTYLED */ 542 543 544 /* 545 * Same as above, with the following additions: 546 * If the TTE found is not executable, branch directly 547 * to exec_fault. If a TSB miss, branch to TSB miss handler. 548 */ 549 #define PROBE_2ND_ITSB(tsbe_ptr, vpg_4m) \ 550 /* BEGIN CSTYLED */ \ 551 ldda [tsbe_ptr]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, g5 = data */ ;\ 552 cmp %g4, vpg_4m /* compare tag w/ TSB */ ;\ 553 bne,pn %xcc, sfmmu_tsb_miss_tt /* branch if !match */ ;\ 554 nop ;\ 555 brgez,pn %g5, sfmmu_tsb_miss_tt ;\ 556 nop ;\ 557 andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ 558 bz,pn %icc, exec_fault ;\ 559 mov tsbe_ptr, %g1 /* trap trace wants ptr in %g1 */ ;\ 560 TT_TRACE(trace_tsbhit) ;\ 561 ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ 562 retry /* retry faulted instruction */ \ 563 /* END CSTYLED */ 564 565 566 #endif /* _ASM */ 567 568 #ifdef __cplusplus 569 } 570 #endif 571 572 #endif /* _VM_MACH_SFMMU_H */ 573