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