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