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 #include <sys/types.h> 29 #include <sys/systm.h> 30 #include <sys/sysmacros.h> 31 #include <sys/archsystm.h> 32 #include <sys/vmsystm.h> 33 #include <sys/machparam.h> 34 #include <sys/machsystm.h> 35 #include <vm/vm_dep.h> 36 #include <vm/hat_sfmmu.h> 37 #include <vm/seg_kmem.h> 38 #include <sys/cmn_err.h> 39 #include <sys/debug.h> 40 #include <sys/cpu_module.h> 41 #include <sys/sysmacros.h> 42 #include <sys/panic.h> 43 44 /* 45 * Note that 'Cheetah PRM' refers to: 46 * SPARC V9 JPS1 Implementation Supplement: Sun UltraSPARC-III 47 */ 48 49 /* 50 * pan_disable_ism_large_pages and pan_disable_large_pages are the Panther- 51 * specific versions of disable_ism_large_pages and disable_large_pages, 52 * and feed back into those two hat variables at hat initialization time, 53 * for Panther-only systems. 54 * 55 * chpjag_disable_ism_large_pages is the Ch/Jaguar-specific version of 56 * disable_ism_large_pages. Ditto for chjag_disable_large_pages. 57 */ 58 static int panther_only = 0; 59 60 static int pan_disable_ism_large_pages = ((1 << TTE64K) | 61 (1 << TTE512K) | (1 << TTE256M)); 62 static int pan_disable_large_pages = (1 << TTE256M); 63 static int pan_disable_auto_large_pages = (1 << TTE4M) | (1 << TTE256M); 64 65 static int chjag_disable_ism_large_pages = ((1 << TTE64K) | 66 (1 << TTE512K) | (1 << TTE32M) | (1 << TTE256M)); 67 static int chjag_disable_large_pages = ((1 << TTE32M) | (1 << TTE256M)); 68 static int chjag_disable_auto_large_pages = ((1 << TTE32M) | (1 << TTE256M)); 69 70 /* 71 * The function returns the USIII-IV mmu-specific values for the 72 * hat's disable_large_pages and disable_ism_large_pages variables. 73 * Currently the hat's disable_large_pages and disable_ism_large_pages 74 * already contain the generic sparc 4 page size info, and the return 75 * values are or'd with those values. 76 */ 77 int 78 mmu_large_pages_disabled(uint_t flag) 79 { 80 int pages_disable = 0; 81 82 if (panther_only) { 83 if (flag == HAT_LOAD) { 84 pages_disable = pan_disable_large_pages; 85 } else if (flag == HAT_LOAD_SHARE) { 86 pages_disable = pan_disable_ism_large_pages; 87 } else if (flag == HAT_LOAD_AUTOLPG) { 88 pages_disable = pan_disable_auto_large_pages; 89 } 90 } else { 91 if (flag == HAT_LOAD) { 92 pages_disable = chjag_disable_large_pages; 93 } else if (flag == HAT_LOAD_SHARE) { 94 pages_disable = chjag_disable_ism_large_pages; 95 } else if (flag == HAT_LOAD_AUTOLPG) { 96 pages_disable = chjag_disable_auto_large_pages; 97 } 98 } 99 return (pages_disable); 100 } 101 102 #if defined(CPU_IMP_DUAL_PAGESIZE) 103 /* 104 * If a platform is running with only Ch+ or Jaguar, and then someone DR's 105 * in a Panther board, the Panther mmu will not like it if one of the already 106 * running threads is context switched to the Panther and tries to program 107 * a 512K or 4M page into the T512_1. So make these platforms pay the price 108 * and follow the Panther DTLB restrictions by default. :) 109 * The mmu_init_mmu_page_sizes code below takes care of heterogeneous 110 * platforms that don't support DR, like daktari. 111 * 112 * The effect of these restrictions is to limit the allowable values in 113 * sfmmu_pgsz[0] and sfmmu_pgsz[1], since these hat variables are used in 114 * mmu_set_ctx_page_sizes to set up the values in the sfmmu_cext that 115 * are used at context switch time. The value in sfmmu_pgsz[0] is used in 116 * P_pgsz0 and sfmmu_pgsz[1] is used in P_pgsz1, as per Figure F-1-1 117 * IMMU and DMMU Primary Context Register in the Panther Implementation 118 * Supplement and Table 15-21 DMMU Primary Context Register in the 119 * Cheetah+ Delta PRM. 120 */ 121 #ifdef MIXEDCPU_DR_SUPPORTED 122 int panther_dtlb_restrictions = 1; 123 #else 124 int panther_dtlb_restrictions = 0; 125 #endif /* MIXEDCPU_DR_SUPPORTED */ 126 127 /* 128 * init_mmu_page_sizes is set to one after the bootup time initialization 129 * via mmu_init_mmu_page_sizes, to indicate that mmu_page_sizes has a 130 * valid value. 131 */ 132 int init_mmu_page_sizes = 0; 133 134 /* 135 * mmu_init_large_pages is called with the desired ism_pagesize parameter, 136 * for Panther-only systems. It may be called from set_platform_defaults, 137 * if some value other than 32M is desired, for Panther-only systems. 138 * mmu_ism_pagesize is the tunable. If it has a bad value, then only warn, 139 * since it would be bad form to panic due 140 * to a user typo. 141 * 142 * The function re-initializes the pan_disable_ism_large_pages and 143 * pan_disable_large_pages variables, which are closely related. 144 * Aka, if 32M is the desired [D]ISM page sizes, then 256M cannot be allowed 145 * for non-ISM large page usage, or DTLB conflict will occur. Please see the 146 * Panther PRM for additional DTLB technical info. 147 */ 148 void 149 mmu_init_large_pages(size_t ism_pagesize) 150 { 151 if (cpu_impl_dual_pgsz == 0) { /* disable_dual_pgsz flag */ 152 pan_disable_ism_large_pages = ((1 << TTE64K) | 153 (1 << TTE512K) | (1 << TTE32M) | (1 << TTE256M)); 154 pan_disable_large_pages = ((1 << TTE32M) | (1 << TTE256M)); 155 auto_lpg_maxszc = TTE4M; 156 return; 157 } 158 159 switch (ism_pagesize) { 160 case MMU_PAGESIZE4M: 161 pan_disable_ism_large_pages = ((1 << TTE64K) | 162 (1 << TTE512K) | (1 << TTE32M) | (1 << TTE256M)); 163 pan_disable_large_pages = (1 << TTE256M); 164 pan_disable_auto_large_pages = (1 << TTE32M) | (1 << TTE256M); 165 auto_lpg_maxszc = TTE4M; 166 break; 167 case MMU_PAGESIZE32M: 168 pan_disable_ism_large_pages = ((1 << TTE64K) | 169 (1 << TTE512K) | (1 << TTE256M)); 170 pan_disable_large_pages = (1 << TTE256M); 171 pan_disable_auto_large_pages = (1 << TTE4M) | (1 << TTE256M); 172 auto_lpg_maxszc = TTE32M; 173 break; 174 case MMU_PAGESIZE256M: 175 pan_disable_ism_large_pages = ((1 << TTE64K) | 176 (1 << TTE512K) | (1 << TTE32M)); 177 pan_disable_large_pages = (1 << TTE32M); 178 pan_disable_auto_large_pages = (1 << TTE4M) | (1 << TTE32M); 179 auto_lpg_maxszc = TTE256M; 180 break; 181 default: 182 cmn_err(CE_WARN, "Unrecognized mmu_ism_pagesize value 0x%lx", 183 ism_pagesize); 184 break; 185 } 186 } 187 188 /* 189 * Re-initialize mmu_page_sizes and friends, for Panther mmu support. 190 * Called during very early bootup from check_cpus_set(). 191 * Can be called to verify that mmu_page_sizes are set up correctly. 192 * Note that ncpus is not initialized at this point in the bootup sequence. 193 */ 194 int 195 mmu_init_mmu_page_sizes(int cinfo) 196 { 197 int npanther = cinfo; 198 199 if (!init_mmu_page_sizes) { 200 if (npanther == ncpunode) { 201 mmu_page_sizes = MMU_PAGE_SIZES; 202 mmu_hashcnt = MAX_HASHCNT; 203 mmu_ism_pagesize = MMU_PAGESIZE32M; 204 mmu_exported_pagesize_mask = (1 << TTE8K) | 205 (1 << TTE64K) | (1 << TTE512K) | (1 << TTE4M) | 206 (1 << TTE32M) | (1 << TTE256M); 207 panther_dtlb_restrictions = 1; 208 panther_only = 1; 209 auto_lpg_maxszc = TTE32M; 210 } else if (npanther > 0) { 211 panther_dtlb_restrictions = 1; 212 } 213 init_mmu_page_sizes = 1; 214 return (0); 215 } 216 return (1); 217 } 218 219 220 /* Cheetah+ and later worst case DTLB parameters */ 221 #ifndef LOCKED_DTLB_ENTRIES 222 #define LOCKED_DTLB_ENTRIES 5 /* 2 user TSBs, 2 nucleus, + OBP */ 223 #endif 224 #define TOTAL_DTLB_ENTRIES 16 225 #define AVAIL_32M_ENTRIES 0 226 #define AVAIL_256M_ENTRIES 0 227 #define AVAIL_DTLB_ENTRIES (TOTAL_DTLB_ENTRIES - LOCKED_DTLB_ENTRIES) 228 static uint64_t ttecnt_threshold[MMU_PAGE_SIZES] = { 229 AVAIL_DTLB_ENTRIES, AVAIL_DTLB_ENTRIES, 230 AVAIL_DTLB_ENTRIES, AVAIL_DTLB_ENTRIES, 231 AVAIL_32M_ENTRIES, AVAIL_256M_ENTRIES }; 232 233 /*ARGSUSED*/ 234 uint_t 235 mmu_preferred_pgsz(struct hat *hat, caddr_t addr, size_t len) 236 { 237 sfmmu_t *sfmmup = (sfmmu_t *)hat; 238 uint_t pgsz0, pgsz1; 239 uint_t szc, maxszc = mmu_page_sizes - 1; 240 size_t pgsz; 241 extern int disable_large_pages; 242 243 pgsz0 = (uint_t)sfmmup->sfmmu_pgsz[0]; 244 pgsz1 = (uint_t)sfmmup->sfmmu_pgsz[1]; 245 246 /* 247 * If either of the TLBs are reprogrammed, choose 248 * the largest mapping size as the preferred size, 249 * if it fits the size and alignment constraints. 250 * Else return the largest mapping size that fits, 251 * if neither TLB is reprogrammed. 252 */ 253 if (pgsz0 > TTE8K || pgsz1 > TTE8K) { 254 if (pgsz1 > pgsz0) { /* First try pgsz1 */ 255 pgsz = hw_page_array[pgsz1].hp_size; 256 if ((len >= pgsz) && IS_P2ALIGNED(addr, pgsz)) 257 return (pgsz1); 258 } 259 if (pgsz0 > TTE8K) { /* Then try pgsz0, if !TTE8K */ 260 pgsz = hw_page_array[pgsz0].hp_size; 261 if ((len >= pgsz) && IS_P2ALIGNED(addr, pgsz)) 262 return (pgsz0); 263 } 264 } else { /* Otherwise pick best fit if neither TLB is reprogrammed. */ 265 for (szc = maxszc; szc > TTE8K; szc--) { 266 if (disable_large_pages & (1 << szc)) 267 continue; 268 269 pgsz = hw_page_array[szc].hp_size; 270 if ((len >= pgsz) && IS_P2ALIGNED(addr, pgsz)) 271 return (szc); 272 } 273 } 274 return (TTE8K); 275 } 276 277 /* 278 * The purpose of this code is to indirectly reorganize the sfmmu_pgsz array 279 * in order to handle the Panther mmu DTLB requirements. Panther only supports 280 * the 32M/256M pages in the T512_1 and not in the T16, so the Panther cpu 281 * can only support one of the two largest page sizes at a time (efficiently). 282 * Panther only supports 512K and 4M pages in the T512_0, and 32M/256M pages 283 * in the T512_1. So check the sfmmu flags and ttecnt before enabling 284 * the T512_1 for 32M or 256M page sizes, and make sure that 512K and 4M 285 * requests go to the T512_0. 286 * 287 * The tmp_pgsz array comes into this routine in sorted order, as it is 288 * sorted from largest to smallest #pages per pagesize in use by the hat code, 289 * and leaves with the Panther mmu DTLB requirements satisfied. Note that 290 * when the array leaves this function it may not contain all of the page 291 * size codes that it had coming into the function. 292 * 293 * Note that for DISM the flag can be set but the ttecnt can be 0, if we 294 * didn't fault any pages in. This allows the t512_1 to be reprogrammed, 295 * because the T16 does not support the two giant page sizes. ouch. 296 */ 297 void 298 mmu_fixup_large_pages(struct hat *hat, uint64_t *ttecnt, uint8_t *tmp_pgsz) 299 { 300 uint_t pgsz0 = tmp_pgsz[0]; 301 uint_t pgsz1 = tmp_pgsz[1]; 302 uint_t spgsz; 303 304 /* 305 * Don't program 2nd dtlb for kernel and ism hat 306 */ 307 ASSERT(hat->sfmmu_ismhat == NULL); 308 ASSERT(hat != ksfmmup); 309 ASSERT(cpu_impl_dual_pgsz == 1); 310 311 ASSERT((!SFMMU_FLAGS_ISSET(hat, HAT_32M_FLAG)) || 312 (!SFMMU_FLAGS_ISSET(hat, HAT_256M_FLAG))); 313 314 if ((SFMMU_FLAGS_ISSET(hat, HAT_32M_FLAG)) || (ttecnt[TTE32M] != 0)) { 315 spgsz = pgsz1; 316 pgsz1 = TTE32M; 317 if (pgsz0 == TTE32M) 318 pgsz0 = spgsz; 319 } else if ((SFMMU_FLAGS_ISSET(hat, HAT_256M_FLAG)) || 320 (ttecnt[TTE256M] != 0)) { 321 spgsz = pgsz1; 322 pgsz1 = TTE256M; 323 if (pgsz0 == TTE256M) 324 pgsz0 = spgsz; 325 } else if ((pgsz1 == TTE512K) || (pgsz1 == TTE4M)) { 326 if ((pgsz0 != TTE512K) && (pgsz0 != TTE4M)) { 327 spgsz = pgsz0; 328 pgsz0 = pgsz1; 329 pgsz1 = spgsz; 330 } else { 331 pgsz1 = page_szc(MMU_PAGESIZE); 332 } 333 } 334 /* 335 * This implements PAGESIZE programming of the T8s 336 * if large TTE counts don't exceed the thresholds. 337 */ 338 if (ttecnt[pgsz0] < ttecnt_threshold[pgsz0]) 339 pgsz0 = page_szc(MMU_PAGESIZE); 340 if (ttecnt[pgsz1] < ttecnt_threshold[pgsz1]) 341 pgsz1 = page_szc(MMU_PAGESIZE); 342 tmp_pgsz[0] = pgsz0; 343 tmp_pgsz[1] = pgsz1; 344 } 345 346 /* 347 * Function to set up the page size values used to reprogram the DTLBs, 348 * when page sizes used by a process change significantly. 349 */ 350 void 351 mmu_setup_page_sizes(struct hat *hat, uint64_t *ttecnt, uint8_t *tmp_pgsz) 352 { 353 uint_t pgsz0, pgsz1; 354 355 /* 356 * Don't program 2nd dtlb for kernel and ism hat 357 */ 358 ASSERT(hat->sfmmu_ismhat == NULL); 359 ASSERT(hat != ksfmmup); 360 361 if (cpu_impl_dual_pgsz == 0) /* disable_dual_pgsz flag */ 362 return; 363 364 /* 365 * hat->sfmmu_pgsz[] is an array whose elements 366 * contain a sorted order of page sizes. Element 367 * 0 is the most commonly used page size, followed 368 * by element 1, and so on. 369 * 370 * ttecnt[] is an array of per-page-size page counts 371 * mapped into the process. 372 * 373 * If the HAT's choice for page sizes is unsuitable, 374 * we can override it here. The new values written 375 * to the array will be handed back to us later to 376 * do the actual programming of the TLB hardware. 377 * 378 * The policy we use for programming the dual T8s on 379 * Cheetah+ and beyond is as follows: 380 * 381 * We have two programmable TLBs, so we look at 382 * the two most common page sizes in the array, which 383 * have already been computed for us by the HAT. 384 * If the TTE count of either of a preferred page size 385 * exceeds the number of unlocked T16 entries, 386 * we reprogram one of the T8s to that page size 387 * to avoid thrashing in the T16. Else we program 388 * that T8 to the base page size. Note that we do 389 * not force either T8 to be the base page size if a 390 * process is using more than two page sizes. Policy 391 * decisions about which page sizes are best to use are 392 * left to the upper layers. 393 * 394 * Note that for Panther, 4M and 512K pages need to be 395 * programmed into T512_0, and 32M and 256M into T512_1, 396 * so we don't want to go through the MIN/MAX code. 397 * For partial-Panther systems, we still want to make sure 398 * that 4M and 512K page sizes NEVER get into the T512_1. 399 * Since the DTLB flags are not set up on a per-cpu basis, 400 * Panther rules must be applied for mixed Panther/Cheetah+/ 401 * Jaguar configurations. 402 */ 403 if (panther_dtlb_restrictions) { 404 if ((tmp_pgsz[1] == TTE512K) || (tmp_pgsz[1] == TTE4M)) { 405 if ((tmp_pgsz[0] != TTE512K) && 406 (tmp_pgsz[0] != TTE4M)) { 407 pgsz1 = tmp_pgsz[0]; 408 pgsz0 = tmp_pgsz[1]; 409 } else { 410 pgsz0 = tmp_pgsz[0]; 411 pgsz1 = page_szc(MMU_PAGESIZE); 412 } 413 } else { 414 pgsz0 = tmp_pgsz[0]; 415 pgsz1 = tmp_pgsz[1]; 416 } 417 } else { 418 pgsz0 = MIN(tmp_pgsz[0], tmp_pgsz[1]); 419 pgsz1 = MAX(tmp_pgsz[0], tmp_pgsz[1]); 420 } 421 422 /* 423 * This implements PAGESIZE programming of the T8s 424 * if large TTE counts don't exceed the thresholds. 425 */ 426 if (ttecnt[pgsz0] < ttecnt_threshold[pgsz0]) 427 pgsz0 = page_szc(MMU_PAGESIZE); 428 if (ttecnt[pgsz1] < ttecnt_threshold[pgsz1]) 429 pgsz1 = page_szc(MMU_PAGESIZE); 430 tmp_pgsz[0] = pgsz0; 431 tmp_pgsz[1] = pgsz1; 432 } 433 434 /* 435 * The HAT calls this function when an MMU context is allocated so that we 436 * can reprogram the large TLBs appropriately for the new process using 437 * the context. 438 * 439 * The caller must hold the HAT lock. 440 */ 441 void 442 mmu_set_ctx_page_sizes(struct hat *hat) 443 { 444 uint_t pgsz0, pgsz1; 445 uint_t new_cext; 446 447 ASSERT(sfmmu_hat_lock_held(hat)); 448 ASSERT(hat != ksfmmup); 449 450 if (cpu_impl_dual_pgsz == 0) /* disable_dual_pgsz flag */ 451 return; 452 453 /* 454 * If supported, reprogram the TLBs to a larger pagesize. 455 */ 456 pgsz0 = hat->sfmmu_pgsz[0]; 457 pgsz1 = hat->sfmmu_pgsz[1]; 458 ASSERT(pgsz0 < mmu_page_sizes); 459 ASSERT(pgsz1 < mmu_page_sizes); 460 #ifdef DEBUG 461 if (panther_dtlb_restrictions) { 462 ASSERT(pgsz1 != TTE512K); 463 ASSERT(pgsz1 != TTE4M); 464 } 465 if (panther_only) { 466 ASSERT(pgsz0 != TTE32M); 467 ASSERT(pgsz0 != TTE256M); 468 } 469 #endif /* DEBUG */ 470 new_cext = TAGACCEXT_MKSZPAIR(pgsz1, pgsz0); 471 if (hat->sfmmu_cext != new_cext) { 472 #ifdef DEBUG 473 int i; 474 /* 475 * assert cnum should be invalid, this is because pagesize 476 * can only be changed after a proc's ctxs are invalidated. 477 */ 478 for (i = 0; i < max_mmu_ctxdoms; i++) { 479 ASSERT(hat->sfmmu_ctxs[i].cnum == INVALID_CONTEXT); 480 } 481 #endif /* DEBUG */ 482 hat->sfmmu_cext = new_cext; 483 } 484 485 /* 486 * sfmmu_setctx_sec() will take care of the 487 * rest of the chores reprogramming the hat->sfmmu_cext 488 * page size values into the DTLBs. 489 */ 490 } 491 492 /* 493 * This function assumes that there are either four or six supported page 494 * sizes and at most two programmable TLBs, so we need to decide which 495 * page sizes are most important and then adjust the TLB page sizes 496 * accordingly (if supported). 497 * 498 * If these assumptions change, this function will need to be 499 * updated to support whatever the new limits are. 500 */ 501 void 502 mmu_check_page_sizes(sfmmu_t *sfmmup, uint64_t *ttecnt) 503 { 504 uint64_t sortcnt[MMU_PAGE_SIZES]; 505 uint8_t tmp_pgsz[MMU_PAGE_SIZES]; 506 uint8_t i, j, max; 507 uint16_t oldval, newval; 508 509 /* 510 * We only consider reprogramming the TLBs if one or more of 511 * the two most used page sizes changes and we're using 512 * large pages in this process, except for Panther 32M/256M pages, 513 * which the Panther T16 does not support. 514 */ 515 if (sfmmup->sfmmu_flags & HAT_LGPG_FLAGS) { 516 /* Sort page sizes. */ 517 for (i = 0; i < mmu_page_sizes; i++) { 518 sortcnt[i] = ttecnt[i]; 519 } 520 for (j = 0; j < mmu_page_sizes; j++) { 521 for (i = mmu_page_sizes - 1, max = 0; i > 0; i--) { 522 if (sortcnt[i] > sortcnt[max]) 523 max = i; 524 } 525 tmp_pgsz[j] = max; 526 sortcnt[max] = 0; 527 } 528 529 /* 530 * Handle Panther page dtlb calcs separately. The check 531 * for actual or potential 32M/256M pages must occur 532 * every time due to lack of T16 support for them. 533 * The sort works fine for Ch+/Jag, but Panther has 534 * pagesize restrictions for both DTLBs. 535 */ 536 oldval = sfmmup->sfmmu_pgsz[0] << 8 | sfmmup->sfmmu_pgsz[1]; 537 538 if (panther_only) { 539 mmu_fixup_large_pages(sfmmup, ttecnt, tmp_pgsz); 540 } else { 541 /* Check 2 largest values after the sort. */ 542 mmu_setup_page_sizes(sfmmup, ttecnt, tmp_pgsz); 543 } 544 newval = tmp_pgsz[0] << 8 | tmp_pgsz[1]; 545 if (newval != oldval) { 546 sfmmu_reprog_pgsz_arr(sfmmup, tmp_pgsz); 547 } 548 } 549 } 550 551 #endif /* CPU_IMP_DUAL_PAGESIZE */ 552 553 struct heap_lp_page_size { 554 int impl; 555 uint_t tte; 556 int use_dt512; 557 }; 558 559 struct heap_lp_page_size heap_lp_pgsz[] = { 560 561 {CHEETAH_IMPL, TTE8K, 0}, /* default */ 562 {CHEETAH_IMPL, TTE64K, 0}, 563 {CHEETAH_IMPL, TTE4M, 0}, 564 565 { CHEETAH_PLUS_IMPL, TTE4M, 1 }, /* default */ 566 { CHEETAH_PLUS_IMPL, TTE4M, 0 }, 567 { CHEETAH_PLUS_IMPL, TTE64K, 1 }, 568 { CHEETAH_PLUS_IMPL, TTE64K, 0 }, 569 { CHEETAH_PLUS_IMPL, TTE8K, 0 }, 570 571 { JALAPENO_IMPL, TTE4M, 1 }, /* default */ 572 { JALAPENO_IMPL, TTE4M, 0 }, 573 { JALAPENO_IMPL, TTE64K, 1 }, 574 { JALAPENO_IMPL, TTE64K, 0 }, 575 { JALAPENO_IMPL, TTE8K, 0 }, 576 577 { JAGUAR_IMPL, TTE4M, 1 }, /* default */ 578 { JAGUAR_IMPL, TTE4M, 0 }, 579 { JAGUAR_IMPL, TTE64K, 1 }, 580 { JAGUAR_IMPL, TTE64K, 0 }, 581 { JAGUAR_IMPL, TTE8K, 0 }, 582 583 { SERRANO_IMPL, TTE4M, 1 }, /* default */ 584 { SERRANO_IMPL, TTE4M, 0 }, 585 { SERRANO_IMPL, TTE64K, 1 }, 586 { SERRANO_IMPL, TTE64K, 0 }, 587 { SERRANO_IMPL, TTE8K, 0 }, 588 589 { PANTHER_IMPL, TTE4M, 1 }, /* default */ 590 { PANTHER_IMPL, TTE4M, 0 }, 591 { PANTHER_IMPL, TTE64K, 1 }, 592 { PANTHER_IMPL, TTE64K, 0 }, 593 { PANTHER_IMPL, TTE8K, 0 } 594 }; 595 596 int heaplp_use_dt512 = -1; 597 598 void 599 mmu_init_kernel_pgsz(struct hat *hat) 600 { 601 uint_t tte = page_szc(segkmem_lpsize); 602 uchar_t new_cext_primary, new_cext_nucleus; 603 604 if (heaplp_use_dt512 == 0 || tte > TTE4M) { 605 /* do not reprogram dt512 tlb */ 606 tte = TTE8K; 607 } 608 609 new_cext_nucleus = TAGACCEXT_MKSZPAIR(tte, TTE8K); 610 new_cext_primary = TAGACCEXT_MKSZPAIR(TTE8K, tte); 611 612 hat->sfmmu_cext = new_cext_primary; 613 kcontextreg = ((uint64_t)new_cext_nucleus << CTXREG_NEXT_SHIFT) | 614 ((uint64_t)new_cext_primary << CTXREG_EXT_SHIFT); 615 mmu_init_kcontext(); 616 } 617 618 size_t 619 mmu_get_kernel_lpsize(size_t lpsize) 620 { 621 struct heap_lp_page_size *p_lpgsz, *pend_lpgsz; 622 int impl = cpunodes[getprocessorid()].implementation; 623 uint_t tte = TTE8K; 624 625 if (cpu_impl_dual_pgsz == 0) { 626 heaplp_use_dt512 = 0; 627 return (MMU_PAGESIZE); 628 } 629 630 pend_lpgsz = (struct heap_lp_page_size *) 631 ((char *)heap_lp_pgsz + sizeof (heap_lp_pgsz)); 632 633 /* search for a valid segkmem_lpsize */ 634 for (p_lpgsz = heap_lp_pgsz; p_lpgsz < pend_lpgsz; p_lpgsz++) { 635 if (impl != p_lpgsz->impl) 636 continue; 637 638 if (lpsize == 0) { 639 /* 640 * no setting for segkmem_lpsize in /etc/system 641 * use default from the table 642 */ 643 tte = p_lpgsz->tte; 644 heaplp_use_dt512 = p_lpgsz->use_dt512; 645 break; 646 } 647 648 if (lpsize == TTEBYTES(p_lpgsz->tte) && 649 (heaplp_use_dt512 == -1 || 650 heaplp_use_dt512 == p_lpgsz->use_dt512)) { 651 652 tte = p_lpgsz->tte; 653 heaplp_use_dt512 = p_lpgsz->use_dt512; 654 655 /* found a match */ 656 break; 657 } 658 } 659 660 if (p_lpgsz == pend_lpgsz) { 661 /* nothing found: disable large page kernel heap */ 662 tte = TTE8K; 663 heaplp_use_dt512 = 0; 664 } 665 666 lpsize = TTEBYTES(tte); 667 668 return (lpsize); 669 } 670