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