1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Kernel Physical Mapping (segkpm) hat interface routines for sun4u. 30 */ 31 32 #include <sys/types.h> 33 #include <vm/hat.h> 34 #include <vm/hat_sfmmu.h> 35 #include <vm/page.h> 36 #include <sys/sysmacros.h> 37 #include <sys/cmn_err.h> 38 #include <sys/machsystm.h> 39 #include <vm/seg_kpm.h> 40 #include <sys/cpu_module.h> 41 #include <vm/mach_kpm.h> 42 43 /* kpm prototypes */ 44 static caddr_t sfmmu_kpm_mapin(page_t *); 45 static void sfmmu_kpm_mapout(page_t *, caddr_t); 46 static int sfmmu_kpme_lookup(struct kpme *, page_t *); 47 static void sfmmu_kpme_add(struct kpme *, page_t *); 48 static void sfmmu_kpme_sub(struct kpme *, page_t *); 49 static caddr_t sfmmu_kpm_getvaddr(page_t *, int *); 50 static int sfmmu_kpm_fault(caddr_t, struct memseg *, page_t *); 51 static int sfmmu_kpm_fault_small(caddr_t, struct memseg *, page_t *); 52 static void sfmmu_kpm_vac_conflict(page_t *, caddr_t); 53 void sfmmu_kpm_pageunload(page_t *); 54 void sfmmu_kpm_vac_unload(page_t *, caddr_t); 55 static void sfmmu_kpm_demap_large(caddr_t); 56 static void sfmmu_kpm_demap_small(caddr_t); 57 static void sfmmu_kpm_demap_tlbs(caddr_t); 58 void sfmmu_kpm_hme_unload(page_t *); 59 kpm_hlk_t *sfmmu_kpm_kpmp_enter(page_t *, pgcnt_t); 60 void sfmmu_kpm_kpmp_exit(kpm_hlk_t *kpmp); 61 void sfmmu_kpm_page_cache(page_t *, int, int); 62 63 /* 64 * Kernel Physical Mapping (kpm) facility 65 */ 66 67 void 68 mach_kpm_init() 69 {} 70 71 /* -- hat_kpm interface section -- */ 72 73 /* 74 * Mapin a locked page and return the vaddr. 75 * When a kpme is provided by the caller it is added to 76 * the page p_kpmelist. The page to be mapped in must 77 * be at least read locked (p_selock). 78 */ 79 caddr_t 80 hat_kpm_mapin(struct page *pp, struct kpme *kpme) 81 { 82 kmutex_t *pml; 83 caddr_t vaddr; 84 85 if (kpm_enable == 0) { 86 cmn_err(CE_WARN, "hat_kpm_mapin: kpm_enable not set"); 87 return ((caddr_t)NULL); 88 } 89 90 if (pp == NULL || PAGE_LOCKED(pp) == 0) { 91 cmn_err(CE_WARN, "hat_kpm_mapin: pp zero or not locked"); 92 return ((caddr_t)NULL); 93 } 94 95 pml = sfmmu_mlist_enter(pp); 96 ASSERT(pp->p_kpmref >= 0); 97 98 vaddr = (pp->p_kpmref == 0) ? 99 sfmmu_kpm_mapin(pp) : hat_kpm_page2va(pp, 1); 100 101 if (kpme != NULL) { 102 /* 103 * Tolerate multiple mapins for the same kpme to avoid 104 * the need for an extra serialization. 105 */ 106 if ((sfmmu_kpme_lookup(kpme, pp)) == 0) 107 sfmmu_kpme_add(kpme, pp); 108 109 ASSERT(pp->p_kpmref > 0); 110 111 } else { 112 pp->p_kpmref++; 113 } 114 115 sfmmu_mlist_exit(pml); 116 return (vaddr); 117 } 118 119 /* 120 * Mapout a locked page. 121 * When a kpme is provided by the caller it is removed from 122 * the page p_kpmelist. The page to be mapped out must be at 123 * least read locked (p_selock). 124 * Note: The seg_kpm layer provides a mapout interface for the 125 * case that a kpme is used and the underlying page is unlocked. 126 * This can be used instead of calling this function directly. 127 */ 128 void 129 hat_kpm_mapout(struct page *pp, struct kpme *kpme, caddr_t vaddr) 130 { 131 kmutex_t *pml; 132 133 if (kpm_enable == 0) { 134 cmn_err(CE_WARN, "hat_kpm_mapout: kpm_enable not set"); 135 return; 136 } 137 138 if (IS_KPM_ADDR(vaddr) == 0) { 139 cmn_err(CE_WARN, "hat_kpm_mapout: no kpm address"); 140 return; 141 } 142 143 if (pp == NULL || PAGE_LOCKED(pp) == 0) { 144 cmn_err(CE_WARN, "hat_kpm_mapout: page zero or not locked"); 145 return; 146 } 147 148 if (kpme != NULL) { 149 ASSERT(pp == kpme->kpe_page); 150 pp = kpme->kpe_page; 151 pml = sfmmu_mlist_enter(pp); 152 153 if (sfmmu_kpme_lookup(kpme, pp) == 0) 154 panic("hat_kpm_mapout: kpme not found pp=%p", 155 (void *)pp); 156 157 ASSERT(pp->p_kpmref > 0); 158 sfmmu_kpme_sub(kpme, pp); 159 160 } else { 161 pml = sfmmu_mlist_enter(pp); 162 pp->p_kpmref--; 163 } 164 165 ASSERT(pp->p_kpmref >= 0); 166 if (pp->p_kpmref == 0) 167 sfmmu_kpm_mapout(pp, vaddr); 168 169 sfmmu_mlist_exit(pml); 170 } 171 172 /* 173 * Return the kpm virtual address for the page at pp. 174 * If checkswap is non zero and the page is backed by a 175 * swap vnode the physical address is used rather than 176 * p_offset to determine the kpm region. 177 * Note: The function has to be used w/ extreme care. The 178 * stability of the page identity is in the responsibility 179 * of the caller. 180 */ 181 /*ARGSUSED*/ 182 caddr_t 183 hat_kpm_page2va(struct page *pp, int checkswap) 184 { 185 int vcolor, vcolor_pa; 186 uintptr_t paddr, vaddr; 187 188 ASSERT(kpm_enable); 189 190 paddr = ptob(pp->p_pagenum); 191 vcolor_pa = addr_to_vcolor(paddr); 192 193 if (checkswap && pp->p_vnode && IS_SWAPFSVP(pp->p_vnode)) 194 vcolor = (PP_ISNC(pp)) ? vcolor_pa : PP_GET_VCOLOR(pp); 195 else 196 vcolor = addr_to_vcolor(pp->p_offset); 197 198 vaddr = (uintptr_t)kpm_vbase + paddr; 199 200 if (vcolor_pa != vcolor) { 201 vaddr += ((uintptr_t)(vcolor - vcolor_pa) << MMU_PAGESHIFT); 202 vaddr += (vcolor_pa > vcolor) ? 203 ((uintptr_t)vcolor_pa << kpm_size_shift) : 204 ((uintptr_t)(vcolor - vcolor_pa) << kpm_size_shift); 205 } 206 207 return ((caddr_t)vaddr); 208 } 209 210 /* 211 * Return the page for the kpm virtual address vaddr. 212 * Caller is responsible for the kpm mapping and lock 213 * state of the page. 214 */ 215 page_t * 216 hat_kpm_vaddr2page(caddr_t vaddr) 217 { 218 uintptr_t paddr; 219 pfn_t pfn; 220 221 ASSERT(IS_KPM_ADDR(vaddr)); 222 223 SFMMU_KPM_VTOP(vaddr, paddr); 224 pfn = (pfn_t)btop(paddr); 225 226 return (page_numtopp_nolock(pfn)); 227 } 228 229 /* page to kpm_page */ 230 #define PP2KPMPG(pp, kp) { \ 231 struct memseg *mseg; \ 232 pgcnt_t inx; \ 233 pfn_t pfn; \ 234 \ 235 pfn = pp->p_pagenum; \ 236 mseg = page_numtomemseg_nolock(pfn); \ 237 ASSERT(mseg); \ 238 inx = ptokpmp(kpmptop(ptokpmp(pfn)) - mseg->kpm_pbase); \ 239 ASSERT(inx < mseg->kpm_nkpmpgs); \ 240 kp = &mseg->kpm_pages[inx]; \ 241 } 242 243 /* page to kpm_spage */ 244 #define PP2KPMSPG(pp, ksp) { \ 245 struct memseg *mseg; \ 246 pgcnt_t inx; \ 247 pfn_t pfn; \ 248 \ 249 pfn = pp->p_pagenum; \ 250 mseg = page_numtomemseg_nolock(pfn); \ 251 ASSERT(mseg); \ 252 inx = pfn - mseg->kpm_pbase; \ 253 ksp = &mseg->kpm_spages[inx]; \ 254 } 255 256 /* 257 * hat_kpm_fault is called from segkpm_fault when a kpm tsbmiss occurred 258 * which could not be resolved by the trap level tsbmiss handler for the 259 * following reasons: 260 * . The vaddr is in VAC alias range (always PAGESIZE mapping size). 261 * . The kpm (s)page range of vaddr is in a VAC alias prevention state. 262 * . tsbmiss handling at trap level is not desired (DEBUG kernel only, 263 * kpm_tsbmtl == 0). 264 */ 265 int 266 hat_kpm_fault(struct hat *hat, caddr_t vaddr) 267 { 268 int error; 269 uintptr_t paddr; 270 pfn_t pfn; 271 struct memseg *mseg; 272 page_t *pp; 273 274 if (kpm_enable == 0) { 275 cmn_err(CE_WARN, "hat_kpm_fault: kpm_enable not set"); 276 return (ENOTSUP); 277 } 278 279 ASSERT(hat == ksfmmup); 280 ASSERT(IS_KPM_ADDR(vaddr)); 281 282 SFMMU_KPM_VTOP(vaddr, paddr); 283 pfn = (pfn_t)btop(paddr); 284 mseg = page_numtomemseg_nolock(pfn); 285 if (mseg == NULL) 286 return (EFAULT); 287 288 pp = &mseg->pages[(pgcnt_t)(pfn - mseg->pages_base)]; 289 ASSERT((pfn_t)pp->p_pagenum == pfn); 290 291 if (!PAGE_LOCKED(pp)) 292 return (EFAULT); 293 294 if (kpm_smallpages == 0) 295 error = sfmmu_kpm_fault(vaddr, mseg, pp); 296 else 297 error = sfmmu_kpm_fault_small(vaddr, mseg, pp); 298 299 return (error); 300 } 301 302 /* 303 * memseg_hash[] was cleared, need to clear memseg_phash[] too. 304 */ 305 void 306 hat_kpm_mseghash_clear(int nentries) 307 { 308 pgcnt_t i; 309 310 if (kpm_enable == 0) 311 return; 312 313 for (i = 0; i < nentries; i++) 314 memseg_phash[i] = MSEG_NULLPTR_PA; 315 } 316 317 /* 318 * Update memseg_phash[inx] when memseg_hash[inx] was changed. 319 */ 320 void 321 hat_kpm_mseghash_update(pgcnt_t inx, struct memseg *msp) 322 { 323 if (kpm_enable == 0) 324 return; 325 326 memseg_phash[inx] = (msp) ? va_to_pa(msp) : MSEG_NULLPTR_PA; 327 } 328 329 /* 330 * Update kpm memseg members from basic memseg info. 331 */ 332 void 333 hat_kpm_addmem_mseg_update(struct memseg *msp, pgcnt_t nkpmpgs, 334 offset_t kpm_pages_off) 335 { 336 if (kpm_enable == 0) 337 return; 338 339 msp->kpm_pages = (kpm_page_t *)((caddr_t)msp->pages + kpm_pages_off); 340 msp->kpm_nkpmpgs = nkpmpgs; 341 msp->kpm_pbase = kpmptop(ptokpmp(msp->pages_base)); 342 msp->pagespa = va_to_pa(msp->pages); 343 msp->epagespa = va_to_pa(msp->epages); 344 msp->kpm_pagespa = va_to_pa(msp->kpm_pages); 345 } 346 347 /* 348 * Setup nextpa when a memseg is inserted. 349 * Assumes that the memsegslock is already held. 350 */ 351 void 352 hat_kpm_addmem_mseg_insert(struct memseg *msp) 353 { 354 if (kpm_enable == 0) 355 return; 356 357 ASSERT(memsegs_lock_held()); 358 msp->nextpa = (memsegs) ? va_to_pa(memsegs) : MSEG_NULLPTR_PA; 359 } 360 361 /* 362 * Setup memsegspa when a memseg is (head) inserted. 363 * Called before memsegs is updated to complete a 364 * memseg insert operation. 365 * Assumes that the memsegslock is already held. 366 */ 367 void 368 hat_kpm_addmem_memsegs_update(struct memseg *msp) 369 { 370 if (kpm_enable == 0) 371 return; 372 373 ASSERT(memsegs_lock_held()); 374 ASSERT(memsegs); 375 memsegspa = va_to_pa(msp); 376 } 377 378 /* 379 * Return end of metadata for an already setup memseg. 380 * 381 * Note: kpm_pages and kpm_spages are aliases and the underlying 382 * member of struct memseg is a union, therefore they always have 383 * the same address within a memseg. They must be differentiated 384 * when pointer arithmetic is used with them. 385 */ 386 caddr_t 387 hat_kpm_mseg_reuse(struct memseg *msp) 388 { 389 caddr_t end; 390 391 if (kpm_smallpages == 0) 392 end = (caddr_t)(msp->kpm_pages + msp->kpm_nkpmpgs); 393 else 394 end = (caddr_t)(msp->kpm_spages + msp->kpm_nkpmpgs); 395 396 return (end); 397 } 398 399 /* 400 * Update memsegspa (when first memseg in list 401 * is deleted) or nextpa when a memseg deleted. 402 * Assumes that the memsegslock is already held. 403 */ 404 void 405 hat_kpm_delmem_mseg_update(struct memseg *msp, struct memseg **mspp) 406 { 407 struct memseg *lmsp; 408 409 if (kpm_enable == 0) 410 return; 411 412 ASSERT(memsegs_lock_held()); 413 414 if (mspp == &memsegs) { 415 memsegspa = (msp->next) ? 416 va_to_pa(msp->next) : MSEG_NULLPTR_PA; 417 } else { 418 lmsp = (struct memseg *) 419 ((uint64_t)mspp - offsetof(struct memseg, next)); 420 lmsp->nextpa = (msp->next) ? 421 va_to_pa(msp->next) : MSEG_NULLPTR_PA; 422 } 423 } 424 425 /* 426 * Update kpm members for all memseg's involved in a split operation 427 * and do the atomic update of the physical memseg chain. 428 * 429 * Note: kpm_pages and kpm_spages are aliases and the underlying member 430 * of struct memseg is a union, therefore they always have the same 431 * address within a memseg. With that the direct assignments and 432 * va_to_pa conversions below don't have to be distinguished wrt. to 433 * kpm_smallpages. They must be differentiated when pointer arithmetic 434 * is used with them. 435 * 436 * Assumes that the memsegslock is already held. 437 */ 438 void 439 hat_kpm_split_mseg_update(struct memseg *msp, struct memseg **mspp, 440 struct memseg *lo, struct memseg *mid, struct memseg *hi) 441 { 442 pgcnt_t start, end, kbase, kstart, num; 443 struct memseg *lmsp; 444 445 if (kpm_enable == 0) 446 return; 447 448 ASSERT(memsegs_lock_held()); 449 ASSERT(msp && mid && msp->kpm_pages); 450 451 kbase = ptokpmp(msp->kpm_pbase); 452 453 if (lo) { 454 num = lo->pages_end - lo->pages_base; 455 start = kpmptop(ptokpmp(lo->pages_base)); 456 /* align end to kpm page size granularity */ 457 end = kpmptop(ptokpmp(start + num - 1)) + kpmpnpgs; 458 lo->kpm_pbase = start; 459 lo->kpm_nkpmpgs = ptokpmp(end - start); 460 lo->kpm_pages = msp->kpm_pages; 461 lo->kpm_pagespa = va_to_pa(lo->kpm_pages); 462 lo->pagespa = va_to_pa(lo->pages); 463 lo->epagespa = va_to_pa(lo->epages); 464 lo->nextpa = va_to_pa(lo->next); 465 } 466 467 /* mid */ 468 num = mid->pages_end - mid->pages_base; 469 kstart = ptokpmp(mid->pages_base); 470 start = kpmptop(kstart); 471 /* align end to kpm page size granularity */ 472 end = kpmptop(ptokpmp(start + num - 1)) + kpmpnpgs; 473 mid->kpm_pbase = start; 474 mid->kpm_nkpmpgs = ptokpmp(end - start); 475 if (kpm_smallpages == 0) { 476 mid->kpm_pages = msp->kpm_pages + (kstart - kbase); 477 } else { 478 mid->kpm_spages = msp->kpm_spages + (kstart - kbase); 479 } 480 mid->kpm_pagespa = va_to_pa(mid->kpm_pages); 481 mid->pagespa = va_to_pa(mid->pages); 482 mid->epagespa = va_to_pa(mid->epages); 483 mid->nextpa = (mid->next) ? va_to_pa(mid->next) : MSEG_NULLPTR_PA; 484 485 if (hi) { 486 num = hi->pages_end - hi->pages_base; 487 kstart = ptokpmp(hi->pages_base); 488 start = kpmptop(kstart); 489 /* align end to kpm page size granularity */ 490 end = kpmptop(ptokpmp(start + num - 1)) + kpmpnpgs; 491 hi->kpm_pbase = start; 492 hi->kpm_nkpmpgs = ptokpmp(end - start); 493 if (kpm_smallpages == 0) { 494 hi->kpm_pages = msp->kpm_pages + (kstart - kbase); 495 } else { 496 hi->kpm_spages = msp->kpm_spages + (kstart - kbase); 497 } 498 hi->kpm_pagespa = va_to_pa(hi->kpm_pages); 499 hi->pagespa = va_to_pa(hi->pages); 500 hi->epagespa = va_to_pa(hi->epages); 501 hi->nextpa = (hi->next) ? va_to_pa(hi->next) : MSEG_NULLPTR_PA; 502 } 503 504 /* 505 * Atomic update of the physical memseg chain 506 */ 507 if (mspp == &memsegs) { 508 memsegspa = (lo) ? va_to_pa(lo) : va_to_pa(mid); 509 } else { 510 lmsp = (struct memseg *) 511 ((uint64_t)mspp - offsetof(struct memseg, next)); 512 lmsp->nextpa = (lo) ? va_to_pa(lo) : va_to_pa(mid); 513 } 514 } 515 516 /* 517 * Walk the memsegs chain, applying func to each memseg span and vcolor. 518 */ 519 void 520 hat_kpm_walk(void (*func)(void *, void *, size_t), void *arg) 521 { 522 pfn_t pbase, pend; 523 int vcolor; 524 void *base; 525 size_t size; 526 struct memseg *msp; 527 extern uint_t vac_colors; 528 529 for (msp = memsegs; msp; msp = msp->next) { 530 pbase = msp->pages_base; 531 pend = msp->pages_end; 532 for (vcolor = 0; vcolor < vac_colors; vcolor++) { 533 base = ptob(pbase) + kpm_vbase + kpm_size * vcolor; 534 size = ptob(pend - pbase); 535 func(arg, base, size); 536 } 537 } 538 } 539 540 541 /* -- sfmmu_kpm internal section -- */ 542 543 /* 544 * Return the page frame number if a valid segkpm mapping exists 545 * for vaddr, otherwise return PFN_INVALID. No locks are grabbed. 546 * Should only be used by other sfmmu routines. 547 */ 548 pfn_t 549 sfmmu_kpm_vatopfn(caddr_t vaddr) 550 { 551 uintptr_t paddr; 552 pfn_t pfn; 553 page_t *pp; 554 555 ASSERT(kpm_enable && IS_KPM_ADDR(vaddr)); 556 557 SFMMU_KPM_VTOP(vaddr, paddr); 558 pfn = (pfn_t)btop(paddr); 559 pp = page_numtopp_nolock(pfn); 560 if (pp && pp->p_kpmref) 561 return (pfn); 562 else 563 return ((pfn_t)PFN_INVALID); 564 } 565 566 /* 567 * Lookup a kpme in the p_kpmelist. 568 */ 569 static int 570 sfmmu_kpme_lookup(struct kpme *kpme, page_t *pp) 571 { 572 struct kpme *p; 573 574 for (p = pp->p_kpmelist; p; p = p->kpe_next) { 575 if (p == kpme) 576 return (1); 577 } 578 return (0); 579 } 580 581 /* 582 * Insert a kpme into the p_kpmelist and increment 583 * the per page kpm reference count. 584 */ 585 static void 586 sfmmu_kpme_add(struct kpme *kpme, page_t *pp) 587 { 588 ASSERT(pp->p_kpmref >= 0); 589 590 /* head insert */ 591 kpme->kpe_prev = NULL; 592 kpme->kpe_next = pp->p_kpmelist; 593 594 if (pp->p_kpmelist) 595 pp->p_kpmelist->kpe_prev = kpme; 596 597 pp->p_kpmelist = kpme; 598 kpme->kpe_page = pp; 599 pp->p_kpmref++; 600 } 601 602 /* 603 * Remove a kpme from the p_kpmelist and decrement 604 * the per page kpm reference count. 605 */ 606 static void 607 sfmmu_kpme_sub(struct kpme *kpme, page_t *pp) 608 { 609 ASSERT(pp->p_kpmref > 0); 610 611 if (kpme->kpe_prev) { 612 ASSERT(pp->p_kpmelist != kpme); 613 ASSERT(kpme->kpe_prev->kpe_page == pp); 614 kpme->kpe_prev->kpe_next = kpme->kpe_next; 615 } else { 616 ASSERT(pp->p_kpmelist == kpme); 617 pp->p_kpmelist = kpme->kpe_next; 618 } 619 620 if (kpme->kpe_next) { 621 ASSERT(kpme->kpe_next->kpe_page == pp); 622 kpme->kpe_next->kpe_prev = kpme->kpe_prev; 623 } 624 625 kpme->kpe_next = kpme->kpe_prev = NULL; 626 kpme->kpe_page = NULL; 627 pp->p_kpmref--; 628 } 629 630 /* 631 * Mapin a single page, it is called every time a page changes it's state 632 * from kpm-unmapped to kpm-mapped. It may not be called, when only a new 633 * kpm instance does a mapin and wants to share the mapping. 634 * Assumes that the mlist mutex is already grabbed. 635 */ 636 static caddr_t 637 sfmmu_kpm_mapin(page_t *pp) 638 { 639 kpm_page_t *kp; 640 kpm_hlk_t *kpmp; 641 caddr_t vaddr; 642 int kpm_vac_range; 643 pfn_t pfn; 644 tte_t tte; 645 kmutex_t *pmtx; 646 int uncached; 647 kpm_spage_t *ksp; 648 kpm_shlk_t *kpmsp; 649 int oldval; 650 651 ASSERT(sfmmu_mlist_held(pp)); 652 ASSERT(pp->p_kpmref == 0); 653 654 vaddr = sfmmu_kpm_getvaddr(pp, &kpm_vac_range); 655 656 ASSERT(IS_KPM_ADDR(vaddr)); 657 uncached = PP_ISNC(pp); 658 pfn = pp->p_pagenum; 659 660 if (kpm_smallpages) 661 goto smallpages_mapin; 662 663 PP2KPMPG(pp, kp); 664 665 kpmp = KPMP_HASH(kp); 666 mutex_enter(&kpmp->khl_mutex); 667 668 ASSERT(PP_ISKPMC(pp) == 0); 669 ASSERT(PP_ISKPMS(pp) == 0); 670 671 if (uncached) { 672 /* ASSERT(pp->p_share); XXX use hat_page_getshare */ 673 if (kpm_vac_range == 0) { 674 if (kp->kp_refcnts == 0) { 675 /* 676 * Must remove large page mapping if it exists. 677 * Pages in uncached state can only be mapped 678 * small (PAGESIZE) within the regular kpm 679 * range. 680 */ 681 if (kp->kp_refcntc == -1) { 682 /* remove go indication */ 683 sfmmu_kpm_tsbmtl(&kp->kp_refcntc, 684 &kpmp->khl_lock, KPMTSBM_STOP); 685 } 686 if (kp->kp_refcnt > 0 && kp->kp_refcntc == 0) 687 sfmmu_kpm_demap_large(vaddr); 688 } 689 ASSERT(kp->kp_refcntc >= 0); 690 kp->kp_refcntc++; 691 } 692 pmtx = sfmmu_page_enter(pp); 693 PP_SETKPMC(pp); 694 sfmmu_page_exit(pmtx); 695 } 696 697 if ((kp->kp_refcntc > 0 || kp->kp_refcnts > 0) && kpm_vac_range == 0) { 698 /* 699 * Have to do a small (PAGESIZE) mapin within this kpm_page 700 * range since it is marked to be in VAC conflict mode or 701 * when there are still other small mappings around. 702 */ 703 704 /* tte assembly */ 705 if (uncached == 0) 706 KPM_TTE_VCACHED(tte.ll, pfn, TTE8K); 707 else 708 KPM_TTE_VUNCACHED(tte.ll, pfn, TTE8K); 709 710 /* tsb dropin */ 711 sfmmu_kpm_load_tsb(vaddr, &tte, MMU_PAGESHIFT); 712 713 pmtx = sfmmu_page_enter(pp); 714 PP_SETKPMS(pp); 715 sfmmu_page_exit(pmtx); 716 717 kp->kp_refcnts++; 718 ASSERT(kp->kp_refcnts > 0); 719 goto exit; 720 } 721 722 if (kpm_vac_range == 0) { 723 /* 724 * Fast path / regular case, no VAC conflict handling 725 * in progress within this kpm_page range. 726 */ 727 if (kp->kp_refcnt == 0) { 728 729 /* tte assembly */ 730 KPM_TTE_VCACHED(tte.ll, pfn, TTE4M); 731 732 /* tsb dropin */ 733 sfmmu_kpm_load_tsb(vaddr, &tte, MMU_PAGESHIFT4M); 734 735 /* Set go flag for TL tsbmiss handler */ 736 if (kp->kp_refcntc == 0) 737 sfmmu_kpm_tsbmtl(&kp->kp_refcntc, 738 &kpmp->khl_lock, KPMTSBM_START); 739 740 ASSERT(kp->kp_refcntc == -1); 741 } 742 kp->kp_refcnt++; 743 ASSERT(kp->kp_refcnt); 744 745 } else { 746 /* 747 * The page is not setup according to the common VAC 748 * prevention rules for the regular and kpm mapping layer 749 * E.g. the page layer was not able to deliver a right 750 * vcolor'ed page for a given vaddr corresponding to 751 * the wanted p_offset. It has to be mapped in small in 752 * within the corresponding kpm vac range in order to 753 * prevent VAC alias conflicts. 754 */ 755 756 /* tte assembly */ 757 if (uncached == 0) { 758 KPM_TTE_VCACHED(tte.ll, pfn, TTE8K); 759 } else { 760 KPM_TTE_VUNCACHED(tte.ll, pfn, TTE8K); 761 } 762 763 /* tsb dropin */ 764 sfmmu_kpm_load_tsb(vaddr, &tte, MMU_PAGESHIFT); 765 766 kp->kp_refcnta++; 767 if (kp->kp_refcntc == -1) { 768 ASSERT(kp->kp_refcnt > 0); 769 770 /* remove go indication */ 771 sfmmu_kpm_tsbmtl(&kp->kp_refcntc, &kpmp->khl_lock, 772 KPMTSBM_STOP); 773 } 774 ASSERT(kp->kp_refcntc >= 0); 775 } 776 exit: 777 mutex_exit(&kpmp->khl_mutex); 778 return (vaddr); 779 780 smallpages_mapin: 781 if (uncached == 0) { 782 /* tte assembly */ 783 KPM_TTE_VCACHED(tte.ll, pfn, TTE8K); 784 } else { 785 /* ASSERT(pp->p_share); XXX use hat_page_getshare */ 786 pmtx = sfmmu_page_enter(pp); 787 PP_SETKPMC(pp); 788 sfmmu_page_exit(pmtx); 789 /* tte assembly */ 790 KPM_TTE_VUNCACHED(tte.ll, pfn, TTE8K); 791 } 792 793 /* tsb dropin */ 794 sfmmu_kpm_load_tsb(vaddr, &tte, MMU_PAGESHIFT); 795 796 PP2KPMSPG(pp, ksp); 797 kpmsp = KPMP_SHASH(ksp); 798 799 oldval = sfmmu_kpm_stsbmtl(&ksp->kp_mapped, &kpmsp->kshl_lock, 800 (uncached) ? KPM_MAPPEDSC : KPM_MAPPEDS); 801 802 if (oldval != 0) 803 panic("sfmmu_kpm_mapin: stale smallpages mapping"); 804 805 return (vaddr); 806 } 807 808 /* 809 * Mapout a single page, it is called every time a page changes it's state 810 * from kpm-mapped to kpm-unmapped. It may not be called, when only a kpm 811 * instance calls mapout and there are still other instances mapping the 812 * page. Assumes that the mlist mutex is already grabbed. 813 * 814 * Note: In normal mode (no VAC conflict prevention pending) TLB's are 815 * not flushed. This is the core segkpm behavior to avoid xcalls. It is 816 * no problem because a translation from a segkpm virtual address to a 817 * physical address is always the same. The only downside is a slighty 818 * increased window of vulnerability for misbehaving _kernel_ modules. 819 */ 820 static void 821 sfmmu_kpm_mapout(page_t *pp, caddr_t vaddr) 822 { 823 kpm_page_t *kp; 824 kpm_hlk_t *kpmp; 825 int alias_range; 826 kmutex_t *pmtx; 827 kpm_spage_t *ksp; 828 kpm_shlk_t *kpmsp; 829 int oldval; 830 831 ASSERT(sfmmu_mlist_held(pp)); 832 ASSERT(pp->p_kpmref == 0); 833 834 alias_range = IS_KPM_ALIAS_RANGE(vaddr); 835 836 if (kpm_smallpages) 837 goto smallpages_mapout; 838 839 PP2KPMPG(pp, kp); 840 kpmp = KPMP_HASH(kp); 841 mutex_enter(&kpmp->khl_mutex); 842 843 if (alias_range) { 844 ASSERT(PP_ISKPMS(pp) == 0); 845 if (kp->kp_refcnta <= 0) { 846 panic("sfmmu_kpm_mapout: bad refcnta kp=%p", 847 (void *)kp); 848 } 849 850 if (PP_ISTNC(pp)) { 851 if (PP_ISKPMC(pp) == 0) { 852 /* 853 * Uncached kpm mappings must always have 854 * forced "small page" mode. 855 */ 856 panic("sfmmu_kpm_mapout: uncached page not " 857 "kpm marked"); 858 } 859 sfmmu_kpm_demap_small(vaddr); 860 861 pmtx = sfmmu_page_enter(pp); 862 PP_CLRKPMC(pp); 863 sfmmu_page_exit(pmtx); 864 865 /* 866 * Check if we can resume cached mode. This might 867 * be the case if the kpm mapping was the only 868 * mapping in conflict with other non rule 869 * compliant mappings. The page is no more marked 870 * as kpm mapped, so the conv_tnc path will not 871 * change kpm state. 872 */ 873 conv_tnc(pp, TTE8K); 874 875 } else if (PP_ISKPMC(pp) == 0) { 876 /* remove TSB entry only */ 877 sfmmu_kpm_unload_tsb(vaddr, MMU_PAGESHIFT); 878 879 } else { 880 /* already demapped */ 881 pmtx = sfmmu_page_enter(pp); 882 PP_CLRKPMC(pp); 883 sfmmu_page_exit(pmtx); 884 } 885 kp->kp_refcnta--; 886 goto exit; 887 } 888 889 if (kp->kp_refcntc <= 0 && kp->kp_refcnts == 0) { 890 /* 891 * Fast path / regular case. 892 */ 893 ASSERT(kp->kp_refcntc >= -1); 894 ASSERT(!(pp->p_nrm & (P_KPMC | P_KPMS | P_TNC | P_PNC))); 895 896 if (kp->kp_refcnt <= 0) 897 panic("sfmmu_kpm_mapout: bad refcnt kp=%p", (void *)kp); 898 899 if (--kp->kp_refcnt == 0) { 900 /* remove go indication */ 901 if (kp->kp_refcntc == -1) { 902 sfmmu_kpm_tsbmtl(&kp->kp_refcntc, 903 &kpmp->khl_lock, KPMTSBM_STOP); 904 } 905 ASSERT(kp->kp_refcntc == 0); 906 907 /* remove TSB entry */ 908 sfmmu_kpm_unload_tsb(vaddr, MMU_PAGESHIFT4M); 909 #ifdef DEBUG 910 if (kpm_tlb_flush) 911 sfmmu_kpm_demap_tlbs(vaddr); 912 #endif 913 } 914 915 } else { 916 /* 917 * The VAC alias path. 918 * We come here if the kpm vaddr is not in any alias_range 919 * and we are unmapping a page within the regular kpm_page 920 * range. The kpm_page either holds conflict pages and/or 921 * is in "small page" mode. If the page is not marked 922 * P_KPMS it couldn't have a valid PAGESIZE sized TSB 923 * entry. Dcache flushing is done lazy and follows the 924 * rules of the regular virtual page coloring scheme. 925 * 926 * Per page states and required actions: 927 * P_KPMC: remove a kpm mapping that is conflicting. 928 * P_KPMS: remove a small kpm mapping within a kpm_page. 929 * P_TNC: check if we can re-cache the page. 930 * P_PNC: we cannot re-cache, sorry. 931 * Per kpm_page: 932 * kp_refcntc > 0: page is part of a kpm_page with conflicts. 933 * kp_refcnts > 0: rm a small mapped page within a kpm_page. 934 */ 935 936 if (PP_ISKPMS(pp)) { 937 if (kp->kp_refcnts < 1) { 938 panic("sfmmu_kpm_mapout: bad refcnts kp=%p", 939 (void *)kp); 940 } 941 sfmmu_kpm_demap_small(vaddr); 942 943 /* 944 * Check if we can resume cached mode. This might 945 * be the case if the kpm mapping was the only 946 * mapping in conflict with other non rule 947 * compliant mappings. The page is no more marked 948 * as kpm mapped, so the conv_tnc path will not 949 * change kpm state. 950 */ 951 if (PP_ISTNC(pp)) { 952 if (!PP_ISKPMC(pp)) { 953 /* 954 * Uncached kpm mappings must always 955 * have forced "small page" mode. 956 */ 957 panic("sfmmu_kpm_mapout: uncached " 958 "page not kpm marked"); 959 } 960 conv_tnc(pp, TTE8K); 961 } 962 kp->kp_refcnts--; 963 kp->kp_refcnt++; 964 pmtx = sfmmu_page_enter(pp); 965 PP_CLRKPMS(pp); 966 sfmmu_page_exit(pmtx); 967 } 968 969 if (PP_ISKPMC(pp)) { 970 if (kp->kp_refcntc < 1) { 971 panic("sfmmu_kpm_mapout: bad refcntc kp=%p", 972 (void *)kp); 973 } 974 pmtx = sfmmu_page_enter(pp); 975 PP_CLRKPMC(pp); 976 sfmmu_page_exit(pmtx); 977 kp->kp_refcntc--; 978 } 979 980 if (kp->kp_refcnt-- < 1) 981 panic("sfmmu_kpm_mapout: bad refcnt kp=%p", (void *)kp); 982 } 983 exit: 984 mutex_exit(&kpmp->khl_mutex); 985 return; 986 987 smallpages_mapout: 988 PP2KPMSPG(pp, ksp); 989 kpmsp = KPMP_SHASH(ksp); 990 991 if (PP_ISKPMC(pp) == 0) { 992 oldval = sfmmu_kpm_stsbmtl(&ksp->kp_mapped, 993 &kpmsp->kshl_lock, 0); 994 995 if (oldval != KPM_MAPPEDS) { 996 /* 997 * When we're called after sfmmu_kpm_hme_unload, 998 * KPM_MAPPEDSC is valid too. 999 */ 1000 if (oldval != KPM_MAPPEDSC) 1001 panic("sfmmu_kpm_mapout: incorrect mapping"); 1002 } 1003 1004 /* remove TSB entry */ 1005 sfmmu_kpm_unload_tsb(vaddr, MMU_PAGESHIFT); 1006 #ifdef DEBUG 1007 if (kpm_tlb_flush) 1008 sfmmu_kpm_demap_tlbs(vaddr); 1009 #endif 1010 1011 } else if (PP_ISTNC(pp)) { 1012 oldval = sfmmu_kpm_stsbmtl(&ksp->kp_mapped, 1013 &kpmsp->kshl_lock, 0); 1014 1015 if (oldval != KPM_MAPPEDSC || PP_ISKPMC(pp) == 0) 1016 panic("sfmmu_kpm_mapout: inconsistent TNC mapping"); 1017 1018 sfmmu_kpm_demap_small(vaddr); 1019 1020 pmtx = sfmmu_page_enter(pp); 1021 PP_CLRKPMC(pp); 1022 sfmmu_page_exit(pmtx); 1023 1024 /* 1025 * Check if we can resume cached mode. This might be 1026 * the case if the kpm mapping was the only mapping 1027 * in conflict with other non rule compliant mappings. 1028 * The page is no more marked as kpm mapped, so the 1029 * conv_tnc path will not change the kpm state. 1030 */ 1031 conv_tnc(pp, TTE8K); 1032 1033 } else { 1034 oldval = sfmmu_kpm_stsbmtl(&ksp->kp_mapped, 1035 &kpmsp->kshl_lock, 0); 1036 1037 if (oldval != KPM_MAPPEDSC) 1038 panic("sfmmu_kpm_mapout: inconsistent mapping"); 1039 1040 pmtx = sfmmu_page_enter(pp); 1041 PP_CLRKPMC(pp); 1042 sfmmu_page_exit(pmtx); 1043 } 1044 } 1045 1046 #define abs(x) ((x) < 0 ? -(x) : (x)) 1047 1048 /* 1049 * Determine appropriate kpm mapping address and handle any kpm/hme 1050 * conflicts. Page mapping list and its vcolor parts must be protected. 1051 */ 1052 static caddr_t 1053 sfmmu_kpm_getvaddr(page_t *pp, int *kpm_vac_rangep) 1054 { 1055 int vcolor, vcolor_pa; 1056 caddr_t vaddr; 1057 uintptr_t paddr; 1058 1059 1060 ASSERT(sfmmu_mlist_held(pp)); 1061 1062 paddr = ptob(pp->p_pagenum); 1063 vcolor_pa = addr_to_vcolor(paddr); 1064 1065 if (pp->p_vnode && IS_SWAPFSVP(pp->p_vnode)) { 1066 vcolor = (PP_NEWPAGE(pp) || PP_ISNC(pp)) ? 1067 vcolor_pa : PP_GET_VCOLOR(pp); 1068 } else { 1069 vcolor = addr_to_vcolor(pp->p_offset); 1070 } 1071 1072 vaddr = kpm_vbase + paddr; 1073 *kpm_vac_rangep = 0; 1074 1075 if (vcolor_pa != vcolor) { 1076 *kpm_vac_rangep = abs(vcolor - vcolor_pa); 1077 vaddr += ((uintptr_t)(vcolor - vcolor_pa) << MMU_PAGESHIFT); 1078 vaddr += (vcolor_pa > vcolor) ? 1079 ((uintptr_t)vcolor_pa << kpm_size_shift) : 1080 ((uintptr_t)(vcolor - vcolor_pa) << kpm_size_shift); 1081 1082 ASSERT(!PP_ISMAPPED_LARGE(pp)); 1083 } 1084 1085 if (PP_ISNC(pp)) 1086 return (vaddr); 1087 1088 if (PP_NEWPAGE(pp)) { 1089 PP_SET_VCOLOR(pp, vcolor); 1090 return (vaddr); 1091 } 1092 1093 if (PP_GET_VCOLOR(pp) == vcolor) 1094 return (vaddr); 1095 1096 ASSERT(!PP_ISMAPPED_KPM(pp)); 1097 sfmmu_kpm_vac_conflict(pp, vaddr); 1098 1099 return (vaddr); 1100 } 1101 1102 /* 1103 * VAC conflict state bit values. 1104 * The following defines are used to make the handling of the 1105 * various input states more concise. For that the kpm states 1106 * per kpm_page and per page are combined in a summary state. 1107 * Each single state has a corresponding bit value in the 1108 * summary state. These defines only apply for kpm large page 1109 * mappings. Within comments the abbreviations "kc, c, ks, s" 1110 * are used as short form of the actual state, e.g. "kc" for 1111 * "kp_refcntc > 0", etc. 1112 */ 1113 #define KPM_KC 0x00000008 /* kpm_page: kp_refcntc > 0 */ 1114 #define KPM_C 0x00000004 /* page: P_KPMC set */ 1115 #define KPM_KS 0x00000002 /* kpm_page: kp_refcnts > 0 */ 1116 #define KPM_S 0x00000001 /* page: P_KPMS set */ 1117 1118 /* 1119 * Summary states used in sfmmu_kpm_fault (KPM_TSBM_*). 1120 * See also more detailed comments within in the sfmmu_kpm_fault switch. 1121 * Abbreviations used: 1122 * CONFL: VAC conflict(s) within a kpm_page. 1123 * MAPS: Mapped small: Page mapped in using a regular page size kpm mapping. 1124 * RASM: Re-assembling of a large page mapping possible. 1125 * RPLS: Replace: TSB miss due to TSB replacement only. 1126 * BRKO: Breakup Other: A large kpm mapping has to be broken because another 1127 * page within the kpm_page is already involved in a VAC conflict. 1128 * BRKT: Breakup This: A large kpm mapping has to be broken, this page is 1129 * is involved in a VAC conflict. 1130 */ 1131 #define KPM_TSBM_CONFL_GONE (0) 1132 #define KPM_TSBM_MAPS_RASM (KPM_KS) 1133 #define KPM_TSBM_RPLS_RASM (KPM_KS | KPM_S) 1134 #define KPM_TSBM_MAPS_BRKO (KPM_KC) 1135 #define KPM_TSBM_MAPS (KPM_KC | KPM_KS) 1136 #define KPM_TSBM_RPLS (KPM_KC | KPM_KS | KPM_S) 1137 #define KPM_TSBM_MAPS_BRKT (KPM_KC | KPM_C) 1138 #define KPM_TSBM_MAPS_CONFL (KPM_KC | KPM_C | KPM_KS) 1139 #define KPM_TSBM_RPLS_CONFL (KPM_KC | KPM_C | KPM_KS | KPM_S) 1140 1141 /* 1142 * kpm fault handler for mappings with large page size. 1143 */ 1144 int 1145 sfmmu_kpm_fault(caddr_t vaddr, struct memseg *mseg, page_t *pp) 1146 { 1147 int error; 1148 pgcnt_t inx; 1149 kpm_page_t *kp; 1150 tte_t tte; 1151 pfn_t pfn = pp->p_pagenum; 1152 kpm_hlk_t *kpmp; 1153 kmutex_t *pml; 1154 int alias_range; 1155 int uncached = 0; 1156 kmutex_t *pmtx; 1157 int badstate; 1158 uint_t tsbmcase; 1159 1160 alias_range = IS_KPM_ALIAS_RANGE(vaddr); 1161 1162 inx = ptokpmp(kpmptop(ptokpmp(pfn)) - mseg->kpm_pbase); 1163 if (inx >= mseg->kpm_nkpmpgs) { 1164 cmn_err(CE_PANIC, "sfmmu_kpm_fault: kpm overflow in memseg " 1165 "0x%p pp 0x%p", (void *)mseg, (void *)pp); 1166 } 1167 1168 kp = &mseg->kpm_pages[inx]; 1169 kpmp = KPMP_HASH(kp); 1170 1171 pml = sfmmu_mlist_enter(pp); 1172 1173 if (!PP_ISMAPPED_KPM(pp)) { 1174 sfmmu_mlist_exit(pml); 1175 return (EFAULT); 1176 } 1177 1178 mutex_enter(&kpmp->khl_mutex); 1179 1180 if (alias_range) { 1181 ASSERT(!PP_ISMAPPED_LARGE(pp)); 1182 if (kp->kp_refcnta > 0) { 1183 if (PP_ISKPMC(pp)) { 1184 pmtx = sfmmu_page_enter(pp); 1185 PP_CLRKPMC(pp); 1186 sfmmu_page_exit(pmtx); 1187 } 1188 /* 1189 * Check for vcolor conflicts. Return here 1190 * w/ either no conflict (fast path), removed hme 1191 * mapping chains (unload conflict) or uncached 1192 * (uncache conflict). VACaches are cleaned and 1193 * p_vcolor and PP_TNC are set accordingly for the 1194 * conflict cases. Drop kpmp for uncache conflict 1195 * cases since it will be grabbed within 1196 * sfmmu_kpm_page_cache in case of an uncache 1197 * conflict. 1198 */ 1199 mutex_exit(&kpmp->khl_mutex); 1200 sfmmu_kpm_vac_conflict(pp, vaddr); 1201 mutex_enter(&kpmp->khl_mutex); 1202 1203 if (PP_ISNC(pp)) { 1204 uncached = 1; 1205 pmtx = sfmmu_page_enter(pp); 1206 PP_SETKPMC(pp); 1207 sfmmu_page_exit(pmtx); 1208 } 1209 goto smallexit; 1210 1211 } else { 1212 /* 1213 * We got a tsbmiss on a not active kpm_page range. 1214 * Let segkpm_fault decide how to panic. 1215 */ 1216 error = EFAULT; 1217 } 1218 goto exit; 1219 } 1220 1221 badstate = (kp->kp_refcnt < 0 || kp->kp_refcnts < 0); 1222 if (kp->kp_refcntc == -1) { 1223 /* 1224 * We should come here only if trap level tsb miss 1225 * handler is disabled. 1226 */ 1227 badstate |= (kp->kp_refcnt == 0 || kp->kp_refcnts > 0 || 1228 PP_ISKPMC(pp) || PP_ISKPMS(pp) || PP_ISNC(pp)); 1229 1230 if (badstate == 0) 1231 goto largeexit; 1232 } 1233 1234 if (badstate || kp->kp_refcntc < 0) 1235 goto badstate_exit; 1236 1237 /* 1238 * Combine the per kpm_page and per page kpm VAC states to 1239 * a summary state in order to make the kpm fault handling 1240 * more concise. 1241 */ 1242 tsbmcase = (((kp->kp_refcntc > 0) ? KPM_KC : 0) | 1243 ((kp->kp_refcnts > 0) ? KPM_KS : 0) | 1244 (PP_ISKPMC(pp) ? KPM_C : 0) | 1245 (PP_ISKPMS(pp) ? KPM_S : 0)); 1246 1247 switch (tsbmcase) { 1248 case KPM_TSBM_CONFL_GONE: /* - - - - */ 1249 /* 1250 * That's fine, we either have no more vac conflict in 1251 * this kpm page or someone raced in and has solved the 1252 * vac conflict for us -- call sfmmu_kpm_vac_conflict 1253 * to take care for correcting the vcolor and flushing 1254 * the dcache if required. 1255 */ 1256 mutex_exit(&kpmp->khl_mutex); 1257 sfmmu_kpm_vac_conflict(pp, vaddr); 1258 mutex_enter(&kpmp->khl_mutex); 1259 1260 if (PP_ISNC(pp) || kp->kp_refcnt <= 0 || 1261 addr_to_vcolor(vaddr) != PP_GET_VCOLOR(pp)) { 1262 panic("sfmmu_kpm_fault: inconsistent CONFL_GONE " 1263 "state, pp=%p", (void *)pp); 1264 } 1265 goto largeexit; 1266 1267 case KPM_TSBM_MAPS_RASM: /* - - ks - */ 1268 /* 1269 * All conflicts in this kpm page are gone but there are 1270 * already small mappings around, so we also map this 1271 * page small. This could be the trigger case for a 1272 * small mapping reaper, if this is really needed. 1273 * For now fall thru to the KPM_TSBM_MAPS handling. 1274 */ 1275 1276 case KPM_TSBM_MAPS: /* kc - ks - */ 1277 /* 1278 * Large page mapping is already broken, this page is not 1279 * conflicting, so map it small. Call sfmmu_kpm_vac_conflict 1280 * to take care for correcting the vcolor and flushing 1281 * the dcache if required. 1282 */ 1283 mutex_exit(&kpmp->khl_mutex); 1284 sfmmu_kpm_vac_conflict(pp, vaddr); 1285 mutex_enter(&kpmp->khl_mutex); 1286 1287 if (PP_ISNC(pp) || kp->kp_refcnt <= 0 || 1288 addr_to_vcolor(vaddr) != PP_GET_VCOLOR(pp)) { 1289 panic("sfmmu_kpm_fault: inconsistent MAPS state, " 1290 "pp=%p", (void *)pp); 1291 } 1292 kp->kp_refcnt--; 1293 kp->kp_refcnts++; 1294 pmtx = sfmmu_page_enter(pp); 1295 PP_SETKPMS(pp); 1296 sfmmu_page_exit(pmtx); 1297 goto smallexit; 1298 1299 case KPM_TSBM_RPLS_RASM: /* - - ks s */ 1300 /* 1301 * All conflicts in this kpm page are gone but this page 1302 * is mapped small. This could be the trigger case for a 1303 * small mapping reaper, if this is really needed. 1304 * For now we drop it in small again. Fall thru to the 1305 * KPM_TSBM_RPLS handling. 1306 */ 1307 1308 case KPM_TSBM_RPLS: /* kc - ks s */ 1309 /* 1310 * Large page mapping is already broken, this page is not 1311 * conflicting but already mapped small, so drop it in 1312 * small again. 1313 */ 1314 if (PP_ISNC(pp) || 1315 addr_to_vcolor(vaddr) != PP_GET_VCOLOR(pp)) { 1316 panic("sfmmu_kpm_fault: inconsistent RPLS state, " 1317 "pp=%p", (void *)pp); 1318 } 1319 goto smallexit; 1320 1321 case KPM_TSBM_MAPS_BRKO: /* kc - - - */ 1322 /* 1323 * The kpm page where we live in is marked conflicting 1324 * but this page is not conflicting. So we have to map it 1325 * in small. Call sfmmu_kpm_vac_conflict to take care for 1326 * correcting the vcolor and flushing the dcache if required. 1327 */ 1328 mutex_exit(&kpmp->khl_mutex); 1329 sfmmu_kpm_vac_conflict(pp, vaddr); 1330 mutex_enter(&kpmp->khl_mutex); 1331 1332 if (PP_ISNC(pp) || kp->kp_refcnt <= 0 || 1333 addr_to_vcolor(vaddr) != PP_GET_VCOLOR(pp)) { 1334 panic("sfmmu_kpm_fault: inconsistent MAPS_BRKO state, " 1335 "pp=%p", (void *)pp); 1336 } 1337 kp->kp_refcnt--; 1338 kp->kp_refcnts++; 1339 pmtx = sfmmu_page_enter(pp); 1340 PP_SETKPMS(pp); 1341 sfmmu_page_exit(pmtx); 1342 goto smallexit; 1343 1344 case KPM_TSBM_MAPS_BRKT: /* kc c - - */ 1345 case KPM_TSBM_MAPS_CONFL: /* kc c ks - */ 1346 if (!PP_ISMAPPED(pp)) { 1347 /* 1348 * We got a tsbmiss on kpm large page range that is 1349 * marked to contain vac conflicting pages introduced 1350 * by hme mappings. The hme mappings are all gone and 1351 * must have bypassed the kpm alias prevention logic. 1352 */ 1353 panic("sfmmu_kpm_fault: stale VAC conflict, pp=%p", 1354 (void *)pp); 1355 } 1356 1357 /* 1358 * Check for vcolor conflicts. Return here w/ either no 1359 * conflict (fast path), removed hme mapping chains 1360 * (unload conflict) or uncached (uncache conflict). 1361 * Dcache is cleaned and p_vcolor and P_TNC are set 1362 * accordingly. Drop kpmp for uncache conflict cases 1363 * since it will be grabbed within sfmmu_kpm_page_cache 1364 * in case of an uncache conflict. 1365 */ 1366 mutex_exit(&kpmp->khl_mutex); 1367 sfmmu_kpm_vac_conflict(pp, vaddr); 1368 mutex_enter(&kpmp->khl_mutex); 1369 1370 if (kp->kp_refcnt <= 0) 1371 panic("sfmmu_kpm_fault: bad refcnt kp=%p", (void *)kp); 1372 1373 if (PP_ISNC(pp)) { 1374 uncached = 1; 1375 } else { 1376 /* 1377 * When an unload conflict is solved and there are 1378 * no other small mappings around, we can resume 1379 * largepage mode. Otherwise we have to map or drop 1380 * in small. This could be a trigger for a small 1381 * mapping reaper when this was the last conflict 1382 * within the kpm page and when there are only 1383 * other small mappings around. 1384 */ 1385 ASSERT(addr_to_vcolor(vaddr) == PP_GET_VCOLOR(pp)); 1386 ASSERT(kp->kp_refcntc > 0); 1387 kp->kp_refcntc--; 1388 pmtx = sfmmu_page_enter(pp); 1389 PP_CLRKPMC(pp); 1390 sfmmu_page_exit(pmtx); 1391 ASSERT(PP_ISKPMS(pp) == 0); 1392 if (kp->kp_refcntc == 0 && kp->kp_refcnts == 0) 1393 goto largeexit; 1394 } 1395 1396 kp->kp_refcnt--; 1397 kp->kp_refcnts++; 1398 pmtx = sfmmu_page_enter(pp); 1399 PP_SETKPMS(pp); 1400 sfmmu_page_exit(pmtx); 1401 goto smallexit; 1402 1403 case KPM_TSBM_RPLS_CONFL: /* kc c ks s */ 1404 if (!PP_ISMAPPED(pp)) { 1405 /* 1406 * We got a tsbmiss on kpm large page range that is 1407 * marked to contain vac conflicting pages introduced 1408 * by hme mappings. They are all gone and must have 1409 * somehow bypassed the kpm alias prevention logic. 1410 */ 1411 panic("sfmmu_kpm_fault: stale VAC conflict, pp=%p", 1412 (void *)pp); 1413 } 1414 1415 /* 1416 * This state is only possible for an uncached mapping. 1417 */ 1418 if (!PP_ISNC(pp)) { 1419 panic("sfmmu_kpm_fault: page not uncached, pp=%p", 1420 (void *)pp); 1421 } 1422 uncached = 1; 1423 goto smallexit; 1424 1425 default: 1426 badstate_exit: 1427 panic("sfmmu_kpm_fault: inconsistent VAC state, vaddr=%p kp=%p " 1428 "pp=%p", (void *)vaddr, (void *)kp, (void *)pp); 1429 } 1430 1431 smallexit: 1432 /* tte assembly */ 1433 if (uncached == 0) 1434 KPM_TTE_VCACHED(tte.ll, pfn, TTE8K); 1435 else 1436 KPM_TTE_VUNCACHED(tte.ll, pfn, TTE8K); 1437 1438 /* tsb dropin */ 1439 sfmmu_kpm_load_tsb(vaddr, &tte, MMU_PAGESHIFT); 1440 1441 error = 0; 1442 goto exit; 1443 1444 largeexit: 1445 if (kp->kp_refcnt > 0) { 1446 1447 /* tte assembly */ 1448 KPM_TTE_VCACHED(tte.ll, pfn, TTE4M); 1449 1450 /* tsb dropin */ 1451 sfmmu_kpm_load_tsb(vaddr, &tte, MMU_PAGESHIFT4M); 1452 1453 if (kp->kp_refcntc == 0) { 1454 /* Set "go" flag for TL tsbmiss handler */ 1455 sfmmu_kpm_tsbmtl(&kp->kp_refcntc, &kpmp->khl_lock, 1456 KPMTSBM_START); 1457 } 1458 ASSERT(kp->kp_refcntc == -1); 1459 error = 0; 1460 1461 } else 1462 error = EFAULT; 1463 exit: 1464 mutex_exit(&kpmp->khl_mutex); 1465 sfmmu_mlist_exit(pml); 1466 return (error); 1467 } 1468 1469 /* 1470 * kpm fault handler for mappings with small page size. 1471 */ 1472 int 1473 sfmmu_kpm_fault_small(caddr_t vaddr, struct memseg *mseg, page_t *pp) 1474 { 1475 int error = 0; 1476 pgcnt_t inx; 1477 kpm_spage_t *ksp; 1478 kpm_shlk_t *kpmsp; 1479 kmutex_t *pml; 1480 pfn_t pfn = pp->p_pagenum; 1481 tte_t tte; 1482 kmutex_t *pmtx; 1483 int oldval; 1484 1485 inx = pfn - mseg->kpm_pbase; 1486 ksp = &mseg->kpm_spages[inx]; 1487 kpmsp = KPMP_SHASH(ksp); 1488 1489 pml = sfmmu_mlist_enter(pp); 1490 1491 if (!PP_ISMAPPED_KPM(pp)) { 1492 sfmmu_mlist_exit(pml); 1493 return (EFAULT); 1494 } 1495 1496 /* 1497 * kp_mapped lookup protected by mlist mutex 1498 */ 1499 if (ksp->kp_mapped == KPM_MAPPEDS) { 1500 /* 1501 * Fast path tsbmiss 1502 */ 1503 ASSERT(!PP_ISKPMC(pp)); 1504 ASSERT(!PP_ISNC(pp)); 1505 1506 /* tte assembly */ 1507 KPM_TTE_VCACHED(tte.ll, pfn, TTE8K); 1508 1509 /* tsb dropin */ 1510 sfmmu_kpm_load_tsb(vaddr, &tte, MMU_PAGESHIFT); 1511 1512 } else if (ksp->kp_mapped == KPM_MAPPEDSC) { 1513 /* 1514 * Got here due to existing or gone kpm/hme VAC conflict. 1515 * Recheck for vcolor conflicts. Return here w/ either 1516 * no conflict, removed hme mapping chain (unload 1517 * conflict) or uncached (uncache conflict). VACaches 1518 * are cleaned and p_vcolor and PP_TNC are set accordingly 1519 * for the conflict cases. 1520 */ 1521 sfmmu_kpm_vac_conflict(pp, vaddr); 1522 1523 if (PP_ISNC(pp)) { 1524 /* ASSERT(pp->p_share); XXX use hat_page_getshare */ 1525 1526 /* tte assembly */ 1527 KPM_TTE_VUNCACHED(tte.ll, pfn, TTE8K); 1528 1529 /* tsb dropin */ 1530 sfmmu_kpm_load_tsb(vaddr, &tte, MMU_PAGESHIFT); 1531 1532 } else { 1533 if (PP_ISKPMC(pp)) { 1534 pmtx = sfmmu_page_enter(pp); 1535 PP_CLRKPMC(pp); 1536 sfmmu_page_exit(pmtx); 1537 } 1538 1539 /* tte assembly */ 1540 KPM_TTE_VCACHED(tte.ll, pfn, TTE8K); 1541 1542 /* tsb dropin */ 1543 sfmmu_kpm_load_tsb(vaddr, &tte, MMU_PAGESHIFT); 1544 1545 oldval = sfmmu_kpm_stsbmtl(&ksp->kp_mapped, 1546 &kpmsp->kshl_lock, KPM_MAPPEDS); 1547 1548 if (oldval != KPM_MAPPEDSC) 1549 panic("sfmmu_kpm_fault_small: " 1550 "stale smallpages mapping"); 1551 } 1552 1553 } else { 1554 /* 1555 * We got a tsbmiss on a not active kpm_page range. 1556 * Let decide segkpm_fault how to panic. 1557 */ 1558 error = EFAULT; 1559 } 1560 1561 sfmmu_mlist_exit(pml); 1562 return (error); 1563 } 1564 1565 /* 1566 * Check/handle potential hme/kpm mapping conflicts 1567 */ 1568 static void 1569 sfmmu_kpm_vac_conflict(page_t *pp, caddr_t vaddr) 1570 { 1571 int vcolor; 1572 struct sf_hment *sfhmep; 1573 struct hat *tmphat; 1574 struct sf_hment *tmphme = NULL; 1575 struct hme_blk *hmeblkp; 1576 tte_t tte; 1577 1578 ASSERT(sfmmu_mlist_held(pp)); 1579 1580 if (PP_ISNC(pp)) 1581 return; 1582 1583 vcolor = addr_to_vcolor(vaddr); 1584 if (PP_GET_VCOLOR(pp) == vcolor) 1585 return; 1586 1587 /* 1588 * There could be no vcolor conflict between a large cached 1589 * hme page and a non alias range kpm page (neither large nor 1590 * small mapped). So if a hme conflict already exists between 1591 * a constituent page of a large hme mapping and a shared small 1592 * conflicting hme mapping, both mappings must be already 1593 * uncached at this point. 1594 */ 1595 ASSERT(!PP_ISMAPPED_LARGE(pp)); 1596 1597 if (!PP_ISMAPPED(pp)) { 1598 /* 1599 * Previous hme user of page had a different color 1600 * but since there are no current users 1601 * we just flush the cache and change the color. 1602 */ 1603 SFMMU_STAT(sf_pgcolor_conflict); 1604 sfmmu_cache_flush(pp->p_pagenum, PP_GET_VCOLOR(pp)); 1605 PP_SET_VCOLOR(pp, vcolor); 1606 return; 1607 } 1608 1609 /* 1610 * If we get here we have a vac conflict with a current hme 1611 * mapping. This must have been established by forcing a wrong 1612 * colored mapping, e.g. by using mmap(2) with MAP_FIXED. 1613 */ 1614 1615 /* 1616 * Check if any mapping is in same as or if it is locked 1617 * since in that case we need to uncache. 1618 */ 1619 for (sfhmep = pp->p_mapping; sfhmep; sfhmep = tmphme) { 1620 tmphme = sfhmep->hme_next; 1621 hmeblkp = sfmmu_hmetohblk(sfhmep); 1622 if (hmeblkp->hblk_xhat_bit) 1623 continue; 1624 tmphat = hblktosfmmu(hmeblkp); 1625 sfmmu_copytte(&sfhmep->hme_tte, &tte); 1626 ASSERT(TTE_IS_VALID(&tte)); 1627 if ((tmphat == ksfmmup) || hmeblkp->hblk_lckcnt) { 1628 /* 1629 * We have an uncache conflict 1630 */ 1631 SFMMU_STAT(sf_uncache_conflict); 1632 sfmmu_page_cache_array(pp, HAT_TMPNC, CACHE_FLUSH, 1); 1633 return; 1634 } 1635 } 1636 1637 /* 1638 * We have an unload conflict 1639 */ 1640 SFMMU_STAT(sf_unload_conflict); 1641 1642 for (sfhmep = pp->p_mapping; sfhmep; sfhmep = tmphme) { 1643 tmphme = sfhmep->hme_next; 1644 hmeblkp = sfmmu_hmetohblk(sfhmep); 1645 if (hmeblkp->hblk_xhat_bit) 1646 continue; 1647 (void) sfmmu_pageunload(pp, sfhmep, TTE8K); 1648 } 1649 1650 /* 1651 * Unloads only does tlb flushes so we need to flush the 1652 * dcache vcolor here. 1653 */ 1654 sfmmu_cache_flush(pp->p_pagenum, PP_GET_VCOLOR(pp)); 1655 PP_SET_VCOLOR(pp, vcolor); 1656 } 1657 1658 /* 1659 * Remove all kpm mappings using kpme's for pp and check that 1660 * all kpm mappings (w/ and w/o kpme's) are gone. 1661 */ 1662 void 1663 sfmmu_kpm_pageunload(page_t *pp) 1664 { 1665 caddr_t vaddr; 1666 struct kpme *kpme, *nkpme; 1667 1668 ASSERT(pp != NULL); 1669 ASSERT(pp->p_kpmref); 1670 ASSERT(sfmmu_mlist_held(pp)); 1671 1672 vaddr = hat_kpm_page2va(pp, 1); 1673 1674 for (kpme = pp->p_kpmelist; kpme; kpme = nkpme) { 1675 ASSERT(kpme->kpe_page == pp); 1676 1677 if (pp->p_kpmref == 0) 1678 panic("sfmmu_kpm_pageunload: stale p_kpmref pp=%p " 1679 "kpme=%p", (void *)pp, (void *)kpme); 1680 1681 nkpme = kpme->kpe_next; 1682 1683 /* Add instance callback here here if needed later */ 1684 sfmmu_kpme_sub(kpme, pp); 1685 } 1686 1687 /* 1688 * Also correct after mixed kpme/nonkpme mappings. If nonkpme 1689 * segkpm clients have unlocked the page and forgot to mapout 1690 * we panic here. 1691 */ 1692 if (pp->p_kpmref != 0) 1693 panic("sfmmu_kpm_pageunload: bad refcnt pp=%p", (void *)pp); 1694 1695 sfmmu_kpm_mapout(pp, vaddr); 1696 } 1697 1698 /* 1699 * Remove a large kpm mapping from kernel TSB and all TLB's. 1700 */ 1701 static void 1702 sfmmu_kpm_demap_large(caddr_t vaddr) 1703 { 1704 sfmmu_kpm_unload_tsb(vaddr, MMU_PAGESHIFT4M); 1705 sfmmu_kpm_demap_tlbs(vaddr); 1706 } 1707 1708 /* 1709 * Remove a small kpm mapping from kernel TSB and all TLB's. 1710 */ 1711 static void 1712 sfmmu_kpm_demap_small(caddr_t vaddr) 1713 { 1714 sfmmu_kpm_unload_tsb(vaddr, MMU_PAGESHIFT); 1715 sfmmu_kpm_demap_tlbs(vaddr); 1716 } 1717 1718 /* 1719 * Demap a kpm mapping in all TLB's. 1720 */ 1721 static void 1722 sfmmu_kpm_demap_tlbs(caddr_t vaddr) 1723 { 1724 cpuset_t cpuset; 1725 1726 kpreempt_disable(); 1727 cpuset = ksfmmup->sfmmu_cpusran; 1728 CPUSET_AND(cpuset, cpu_ready_set); 1729 CPUSET_DEL(cpuset, CPU->cpu_id); 1730 SFMMU_XCALL_STATS(ksfmmup); 1731 1732 xt_some(cpuset, vtag_flushpage_tl1, (uint64_t)vaddr, 1733 (uint64_t)ksfmmup); 1734 vtag_flushpage(vaddr, (uint64_t)ksfmmup); 1735 1736 kpreempt_enable(); 1737 } 1738 1739 /* 1740 * Summary states used in sfmmu_kpm_vac_unload (KPM_VUL__*). 1741 * See also more detailed comments within in the sfmmu_kpm_vac_unload switch. 1742 * Abbreviations used: 1743 * BIG: Large page kpm mapping in use. 1744 * CONFL: VAC conflict(s) within a kpm_page. 1745 * INCR: Count of conflicts within a kpm_page is going to be incremented. 1746 * DECR: Count of conflicts within a kpm_page is going to be decremented. 1747 * UNMAP_SMALL: A small (regular page size) mapping is going to be unmapped. 1748 * TNC: Temporary non cached: a kpm mapped page is mapped in TNC state. 1749 */ 1750 #define KPM_VUL_BIG (0) 1751 #define KPM_VUL_CONFL_INCR1 (KPM_KS) 1752 #define KPM_VUL_UNMAP_SMALL1 (KPM_KS | KPM_S) 1753 #define KPM_VUL_CONFL_INCR2 (KPM_KC) 1754 #define KPM_VUL_CONFL_INCR3 (KPM_KC | KPM_KS) 1755 #define KPM_VUL_UNMAP_SMALL2 (KPM_KC | KPM_KS | KPM_S) 1756 #define KPM_VUL_CONFL_DECR1 (KPM_KC | KPM_C) 1757 #define KPM_VUL_CONFL_DECR2 (KPM_KC | KPM_C | KPM_KS) 1758 #define KPM_VUL_TNC (KPM_KC | KPM_C | KPM_KS | KPM_S) 1759 1760 /* 1761 * Handle VAC unload conflicts introduced by hme mappings or vice 1762 * versa when a hme conflict mapping is replaced by a non conflict 1763 * one. Perform actions and state transitions according to the 1764 * various page and kpm_page entry states. VACache flushes are in 1765 * the responsibiliy of the caller. We still hold the mlist lock. 1766 */ 1767 void 1768 sfmmu_kpm_vac_unload(page_t *pp, caddr_t vaddr) 1769 { 1770 kpm_page_t *kp; 1771 kpm_hlk_t *kpmp; 1772 caddr_t kpmvaddr = hat_kpm_page2va(pp, 1); 1773 int newcolor; 1774 kmutex_t *pmtx; 1775 uint_t vacunlcase; 1776 int badstate = 0; 1777 kpm_spage_t *ksp; 1778 kpm_shlk_t *kpmsp; 1779 1780 ASSERT(PAGE_LOCKED(pp)); 1781 ASSERT(sfmmu_mlist_held(pp)); 1782 ASSERT(!PP_ISNC(pp)); 1783 1784 newcolor = addr_to_vcolor(kpmvaddr) != addr_to_vcolor(vaddr); 1785 if (kpm_smallpages) 1786 goto smallpages_vac_unload; 1787 1788 PP2KPMPG(pp, kp); 1789 kpmp = KPMP_HASH(kp); 1790 mutex_enter(&kpmp->khl_mutex); 1791 1792 if (IS_KPM_ALIAS_RANGE(kpmvaddr)) { 1793 if (kp->kp_refcnta < 1) { 1794 panic("sfmmu_kpm_vac_unload: bad refcnta kpm_page=%p\n", 1795 (void *)kp); 1796 } 1797 1798 if (PP_ISKPMC(pp) == 0) { 1799 if (newcolor == 0) 1800 goto exit; 1801 sfmmu_kpm_demap_small(kpmvaddr); 1802 pmtx = sfmmu_page_enter(pp); 1803 PP_SETKPMC(pp); 1804 sfmmu_page_exit(pmtx); 1805 1806 } else if (newcolor == 0) { 1807 pmtx = sfmmu_page_enter(pp); 1808 PP_CLRKPMC(pp); 1809 sfmmu_page_exit(pmtx); 1810 1811 } else { 1812 badstate++; 1813 } 1814 1815 goto exit; 1816 } 1817 1818 badstate = (kp->kp_refcnt < 0 || kp->kp_refcnts < 0); 1819 if (kp->kp_refcntc == -1) { 1820 /* 1821 * We should come here only if trap level tsb miss 1822 * handler is disabled. 1823 */ 1824 badstate |= (kp->kp_refcnt == 0 || kp->kp_refcnts > 0 || 1825 PP_ISKPMC(pp) || PP_ISKPMS(pp) || PP_ISNC(pp)); 1826 } else { 1827 badstate |= (kp->kp_refcntc < 0); 1828 } 1829 1830 if (badstate) 1831 goto exit; 1832 1833 if (PP_ISKPMC(pp) == 0 && newcolor == 0) { 1834 ASSERT(PP_ISKPMS(pp) == 0); 1835 goto exit; 1836 } 1837 1838 /* 1839 * Combine the per kpm_page and per page kpm VAC states 1840 * to a summary state in order to make the vac unload 1841 * handling more concise. 1842 */ 1843 vacunlcase = (((kp->kp_refcntc > 0) ? KPM_KC : 0) | 1844 ((kp->kp_refcnts > 0) ? KPM_KS : 0) | 1845 (PP_ISKPMC(pp) ? KPM_C : 0) | 1846 (PP_ISKPMS(pp) ? KPM_S : 0)); 1847 1848 switch (vacunlcase) { 1849 case KPM_VUL_BIG: /* - - - - */ 1850 /* 1851 * Have to breakup the large page mapping to be 1852 * able to handle the conflicting hme vaddr. 1853 */ 1854 if (kp->kp_refcntc == -1) { 1855 /* remove go indication */ 1856 sfmmu_kpm_tsbmtl(&kp->kp_refcntc, 1857 &kpmp->khl_lock, KPMTSBM_STOP); 1858 } 1859 sfmmu_kpm_demap_large(kpmvaddr); 1860 1861 ASSERT(kp->kp_refcntc == 0); 1862 kp->kp_refcntc++; 1863 pmtx = sfmmu_page_enter(pp); 1864 PP_SETKPMC(pp); 1865 sfmmu_page_exit(pmtx); 1866 break; 1867 1868 case KPM_VUL_UNMAP_SMALL1: /* - - ks s */ 1869 case KPM_VUL_UNMAP_SMALL2: /* kc - ks s */ 1870 /* 1871 * New conflict w/ an active kpm page, actually mapped 1872 * in by small TSB/TLB entries. Remove the mapping and 1873 * update states. 1874 */ 1875 ASSERT(newcolor); 1876 sfmmu_kpm_demap_small(kpmvaddr); 1877 kp->kp_refcnts--; 1878 kp->kp_refcnt++; 1879 kp->kp_refcntc++; 1880 pmtx = sfmmu_page_enter(pp); 1881 PP_CLRKPMS(pp); 1882 PP_SETKPMC(pp); 1883 sfmmu_page_exit(pmtx); 1884 break; 1885 1886 case KPM_VUL_CONFL_INCR1: /* - - ks - */ 1887 case KPM_VUL_CONFL_INCR2: /* kc - - - */ 1888 case KPM_VUL_CONFL_INCR3: /* kc - ks - */ 1889 /* 1890 * New conflict on a active kpm mapped page not yet in 1891 * TSB/TLB. Mark page and increment the kpm_page conflict 1892 * count. 1893 */ 1894 ASSERT(newcolor); 1895 kp->kp_refcntc++; 1896 pmtx = sfmmu_page_enter(pp); 1897 PP_SETKPMC(pp); 1898 sfmmu_page_exit(pmtx); 1899 break; 1900 1901 case KPM_VUL_CONFL_DECR1: /* kc c - - */ 1902 case KPM_VUL_CONFL_DECR2: /* kc c ks - */ 1903 /* 1904 * A conflicting hme mapping is removed for an active 1905 * kpm page not yet in TSB/TLB. Unmark page and decrement 1906 * the kpm_page conflict count. 1907 */ 1908 ASSERT(newcolor == 0); 1909 kp->kp_refcntc--; 1910 pmtx = sfmmu_page_enter(pp); 1911 PP_CLRKPMC(pp); 1912 sfmmu_page_exit(pmtx); 1913 break; 1914 1915 case KPM_VUL_TNC: /* kc c ks s */ 1916 cmn_err(CE_NOTE, "sfmmu_kpm_vac_unload: " 1917 "page not in NC state"); 1918 /* FALLTHRU */ 1919 1920 default: 1921 badstate++; 1922 } 1923 exit: 1924 if (badstate) { 1925 panic("sfmmu_kpm_vac_unload: inconsistent VAC state, " 1926 "kpmvaddr=%p kp=%p pp=%p", 1927 (void *)kpmvaddr, (void *)kp, (void *)pp); 1928 } 1929 mutex_exit(&kpmp->khl_mutex); 1930 1931 return; 1932 1933 smallpages_vac_unload: 1934 if (newcolor == 0) 1935 return; 1936 1937 PP2KPMSPG(pp, ksp); 1938 kpmsp = KPMP_SHASH(ksp); 1939 1940 if (PP_ISKPMC(pp) == 0) { 1941 if (ksp->kp_mapped == KPM_MAPPEDS) { 1942 /* 1943 * Stop TL tsbmiss handling 1944 */ 1945 (void) sfmmu_kpm_stsbmtl(&ksp->kp_mapped, 1946 &kpmsp->kshl_lock, KPM_MAPPEDSC); 1947 1948 sfmmu_kpm_demap_small(kpmvaddr); 1949 1950 } else if (ksp->kp_mapped != KPM_MAPPEDSC) { 1951 panic("sfmmu_kpm_vac_unload: inconsistent mapping"); 1952 } 1953 1954 pmtx = sfmmu_page_enter(pp); 1955 PP_SETKPMC(pp); 1956 sfmmu_page_exit(pmtx); 1957 1958 } else { 1959 if (ksp->kp_mapped != KPM_MAPPEDSC) 1960 panic("sfmmu_kpm_vac_unload: inconsistent mapping"); 1961 } 1962 } 1963 1964 /* 1965 * Page is marked to be in VAC conflict to an existing kpm mapping 1966 * or is kpm mapped using only the regular pagesize. Called from 1967 * sfmmu_hblk_unload when a mlist is completely removed. 1968 */ 1969 void 1970 sfmmu_kpm_hme_unload(page_t *pp) 1971 { 1972 /* tte assembly */ 1973 kpm_page_t *kp; 1974 kpm_hlk_t *kpmp; 1975 caddr_t vaddr; 1976 kmutex_t *pmtx; 1977 uint_t flags; 1978 kpm_spage_t *ksp; 1979 1980 ASSERT(sfmmu_mlist_held(pp)); 1981 ASSERT(PP_ISMAPPED_KPM(pp)); 1982 1983 flags = pp->p_nrm & (P_KPMC | P_KPMS); 1984 if (kpm_smallpages) 1985 goto smallpages_hme_unload; 1986 1987 if (flags == (P_KPMC | P_KPMS)) { 1988 panic("sfmmu_kpm_hme_unload: page should be uncached"); 1989 1990 } else if (flags == P_KPMS) { 1991 /* 1992 * Page mapped small but not involved in VAC conflict 1993 */ 1994 return; 1995 } 1996 1997 vaddr = hat_kpm_page2va(pp, 1); 1998 1999 PP2KPMPG(pp, kp); 2000 kpmp = KPMP_HASH(kp); 2001 mutex_enter(&kpmp->khl_mutex); 2002 2003 if (IS_KPM_ALIAS_RANGE(vaddr)) { 2004 if (kp->kp_refcnta < 1) { 2005 panic("sfmmu_kpm_hme_unload: bad refcnta kpm_page=%p\n", 2006 (void *)kp); 2007 } 2008 } else { 2009 if (kp->kp_refcntc < 1) { 2010 panic("sfmmu_kpm_hme_unload: bad refcntc kpm_page=%p\n", 2011 (void *)kp); 2012 } 2013 kp->kp_refcntc--; 2014 } 2015 2016 pmtx = sfmmu_page_enter(pp); 2017 PP_CLRKPMC(pp); 2018 sfmmu_page_exit(pmtx); 2019 2020 mutex_exit(&kpmp->khl_mutex); 2021 return; 2022 2023 smallpages_hme_unload: 2024 if (flags != P_KPMC) 2025 panic("sfmmu_kpm_hme_unload: page should be uncached"); 2026 2027 vaddr = hat_kpm_page2va(pp, 1); 2028 PP2KPMSPG(pp, ksp); 2029 2030 if (ksp->kp_mapped != KPM_MAPPEDSC) 2031 panic("sfmmu_kpm_hme_unload: inconsistent mapping"); 2032 2033 /* 2034 * Keep KPM_MAPPEDSC until the next kpm tsbmiss where it 2035 * prevents TL tsbmiss handling and force a hat_kpm_fault. 2036 * There we can start over again. 2037 */ 2038 2039 pmtx = sfmmu_page_enter(pp); 2040 PP_CLRKPMC(pp); 2041 sfmmu_page_exit(pmtx); 2042 } 2043 2044 /* 2045 * Special hooks for sfmmu_page_cache_array() when changing the 2046 * cacheability of a page. It is used to obey the hat_kpm lock 2047 * ordering (mlist -> kpmp -> spl, and back). 2048 */ 2049 kpm_hlk_t * 2050 sfmmu_kpm_kpmp_enter(page_t *pp, pgcnt_t npages) 2051 { 2052 kpm_page_t *kp; 2053 kpm_hlk_t *kpmp; 2054 2055 ASSERT(sfmmu_mlist_held(pp)); 2056 2057 if (kpm_smallpages || PP_ISMAPPED_KPM(pp) == 0) 2058 return (NULL); 2059 2060 ASSERT(npages <= kpmpnpgs); 2061 2062 PP2KPMPG(pp, kp); 2063 kpmp = KPMP_HASH(kp); 2064 mutex_enter(&kpmp->khl_mutex); 2065 2066 return (kpmp); 2067 } 2068 2069 void 2070 sfmmu_kpm_kpmp_exit(kpm_hlk_t *kpmp) 2071 { 2072 if (kpm_smallpages || kpmp == NULL) 2073 return; 2074 2075 mutex_exit(&kpmp->khl_mutex); 2076 } 2077 2078 /* 2079 * Summary states used in sfmmu_kpm_page_cache (KPM_*). 2080 * See also more detailed comments within in the sfmmu_kpm_page_cache switch. 2081 * Abbreviations used: 2082 * UNC: Input state for an uncache request. 2083 * BIG: Large page kpm mapping in use. 2084 * SMALL: Page has a small kpm mapping within a kpm_page range. 2085 * NODEMAP: No demap needed. 2086 * NOP: No operation needed on this input state. 2087 * CACHE: Input state for a re-cache request. 2088 * MAPS: Page is in TNC and kpm VAC conflict state and kpm mapped small. 2089 * NOMAP: Page is in TNC and kpm VAC conflict state, but not small kpm 2090 * mapped. 2091 * NOMAPO: Page is in TNC and kpm VAC conflict state, but not small kpm 2092 * mapped. There are also other small kpm mappings within this 2093 * kpm_page. 2094 */ 2095 #define KPM_UNC_BIG (0) 2096 #define KPM_UNC_NODEMAP1 (KPM_KS) 2097 #define KPM_UNC_SMALL1 (KPM_KS | KPM_S) 2098 #define KPM_UNC_NODEMAP2 (KPM_KC) 2099 #define KPM_UNC_NODEMAP3 (KPM_KC | KPM_KS) 2100 #define KPM_UNC_SMALL2 (KPM_KC | KPM_KS | KPM_S) 2101 #define KPM_UNC_NOP1 (KPM_KC | KPM_C) 2102 #define KPM_UNC_NOP2 (KPM_KC | KPM_C | KPM_KS) 2103 #define KPM_CACHE_NOMAP (KPM_KC | KPM_C) 2104 #define KPM_CACHE_NOMAPO (KPM_KC | KPM_C | KPM_KS) 2105 #define KPM_CACHE_MAPS (KPM_KC | KPM_C | KPM_KS | KPM_S) 2106 2107 /* 2108 * This function is called when the virtual cacheability of a page 2109 * is changed and the page has an actice kpm mapping. The mlist mutex, 2110 * the spl hash lock and the kpmp mutex (if needed) are already grabbed. 2111 */ 2112 /*ARGSUSED2*/ 2113 void 2114 sfmmu_kpm_page_cache(page_t *pp, int flags, int cache_flush_tag) 2115 { 2116 kpm_page_t *kp; 2117 kpm_hlk_t *kpmp; 2118 caddr_t kpmvaddr; 2119 int badstate = 0; 2120 uint_t pgcacase; 2121 kpm_spage_t *ksp; 2122 kpm_shlk_t *kpmsp; 2123 int oldval; 2124 2125 ASSERT(PP_ISMAPPED_KPM(pp)); 2126 ASSERT(sfmmu_mlist_held(pp)); 2127 ASSERT(sfmmu_page_spl_held(pp)); 2128 2129 if (flags != HAT_TMPNC && flags != HAT_CACHE) 2130 panic("sfmmu_kpm_page_cache: bad flags"); 2131 2132 kpmvaddr = hat_kpm_page2va(pp, 1); 2133 2134 if (flags == HAT_TMPNC && cache_flush_tag == CACHE_FLUSH) { 2135 pfn_t pfn = pp->p_pagenum; 2136 int vcolor = addr_to_vcolor(kpmvaddr); 2137 cpuset_t cpuset = cpu_ready_set; 2138 2139 /* Flush vcolor in DCache */ 2140 CPUSET_DEL(cpuset, CPU->cpu_id); 2141 SFMMU_XCALL_STATS(ksfmmup); 2142 xt_some(cpuset, vac_flushpage_tl1, pfn, vcolor); 2143 vac_flushpage(pfn, vcolor); 2144 } 2145 2146 if (kpm_smallpages) 2147 goto smallpages_page_cache; 2148 2149 PP2KPMPG(pp, kp); 2150 kpmp = KPMP_HASH(kp); 2151 ASSERT(MUTEX_HELD(&kpmp->khl_mutex)); 2152 2153 if (IS_KPM_ALIAS_RANGE(kpmvaddr)) { 2154 if (kp->kp_refcnta < 1) { 2155 panic("sfmmu_kpm_page_cache: bad refcnta " 2156 "kpm_page=%p\n", (void *)kp); 2157 } 2158 sfmmu_kpm_demap_small(kpmvaddr); 2159 if (flags == HAT_TMPNC) { 2160 PP_SETKPMC(pp); 2161 ASSERT(!PP_ISKPMS(pp)); 2162 } else { 2163 ASSERT(PP_ISKPMC(pp)); 2164 PP_CLRKPMC(pp); 2165 } 2166 goto exit; 2167 } 2168 2169 badstate = (kp->kp_refcnt < 0 || kp->kp_refcnts < 0); 2170 if (kp->kp_refcntc == -1) { 2171 /* 2172 * We should come here only if trap level tsb miss 2173 * handler is disabled. 2174 */ 2175 badstate |= (kp->kp_refcnt == 0 || kp->kp_refcnts > 0 || 2176 PP_ISKPMC(pp) || PP_ISKPMS(pp) || PP_ISNC(pp)); 2177 } else { 2178 badstate |= (kp->kp_refcntc < 0); 2179 } 2180 2181 if (badstate) 2182 goto exit; 2183 2184 /* 2185 * Combine the per kpm_page and per page kpm VAC states to 2186 * a summary state in order to make the VAC cache/uncache 2187 * handling more concise. 2188 */ 2189 pgcacase = (((kp->kp_refcntc > 0) ? KPM_KC : 0) | 2190 ((kp->kp_refcnts > 0) ? KPM_KS : 0) | 2191 (PP_ISKPMC(pp) ? KPM_C : 0) | 2192 (PP_ISKPMS(pp) ? KPM_S : 0)); 2193 2194 if (flags == HAT_CACHE) { 2195 switch (pgcacase) { 2196 case KPM_CACHE_MAPS: /* kc c ks s */ 2197 sfmmu_kpm_demap_small(kpmvaddr); 2198 if (kp->kp_refcnts < 1) { 2199 panic("sfmmu_kpm_page_cache: bad refcnts " 2200 "kpm_page=%p\n", (void *)kp); 2201 } 2202 kp->kp_refcnts--; 2203 kp->kp_refcnt++; 2204 PP_CLRKPMS(pp); 2205 /* FALLTHRU */ 2206 2207 case KPM_CACHE_NOMAP: /* kc c - - */ 2208 case KPM_CACHE_NOMAPO: /* kc c ks - */ 2209 kp->kp_refcntc--; 2210 PP_CLRKPMC(pp); 2211 break; 2212 2213 default: 2214 badstate++; 2215 } 2216 goto exit; 2217 } 2218 2219 switch (pgcacase) { 2220 case KPM_UNC_BIG: /* - - - - */ 2221 if (kp->kp_refcnt < 1) { 2222 panic("sfmmu_kpm_page_cache: bad refcnt " 2223 "kpm_page=%p\n", (void *)kp); 2224 } 2225 2226 /* 2227 * Have to breakup the large page mapping in preparation 2228 * to the upcoming TNC mode handled by small mappings. 2229 * The demap can already be done due to another conflict 2230 * within the kpm_page. 2231 */ 2232 if (kp->kp_refcntc == -1) { 2233 /* remove go indication */ 2234 sfmmu_kpm_tsbmtl(&kp->kp_refcntc, 2235 &kpmp->khl_lock, KPMTSBM_STOP); 2236 } 2237 ASSERT(kp->kp_refcntc == 0); 2238 sfmmu_kpm_demap_large(kpmvaddr); 2239 kp->kp_refcntc++; 2240 PP_SETKPMC(pp); 2241 break; 2242 2243 case KPM_UNC_SMALL1: /* - - ks s */ 2244 case KPM_UNC_SMALL2: /* kc - ks s */ 2245 /* 2246 * Have to demap an already small kpm mapping in preparation 2247 * to the upcoming TNC mode. The demap can already be done 2248 * due to another conflict within the kpm_page. 2249 */ 2250 sfmmu_kpm_demap_small(kpmvaddr); 2251 kp->kp_refcntc++; 2252 kp->kp_refcnts--; 2253 kp->kp_refcnt++; 2254 PP_CLRKPMS(pp); 2255 PP_SETKPMC(pp); 2256 break; 2257 2258 case KPM_UNC_NODEMAP1: /* - - ks - */ 2259 /* fallthru */ 2260 2261 case KPM_UNC_NODEMAP2: /* kc - - - */ 2262 case KPM_UNC_NODEMAP3: /* kc - ks - */ 2263 kp->kp_refcntc++; 2264 PP_SETKPMC(pp); 2265 break; 2266 2267 case KPM_UNC_NOP1: /* kc c - - */ 2268 case KPM_UNC_NOP2: /* kc c ks - */ 2269 break; 2270 2271 default: 2272 badstate++; 2273 } 2274 exit: 2275 if (badstate) { 2276 panic("sfmmu_kpm_page_cache: inconsistent VAC state " 2277 "kpmvaddr=%p kp=%p pp=%p", (void *)kpmvaddr, 2278 (void *)kp, (void *)pp); 2279 } 2280 return; 2281 2282 smallpages_page_cache: 2283 PP2KPMSPG(pp, ksp); 2284 kpmsp = KPMP_SHASH(ksp); 2285 2286 oldval = sfmmu_kpm_stsbmtl(&ksp->kp_mapped, 2287 &kpmsp->kshl_lock, KPM_MAPPEDSC); 2288 2289 if (!(oldval == KPM_MAPPEDS || oldval == KPM_MAPPEDSC)) 2290 panic("smallpages_page_cache: inconsistent mapping"); 2291 2292 sfmmu_kpm_demap_small(kpmvaddr); 2293 2294 if (flags == HAT_TMPNC) { 2295 PP_SETKPMC(pp); 2296 ASSERT(!PP_ISKPMS(pp)); 2297 2298 } else { 2299 ASSERT(PP_ISKPMC(pp)); 2300 PP_CLRKPMC(pp); 2301 } 2302 2303 /* 2304 * Keep KPM_MAPPEDSC until the next kpm tsbmiss where it 2305 * prevents TL tsbmiss handling and force a hat_kpm_fault. 2306 * There we can start over again. 2307 */ 2308 } 2309