xref: /titanic_44/usr/src/uts/sun4u/cpu/us3_common_mmu.c (revision 1426d65aa9264a283c76d271972aeb7f6a070be3)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51e2e7a75Shuah  * Common Development and Distribution License (the "License").
61e2e7a75Shuah  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*1426d65aSsm142603  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <sys/types.h>
297c478bd9Sstevel@tonic-gate #include <sys/systm.h>
307c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
317c478bd9Sstevel@tonic-gate #include <sys/archsystm.h>
327c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h>
337c478bd9Sstevel@tonic-gate #include <sys/machparam.h>
347c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
357c478bd9Sstevel@tonic-gate #include <vm/vm_dep.h>
367c478bd9Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
377c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h>
387c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
397c478bd9Sstevel@tonic-gate #include <sys/debug.h>
407c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h>
417c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
427c478bd9Sstevel@tonic-gate #include <sys/panic.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate  * pan_disable_ism_large_pages and pan_disable_large_pages are the Panther-
467c478bd9Sstevel@tonic-gate  * specific versions of disable_ism_large_pages and disable_large_pages,
477c478bd9Sstevel@tonic-gate  * and feed back into those two hat variables at hat initialization time,
487c478bd9Sstevel@tonic-gate  * for Panther-only systems.
497c478bd9Sstevel@tonic-gate  *
50ec25b48fSsusans  * chpjag_disable_large_pages is the Ch/Jaguar-specific version of
51ec25b48fSsusans  * disable_large_pages. Ditto for pan_disable_large_pages.
52ec25b48fSsusans  * Note that the Panther and Ch/Jaguar ITLB do not support 32M/256M pages.
537c478bd9Sstevel@tonic-gate  */
547c478bd9Sstevel@tonic-gate static int panther_only = 0;
557c478bd9Sstevel@tonic-gate 
56ec25b48fSsusans static uint_t pan_disable_large_pages = (1 << TTE256M);
57ec25b48fSsusans static uint_t chjag_disable_large_pages = ((1 << TTE32M) | (1 << TTE256M));
587c478bd9Sstevel@tonic-gate 
59ec25b48fSsusans static uint_t mmu_disable_ism_large_pages = ((1 << TTE64K) |
607c478bd9Sstevel@tonic-gate 	(1 << TTE512K) | (1 << TTE32M) | (1 << TTE256M));
61ec25b48fSsusans static uint_t mmu_disable_auto_data_large_pages =  ((1 << TTE64K) |
62ec25b48fSsusans 	(1 << TTE512K) | (1 << TTE32M) | (1 << TTE256M));
63ec25b48fSsusans static uint_t mmu_disable_auto_text_large_pages =  ((1 << TTE64K) |
64582cbfcbSjimand 	(1 << TTE512K) | (1 << TTE32M) | (1 << TTE256M));
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate /*
67ec25b48fSsusans  * The function returns the USIII+(i)-IV+ mmu-specific values for the
687c478bd9Sstevel@tonic-gate  * hat's disable_large_pages and disable_ism_large_pages variables.
697c478bd9Sstevel@tonic-gate  * Currently the hat's disable_large_pages and disable_ism_large_pages
707c478bd9Sstevel@tonic-gate  * already contain the generic sparc 4 page size info, and the return
717c478bd9Sstevel@tonic-gate  * values are or'd with those values.
727c478bd9Sstevel@tonic-gate  */
73ec25b48fSsusans uint_t
mmu_large_pages_disabled(uint_t flag)747c478bd9Sstevel@tonic-gate mmu_large_pages_disabled(uint_t flag)
757c478bd9Sstevel@tonic-gate {
76ec25b48fSsusans 	uint_t pages_disable = 0;
77ec25b48fSsusans 	extern int use_text_pgsz64K;
78ec25b48fSsusans 	extern int use_text_pgsz512K;
797c478bd9Sstevel@tonic-gate 
80ec25b48fSsusans 	if (flag == HAT_LOAD) {
817c478bd9Sstevel@tonic-gate 		if (panther_only) {
827c478bd9Sstevel@tonic-gate 			pages_disable = pan_disable_large_pages;
837c478bd9Sstevel@tonic-gate 		} else {
847c478bd9Sstevel@tonic-gate 			pages_disable = chjag_disable_large_pages;
85ec25b48fSsusans 		}
867c478bd9Sstevel@tonic-gate 	} else if (flag == HAT_LOAD_SHARE) {
87ec25b48fSsusans 		pages_disable = mmu_disable_ism_large_pages;
88ec25b48fSsusans 	} else if (flag == HAT_AUTO_DATA) {
89ec25b48fSsusans 		pages_disable = mmu_disable_auto_data_large_pages;
90ec25b48fSsusans 	} else if (flag == HAT_AUTO_TEXT) {
91ec25b48fSsusans 		pages_disable = mmu_disable_auto_text_large_pages;
92ec25b48fSsusans 		if (use_text_pgsz512K) {
93ec25b48fSsusans 			pages_disable &= ~(1 << TTE512K);
94ec25b48fSsusans 		}
95ec25b48fSsusans 		if (use_text_pgsz64K) {
96ec25b48fSsusans 			pages_disable &= ~(1 << TTE64K);
977c478bd9Sstevel@tonic-gate 		}
987c478bd9Sstevel@tonic-gate 	}
997c478bd9Sstevel@tonic-gate 	return (pages_disable);
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate #if defined(CPU_IMP_DUAL_PAGESIZE)
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate  * If a platform is running with only Ch+ or Jaguar, and then someone DR's
1057c478bd9Sstevel@tonic-gate  * in a Panther board, the Panther mmu will not like it if one of the already
1067c478bd9Sstevel@tonic-gate  * running threads is context switched to the Panther and tries to program
1077c478bd9Sstevel@tonic-gate  * a 512K or 4M page into the T512_1. So make these platforms pay the price
1087c478bd9Sstevel@tonic-gate  * and follow the Panther DTLB restrictions by default. :)
1097c478bd9Sstevel@tonic-gate  * The mmu_init_mmu_page_sizes code below takes care of heterogeneous
1107c478bd9Sstevel@tonic-gate  * platforms that don't support DR, like daktari.
1117c478bd9Sstevel@tonic-gate  *
1127c478bd9Sstevel@tonic-gate  * The effect of these restrictions is to limit the allowable values in
1137c478bd9Sstevel@tonic-gate  * sfmmu_pgsz[0] and sfmmu_pgsz[1], since these hat variables are used in
1141e2e7a75Shuah  * mmu_set_ctx_page_sizes to set up the values in the sfmmu_cext that
1157c478bd9Sstevel@tonic-gate  * are used at context switch time. The value in sfmmu_pgsz[0] is used in
1167c478bd9Sstevel@tonic-gate  * P_pgsz0 and sfmmu_pgsz[1] is used in P_pgsz1, as per Figure F-1-1
1177c478bd9Sstevel@tonic-gate  * IMMU and DMMU Primary Context Register in the Panther Implementation
1187c478bd9Sstevel@tonic-gate  * Supplement and Table 15-21 DMMU Primary Context Register in the
1197c478bd9Sstevel@tonic-gate  * Cheetah+ Delta PRM.
1207c478bd9Sstevel@tonic-gate  */
1217c478bd9Sstevel@tonic-gate #ifdef MIXEDCPU_DR_SUPPORTED
1227c478bd9Sstevel@tonic-gate int panther_dtlb_restrictions = 1;
1237c478bd9Sstevel@tonic-gate #else
1247c478bd9Sstevel@tonic-gate int panther_dtlb_restrictions = 0;
1257c478bd9Sstevel@tonic-gate #endif /* MIXEDCPU_DR_SUPPORTED */
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate /*
1287c478bd9Sstevel@tonic-gate  * init_mmu_page_sizes is set to one after the bootup time initialization
1297c478bd9Sstevel@tonic-gate  * via mmu_init_mmu_page_sizes, to indicate that mmu_page_sizes has a
1307c478bd9Sstevel@tonic-gate  * valid value.
1317c478bd9Sstevel@tonic-gate  */
1327c478bd9Sstevel@tonic-gate int init_mmu_page_sizes = 0;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate /*
1357c478bd9Sstevel@tonic-gate  * mmu_init_large_pages is called with the desired ism_pagesize parameter,
1367c478bd9Sstevel@tonic-gate  * for Panther-only systems. It may be called from set_platform_defaults,
137*1426d65aSsm142603  * if some value other than 4M is desired, for Panther-only systems.
1387c478bd9Sstevel@tonic-gate  * mmu_ism_pagesize is the tunable.  If it has a bad value, then only warn,
1397c478bd9Sstevel@tonic-gate  * since it would be bad form to panic due
1407c478bd9Sstevel@tonic-gate  * to a user typo.
1417c478bd9Sstevel@tonic-gate  *
142ec25b48fSsusans  * The function re-initializes the disable_ism_large_pages and
1437c478bd9Sstevel@tonic-gate  * pan_disable_large_pages variables, which are closely related.
1447c478bd9Sstevel@tonic-gate  * Aka, if 32M is the desired [D]ISM page sizes, then 256M cannot be allowed
1457c478bd9Sstevel@tonic-gate  * for non-ISM large page usage, or DTLB conflict will occur. Please see the
1467c478bd9Sstevel@tonic-gate  * Panther PRM for additional DTLB technical info.
1477c478bd9Sstevel@tonic-gate  */
1487c478bd9Sstevel@tonic-gate void
mmu_init_large_pages(size_t ism_pagesize)1497c478bd9Sstevel@tonic-gate mmu_init_large_pages(size_t ism_pagesize)
1507c478bd9Sstevel@tonic-gate {
1511e2e7a75Shuah 	if (cpu_impl_dual_pgsz == 0) {	/* disable_dual_pgsz flag */
1527c478bd9Sstevel@tonic-gate 		pan_disable_large_pages = ((1 << TTE32M) | (1 << TTE256M));
153ec25b48fSsusans 		mmu_disable_ism_large_pages = ((1 << TTE64K) |
154ec25b48fSsusans 		    (1 << TTE512K) | (1 << TTE32M) | (1 << TTE256M));
155ec25b48fSsusans 		mmu_disable_auto_data_large_pages = ((1 << TTE64K) |
156ec25b48fSsusans 		    (1 << TTE512K) | (1 << TTE32M) | (1 << TTE256M));
1577c478bd9Sstevel@tonic-gate 		return;
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	switch (ism_pagesize) {
1617c478bd9Sstevel@tonic-gate 	case MMU_PAGESIZE4M:
1627c478bd9Sstevel@tonic-gate 		pan_disable_large_pages = (1 << TTE256M);
163ec25b48fSsusans 		mmu_disable_ism_large_pages = ((1 << TTE64K) |
164582cbfcbSjimand 		    (1 << TTE512K) | (1 << TTE32M) | (1 << TTE256M));
165ec25b48fSsusans 		mmu_disable_auto_data_large_pages = ((1 << TTE64K) |
166ec25b48fSsusans 		    (1 << TTE512K) | (1 << TTE32M) | (1 << TTE256M));
1677c478bd9Sstevel@tonic-gate 		break;
1687c478bd9Sstevel@tonic-gate 	case MMU_PAGESIZE32M:
1697c478bd9Sstevel@tonic-gate 		pan_disable_large_pages = (1 << TTE256M);
170ec25b48fSsusans 		mmu_disable_ism_large_pages = ((1 << TTE64K) |
171ec25b48fSsusans 		    (1 << TTE512K) | (1 << TTE256M));
172ec25b48fSsusans 		mmu_disable_auto_data_large_pages = ((1 << TTE64K) |
173582cbfcbSjimand 		    (1 << TTE512K) | (1 << TTE4M) | (1 << TTE256M));
174ec25b48fSsusans 		adjust_data_maxlpsize(ism_pagesize);
1757c478bd9Sstevel@tonic-gate 		break;
1767c478bd9Sstevel@tonic-gate 	case MMU_PAGESIZE256M:
1777c478bd9Sstevel@tonic-gate 		pan_disable_large_pages = (1 << TTE32M);
178ec25b48fSsusans 		mmu_disable_ism_large_pages = ((1 << TTE64K) |
179ec25b48fSsusans 		    (1 << TTE512K) | (1 << TTE32M));
180ec25b48fSsusans 		mmu_disable_auto_data_large_pages = ((1 << TTE64K) |
181582cbfcbSjimand 		    (1 << TTE512K) | (1 << TTE4M) | (1 << TTE32M));
182ec25b48fSsusans 		adjust_data_maxlpsize(ism_pagesize);
1837c478bd9Sstevel@tonic-gate 		break;
1847c478bd9Sstevel@tonic-gate 	default:
1857c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "Unrecognized mmu_ism_pagesize value 0x%lx",
1867c478bd9Sstevel@tonic-gate 		    ism_pagesize);
1877c478bd9Sstevel@tonic-gate 		break;
1887c478bd9Sstevel@tonic-gate 	}
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate /*
1927c478bd9Sstevel@tonic-gate  * Re-initialize mmu_page_sizes and friends, for Panther mmu support.
1937c478bd9Sstevel@tonic-gate  * Called during very early bootup from check_cpus_set().
1947c478bd9Sstevel@tonic-gate  * Can be called to verify that mmu_page_sizes are set up correctly.
1957c478bd9Sstevel@tonic-gate  * Note that ncpus is not initialized at this point in the bootup sequence.
1967c478bd9Sstevel@tonic-gate  */
1977c478bd9Sstevel@tonic-gate int
mmu_init_mmu_page_sizes(int cinfo)1987c478bd9Sstevel@tonic-gate mmu_init_mmu_page_sizes(int cinfo)
1997c478bd9Sstevel@tonic-gate {
2007c478bd9Sstevel@tonic-gate 	int npanther = cinfo;
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	if (!init_mmu_page_sizes) {
2037c478bd9Sstevel@tonic-gate 		if (npanther == ncpunode) {
2047c478bd9Sstevel@tonic-gate 			mmu_page_sizes = MMU_PAGE_SIZES;
2057c478bd9Sstevel@tonic-gate 			mmu_hashcnt = MAX_HASHCNT;
206e12a8a13Ssusans 			mmu_ism_pagesize = DEFAULT_ISM_PAGESIZE;
2077c478bd9Sstevel@tonic-gate 			mmu_exported_pagesize_mask = (1 << TTE8K) |
2087c478bd9Sstevel@tonic-gate 			    (1 << TTE64K) | (1 << TTE512K) | (1 << TTE4M) |
2097c478bd9Sstevel@tonic-gate 			    (1 << TTE32M) | (1 << TTE256M);
2107c478bd9Sstevel@tonic-gate 			panther_dtlb_restrictions = 1;
2117c478bd9Sstevel@tonic-gate 			panther_only = 1;
2127c478bd9Sstevel@tonic-gate 		} else if (npanther > 0) {
2137c478bd9Sstevel@tonic-gate 			panther_dtlb_restrictions = 1;
2147c478bd9Sstevel@tonic-gate 		}
2157c478bd9Sstevel@tonic-gate 		init_mmu_page_sizes = 1;
2167c478bd9Sstevel@tonic-gate 		return (0);
2177c478bd9Sstevel@tonic-gate 	}
2187c478bd9Sstevel@tonic-gate 	return (1);
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate /* Cheetah+ and later worst case DTLB parameters */
2237c478bd9Sstevel@tonic-gate #ifndef	LOCKED_DTLB_ENTRIES
2247c478bd9Sstevel@tonic-gate #define	LOCKED_DTLB_ENTRIES	5	/* 2 user TSBs, 2 nucleus, + OBP */
2257c478bd9Sstevel@tonic-gate #endif
2267c478bd9Sstevel@tonic-gate #define	TOTAL_DTLB_ENTRIES	16
2277c478bd9Sstevel@tonic-gate #define	AVAIL_32M_ENTRIES	0
2287c478bd9Sstevel@tonic-gate #define	AVAIL_256M_ENTRIES	0
2297c478bd9Sstevel@tonic-gate #define	AVAIL_DTLB_ENTRIES	(TOTAL_DTLB_ENTRIES - LOCKED_DTLB_ENTRIES)
2307c478bd9Sstevel@tonic-gate static uint64_t ttecnt_threshold[MMU_PAGE_SIZES] = {
2317c478bd9Sstevel@tonic-gate 	AVAIL_DTLB_ENTRIES, AVAIL_DTLB_ENTRIES,
2327c478bd9Sstevel@tonic-gate 	AVAIL_DTLB_ENTRIES, AVAIL_DTLB_ENTRIES,
2337c478bd9Sstevel@tonic-gate 	AVAIL_32M_ENTRIES, AVAIL_256M_ENTRIES };
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate /*
2367c478bd9Sstevel@tonic-gate  * The purpose of this code is to indirectly reorganize the sfmmu_pgsz array
2377c478bd9Sstevel@tonic-gate  * in order to handle the Panther mmu DTLB requirements. Panther only supports
2387c478bd9Sstevel@tonic-gate  * the 32M/256M pages in the T512_1 and not in the T16, so the Panther cpu
2397c478bd9Sstevel@tonic-gate  * can only support one of the two largest page sizes at a time (efficiently).
2407c478bd9Sstevel@tonic-gate  * Panther only supports 512K and 4M pages in the T512_0, and 32M/256M pages
2417c478bd9Sstevel@tonic-gate  * in the T512_1.  So check the sfmmu flags and ttecnt before enabling
2427c478bd9Sstevel@tonic-gate  * the T512_1 for 32M or 256M page sizes, and make sure that 512K and 4M
2437c478bd9Sstevel@tonic-gate  * requests go to the T512_0.
2447c478bd9Sstevel@tonic-gate  *
2457c478bd9Sstevel@tonic-gate  * The tmp_pgsz array comes into this routine in sorted order, as it is
2467c478bd9Sstevel@tonic-gate  * sorted from largest to smallest #pages per pagesize in use by the hat code,
2477c478bd9Sstevel@tonic-gate  * and leaves with the Panther mmu DTLB requirements satisfied. Note that
2487c478bd9Sstevel@tonic-gate  * when the array leaves this function it may not contain all of the page
2497c478bd9Sstevel@tonic-gate  * size codes that it had coming into the function.
2507c478bd9Sstevel@tonic-gate  *
2517c478bd9Sstevel@tonic-gate  * Note that for DISM the flag can be set but the ttecnt can be 0, if we
2527c478bd9Sstevel@tonic-gate  * didn't fault any pages in. This allows the t512_1 to be reprogrammed,
2537c478bd9Sstevel@tonic-gate  * because the T16 does not support the two giant page sizes. ouch.
2547c478bd9Sstevel@tonic-gate  */
255*1426d65aSsm142603 static void
mmu_fixup_large_pages(struct hat * hat,uint64_t * ttecnt,uint8_t * tmp_pgsz)2567c478bd9Sstevel@tonic-gate mmu_fixup_large_pages(struct hat *hat, uint64_t *ttecnt, uint8_t *tmp_pgsz)
2577c478bd9Sstevel@tonic-gate {
2587c478bd9Sstevel@tonic-gate 	uint_t pgsz0 = tmp_pgsz[0];
2597c478bd9Sstevel@tonic-gate 	uint_t pgsz1 = tmp_pgsz[1];
2607c478bd9Sstevel@tonic-gate 	uint_t spgsz;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	/*
2637c478bd9Sstevel@tonic-gate 	 * Don't program 2nd dtlb for kernel and ism hat
2647c478bd9Sstevel@tonic-gate 	 */
26505d3dc4bSpaulsan 	ASSERT(hat->sfmmu_ismhat == 0);
2667c478bd9Sstevel@tonic-gate 	ASSERT(hat != ksfmmup);
2671e2e7a75Shuah 	ASSERT(cpu_impl_dual_pgsz == 1);
2687c478bd9Sstevel@tonic-gate 
26905d3dc4bSpaulsan 	ASSERT(!SFMMU_TTEFLAGS_ISSET(hat, HAT_32M_FLAG) ||
27005d3dc4bSpaulsan 	    !SFMMU_TTEFLAGS_ISSET(hat, HAT_256M_FLAG));
27105d3dc4bSpaulsan 	ASSERT(!SFMMU_TTEFLAGS_ISSET(hat, HAT_256M_FLAG) ||
27205d3dc4bSpaulsan 	    !SFMMU_TTEFLAGS_ISSET(hat, HAT_32M_FLAG));
27305d3dc4bSpaulsan 	ASSERT(!SFMMU_FLAGS_ISSET(hat, HAT_32M_ISM) ||
27405d3dc4bSpaulsan 	    !SFMMU_FLAGS_ISSET(hat, HAT_256M_ISM));
27505d3dc4bSpaulsan 	ASSERT(!SFMMU_FLAGS_ISSET(hat, HAT_256M_ISM) ||
27605d3dc4bSpaulsan 	    !SFMMU_FLAGS_ISSET(hat, HAT_32M_ISM));
2777c478bd9Sstevel@tonic-gate 
27805d3dc4bSpaulsan 	if (SFMMU_TTEFLAGS_ISSET(hat, HAT_32M_FLAG) ||
27905d3dc4bSpaulsan 	    (ttecnt[TTE32M] != 0) ||
28005d3dc4bSpaulsan 	    SFMMU_FLAGS_ISSET(hat, HAT_32M_ISM)) {
28105d3dc4bSpaulsan 
2827c478bd9Sstevel@tonic-gate 		spgsz = pgsz1;
2837c478bd9Sstevel@tonic-gate 		pgsz1 = TTE32M;
2847c478bd9Sstevel@tonic-gate 		if (pgsz0 == TTE32M)
2857c478bd9Sstevel@tonic-gate 			pgsz0 = spgsz;
28605d3dc4bSpaulsan 
28705d3dc4bSpaulsan 	} else if (SFMMU_TTEFLAGS_ISSET(hat, HAT_256M_FLAG) ||
28805d3dc4bSpaulsan 	    (ttecnt[TTE256M] != 0) ||
28905d3dc4bSpaulsan 	    SFMMU_FLAGS_ISSET(hat, HAT_256M_ISM)) {
29005d3dc4bSpaulsan 
2917c478bd9Sstevel@tonic-gate 		spgsz = pgsz1;
2927c478bd9Sstevel@tonic-gate 		pgsz1 = TTE256M;
2937c478bd9Sstevel@tonic-gate 		if (pgsz0 == TTE256M)
2947c478bd9Sstevel@tonic-gate 			pgsz0 = spgsz;
29505d3dc4bSpaulsan 
2967c478bd9Sstevel@tonic-gate 	} else if ((pgsz1 == TTE512K) || (pgsz1 == TTE4M)) {
2977c478bd9Sstevel@tonic-gate 		if ((pgsz0 != TTE512K) && (pgsz0 != TTE4M)) {
2987c478bd9Sstevel@tonic-gate 			spgsz = pgsz0;
2997c478bd9Sstevel@tonic-gate 			pgsz0 = pgsz1;
3007c478bd9Sstevel@tonic-gate 			pgsz1 = spgsz;
3017c478bd9Sstevel@tonic-gate 		} else {
3027c478bd9Sstevel@tonic-gate 			pgsz1 = page_szc(MMU_PAGESIZE);
3037c478bd9Sstevel@tonic-gate 		}
3047c478bd9Sstevel@tonic-gate 	}
3057c478bd9Sstevel@tonic-gate 	/*
3067c478bd9Sstevel@tonic-gate 	 * This implements PAGESIZE programming of the T8s
3077c478bd9Sstevel@tonic-gate 	 * if large TTE counts don't exceed the thresholds.
3087c478bd9Sstevel@tonic-gate 	 */
3097c478bd9Sstevel@tonic-gate 	if (ttecnt[pgsz0] < ttecnt_threshold[pgsz0])
3107c478bd9Sstevel@tonic-gate 		pgsz0 = page_szc(MMU_PAGESIZE);
3117c478bd9Sstevel@tonic-gate 	if (ttecnt[pgsz1] < ttecnt_threshold[pgsz1])
3127c478bd9Sstevel@tonic-gate 		pgsz1 = page_szc(MMU_PAGESIZE);
3137c478bd9Sstevel@tonic-gate 	tmp_pgsz[0] = pgsz0;
3147c478bd9Sstevel@tonic-gate 	tmp_pgsz[1] = pgsz1;
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate /*
3187c478bd9Sstevel@tonic-gate  * Function to set up the page size values used to reprogram the DTLBs,
3197c478bd9Sstevel@tonic-gate  * when page sizes used by a process change significantly.
3207c478bd9Sstevel@tonic-gate  */
321*1426d65aSsm142603 static void
mmu_setup_page_sizes(struct hat * hat,uint64_t * ttecnt,uint8_t * tmp_pgsz)3227c478bd9Sstevel@tonic-gate mmu_setup_page_sizes(struct hat *hat, uint64_t *ttecnt, uint8_t *tmp_pgsz)
3237c478bd9Sstevel@tonic-gate {
3247c478bd9Sstevel@tonic-gate 	uint_t pgsz0, pgsz1;
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	/*
3277c478bd9Sstevel@tonic-gate 	 * Don't program 2nd dtlb for kernel and ism hat
3287c478bd9Sstevel@tonic-gate 	 */
3297c478bd9Sstevel@tonic-gate 	ASSERT(hat->sfmmu_ismhat == NULL);
3307c478bd9Sstevel@tonic-gate 	ASSERT(hat != ksfmmup);
3317c478bd9Sstevel@tonic-gate 
3321e2e7a75Shuah 	if (cpu_impl_dual_pgsz == 0)	/* disable_dual_pgsz flag */
3337c478bd9Sstevel@tonic-gate 		return;
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	/*
3367c478bd9Sstevel@tonic-gate 	 * hat->sfmmu_pgsz[] is an array whose elements
3377c478bd9Sstevel@tonic-gate 	 * contain a sorted order of page sizes.  Element
3387c478bd9Sstevel@tonic-gate 	 * 0 is the most commonly used page size, followed
3397c478bd9Sstevel@tonic-gate 	 * by element 1, and so on.
3407c478bd9Sstevel@tonic-gate 	 *
3417c478bd9Sstevel@tonic-gate 	 * ttecnt[] is an array of per-page-size page counts
3427c478bd9Sstevel@tonic-gate 	 * mapped into the process.
3437c478bd9Sstevel@tonic-gate 	 *
3447c478bd9Sstevel@tonic-gate 	 * If the HAT's choice for page sizes is unsuitable,
3457c478bd9Sstevel@tonic-gate 	 * we can override it here.  The new values written
3467c478bd9Sstevel@tonic-gate 	 * to the array will be handed back to us later to
3477c478bd9Sstevel@tonic-gate 	 * do the actual programming of the TLB hardware.
3487c478bd9Sstevel@tonic-gate 	 *
3497c478bd9Sstevel@tonic-gate 	 * The policy we use for programming the dual T8s on
3507c478bd9Sstevel@tonic-gate 	 * Cheetah+ and beyond is as follows:
3517c478bd9Sstevel@tonic-gate 	 *
3527c478bd9Sstevel@tonic-gate 	 *   We have two programmable TLBs, so we look at
3537c478bd9Sstevel@tonic-gate 	 *   the two most common page sizes in the array, which
3547c478bd9Sstevel@tonic-gate 	 *   have already been computed for us by the HAT.
3557c478bd9Sstevel@tonic-gate 	 *   If the TTE count of either of a preferred page size
3567c478bd9Sstevel@tonic-gate 	 *   exceeds the number of unlocked T16 entries,
3577c478bd9Sstevel@tonic-gate 	 *   we reprogram one of the T8s to that page size
3587c478bd9Sstevel@tonic-gate 	 *   to avoid thrashing in the T16.  Else we program
3597c478bd9Sstevel@tonic-gate 	 *   that T8 to the base page size.  Note that we do
3607c478bd9Sstevel@tonic-gate 	 *   not force either T8 to be the base page size if a
3617c478bd9Sstevel@tonic-gate 	 *   process is using more than two page sizes.  Policy
3627c478bd9Sstevel@tonic-gate 	 *   decisions about which page sizes are best to use are
3637c478bd9Sstevel@tonic-gate 	 *   left to the upper layers.
3647c478bd9Sstevel@tonic-gate 	 *
3657c478bd9Sstevel@tonic-gate 	 *   Note that for Panther, 4M and 512K pages need to be
3667c478bd9Sstevel@tonic-gate 	 *   programmed into T512_0, and 32M and 256M into T512_1,
3677c478bd9Sstevel@tonic-gate 	 *   so we don't want to go through the MIN/MAX code.
3687c478bd9Sstevel@tonic-gate 	 *   For partial-Panther systems, we still want to make sure
3697c478bd9Sstevel@tonic-gate 	 *   that 4M and 512K page sizes NEVER get into the T512_1.
3707c478bd9Sstevel@tonic-gate 	 *   Since the DTLB flags are not set up on a per-cpu basis,
3717c478bd9Sstevel@tonic-gate 	 *   Panther rules must be applied for mixed Panther/Cheetah+/
3727c478bd9Sstevel@tonic-gate 	 *   Jaguar configurations.
3737c478bd9Sstevel@tonic-gate 	 */
3747c478bd9Sstevel@tonic-gate 	if (panther_dtlb_restrictions) {
3757c478bd9Sstevel@tonic-gate 		if ((tmp_pgsz[1] == TTE512K) || (tmp_pgsz[1] == TTE4M)) {
3767c478bd9Sstevel@tonic-gate 			if ((tmp_pgsz[0] != TTE512K) &&
3777c478bd9Sstevel@tonic-gate 			    (tmp_pgsz[0] != TTE4M)) {
3787c478bd9Sstevel@tonic-gate 				pgsz1 = tmp_pgsz[0];
3797c478bd9Sstevel@tonic-gate 				pgsz0 = tmp_pgsz[1];
3807c478bd9Sstevel@tonic-gate 			} else {
3817c478bd9Sstevel@tonic-gate 				pgsz0 = tmp_pgsz[0];
3827c478bd9Sstevel@tonic-gate 				pgsz1 = page_szc(MMU_PAGESIZE);
3837c478bd9Sstevel@tonic-gate 			}
3847c478bd9Sstevel@tonic-gate 		} else {
3857c478bd9Sstevel@tonic-gate 			pgsz0 = tmp_pgsz[0];
3867c478bd9Sstevel@tonic-gate 			pgsz1 = tmp_pgsz[1];
3877c478bd9Sstevel@tonic-gate 		}
3887c478bd9Sstevel@tonic-gate 	} else {
3897c478bd9Sstevel@tonic-gate 		pgsz0 = MIN(tmp_pgsz[0], tmp_pgsz[1]);
3907c478bd9Sstevel@tonic-gate 		pgsz1 = MAX(tmp_pgsz[0], tmp_pgsz[1]);
3917c478bd9Sstevel@tonic-gate 	}
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	/*
3947c478bd9Sstevel@tonic-gate 	 * This implements PAGESIZE programming of the T8s
3957c478bd9Sstevel@tonic-gate 	 * if large TTE counts don't exceed the thresholds.
3967c478bd9Sstevel@tonic-gate 	 */
3977c478bd9Sstevel@tonic-gate 	if (ttecnt[pgsz0] < ttecnt_threshold[pgsz0])
3987c478bd9Sstevel@tonic-gate 		pgsz0 = page_szc(MMU_PAGESIZE);
3997c478bd9Sstevel@tonic-gate 	if (ttecnt[pgsz1] < ttecnt_threshold[pgsz1])
4007c478bd9Sstevel@tonic-gate 		pgsz1 = page_szc(MMU_PAGESIZE);
4017c478bd9Sstevel@tonic-gate 	tmp_pgsz[0] = pgsz0;
4027c478bd9Sstevel@tonic-gate 	tmp_pgsz[1] = pgsz1;
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate /*
4067c478bd9Sstevel@tonic-gate  * The HAT calls this function when an MMU context is allocated so that we
4077c478bd9Sstevel@tonic-gate  * can reprogram the large TLBs appropriately for the new process using
4087c478bd9Sstevel@tonic-gate  * the context.
4097c478bd9Sstevel@tonic-gate  *
4107c478bd9Sstevel@tonic-gate  * The caller must hold the HAT lock.
4117c478bd9Sstevel@tonic-gate  */
4127c478bd9Sstevel@tonic-gate void
mmu_set_ctx_page_sizes(struct hat * hat)4137c478bd9Sstevel@tonic-gate mmu_set_ctx_page_sizes(struct hat *hat)
4147c478bd9Sstevel@tonic-gate {
4157c478bd9Sstevel@tonic-gate 	uint_t pgsz0, pgsz1;
4167c478bd9Sstevel@tonic-gate 	uint_t new_cext;
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	ASSERT(sfmmu_hat_lock_held(hat));
4197c478bd9Sstevel@tonic-gate 	ASSERT(hat != ksfmmup);
4207c478bd9Sstevel@tonic-gate 
4211e2e7a75Shuah 	if (cpu_impl_dual_pgsz == 0)	/* disable_dual_pgsz flag */
4227c478bd9Sstevel@tonic-gate 		return;
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	/*
4257c478bd9Sstevel@tonic-gate 	 * If supported, reprogram the TLBs to a larger pagesize.
4267c478bd9Sstevel@tonic-gate 	 */
4277c478bd9Sstevel@tonic-gate 	pgsz0 = hat->sfmmu_pgsz[0];
4287c478bd9Sstevel@tonic-gate 	pgsz1 = hat->sfmmu_pgsz[1];
4297c478bd9Sstevel@tonic-gate 	ASSERT(pgsz0 < mmu_page_sizes);
4307c478bd9Sstevel@tonic-gate 	ASSERT(pgsz1 < mmu_page_sizes);
4317c478bd9Sstevel@tonic-gate #ifdef DEBUG
4327c478bd9Sstevel@tonic-gate 	if (panther_dtlb_restrictions) {
4337c478bd9Sstevel@tonic-gate 		ASSERT(pgsz1 != TTE512K);
4347c478bd9Sstevel@tonic-gate 		ASSERT(pgsz1 != TTE4M);
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate 	if (panther_only) {
4377c478bd9Sstevel@tonic-gate 		ASSERT(pgsz0 != TTE32M);
4387c478bd9Sstevel@tonic-gate 		ASSERT(pgsz0 != TTE256M);
4397c478bd9Sstevel@tonic-gate 	}
4407c478bd9Sstevel@tonic-gate #endif /* DEBUG */
4417c478bd9Sstevel@tonic-gate 	new_cext = TAGACCEXT_MKSZPAIR(pgsz1, pgsz0);
4427c478bd9Sstevel@tonic-gate 	if (hat->sfmmu_cext != new_cext) {
4431e2e7a75Shuah #ifdef DEBUG
4441e2e7a75Shuah 		int i;
4451e2e7a75Shuah 		/*
4461e2e7a75Shuah 		 * assert cnum should be invalid, this is because pagesize
4471e2e7a75Shuah 		 * can only be changed after a proc's ctxs are invalidated.
4481e2e7a75Shuah 		 */
4491e2e7a75Shuah 		for (i = 0; i < max_mmu_ctxdoms; i++) {
4501e2e7a75Shuah 			ASSERT(hat->sfmmu_ctxs[i].cnum == INVALID_CONTEXT);
4511e2e7a75Shuah 		}
4521e2e7a75Shuah #endif /* DEBUG */
4537c478bd9Sstevel@tonic-gate 		hat->sfmmu_cext = new_cext;
4547c478bd9Sstevel@tonic-gate 	}
4551e2e7a75Shuah 
4567c478bd9Sstevel@tonic-gate 	/*
4577c478bd9Sstevel@tonic-gate 	 * sfmmu_setctx_sec() will take care of the
4581e2e7a75Shuah 	 * rest of the chores reprogramming the hat->sfmmu_cext
4597c478bd9Sstevel@tonic-gate 	 * page size values into the DTLBs.
4607c478bd9Sstevel@tonic-gate 	 */
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate /*
4647c478bd9Sstevel@tonic-gate  * This function assumes that there are either four or six supported page
4657c478bd9Sstevel@tonic-gate  * sizes and at most two programmable TLBs, so we need to decide which
4667c478bd9Sstevel@tonic-gate  * page sizes are most important and then adjust the TLB page sizes
4677c478bd9Sstevel@tonic-gate  * accordingly (if supported).
4687c478bd9Sstevel@tonic-gate  *
4697c478bd9Sstevel@tonic-gate  * If these assumptions change, this function will need to be
4707c478bd9Sstevel@tonic-gate  * updated to support whatever the new limits are.
4717c478bd9Sstevel@tonic-gate  */
4727c478bd9Sstevel@tonic-gate void
mmu_check_page_sizes(sfmmu_t * sfmmup,uint64_t * ttecnt)4737c478bd9Sstevel@tonic-gate mmu_check_page_sizes(sfmmu_t *sfmmup, uint64_t *ttecnt)
4747c478bd9Sstevel@tonic-gate {
4757c478bd9Sstevel@tonic-gate 	uint64_t sortcnt[MMU_PAGE_SIZES];
4767c478bd9Sstevel@tonic-gate 	uint8_t tmp_pgsz[MMU_PAGE_SIZES];
4777c478bd9Sstevel@tonic-gate 	uint8_t i, j, max;
4787c478bd9Sstevel@tonic-gate 	uint16_t oldval, newval;
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	/*
4817c478bd9Sstevel@tonic-gate 	 * We only consider reprogramming the TLBs if one or more of
4827c478bd9Sstevel@tonic-gate 	 * the two most used page sizes changes and we're using
4837c478bd9Sstevel@tonic-gate 	 * large pages in this process, except for Panther 32M/256M pages,
4847c478bd9Sstevel@tonic-gate 	 * which the Panther T16 does not support.
4857c478bd9Sstevel@tonic-gate 	 */
48605d3dc4bSpaulsan 	if (SFMMU_LGPGS_INUSE(sfmmup)) {
4877c478bd9Sstevel@tonic-gate 		/* Sort page sizes. */
4887c478bd9Sstevel@tonic-gate 		for (i = 0; i < mmu_page_sizes; i++) {
4897c478bd9Sstevel@tonic-gate 			sortcnt[i] = ttecnt[i];
4907c478bd9Sstevel@tonic-gate 		}
4917c478bd9Sstevel@tonic-gate 		for (j = 0; j < mmu_page_sizes; j++) {
4927c478bd9Sstevel@tonic-gate 			for (i = mmu_page_sizes - 1, max = 0; i > 0; i--) {
4937c478bd9Sstevel@tonic-gate 				if (sortcnt[i] > sortcnt[max])
4947c478bd9Sstevel@tonic-gate 					max = i;
4957c478bd9Sstevel@tonic-gate 			}
4967c478bd9Sstevel@tonic-gate 			tmp_pgsz[j] = max;
4977c478bd9Sstevel@tonic-gate 			sortcnt[max] = 0;
4987c478bd9Sstevel@tonic-gate 		}
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 		/*
5017c478bd9Sstevel@tonic-gate 		 * Handle Panther page dtlb calcs separately. The check
5027c478bd9Sstevel@tonic-gate 		 * for actual or potential 32M/256M pages must occur
5037c478bd9Sstevel@tonic-gate 		 * every time due to lack of T16 support for them.
5047c478bd9Sstevel@tonic-gate 		 * The sort works fine for Ch+/Jag, but Panther has
5057c478bd9Sstevel@tonic-gate 		 * pagesize restrictions for both DTLBs.
5067c478bd9Sstevel@tonic-gate 		 */
5077c478bd9Sstevel@tonic-gate 		oldval = sfmmup->sfmmu_pgsz[0] << 8 | sfmmup->sfmmu_pgsz[1];
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 		if (panther_only) {
5107c478bd9Sstevel@tonic-gate 			mmu_fixup_large_pages(sfmmup, ttecnt, tmp_pgsz);
5117c478bd9Sstevel@tonic-gate 		} else {
5127c478bd9Sstevel@tonic-gate 			/* Check 2 largest values after the sort. */
5137c478bd9Sstevel@tonic-gate 			mmu_setup_page_sizes(sfmmup, ttecnt, tmp_pgsz);
5147c478bd9Sstevel@tonic-gate 		}
5157c478bd9Sstevel@tonic-gate 		newval = tmp_pgsz[0] << 8 | tmp_pgsz[1];
5167c478bd9Sstevel@tonic-gate 		if (newval != oldval) {
5171e2e7a75Shuah 			sfmmu_reprog_pgsz_arr(sfmmup, tmp_pgsz);
5187c478bd9Sstevel@tonic-gate 		}
5197c478bd9Sstevel@tonic-gate 	}
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate #endif	/* CPU_IMP_DUAL_PAGESIZE */
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate struct heap_lp_page_size {
5257c478bd9Sstevel@tonic-gate 	int    impl;
5267c478bd9Sstevel@tonic-gate 	uint_t tte;
5277c478bd9Sstevel@tonic-gate 	int    use_dt512;
5287c478bd9Sstevel@tonic-gate };
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate struct heap_lp_page_size heap_lp_pgsz[] = {
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 	{CHEETAH_IMPL, TTE8K, 0},		/* default */
5337c478bd9Sstevel@tonic-gate 	{CHEETAH_IMPL, TTE64K, 0},
5347c478bd9Sstevel@tonic-gate 	{CHEETAH_IMPL, TTE4M, 0},
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 	{ CHEETAH_PLUS_IMPL, TTE4M,  1 },	/* default */
5377c478bd9Sstevel@tonic-gate 	{ CHEETAH_PLUS_IMPL, TTE4M,  0 },
5387c478bd9Sstevel@tonic-gate 	{ CHEETAH_PLUS_IMPL, TTE64K, 1 },
5397c478bd9Sstevel@tonic-gate 	{ CHEETAH_PLUS_IMPL, TTE64K, 0 },
5407c478bd9Sstevel@tonic-gate 	{ CHEETAH_PLUS_IMPL, TTE8K,  0 },
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	{ JALAPENO_IMPL, TTE4M,  1 },		/* default */
5437c478bd9Sstevel@tonic-gate 	{ JALAPENO_IMPL, TTE4M,  0 },
5447c478bd9Sstevel@tonic-gate 	{ JALAPENO_IMPL, TTE64K, 1 },
5457c478bd9Sstevel@tonic-gate 	{ JALAPENO_IMPL, TTE64K, 0 },
5467c478bd9Sstevel@tonic-gate 	{ JALAPENO_IMPL, TTE8K,  0 },
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	{ JAGUAR_IMPL, TTE4M, 1 },		/* default */
5497c478bd9Sstevel@tonic-gate 	{ JAGUAR_IMPL, TTE4M, 0 },
5507c478bd9Sstevel@tonic-gate 	{ JAGUAR_IMPL, TTE64K, 1 },
5517c478bd9Sstevel@tonic-gate 	{ JAGUAR_IMPL, TTE64K, 0 },
5527c478bd9Sstevel@tonic-gate 	{ JAGUAR_IMPL, TTE8K, 0 },
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	{ SERRANO_IMPL, TTE4M,  1 },		/* default */
5557c478bd9Sstevel@tonic-gate 	{ SERRANO_IMPL, TTE4M,  0 },
5567c478bd9Sstevel@tonic-gate 	{ SERRANO_IMPL, TTE64K, 1 },
5577c478bd9Sstevel@tonic-gate 	{ SERRANO_IMPL, TTE64K, 0 },
5587c478bd9Sstevel@tonic-gate 	{ SERRANO_IMPL, TTE8K,  0 },
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	{ PANTHER_IMPL, TTE4M, 1 },		/* default */
5617c478bd9Sstevel@tonic-gate 	{ PANTHER_IMPL, TTE4M, 0 },
5627c478bd9Sstevel@tonic-gate 	{ PANTHER_IMPL, TTE64K, 1 },
5637c478bd9Sstevel@tonic-gate 	{ PANTHER_IMPL, TTE64K, 0 },
5647c478bd9Sstevel@tonic-gate 	{ PANTHER_IMPL, TTE8K, 0 }
5657c478bd9Sstevel@tonic-gate };
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate int	heaplp_use_dt512 = -1;
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate void
mmu_init_kernel_pgsz(struct hat * hat)5707c478bd9Sstevel@tonic-gate mmu_init_kernel_pgsz(struct hat *hat)
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate 	uint_t tte = page_szc(segkmem_lpsize);
5737c478bd9Sstevel@tonic-gate 	uchar_t new_cext_primary, new_cext_nucleus;
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	if (heaplp_use_dt512 == 0 || tte > TTE4M) {
5767c478bd9Sstevel@tonic-gate 		/* do not reprogram dt512 tlb */
5777c478bd9Sstevel@tonic-gate 		tte = TTE8K;
5787c478bd9Sstevel@tonic-gate 	}
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	new_cext_nucleus = TAGACCEXT_MKSZPAIR(tte, TTE8K);
5817c478bd9Sstevel@tonic-gate 	new_cext_primary = TAGACCEXT_MKSZPAIR(TTE8K, tte);
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	hat->sfmmu_cext = new_cext_primary;
5847c478bd9Sstevel@tonic-gate 	kcontextreg = ((uint64_t)new_cext_nucleus << CTXREG_NEXT_SHIFT) |
5857c478bd9Sstevel@tonic-gate 	    ((uint64_t)new_cext_primary << CTXREG_EXT_SHIFT);
5867c478bd9Sstevel@tonic-gate }
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate size_t
mmu_get_kernel_lpsize(size_t lpsize)5897c478bd9Sstevel@tonic-gate mmu_get_kernel_lpsize(size_t lpsize)
5907c478bd9Sstevel@tonic-gate {
5917c478bd9Sstevel@tonic-gate 	struct heap_lp_page_size *p_lpgsz, *pend_lpgsz;
5927c478bd9Sstevel@tonic-gate 	int impl = cpunodes[getprocessorid()].implementation;
5937c478bd9Sstevel@tonic-gate 	uint_t tte = TTE8K;
5947c478bd9Sstevel@tonic-gate 
5951e2e7a75Shuah 	if (cpu_impl_dual_pgsz == 0) {
5961e2e7a75Shuah 		heaplp_use_dt512 = 0;
5971e2e7a75Shuah 		return (MMU_PAGESIZE);
5981e2e7a75Shuah 	}
5991e2e7a75Shuah 
6007c478bd9Sstevel@tonic-gate 	pend_lpgsz = (struct heap_lp_page_size *)
6017c478bd9Sstevel@tonic-gate 	    ((char *)heap_lp_pgsz + sizeof (heap_lp_pgsz));
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 	/* search for a valid segkmem_lpsize */
6047c478bd9Sstevel@tonic-gate 	for (p_lpgsz = heap_lp_pgsz; p_lpgsz < pend_lpgsz; p_lpgsz++) {
6057c478bd9Sstevel@tonic-gate 		if (impl != p_lpgsz->impl)
6067c478bd9Sstevel@tonic-gate 			continue;
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 		if (lpsize == 0) {
6097c478bd9Sstevel@tonic-gate 			/*
6107c478bd9Sstevel@tonic-gate 			 * no setting for segkmem_lpsize in /etc/system
6117c478bd9Sstevel@tonic-gate 			 * use default from the table
6127c478bd9Sstevel@tonic-gate 			 */
6137c478bd9Sstevel@tonic-gate 			tte = p_lpgsz->tte;
6147c478bd9Sstevel@tonic-gate 			heaplp_use_dt512 = p_lpgsz->use_dt512;
6157c478bd9Sstevel@tonic-gate 			break;
6167c478bd9Sstevel@tonic-gate 		}
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 		if (lpsize == TTEBYTES(p_lpgsz->tte) &&
6197c478bd9Sstevel@tonic-gate 		    (heaplp_use_dt512 == -1 ||
6207c478bd9Sstevel@tonic-gate 		    heaplp_use_dt512 == p_lpgsz->use_dt512)) {
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 			tte = p_lpgsz->tte;
6237c478bd9Sstevel@tonic-gate 			heaplp_use_dt512 = p_lpgsz->use_dt512;
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate 			/* found a match */
6267c478bd9Sstevel@tonic-gate 			break;
6277c478bd9Sstevel@tonic-gate 		}
6287c478bd9Sstevel@tonic-gate 	}
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 	if (p_lpgsz == pend_lpgsz) {
6317c478bd9Sstevel@tonic-gate 		/* nothing found: disable large page kernel heap */
6327c478bd9Sstevel@tonic-gate 		tte = TTE8K;
6337c478bd9Sstevel@tonic-gate 		heaplp_use_dt512 = 0;
6347c478bd9Sstevel@tonic-gate 	}
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	lpsize = TTEBYTES(tte);
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 	return (lpsize);
6397c478bd9Sstevel@tonic-gate }
640