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