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 /* 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/cheetahregs.h> 41 #include <sys/spitregs.h> 42 #include <sys/opl_olympus_regs.h> 43 44 #ifdef __cplusplus 45 extern "C" { 46 #endif 47 48 /* 49 * On sun4u platforms, user TSBs are accessed via virtual address by default. 50 * Platforms that support ASI_SCRATCHPAD registers can define UTSB_PHYS in the 51 * platform Makefile to access user TSBs via physical address but must also 52 * designate one ASI_SCRATCHPAD register to hold the second user TSB. To 53 * designate the user TSB scratchpad register, platforms must provide a 54 * definition for SCRATCHPAD_UTSBREG below. 55 * 56 * Platforms that use UTSB_PHYS do not allocate 2 locked TLB entries to access 57 * the user TSBs. 58 */ 59 #if defined(UTSB_PHYS) 60 61 #if defined(_OPL) 62 #define SCRATCHPAD_UTSBREG OPL_SCRATCHPAD_UTSBREG4 63 #else 64 #error "Compiling UTSB_PHYS but no SCRATCHPAD_UTSBREG specified" 65 #endif 66 67 #endif /* UTSB_PHYS */ 68 69 70 #ifdef _ASM 71 72 /* 73 * This macro is used in the MMU code to check if TL should be lowered from 74 * 2 to 1 to pop trapstat's state. See the block comment in trapstat.c 75 * for details. 76 */ 77 78 #define TSTAT_CHECK_TL1(label, scr1, scr2) \ 79 rdpr %tpc, scr1; \ 80 sethi %hi(KERNELBASE), scr2; \ 81 or scr2, %lo(KERNELBASE), scr2; \ 82 cmp scr1, scr2; \ 83 bgeu %xcc, 9f; \ 84 nop; \ 85 ba label; \ 86 wrpr %g0, 1, %tl; \ 87 9: 88 89 90 /* 91 * The following macros allow us to share majority of the 92 * SFMMU code between sun4u and sun4v platforms. 93 */ 94 95 #define SETUP_TSB_ASI(qlp, tmp) \ 96 movrz qlp, ASI_N, tmp; \ 97 movrnz qlp, ASI_MEM, tmp; \ 98 mov tmp, %asi 99 100 /* 101 * Macro to swtich to alternate global register on sun4u platforms 102 * (not applicable to sun4v platforms) 103 */ 104 #define USE_ALTERNATE_GLOBALS(scr) \ 105 rdpr %pstate, scr; \ 106 wrpr scr, PSTATE_MG | PSTATE_AG, %pstate 107 108 /* 109 * Macro to set %gl register value on sun4v platforms 110 * (not applicable to sun4u platforms) 111 */ 112 #define SET_GL_REG(val) 113 114 /* 115 * Get MMU data tag access register value 116 * 117 * In: 118 * tagacc, scr1 = scratch registers 119 * Out: 120 * tagacc = MMU data tag access register value 121 */ 122 #define GET_MMU_D_TAGACC(tagacc, scr1) \ 123 mov MMU_TAG_ACCESS, scr1; \ 124 ldxa [scr1]ASI_DMMU, tagacc 125 126 /* 127 * Get MMU data tag target register 128 * 129 * In: 130 * ttarget, scr1 = scratch registers 131 * Out: 132 * ttarget = MMU data tag target register value 133 */ 134 #define GET_MMU_D_TTARGET(ttarget, scr1) \ 135 ldxa [%g0]ASI_DMMU, ttarget 136 137 /* 138 * Get MMU data/instruction tag access register values 139 * 140 * In: 141 * dtagacc, itagacc, scr1, scr2 = scratch registers 142 * Out: 143 * dtagacc = MMU data tag access register value 144 * itagacc = MMU instruction tag access register value 145 */ 146 #define GET_MMU_BOTH_TAGACC(dtagacc, itagacc, scr1, scr2) \ 147 mov MMU_TAG_ACCESS, scr1; \ 148 ldxa [scr1]ASI_DMMU, dtagacc; \ 149 ldxa [scr1]ASI_IMMU, itagacc 150 151 /* 152 * Get MMU data fault address from the tag access register 153 * 154 * In: 155 * daddr, scr1 = scratch registers 156 * Out: 157 * daddr = MMU data fault address 158 */ 159 #define GET_MMU_D_ADDR(daddr, scr1) \ 160 mov MMU_TAG_ACCESS, scr1; \ 161 ldxa [scr1]ASI_DMMU, daddr; \ 162 set TAGACC_CTX_MASK, scr1; \ 163 andn daddr, scr1, daddr 164 165 166 /* 167 * Load ITLB entry 168 * 169 * In: 170 * tte = reg containing tte 171 * scr1, scr2, scr3, scr4 = scratch registers (not used) 172 */ 173 #define ITLB_STUFF(tte, scr1, scr2, scr3, scr4) \ 174 stxa tte, [%g0]ASI_ITLB_IN 175 176 /* 177 * Load DTLB entry 178 * 179 * In: 180 * tte = reg containing tte 181 * scr1, scr2, scr3, scr4 = scratch register (not used) 182 */ 183 #define DTLB_STUFF(tte, scr1, scr2, scr3, scr4) \ 184 stxa tte, [%g0]ASI_DTLB_IN 185 186 187 /* 188 * Returns PFN given the TTE and vaddr 189 * 190 * In: 191 * tte = reg containing tte 192 * vaddr = reg containing vaddr 193 * scr1, scr2, scr3 = scratch registers 194 * Out: 195 * tte = PFN value 196 */ 197 #define TTETOPFN(tte, vaddr, label, scr1, scr2, scr3) \ 198 srlx tte, TTE_SZ_SHFT, scr1; \ 199 and scr1, TTE_SZ_BITS, scr1; /* scr1 = tte_size */ \ 200 srlx tte, TTE_SZ2_SHFT, scr3; \ 201 and scr3, TTE_SZ2_BITS, scr3; /* scr3 = tte_size2 */ \ 202 or scr1, scr3, scr1; \ 203 sllx scr1, 1, scr2; \ 204 add scr2, scr1, scr2; /* mulx 3 */ \ 205 sllx tte, TTE_PA_LSHIFT, tte; \ 206 add scr2, MMU_PAGESHIFT + TTE_PA_LSHIFT, scr3; \ 207 /* BEGIN CSTYLED */ \ 208 brz,pt scr2, label/**/1; \ 209 srlx tte, scr3, tte; \ 210 /* END CSTYLED */ \ 211 sllx tte, scr2, tte; \ 212 set 1, scr1; \ 213 add scr2, MMU_PAGESHIFT, scr3; \ 214 sllx scr1, scr3, scr1; \ 215 sub scr1, 1, scr1; /* g2=TTE_PAGE_OFFSET(ttesz) */ \ 216 and vaddr, scr1, scr2; \ 217 srln scr2, MMU_PAGESHIFT, scr2; \ 218 or tte, scr2, tte; \ 219 /* CSTYLED */ \ 220 label/**/1: 221 222 223 /* 224 * TTE_SET_REF_ML is a macro that updates the reference bit if it is 225 * not already set. 226 * 227 * Parameters: 228 * tte = reg containing tte 229 * ttepa = physical pointer to tte 230 * tteva = virtual ptr to tte 231 * tsbarea = tsb miss area 232 * tmp1 = tmp reg 233 * label = temporary label 234 */ 235 236 #define TTE_SET_REF_ML(tte, ttepa, tteva, tsbarea, tmp1, label) \ 237 /* BEGIN CSTYLED */ \ 238 /* check reference bit */ \ 239 andcc tte, TTE_REF_INT, %g0; \ 240 bnz,pt %xcc, label/**/4; /* if ref bit set-skip ahead */ \ 241 nop; \ 242 GET_CPU_IMPL(tmp1); \ 243 cmp tmp1, SPITFIRE_IMPL; \ 244 blt %icc, label/**/2; /* skip flush if FJ-OPL cpus */ \ 245 cmp tmp1, CHEETAH_IMPL; \ 246 bl,a %icc, label/**/1; \ 247 /* update reference bit */ \ 248 lduh [tsbarea + TSBMISS_DMASK], tmp1; \ 249 stxa %g0, [ttepa]ASI_DC_INVAL; /* flush line from dcache */ \ 250 membar #Sync; \ 251 ba label/**/2; \ 252 label/**/1: \ 253 and tteva, tmp1, tmp1; \ 254 stxa %g0, [tmp1]ASI_DC_TAG; /* flush line from dcache */ \ 255 membar #Sync; \ 256 label/**/2: \ 257 or tte, TTE_REF_INT, tmp1; \ 258 casxa [ttepa]ASI_MEM, tte, tmp1; /* update ref bit */ \ 259 cmp tte, tmp1; \ 260 bne,a,pn %xcc, label/**/2; \ 261 ldxa [ttepa]ASI_MEM, tte; /* MMU_READTTE through pa */ \ 262 or tte, TTE_REF_INT, tte; \ 263 label/**/4: \ 264 /* END CSTYLED */ 265 266 267 /* 268 * TTE_SET_REFMOD_ML is a macro that updates the reference and modify bits 269 * if not already set. 270 * 271 * Parameters: 272 * tte = reg containing tte 273 * ttepa = physical pointer to tte 274 * tteva = virtual ptr to tte 275 * tsbarea = tsb miss area 276 * tmp1 = tmp reg 277 * label = temporary label 278 * exitlabel = label where to jump to if write perm bit not set. 279 */ 280 281 #define TTE_SET_REFMOD_ML(tte, ttepa, tteva, tsbarea, tmp1, label, \ 282 exitlabel) \ 283 /* BEGIN CSTYLED */ \ 284 /* check reference bit */ \ 285 andcc tte, TTE_WRPRM_INT, %g0; \ 286 bz,pn %xcc, exitlabel; /* exit if wr_perm not set */ \ 287 nop; \ 288 andcc tte, TTE_HWWR_INT, %g0; \ 289 bnz,pn %xcc, label/**/4; /* nothing to do */ \ 290 nop; \ 291 GET_CPU_IMPL(tmp1); \ 292 cmp tmp1, SPITFIRE_IMPL; \ 293 blt %icc, label/**/2; /* skip flush if FJ-OPL cpus */ \ 294 cmp tmp1, CHEETAH_IMPL; \ 295 bl,a %icc, label/**/1; \ 296 /* update reference bit */ \ 297 lduh [tsbarea + TSBMISS_DMASK], tmp1; \ 298 stxa %g0, [ttepa]ASI_DC_INVAL; /* flush line from dcache */ \ 299 membar #Sync; \ 300 ba label/**/2; \ 301 label/**/1: \ 302 and tteva, tmp1, tmp1; \ 303 stxa %g0, [tmp1]ASI_DC_TAG; /* flush line from dcache */ \ 304 membar #Sync; \ 305 label/**/2: \ 306 or tte, TTE_HWWR_INT | TTE_REF_INT, tmp1; \ 307 casxa [ttepa]ASI_MEM, tte, tmp1; /* update ref/mod bit */ \ 308 cmp tte, tmp1; \ 309 bne,a,pn %xcc, label/**/2; \ 310 ldxa [ttepa]ASI_MEM, tte; /* MMU_READTTE through pa */ \ 311 or tte, TTE_HWWR_INT | TTE_REF_INT, tte; \ 312 label/**/4: \ 313 /* END CSTYLED */ 314 315 316 #ifndef UTSB_PHYS 317 318 /* 319 * Synthesize TSB base register contents for a process with 320 * a single TSB. 321 * 322 * We patch the virtual address mask in at runtime since the 323 * number of significant virtual address bits in the TSB VA 324 * can vary depending upon the TSB slab size being used on the 325 * machine. 326 * 327 * In: 328 * tsbinfo = TSB info pointer (ro) 329 * vabase = value of utsb_vabase (ro) 330 * Out: 331 * tsbreg = value to program into TSB base register 332 */ 333 334 #define MAKE_TSBREG(tsbreg, tsbinfo, vabase, tmp1, tmp2, label) \ 335 /* BEGIN CSTYLED */ \ 336 ldx [tsbinfo + TSBINFO_VADDR], tmp1; \ 337 .global label/**/_tsbreg_vamask ;\ 338 label/**/_tsbreg_vamask: \ 339 or %g0, RUNTIME_PATCH, tsbreg; \ 340 lduh [tsbinfo + TSBINFO_SZCODE], tmp2; \ 341 sllx tsbreg, TSBREG_VAMASK_SHIFT, tsbreg; \ 342 or vabase, tmp2, tmp2; \ 343 and tmp1, tsbreg, tsbreg; \ 344 or tsbreg, tmp2, tsbreg; \ 345 /* END CSTYLED */ 346 347 348 /* 349 * Synthesize TSB base register contents for a process with 350 * two TSBs. See hat_sfmmu.h for the layout of the TSB base 351 * register in this case. 352 * 353 * In: 354 * tsb1 = pointer to first TSB info (ro) 355 * tsb2 = pointer to second TSB info (ro) 356 * Out: 357 * tsbreg = value to program into TSB base register 358 */ 359 #define MAKE_TSBREG_SECTSB(tsbreg, tsb1, tsb2, tmp1, tmp2, tmp3, label) \ 360 /* BEGIN CSTYLED */ \ 361 set TSBREG_MSB_CONST, tmp3 ;\ 362 sllx tmp3, TSBREG_MSB_SHIFT, tsbreg ;\ 363 .global label/**/_tsbreg_vamask ;\ 364 label/**/_tsbreg_vamask: ;\ 365 or %g0, RUNTIME_PATCH, tmp3 ;\ 366 sll tmp3, TSBREG_VAMASK_SHIFT, tmp3 ;\ 367 ldx [tsb1 + TSBINFO_VADDR], tmp1 ;\ 368 ldx [tsb2 + TSBINFO_VADDR], tmp2 ;\ 369 and tmp1, tmp3, tmp1 ;\ 370 and tmp2, tmp3, tmp2 ;\ 371 sllx tmp2, TSBREG_SECTSB_MKSHIFT, tmp2 ;\ 372 or tmp1, tmp2, tmp3 ;\ 373 or tsbreg, tmp3, tsbreg ;\ 374 lduh [tsb1 + TSBINFO_SZCODE], tmp1 ;\ 375 lduh [tsb2 + TSBINFO_SZCODE], tmp2 ;\ 376 and tmp1, TSB_SOFTSZ_MASK, tmp1 ;\ 377 and tmp2, TSB_SOFTSZ_MASK, tmp2 ;\ 378 sllx tmp2, TSBREG_SECSZ_SHIFT, tmp2 ;\ 379 or tmp1, tmp2, tmp3 ;\ 380 or tsbreg, tmp3, tsbreg ;\ 381 /* END CSTYLED */ 382 383 384 /* 385 * Load the locked TSB TLB entry. 386 * 387 * In: 388 * tsbinfo = tsb_info pointer as va (ro) 389 * tteidx = shifted index into TLB to load the locked entry (ro) 390 * va = virtual address at which to load the locked TSB entry (ro) 391 * Out: 392 * Scratch: 393 * tmp 394 */ 395 #define LOAD_TSBTTE(tsbinfo, tteidx, va, tmp) \ 396 mov MMU_TAG_ACCESS, tmp; \ 397 stxa va, [tmp]ASI_DMMU; /* set tag access */ \ 398 membar #Sync; \ 399 ldx [tsbinfo + TSBINFO_TTE], tmp; /* fetch locked tte */ \ 400 stxa tmp, [tteidx]ASI_DTLB_ACCESS; /* load locked tte */ \ 401 membar #Sync 402 403 404 /* 405 * In the current implementation, TSBs usually come from physically 406 * contiguous chunks of memory up to 4MB in size, but 8K TSBs may be 407 * allocated from 8K chunks of memory under certain conditions. To 408 * prevent aliasing in the virtual address cache when the TSB slab is 409 * 8K in size we must align the reserved (TL>0) TSB virtual address to 410 * have the same low-order bits as the kernel (TL=0) TSB virtual address, 411 * and map 8K TSBs with an 8K TTE. In cases where the TSB reserved VA 412 * range is smaller than the assumed 4M we will patch the shift at 413 * runtime; otherwise we leave it alone (which is why RUNTIME_PATCH 414 * constant doesn't appear below). 415 * 416 * In: 417 * tsbinfo (ro) 418 * resva: reserved VA base for this TSB 419 * Out: 420 * resva: corrected VA for this TSB 421 */ 422 #define RESV_OFFSET(tsbinfo, resva, tmp1, label) \ 423 /* BEGIN CSTYLED */ \ 424 lduh [tsbinfo + TSBINFO_SZCODE], tmp1 ;\ 425 brgz,pn tmp1, 9f ;\ 426 nop ;\ 427 ldx [tsbinfo + TSBINFO_VADDR], tmp1 ;\ 428 .global label/**/_resv_offset ;\ 429 label/**/_resv_offset: ;\ 430 sllx tmp1, (64 - MMU_PAGESHIFT4M), tmp1 ;\ 431 srlx tmp1, (64 - MMU_PAGESHIFT4M), tmp1 ;\ 432 or tmp1, resva, resva ;\ 433 9: /* END CSTYLED */ 434 435 /* 436 * Determine the pointer of the entry in the first TSB to probe given 437 * the 8K TSB pointer register contents. 438 * 439 * In: 440 * tsbp8k = 8K TSB pointer register (ro) 441 * tmp = scratch register 442 * label = label for hot patching of utsb_vabase 443 * 444 * Out: tsbe_ptr = TSB entry address 445 * 446 * Note: This function is patched at runtime for performance reasons. 447 * Any changes here require sfmmu_patch_utsb fixed. 448 */ 449 450 #define GET_1ST_TSBE_PTR(tsbp8k, tsbe_ptr, tmp, label) \ 451 /* BEGIN CSTYLED */ \ 452 label/**/_get_1st_tsbe_ptr: ;\ 453 RUNTIME_PATCH_SETX(tsbe_ptr, tmp) ;\ 454 /* tsbeptr = contents of utsb_vabase */ ;\ 455 /* clear upper bits leaving just bits 21:0 of TSB ptr. */ ;\ 456 sllx tsbp8k, TSBREG_FIRTSB_SHIFT, tmp ;\ 457 /* finish clear */ ;\ 458 srlx tmp, TSBREG_FIRTSB_SHIFT, tmp ;\ 459 /* or-in bits 41:22 of the VA to form the real pointer. */ ;\ 460 or tsbe_ptr, tmp, tsbe_ptr \ 461 /* END CSTYLED */ 462 463 /* 464 * Determine the base address of the second TSB given the 8K TSB 465 * pointer register contents. 466 * 467 * In: 468 * tsbp8k = 8K TSB pointer register (ro) 469 * tmp = scratch register 470 * label = label for hot patching of utsb_vabase 471 * 472 * Out: 473 * tsbbase = TSB base address 474 * 475 * Note: This function is patched at runtime for performance reasons. 476 * Any changes here require sfmmu_patch_utsb fixed. 477 */ 478 479 #define GET_2ND_TSB_BASE(tsbp8k, tsbbase, tmp, label) \ 480 /* BEGIN CSTYLED */ \ 481 label/**/_get_2nd_tsb_base: ;\ 482 RUNTIME_PATCH_SETX(tsbbase, tmp) ;\ 483 /* tsbbase = contents of utsb4m_vabase */ ;\ 484 /* clear upper bits leaving just bits 21:xx of TSB addr. */ ;\ 485 sllx tsbp8k, TSBREG_SECTSB_LSHIFT, tmp ;\ 486 /* clear lower bits leaving just 21:13 in 8:0 */ ;\ 487 srlx tmp, (TSBREG_SECTSB_RSHIFT + MMU_PAGESHIFT), tmp ;\ 488 /* adjust TSB offset to bits 21:13 */ ;\ 489 sllx tmp, MMU_PAGESHIFT, tmp ;\ 490 or tsbbase, tmp, tsbbase ;\ 491 /* END CSTYLED */ 492 493 /* 494 * Determine the size code of the second TSB given the 8K TSB 495 * pointer register contents. 496 * 497 * In: 498 * tsbp8k = 8K TSB pointer register (ro) 499 * Out: 500 * size = TSB size code 501 */ 502 503 #define GET_2ND_TSB_SIZE(tsbp8k, size) \ 504 srlx tsbp8k, TSBREG_SECSZ_SHIFT, size; \ 505 and size, TSB_SOFTSZ_MASK, size 506 507 /* 508 * Get the location in the 2nd TSB of the tsbe for this fault. 509 * Assumes that the second TSB only contains 4M mappings. 510 * 511 * In: 512 * tagacc = tag access register (clobbered) 513 * tsbp8k = contents of TSB8K pointer register (ro) 514 * tmp1, tmp2 = scratch registers 515 * label = label at which to patch in reserved TSB 4M VA range 516 * Out: 517 * tsbe_ptr = pointer to the tsbe in the 2nd TSB 518 */ 519 #define GET_2ND_TSBE_PTR(tagacc, tsbp8k, tsbe_ptr, tmp1, tmp2, label) \ 520 GET_2ND_TSB_BASE(tsbp8k, tsbe_ptr, tmp2, label); \ 521 /* tsbe_ptr = TSB base address, tmp2 = junk */ \ 522 GET_2ND_TSB_SIZE(tsbp8k, tmp1); \ 523 /* tmp1 = TSB size code */ \ 524 GET_TSBE_POINTER(MMU_PAGESHIFT4M, tsbe_ptr, tagacc, tmp1, tmp2) 525 526 #endif /* UTSB_PHYS */ 527 528 529 #ifdef UTSB_PHYS 530 531 /* 532 * Synthesize a TSB base register contents for a process. 533 * 534 * In: 535 * tsbinfo = TSB info pointer (ro) 536 * tsbreg, tmp1 = scratch registers 537 * Out: 538 * tsbreg = value to program into TSB base register 539 */ 540 541 #define MAKE_UTSBREG_PHYS(tsbinfo, tsbreg, tmp1) \ 542 ldx [tsbinfo + TSBINFO_PADDR], tsbreg; \ 543 lduh [tsbinfo + TSBINFO_SZCODE], tmp1; \ 544 and tmp1, TSB_SOFTSZ_MASK, tmp1; \ 545 or tsbreg, tmp1, tsbreg; \ 546 547 /* 548 * Load TSB base register into a dedicated scratchpad register. 549 * This register contains utsb_pabase in bits 63:13, and TSB size 550 * code in bits 2:0. 551 * 552 * In: 553 * tsbreg = value to load (ro) 554 * regnum = constant or register 555 * tmp1 = scratch register 556 * Out: 557 * Specified scratchpad register updated 558 * 559 * Note: If this is enabled on Panther, a membar #Sync is required 560 * following an ASI store to the scratchpad registers. 561 */ 562 563 #define SET_UTSBREG(regnum, tsbreg, tmp1) \ 564 mov regnum, tmp1; \ 565 stxa tsbreg, [tmp1]ASI_SCRATCHPAD; /* save tsbreg */ \ 566 567 /* 568 * Get TSB base register from the scratchpad 569 * 570 * In: 571 * regnum = constant or register 572 * tsbreg = scratch 573 * Out: 574 * tsbreg = tsbreg from the specified scratchpad register 575 */ 576 577 #define GET_UTSBREG(regnum, tsbreg) \ 578 mov regnum, tsbreg; \ 579 ldxa [tsbreg]ASI_SCRATCHPAD, tsbreg 580 581 /* 582 * Determine the pointer of the entry in the first TSB to probe given 583 * the 8K TSB pointer register contents. 584 * 585 * In: 586 * tagacc = tag access register 587 * tsbe_ptr = 8K TSB pointer register 588 * tmp = scratch registers 589 * 590 * Out: tsbe_ptr = TSB entry address 591 * 592 * Note: This macro is a nop since the 8K TSB pointer register 593 * is the entry pointer and does not need to be decoded. 594 * It is defined to allow for code sharing with sun4v. 595 */ 596 597 #define GET_1ST_TSBE_PTR(tagacc, tsbe_ptr, tmp1, tmp2) 598 599 /* 600 * Get the location in the 2nd TSB of the tsbe for this fault. 601 * Assumes that the second TSB only contains 4M mappings. 602 * 603 * In: 604 * tagacc = tag access register (not clobbered) 605 * tsbe = 2nd TSB base register 606 * tmp1, tmp2 = scratch registers 607 * Out: 608 * tsbe = pointer to the tsbe in the 2nd TSB 609 */ 610 611 #define GET_2ND_TSBE_PTR(tagacc, tsbe, tmp1, tmp2) \ 612 and tsbe, TSB_SOFTSZ_MASK, tmp2; /* tmp2=szc */ \ 613 andn tsbe, TSB_SOFTSZ_MASK, tsbe; /* tsbbase */ \ 614 mov TSB_ENTRIES(0), tmp1; /* nentries in TSB size 0 */ \ 615 sllx tmp1, tmp2, tmp1; /* tmp1 = nentries in TSB */ \ 616 sub tmp1, 1, tmp1; /* mask = nentries - 1 */ \ 617 srlx tagacc, MMU_PAGESHIFT4M, tmp2; \ 618 and tmp2, tmp1, tmp1; /* tsbent = virtpage & mask */ \ 619 sllx tmp1, TSB_ENTRY_SHIFT, tmp1; /* entry num --> ptr */ \ 620 add tsbe, tmp1, tsbe /* add entry offset to TSB base */ 621 622 /* 623 * Read the 2nd TSB base register. This is not done in GET_2ND_TSBE_PTR as 624 * an optimization since the TLB miss trap handler entries have potentially 625 * already loaded the 2nd TSB base reg when we invoke GET_2ND_TSBE_PTR. 626 * 627 * Out: 628 * tsbreg = contents of the 2nd TSB base register 629 */ 630 #define GET_2ND_TSBREG(tsbreg) \ 631 GET_UTSBREG(SCRATCHPAD_UTSBREG, tsbreg); 632 633 /* 634 * Load the 2nd TSB base into a dedicated scratchpad register which 635 * is used as a pseudo TSB base register. 636 * 637 * In: 638 * tsbreg = value to load (ro) 639 * regnum = constant or register 640 * tmp1 = scratch register 641 * Out: 642 * Specified scratchpad register updated 643 */ 644 #define LOAD_2ND_TSBREG(tsbreg, tmp1) \ 645 SET_UTSBREG(SCRATCHPAD_UTSBREG, tsbreg, tmp1); 646 647 #endif /* UTSB_PHYS */ 648 649 650 /* 651 * Load TSB base register. In the single TSB case this register 652 * contains utsb_vabase, bits 21:13 of tsbinfo->tsb_va, and the 653 * TSB size code in bits 2:0. See hat_sfmmu.h for the layout in 654 * the case where we have multiple TSBs per process. 655 * 656 * In: 657 * tsbreg = value to load (ro) 658 */ 659 #define LOAD_TSBREG(tsbreg, tmp1, tmp2) \ 660 mov MMU_TSB, tmp1; \ 661 sethi %hi(FLUSH_ADDR), tmp2; \ 662 stxa tsbreg, [tmp1]ASI_DMMU; /* dtsb reg */ \ 663 stxa tsbreg, [tmp1]ASI_IMMU; /* itsb reg */ \ 664 flush tmp2 665 666 #ifdef UTSB_PHYS 667 #define UTSB_PROBE_ASI ASI_QUAD_LDD_PHYS 668 #else 669 #define UTSB_PROBE_ASI ASI_NQUAD_LD 670 #endif 671 672 /* 673 * Will probe the first TSB, and if it finds a match, will insert it 674 * into the TLB and retry. 675 * 676 * tsbe_ptr = precomputed first TSB entry pointer (in, ro) 677 * vpg_4m = 4M virtual page number for tag matching (in, ro) 678 * label = where to branch to if this is a miss (text) 679 * %asi = atomic ASI to use for the TSB access 680 * 681 * For trapstat, we have to explicily use these registers. 682 * g4 = location tag will be retrieved into from TSB (out) 683 * g5 = location data(tte) will be retrieved into from TSB (out) 684 */ 685 #define PROBE_1ST_DTSB(tsbe_ptr, vpg_4m, label) /* g4/g5 clobbered */ \ 686 /* BEGIN CSTYLED */ \ 687 ldda [tsbe_ptr]UTSB_PROBE_ASI, %g4 /* g4 = tag, g5 = data */ ;\ 688 cmp %g4, vpg_4m /* compare tag w/ TSB */ ;\ 689 bne,pn %xcc, label/**/1 /* branch if !match */ ;\ 690 nop ;\ 691 TT_TRACE(trace_tsbhit) ;\ 692 DTLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ 693 /* trapstat expects tte in %g5 */ ;\ 694 retry /* retry faulted instruction */ ;\ 695 label/**/1: \ 696 /* END CSTYLED */ 697 698 /* 699 * Same as above, only if the TTE doesn't have the execute 700 * bit set, will branch to exec_fault directly. 701 */ 702 #define PROBE_1ST_ITSB(tsbe_ptr, vpg_4m, label) \ 703 /* BEGIN CSTYLED */ \ 704 ldda [tsbe_ptr]UTSB_PROBE_ASI, %g4 /* g4 = tag, g5 = data */ ;\ 705 cmp %g4, vpg_4m /* compare tag w/ TSB */ ;\ 706 bne,pn %xcc, label/**/1 /* branch if !match */ ;\ 707 nop ;\ 708 andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ 709 bz,pn %icc, exec_fault ;\ 710 nop ;\ 711 TT_TRACE(trace_tsbhit) ;\ 712 ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ 713 retry /* retry faulted instruction */ ;\ 714 label/**/1: \ 715 /* END CSTYLED */ 716 717 /* 718 * vpg_4m = 4M virtual page number for tag matching (in) 719 * tsbe_ptr = precomputed second TSB entry pointer (in) 720 * label = label to use to make branch targets unique (text) 721 * 722 * For trapstat, we have to explicity use these registers. 723 * g4 = tag portion of TSBE (out) 724 * g5 = data portion of TSBE (out) 725 */ 726 #define PROBE_2ND_DTSB(tsbe_ptr, vpg_4m, label) \ 727 /* BEGIN CSTYLED */ \ 728 ldda [tsbe_ptr]UTSB_PROBE_ASI, %g4 /* g4 = tag, g5 = data */ ;\ 729 /* since we are looking at 2nd tsb, if it's valid, it must be 4M */ ;\ 730 cmp %g4, vpg_4m ;\ 731 bne,pn %xcc, label/**/1 ;\ 732 nop ;\ 733 mov tsbe_ptr, %g1 /* trace_tsbhit wants ptr in %g1 */ ;\ 734 TT_TRACE(trace_tsbhit) ;\ 735 DTLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ 736 /* trapstat expects tte in %g5 */ ;\ 737 retry /* retry faulted instruction */ ;\ 738 label/**/1: \ 739 /* END CSTYLED */ 740 741 #ifndef TRAPTRACE 742 /* 743 * Same as above, with the following additions: 744 * If the TTE found is not executable, branch directly 745 * to exec_fault after checking for ITLB synthesis. 746 * If a TSB miss, branch to TSB miss handler. 747 */ 748 #define PROBE_2ND_ITSB(tsbe_ptr, vpg_4m, label) \ 749 /* BEGIN CSTYLED */ \ 750 ldda [tsbe_ptr]UTSB_PROBE_ASI, %g4 /* g4 = tag, g5 = data */ ;\ 751 cmp %g4, vpg_4m /* compare tag w/ TSB */ ;\ 752 bne,pn %xcc, sfmmu_tsb_miss_tt /* branch if !match */ ;\ 753 or %g0, TTE4M, %g6 ;\ 754 andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ 755 bz,a,pn %icc, label/**/1 ;\ 756 sllx %g6, TTE_SZ_SHFT, %g6 ;\ 757 ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ 758 retry /* retry faulted instruction */ ;\ 759 label/**/1: ;\ 760 andcc %g5, TTE_E_SYNTH_INT, %g0 ;\ 761 bz,pn %icc, exec_fault ;\ 762 or %g5, %g6, %g5 ;\ 763 ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ 764 retry /* retry faulted instruction */ \ 765 /* END CSTYLED */ 766 #else /* TRAPTRACE */ 767 /* 768 * Same as above, with the TT_TRACE and mov tsbe_ptr, %g1 additions. 769 */ 770 #define PROBE_2ND_ITSB(tsbe_ptr, vpg_4m, label) \ 771 /* BEGIN CSTYLED */ \ 772 ldda [tsbe_ptr]UTSB_PROBE_ASI, %g4 /* g4 = tag, g5 = data */ ;\ 773 cmp %g4, vpg_4m /* compare tag w/ TSB */ ;\ 774 bne,pn %xcc, sfmmu_tsb_miss_tt /* branch if !match */ ;\ 775 or %g0, TTE4M, %g6 ;\ 776 andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ 777 bz,a,pn %icc, label/**/1 ;\ 778 sllx %g6, TTE_SZ_SHFT, %g6 ;\ 779 mov tsbe_ptr, %g1 /* trap trace wants ptr in %g1 */ ;\ 780 TT_TRACE(trace_tsbhit) ;\ 781 ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ 782 retry /* retry faulted instruction */ ;\ 783 label/**/1: ;\ 784 andcc %g5, TTE_E_SYNTH_INT, %g0 ;\ 785 bz,pn %icc, exec_fault ;\ 786 mov tsbe_ptr, %g1 /* trap trace wants ptr in %g1 */ ;\ 787 or %g5, %g6, %g5 ;\ 788 TT_TRACE(trace_tsbhit) ;\ 789 ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ 790 retry /* retry faulted instruction */ \ 791 /* END CSTYLED */ 792 793 #endif /* TRAPTRACE */ 794 #endif /* _ASM */ 795 796 #ifdef __cplusplus 797 } 798 #endif 799 800 #endif /* _VM_MACH_SFMMU_H */ 801