xref: /illumos-gate/usr/src/uts/sun4v/os/fillsysinfo.c (revision 9853d9e82e7a067a2b88dae2fd257207e6be5f94)
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
51ae08745Sheppo  * Common Development and Distribution License (the "License").
61ae08745Sheppo  * 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 /*
22125be069SJason Beloro  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <sys/errno.h>
277c478bd9Sstevel@tonic-gate #include <sys/types.h>
287c478bd9Sstevel@tonic-gate #include <sys/param.h>
297c478bd9Sstevel@tonic-gate #include <sys/cpu.h>
307c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
317c478bd9Sstevel@tonic-gate #include <sys/clock.h>
327c478bd9Sstevel@tonic-gate #include <sys/promif.h>
337c478bd9Sstevel@tonic-gate #include <sys/promimpl.h>
347c478bd9Sstevel@tonic-gate #include <sys/systm.h>
357c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
367c478bd9Sstevel@tonic-gate #include <sys/debug.h>
377c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
387c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
397c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h>
407c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
417c478bd9Sstevel@tonic-gate #include <sys/cmp.h>
427c478bd9Sstevel@tonic-gate #include <sys/async.h>
437c478bd9Sstevel@tonic-gate #include <vm/page.h>
442f0fcb93SJason Beloro #include <vm/vm_dep.h>
451ae08745Sheppo #include <vm/hat_sfmmu.h>
461ae08745Sheppo #include <sys/sysmacros.h>
471ae08745Sheppo #include <sys/mach_descrip.h>
481ae08745Sheppo #include <sys/mdesc.h>
491ae08745Sheppo #include <sys/archsystm.h>
501ae08745Sheppo #include <sys/error.h>
511ae08745Sheppo #include <sys/mmu.h>
521ae08745Sheppo #include <sys/bitmap.h>
534bac2208Snarayan #include <sys/intreg.h>
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate struct cpu_node cpunodes[NCPU];
567c478bd9Sstevel@tonic-gate 
571ae08745Sheppo uint64_t cpu_q_entries;
581ae08745Sheppo uint64_t dev_q_entries;
591ae08745Sheppo uint64_t cpu_rq_entries;
601ae08745Sheppo uint64_t cpu_nrq_entries;
61aaa10e67Sha uint64_t ncpu_guest_max;
621ae08745Sheppo 
631ae08745Sheppo void fill_cpu(md_t *, mde_cookie_t);
641ae08745Sheppo 
651ae08745Sheppo static uint64_t get_mmu_ctx_bits(md_t *, mde_cookie_t);
6605d3dc4bSpaulsan static uint64_t get_mmu_tsbs(md_t *, mde_cookie_t);
6705d3dc4bSpaulsan static uint64_t	get_mmu_shcontexts(md_t *, mde_cookie_t);
681ae08745Sheppo static uint64_t get_cpu_pagesizes(md_t *, mde_cookie_t);
69125be069SJason Beloro static int check_mmu_pgsz_search(md_t *, mde_cookie_t);
701ae08745Sheppo static char *construct_isalist(md_t *, mde_cookie_t, char **);
714bac2208Snarayan static void init_md_broken(md_t *, mde_cookie_t *);
721ae08745Sheppo static int get_l2_cache_info(md_t *, mde_cookie_t, uint64_t *, uint64_t *,
731ae08745Sheppo     uint64_t *);
742f0fcb93SJason Beloro static void get_hwcaps(md_t *, mde_cookie_t);
752c5124a1SPrashanth Sreenivasa static void get_weakest_mem_model(md_t *, mde_cookie_t);
761ae08745Sheppo static void get_q_sizes(md_t *, mde_cookie_t);
771ae08745Sheppo static void get_va_bits(md_t *, mde_cookie_t);
78*9853d9e8SJason Beloro static size_t get_ra_limit(md_t *, mde_cookie_t);
79575a7426Spt static int get_l2_cache_node_count(md_t *);
802f0fcb93SJason Beloro static unsigned long names2bits(char *tokens, size_t tokenslen,
812f0fcb93SJason Beloro     char *bit_formatter, char *warning);
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate uint64_t	system_clock_freq;
847c478bd9Sstevel@tonic-gate uint_t		niommu_tsbs = 0;
857c478bd9Sstevel@tonic-gate 
86575a7426Spt static int n_l2_caches = 0;
87575a7426Spt 
88fedab560Sae /* prevent compilation with VAC defined */
89fedab560Sae #ifdef VAC
90fedab560Sae #error "The sun4v architecture does not support VAC"
91fedab560Sae #endif
92fedab560Sae 
93fedab560Sae #define	S_VAC_SIZE	MMU_PAGESIZE
94fedab560Sae #define	S_VAC_SHIFT	MMU_PAGESHIFT
95fedab560Sae 
96fedab560Sae int		vac_size = S_VAC_SIZE;
97fedab560Sae uint_t		vac_mask = MMU_PAGEMASK & (S_VAC_SIZE - 1);
98fedab560Sae int		vac_shift = S_VAC_SHIFT;
99fedab560Sae uintptr_t	shm_alignment = S_VAC_SIZE;
100fedab560Sae 
1011ae08745Sheppo void
1021ae08745Sheppo map_wellknown_devices()
1031ae08745Sheppo {
1041ae08745Sheppo }
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate void
1071ae08745Sheppo fill_cpu(md_t *mdp, mde_cookie_t cpuc)
1087c478bd9Sstevel@tonic-gate {
1091ae08745Sheppo 	struct cpu_node *cpunode;
1101ae08745Sheppo 	uint64_t cpuid;
1111ae08745Sheppo 	uint64_t clk_freq;
1121ae08745Sheppo 	char *namebuf;
1131ae08745Sheppo 	char *namebufp;
1141ae08745Sheppo 	int namelen;
1151ae08745Sheppo 	uint64_t associativity = 0, linesize = 0, size = 0;
1161ae08745Sheppo 
1171ae08745Sheppo 	if (md_get_prop_val(mdp, cpuc, "id", &cpuid)) {
1181ae08745Sheppo 		return;
1191ae08745Sheppo 	}
1207c478bd9Sstevel@tonic-gate 
1214bac2208Snarayan 	/* All out-of-range cpus will be stopped later. */
1221ae08745Sheppo 	if (cpuid >= NCPU) {
1231ae08745Sheppo 		cmn_err(CE_CONT, "fill_cpu: out of range cpuid %ld - "
1244bac2208Snarayan 		    "cpu excluded from configuration\n", cpuid);
1251ae08745Sheppo 
1261ae08745Sheppo 		return;
1271ae08745Sheppo 	}
1281ae08745Sheppo 
1291ae08745Sheppo 	cpunode = &cpunodes[cpuid];
1301ae08745Sheppo 	cpunode->cpuid = (int)cpuid;
1311ae08745Sheppo 	cpunode->device_id = cpuid;
1321ae08745Sheppo 
1331ae08745Sheppo 	if (sizeof (cpunode->fru_fmri) > strlen(CPU_FRU_FMRI))
1341ae08745Sheppo 		(void) strcpy(cpunode->fru_fmri, CPU_FRU_FMRI);
1351ae08745Sheppo 
1361ae08745Sheppo 	if (md_get_prop_data(mdp, cpuc,
1371ae08745Sheppo 	    "compatible", (uint8_t **)&namebuf, &namelen)) {
1381ae08745Sheppo 		cmn_err(CE_PANIC, "fill_cpu: Cannot read compatible "
1391ae08745Sheppo 		    "property");
1401ae08745Sheppo 	}
1411ae08745Sheppo 	namebufp = namebuf;
1421ae08745Sheppo 	if (strncmp(namebufp, "SUNW,", 5) == 0)
1431ae08745Sheppo 		namebufp += 5;
1441ae08745Sheppo 	if (strlen(namebufp) > sizeof (cpunode->name))
1451ae08745Sheppo 		cmn_err(CE_PANIC, "Compatible property too big to "
1461ae08745Sheppo 		    "fit into the cpunode name buffer");
1471ae08745Sheppo 	(void) strcpy(cpunode->name, namebufp);
1481ae08745Sheppo 
1491ae08745Sheppo 	if (md_get_prop_val(mdp, cpuc,
1501ae08745Sheppo 	    "clock-frequency", &clk_freq)) {
1511ae08745Sheppo 			clk_freq = 0;
1521ae08745Sheppo 	}
1531ae08745Sheppo 	cpunode->clock_freq = clk_freq;
1541ae08745Sheppo 
1551ae08745Sheppo 	ASSERT(cpunode->clock_freq != 0);
1567c478bd9Sstevel@tonic-gate 	/*
1571ae08745Sheppo 	 * Compute scaling factor based on rate of %tick. This is used
1581ae08745Sheppo 	 * to convert from ticks derived from %tick to nanoseconds. See
1591ae08745Sheppo 	 * comment in sun4u/sys/clock.h for details.
1607c478bd9Sstevel@tonic-gate 	 */
1611ae08745Sheppo 	cpunode->tick_nsec_scale = (uint_t)(((uint64_t)NANOSEC <<
1621ae08745Sheppo 	    (32 - TICK_NSEC_SHIFT)) / cpunode->clock_freq);
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	/*
1651ae08745Sheppo 	 * The nodeid is not used in sun4v at all. Setting it
1661ae08745Sheppo 	 * to positive value to make starting of slave CPUs
1671ae08745Sheppo 	 * code happy.
1687c478bd9Sstevel@tonic-gate 	 */
1691ae08745Sheppo 	cpunode->nodeid = cpuid + 1;
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	/*
1721ae08745Sheppo 	 * Obtain the L2 cache information from MD.
1731ae08745Sheppo 	 * If "Cache" node exists, then set L2 cache properties
1741ae08745Sheppo 	 * as read from MD.
1751ae08745Sheppo 	 * If node does not exists, then set the L2 cache properties
1761ae08745Sheppo 	 * in individual CPU module.
1777c478bd9Sstevel@tonic-gate 	 */
1781ae08745Sheppo 	if ((!get_l2_cache_info(mdp, cpuc,
1791ae08745Sheppo 	    &associativity, &size, &linesize)) ||
1801ae08745Sheppo 	    associativity == 0 || size == 0 || linesize == 0) {
1811ae08745Sheppo 		cpu_fiximp(cpunode);
1821ae08745Sheppo 	} else {
1831ae08745Sheppo 		/*
1841ae08745Sheppo 		 * Do not expect L2 cache properties to be bigger
1851ae08745Sheppo 		 * than 32-bit quantity.
1861ae08745Sheppo 		 */
1871ae08745Sheppo 		cpunode->ecache_associativity = (int)associativity;
1881ae08745Sheppo 		cpunode->ecache_size = (int)size;
1891ae08745Sheppo 		cpunode->ecache_linesize = (int)linesize;
1907c478bd9Sstevel@tonic-gate 	}
1911ae08745Sheppo 
1921ae08745Sheppo 	cpunode->ecache_setsize =
1931ae08745Sheppo 	    cpunode->ecache_size / cpunode->ecache_associativity;
1941ae08745Sheppo 
19559ac0c16Sdavemq 	/*
19659ac0c16Sdavemq 	 * Initialize the mapping for exec unit, chip and core.
19759ac0c16Sdavemq 	 */
1981ae08745Sheppo 	cpunode->exec_unit_mapping = NO_EU_MAPPING_FOUND;
19959ac0c16Sdavemq 	cpunode->l2_cache_mapping = NO_MAPPING_FOUND;
20059ac0c16Sdavemq 	cpunode->core_mapping = NO_CORE_MAPPING_FOUND;
2011ae08745Sheppo 
2021ae08745Sheppo 	if (ecache_setsize == 0)
2031ae08745Sheppo 		ecache_setsize = cpunode->ecache_setsize;
2041ae08745Sheppo 	if (ecache_alignsize == 0)
2051ae08745Sheppo 		ecache_alignsize = cpunode->ecache_linesize;
2061ae08745Sheppo 
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate 
2091ae08745Sheppo void
2101ae08745Sheppo empty_cpu(int cpuid)
2117c478bd9Sstevel@tonic-gate {
2121ae08745Sheppo 	bzero(&cpunodes[cpuid], sizeof (struct cpu_node));
2131ae08745Sheppo }
2147c478bd9Sstevel@tonic-gate 
21559ac0c16Sdavemq /*
21659ac0c16Sdavemq  * Use L2 cache node to derive the chip mapping.
21759ac0c16Sdavemq  */
21859ac0c16Sdavemq void
21959ac0c16Sdavemq setup_chip_mappings(md_t *mdp)
22059ac0c16Sdavemq {
2212f0fcb93SJason Beloro 	int ncache, ncpu;
22259ac0c16Sdavemq 	mde_cookie_t *node, *cachelist;
22359ac0c16Sdavemq 	int i, j;
22459ac0c16Sdavemq 	processorid_t cpuid;
22559ac0c16Sdavemq 	int idx = 0;
22659ac0c16Sdavemq 
22759ac0c16Sdavemq 	ncache = md_alloc_scan_dag(mdp, md_root_node(mdp), "cache",
22859ac0c16Sdavemq 	    "fwd", &cachelist);
22959ac0c16Sdavemq 
23059ac0c16Sdavemq 	/*
23159ac0c16Sdavemq 	 * The "cache" node is optional in MD, therefore ncaches can be 0.
23259ac0c16Sdavemq 	 */
23359ac0c16Sdavemq 	if (ncache < 1) {
23459ac0c16Sdavemq 		return;
23559ac0c16Sdavemq 	}
23659ac0c16Sdavemq 
23759ac0c16Sdavemq 	for (i = 0; i < ncache; i++) {
23859ac0c16Sdavemq 		uint64_t cache_level;
23959ac0c16Sdavemq 		uint64_t lcpuid;
24059ac0c16Sdavemq 
24159ac0c16Sdavemq 		if (md_get_prop_val(mdp, cachelist[i], "level", &cache_level))
24259ac0c16Sdavemq 			continue;
24359ac0c16Sdavemq 
24459ac0c16Sdavemq 		if (cache_level != 2)
24559ac0c16Sdavemq 			continue;
24659ac0c16Sdavemq 
24759ac0c16Sdavemq 		/*
24859ac0c16Sdavemq 		 * Found a l2 cache node. Find out the cpu nodes it
24959ac0c16Sdavemq 		 * points to.
25059ac0c16Sdavemq 		 */
25159ac0c16Sdavemq 		ncpu = md_alloc_scan_dag(mdp, cachelist[i], "cpu",
25259ac0c16Sdavemq 		    "back", &node);
25359ac0c16Sdavemq 
25459ac0c16Sdavemq 		if (ncpu < 1)
25559ac0c16Sdavemq 			continue;
25659ac0c16Sdavemq 
25759ac0c16Sdavemq 		for (j = 0; j < ncpu; j++) {
25859ac0c16Sdavemq 			if (md_get_prop_val(mdp, node[j], "id", &lcpuid))
25959ac0c16Sdavemq 				continue;
26059ac0c16Sdavemq 			if (lcpuid >= NCPU)
26159ac0c16Sdavemq 				continue;
26259ac0c16Sdavemq 			cpuid = (processorid_t)lcpuid;
26359ac0c16Sdavemq 			cpunodes[cpuid].l2_cache_mapping = idx;
26459ac0c16Sdavemq 		}
26559ac0c16Sdavemq 		md_free_scan_dag(mdp, &node);
26659ac0c16Sdavemq 
26759ac0c16Sdavemq 		idx++;
26859ac0c16Sdavemq 	}
26959ac0c16Sdavemq 
27059ac0c16Sdavemq 	md_free_scan_dag(mdp, &cachelist);
27159ac0c16Sdavemq }
27259ac0c16Sdavemq 
2731ae08745Sheppo void
2741ae08745Sheppo setup_exec_unit_mappings(md_t *mdp)
2751ae08745Sheppo {
2762f0fcb93SJason Beloro 	int num, num_eunits;
2771ae08745Sheppo 	mde_cookie_t cpus_node;
2781ae08745Sheppo 	mde_cookie_t *node, *eunit;
2791ae08745Sheppo 	int idx, i, j;
2801ae08745Sheppo 	processorid_t cpuid;
2811ae08745Sheppo 	char *eunit_name = broken_md_flag ? "exec_unit" : "exec-unit";
282fb2f18f8Sesaxe 	enum eu_type { INTEGER, FPU } etype;
2837c478bd9Sstevel@tonic-gate 
2841ae08745Sheppo 	/*
2851ae08745Sheppo 	 * Find the cpu integer exec units - and
2861ae08745Sheppo 	 * setup the mappings appropriately.
2871ae08745Sheppo 	 */
2881ae08745Sheppo 	num = md_alloc_scan_dag(mdp, md_root_node(mdp), "cpus", "fwd", &node);
2891ae08745Sheppo 	if (num < 1)
2904bac2208Snarayan 		cmn_err(CE_PANIC, "No cpus node in machine description");
2911ae08745Sheppo 	if (num > 1)
2921ae08745Sheppo 		cmn_err(CE_PANIC, "More than 1 cpus node in machine"
2931ae08745Sheppo 		    " description");
2941ae08745Sheppo 
2951ae08745Sheppo 	cpus_node = node[0];
2961ae08745Sheppo 	md_free_scan_dag(mdp, &node);
2971ae08745Sheppo 
2981ae08745Sheppo 	num_eunits = md_alloc_scan_dag(mdp, cpus_node, eunit_name,
2991ae08745Sheppo 	    "fwd", &eunit);
3001ae08745Sheppo 	if (num_eunits > 0) {
301fb2f18f8Sesaxe 		char *int_str = broken_md_flag ? "int" : "integer";
302fb2f18f8Sesaxe 		char *fpu_str = "fp";
3031ae08745Sheppo 
3041ae08745Sheppo 		/* Spin through and find all the integer exec units */
3051ae08745Sheppo 		for (i = 0; i < num_eunits; i++) {
3061ae08745Sheppo 			char *p;
3071ae08745Sheppo 			char *val;
3081ae08745Sheppo 			int vallen;
3091ae08745Sheppo 			uint64_t lcpuid;
3101ae08745Sheppo 
311fb2f18f8Sesaxe 			/* ignore nodes with no type */
3121ae08745Sheppo 			if (md_get_prop_data(mdp, eunit[i], "type",
313ad8d2eb8Szx 			    (uint8_t **)&val, &vallen))
314ad8d2eb8Szx 				continue;
3151ae08745Sheppo 
3161ae08745Sheppo 			for (p = val; *p != '\0'; p += strlen(p) + 1) {
317fb2f18f8Sesaxe 				if (strcmp(p, int_str) == 0) {
318fb2f18f8Sesaxe 					etype = INTEGER;
3191ae08745Sheppo 					goto found;
320fb2f18f8Sesaxe 				}
321fb2f18f8Sesaxe 				if (strcmp(p, fpu_str) == 0) {
322fb2f18f8Sesaxe 					etype = FPU;
323fb2f18f8Sesaxe 					goto found;
324fb2f18f8Sesaxe 				}
3257c478bd9Sstevel@tonic-gate 			}
3261ae08745Sheppo 
3271ae08745Sheppo 			continue;
3281ae08745Sheppo found:
3291ae08745Sheppo 			idx = NCPU + i;
3307c478bd9Sstevel@tonic-gate 			/*
3311ae08745Sheppo 			 * find the cpus attached to this EU and
3321ae08745Sheppo 			 * update their mapping indices
3337c478bd9Sstevel@tonic-gate 			 */
3341ae08745Sheppo 			num = md_alloc_scan_dag(mdp, eunit[i], "cpu",
3351ae08745Sheppo 			    "back", &node);
3361ae08745Sheppo 
3371ae08745Sheppo 			if (num < 1)
3381ae08745Sheppo 				cmn_err(CE_PANIC, "exec-unit node in MD"
3391ae08745Sheppo 				    " not attached to a cpu node");
3401ae08745Sheppo 
3411ae08745Sheppo 			for (j = 0; j < num; j++) {
3421ae08745Sheppo 				if (md_get_prop_val(mdp, node[j], "id",
3431ae08745Sheppo 				    &lcpuid))
3441ae08745Sheppo 					continue;
3451ae08745Sheppo 				if (lcpuid >= NCPU)
3461ae08745Sheppo 					continue;
3471ae08745Sheppo 				cpuid = (processorid_t)lcpuid;
348fb2f18f8Sesaxe 				switch (etype) {
349fb2f18f8Sesaxe 				case INTEGER:
350fb2f18f8Sesaxe 					cpunodes[cpuid].exec_unit_mapping = idx;
351fb2f18f8Sesaxe 					break;
352fb2f18f8Sesaxe 				case FPU:
353fb2f18f8Sesaxe 					cpunodes[cpuid].fpu_mapping = idx;
354fb2f18f8Sesaxe 					break;
355fb2f18f8Sesaxe 				}
3561ae08745Sheppo 			}
3571ae08745Sheppo 			md_free_scan_dag(mdp, &node);
3587c478bd9Sstevel@tonic-gate 		}
3592f0fcb93SJason Beloro 		md_free_scan_dag(mdp, &eunit);
3602f0fcb93SJason Beloro 	}
3612f0fcb93SJason Beloro }
3622f0fcb93SJason Beloro 
3632f0fcb93SJason Beloro /*
3642f0fcb93SJason Beloro  * Setup instruction cache coherency.  The "memory-coherent" property
3652f0fcb93SJason Beloro  * is optional.  Default for Icache_coherency is 1 (I$ is coherent).
3662f0fcb93SJason Beloro  * If we find an Icache with coherency == 0, then enable non-coherent
3672f0fcb93SJason Beloro  * Icache support.
3682f0fcb93SJason Beloro  */
3692f0fcb93SJason Beloro void
3702f0fcb93SJason Beloro setup_icache_coherency(md_t *mdp)
3712f0fcb93SJason Beloro {
3722f0fcb93SJason Beloro 	int ncache;
3732f0fcb93SJason Beloro 	mde_cookie_t *cachelist;
3742f0fcb93SJason Beloro 	int i;
3757c478bd9Sstevel@tonic-gate 
3762f0fcb93SJason Beloro 	ncache = md_alloc_scan_dag(mdp, md_root_node(mdp), "cache",
3772f0fcb93SJason Beloro 	    "fwd", &cachelist);
3781ae08745Sheppo 
3792f0fcb93SJason Beloro 	/*
3802f0fcb93SJason Beloro 	 * The "cache" node is optional in MD, therefore ncaches can be 0.
3812f0fcb93SJason Beloro 	 */
3822f0fcb93SJason Beloro 	if (ncache < 1) {
3832f0fcb93SJason Beloro 		return;
3847c478bd9Sstevel@tonic-gate 	}
3852f0fcb93SJason Beloro 
3862f0fcb93SJason Beloro 	for (i = 0; i < ncache; i++) {
3872f0fcb93SJason Beloro 		uint64_t cache_level;
3882f0fcb93SJason Beloro 		uint64_t memory_coherent;
3892f0fcb93SJason Beloro 		uint8_t *type;
3902f0fcb93SJason Beloro 		int typelen;
3912f0fcb93SJason Beloro 
3922f0fcb93SJason Beloro 		if (md_get_prop_val(mdp, cachelist[i], "level",
3932f0fcb93SJason Beloro 		    &cache_level))
3942f0fcb93SJason Beloro 			continue;
3952f0fcb93SJason Beloro 
3962f0fcb93SJason Beloro 		if (cache_level != 1)
3972f0fcb93SJason Beloro 			continue;
3982f0fcb93SJason Beloro 
3992f0fcb93SJason Beloro 		if (md_get_prop_data(mdp, cachelist[i], "type",
4002f0fcb93SJason Beloro 		    &type, &typelen))
4012f0fcb93SJason Beloro 			continue;
4022f0fcb93SJason Beloro 
4032f0fcb93SJason Beloro 		if (strcmp((char *)type, "instn") != 0)
4042f0fcb93SJason Beloro 			continue;
4052f0fcb93SJason Beloro 
4062f0fcb93SJason Beloro 		if (md_get_prop_val(mdp, cachelist[i], "memory-coherent",
4072f0fcb93SJason Beloro 		    &memory_coherent))
4082f0fcb93SJason Beloro 			continue;
4092f0fcb93SJason Beloro 
4102f0fcb93SJason Beloro 		if (memory_coherent != 0)
4112f0fcb93SJason Beloro 			continue;
4122f0fcb93SJason Beloro 
4132f0fcb93SJason Beloro 		mach_setup_icache(memory_coherent);
4142f0fcb93SJason Beloro 		break;
4152f0fcb93SJason Beloro 	}
4162f0fcb93SJason Beloro 
4172f0fcb93SJason Beloro 	md_free_scan_dag(mdp, &cachelist);
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate 
4201ae08745Sheppo /*
4211ae08745Sheppo  * All the common setup of sun4v CPU modules is done by this routine.
4221ae08745Sheppo  */
4231ae08745Sheppo void
4241ae08745Sheppo cpu_setup_common(char **cpu_module_isa_set)
4257c478bd9Sstevel@tonic-gate {
4261ae08745Sheppo 	extern int mmu_exported_pagesize_mask;
4271ae08745Sheppo 	int nocpus, i;
4281ae08745Sheppo 	size_t ra_limit;
4291ae08745Sheppo 	mde_cookie_t *cpulist;
4301ae08745Sheppo 	md_t *mdp;
4311ae08745Sheppo 
4321ae08745Sheppo 	if ((mdp = md_get_handle()) == NULL)
4331ae08745Sheppo 		cmn_err(CE_PANIC, "Unable to initialize machine description");
4341ae08745Sheppo 
43506fb6a36Sdv 	boot_ncpus = nocpus = md_alloc_scan_dag(mdp,
4361ae08745Sheppo 	    md_root_node(mdp), "cpu", "fwd", &cpulist);
4371ae08745Sheppo 	if (nocpus < 1) {
4381ae08745Sheppo 		cmn_err(CE_PANIC, "cpu_common_setup: cpulist allocation "
4391ae08745Sheppo 		    "failed or incorrect number of CPUs in MD");
4401ae08745Sheppo 	}
4417c478bd9Sstevel@tonic-gate 
4424bac2208Snarayan 	init_md_broken(mdp, cpulist);
4434bac2208Snarayan 
4441ae08745Sheppo 	if (use_page_coloring) {
4451ae08745Sheppo 		do_pg_coloring = 1;
4461ae08745Sheppo 	}
4471ae08745Sheppo 
4481ae08745Sheppo 	/*
4491e2e7a75Shuah 	 * Get the valid mmu page sizes mask, Q sizes and isalist/r
4501ae08745Sheppo 	 * from the MD for the first available CPU in cpulist.
4511e2e7a75Shuah 	 *
4521e2e7a75Shuah 	 * Do not expect the MMU page sizes mask to be more than 32-bit.
4531ae08745Sheppo 	 */
4541ae08745Sheppo 	mmu_exported_pagesize_mask = (int)get_cpu_pagesizes(mdp, cpulist[0]);
4551ae08745Sheppo 
45605d3dc4bSpaulsan 	/*
45705d3dc4bSpaulsan 	 * Get the number of contexts and tsbs supported.
45805d3dc4bSpaulsan 	 */
45905d3dc4bSpaulsan 	if (get_mmu_shcontexts(mdp, cpulist[0]) >= MIN_NSHCONTEXTS &&
46005d3dc4bSpaulsan 	    get_mmu_tsbs(mdp, cpulist[0]) >= MIN_NTSBS) {
46105d3dc4bSpaulsan 		shctx_on = 1;
46205d3dc4bSpaulsan 	}
46305d3dc4bSpaulsan 
464125be069SJason Beloro 	/*
465125be069SJason Beloro 	 *  Get and check page search register properties.
466125be069SJason Beloro 	 */
467125be069SJason Beloro 	pgsz_search_on = check_mmu_pgsz_search(mdp, cpulist[0]);
468125be069SJason Beloro 
4691ae08745Sheppo 	for (i = 0; i < nocpus; i++)
4701ae08745Sheppo 		fill_cpu(mdp, cpulist[i]);
4711ae08745Sheppo 
472575a7426Spt 	/* setup l2 cache count. */
473575a7426Spt 	n_l2_caches = get_l2_cache_node_count(mdp);
474575a7426Spt 
47559ac0c16Sdavemq 	setup_chip_mappings(mdp);
4761ae08745Sheppo 	setup_exec_unit_mappings(mdp);
4772f0fcb93SJason Beloro 	setup_icache_coherency(mdp);
4781ae08745Sheppo 
4791ae08745Sheppo 	/*
4801ae08745Sheppo 	 * If MD is broken then append the passed ISA set,
4811ae08745Sheppo 	 * otherwise trust the MD.
4821ae08745Sheppo 	 */
4831ae08745Sheppo 
4841ae08745Sheppo 	if (broken_md_flag)
4851ae08745Sheppo 		isa_list = construct_isalist(mdp, cpulist[0],
4861ae08745Sheppo 		    cpu_module_isa_set);
4871ae08745Sheppo 	else
4881ae08745Sheppo 		isa_list = construct_isalist(mdp, cpulist[0], NULL);
4891ae08745Sheppo 
4902f0fcb93SJason Beloro 	get_hwcaps(mdp, cpulist[0]);
4912c5124a1SPrashanth Sreenivasa 	get_weakest_mem_model(mdp, cpulist[0]);
4921ae08745Sheppo 	get_q_sizes(mdp, cpulist[0]);
4931ae08745Sheppo 	get_va_bits(mdp, cpulist[0]);
4941ae08745Sheppo 
4951ae08745Sheppo 	/*
4961ae08745Sheppo 	 * ra_limit is the highest real address in the machine.
4971ae08745Sheppo 	 */
498*9853d9e8SJason Beloro 	ra_limit = get_ra_limit(mdp, cpulist[0]);
4991ae08745Sheppo 
5001ae08745Sheppo 	md_free_scan_dag(mdp, &cpulist);
5011ae08745Sheppo 
5021ae08745Sheppo 	(void) md_fini_handle(mdp);
5031ae08745Sheppo 
5041ae08745Sheppo 	/*
5051ae08745Sheppo 	 * Block stores invalidate all pages of the d$ so pagecopy
5061ae08745Sheppo 	 * et. al. do not need virtual translations with virtual
5071ae08745Sheppo 	 * coloring taken into consideration.
5081ae08745Sheppo 	 */
5091ae08745Sheppo 	pp_consistent_coloring = 0;
5101ae08745Sheppo 
5111ae08745Sheppo 	/*
5121ae08745Sheppo 	 * The kpm mapping window.
5131ae08745Sheppo 	 * kpm_size:
5141ae08745Sheppo 	 *	The size of a single kpm range.
5151ae08745Sheppo 	 *	The overall size will be: kpm_size * vac_colors.
5161ae08745Sheppo 	 * kpm_vbase:
5171ae08745Sheppo 	 *	The virtual start address of the kpm range within the kernel
5181ae08745Sheppo 	 *	virtual address space. kpm_vbase has to be kpm_size aligned.
5191ae08745Sheppo 	 */
5201ae08745Sheppo 
5211ae08745Sheppo 	/*
5221ae08745Sheppo 	 * Make kpm_vbase, kpm_size aligned to kpm_size_shift.
5231ae08745Sheppo 	 * To do this find the nearest power of 2 size that the
5241ae08745Sheppo 	 * actual ra_limit fits within.
5251ae08745Sheppo 	 * If it is an even power of two use that, otherwise use the
5261ae08745Sheppo 	 * next power of two larger than ra_limit.
5271ae08745Sheppo 	 */
5281ae08745Sheppo 
5291ae08745Sheppo 	ASSERT(ra_limit != 0);
5301ae08745Sheppo 
5311ae08745Sheppo 	kpm_size_shift = (ra_limit & (ra_limit - 1)) != 0 ?
532ad8d2eb8Szx 	    highbit(ra_limit) : highbit(ra_limit) - 1;
5331ae08745Sheppo 
5341ae08745Sheppo 	/*
5351ae08745Sheppo 	 * No virtual caches on sun4v so size matches size shift
5361ae08745Sheppo 	 */
5371ae08745Sheppo 	kpm_size = 1ul << kpm_size_shift;
5381ae08745Sheppo 
5391ae08745Sheppo 	if (va_bits < VA_ADDRESS_SPACE_BITS) {
5407c478bd9Sstevel@tonic-gate 		/*
5411ae08745Sheppo 		 * In case of VA hole
5421ae08745Sheppo 		 * kpm_base = hole_end + 1TB
5431ae08745Sheppo 		 * Starting 1TB beyond where VA hole ends because on Niagara
5441ae08745Sheppo 		 * processor software must not use pages within 4GB of the
5451ae08745Sheppo 		 * VA hole as instruction pages to avoid problems with
5461ae08745Sheppo 		 * prefetching into the VA hole.
5477c478bd9Sstevel@tonic-gate 		 */
5481ae08745Sheppo 		kpm_vbase = (caddr_t)((0ull - (1ull << (va_bits - 1))) +
5491ae08745Sheppo 		    (1ull << 40));
5501ae08745Sheppo 	} else {		/* Number of VA bits 64 ... no VA hole */
5511ae08745Sheppo 		kpm_vbase = (caddr_t)0x8000000000000000ull;	/* 8 EB */
5527c478bd9Sstevel@tonic-gate 	}
5531ae08745Sheppo 
5541ae08745Sheppo 	/*
5551ae08745Sheppo 	 * The traptrace code uses either %tick or %stick for
5561ae08745Sheppo 	 * timestamping.  The sun4v require use of %stick.
5571ae08745Sheppo 	 */
5581ae08745Sheppo 	traptrace_use_stick = 1;
5597c478bd9Sstevel@tonic-gate }
5607c478bd9Sstevel@tonic-gate 
5611ae08745Sheppo /*
5621ae08745Sheppo  * Get the nctxs from MD. If absent panic.
5631ae08745Sheppo  */
5641ae08745Sheppo static uint64_t
5651ae08745Sheppo get_mmu_ctx_bits(md_t *mdp, mde_cookie_t cpu_node_cookie)
5667c478bd9Sstevel@tonic-gate {
5671ae08745Sheppo 	uint64_t ctx_bits;
5687c478bd9Sstevel@tonic-gate 
5691ae08745Sheppo 	if (md_get_prop_val(mdp, cpu_node_cookie, "mmu-#context-bits",
5701ae08745Sheppo 	    &ctx_bits))
5711ae08745Sheppo 		ctx_bits = 0;
5727c478bd9Sstevel@tonic-gate 
5731ae08745Sheppo 	if (ctx_bits < MIN_NCTXS_BITS || ctx_bits > MAX_NCTXS_BITS)
5741ae08745Sheppo 		cmn_err(CE_PANIC, "Incorrect %ld number of contexts bits "
5751ae08745Sheppo 		    "returned by MD", ctx_bits);
5767c478bd9Sstevel@tonic-gate 
5771ae08745Sheppo 	return (ctx_bits);
5781ae08745Sheppo }
5797c478bd9Sstevel@tonic-gate 
58005d3dc4bSpaulsan /*
58105d3dc4bSpaulsan  * Get the number of tsbs from MD. If absent the default value is 0.
58205d3dc4bSpaulsan  */
58305d3dc4bSpaulsan static uint64_t
58405d3dc4bSpaulsan get_mmu_tsbs(md_t *mdp, mde_cookie_t cpu_node_cookie)
58505d3dc4bSpaulsan {
58605d3dc4bSpaulsan 	uint64_t number_tsbs;
58705d3dc4bSpaulsan 
58805d3dc4bSpaulsan 	if (md_get_prop_val(mdp, cpu_node_cookie, "mmu-max-#tsbs",
58905d3dc4bSpaulsan 	    &number_tsbs))
59005d3dc4bSpaulsan 		number_tsbs = 0;
59105d3dc4bSpaulsan 
59205d3dc4bSpaulsan 	return (number_tsbs);
59305d3dc4bSpaulsan }
59405d3dc4bSpaulsan 
59505d3dc4bSpaulsan /*
5967dacfc44Spaulsan  * Get the number of shared contexts from MD. If absent the default value is 0.
59705d3dc4bSpaulsan  *
59805d3dc4bSpaulsan  */
59905d3dc4bSpaulsan static uint64_t
60005d3dc4bSpaulsan get_mmu_shcontexts(md_t *mdp, mde_cookie_t cpu_node_cookie)
60105d3dc4bSpaulsan {
60205d3dc4bSpaulsan 	uint64_t number_contexts;
60305d3dc4bSpaulsan 
60405d3dc4bSpaulsan 	if (md_get_prop_val(mdp, cpu_node_cookie, "mmu-#shared-contexts",
60505d3dc4bSpaulsan 	    &number_contexts))
60605d3dc4bSpaulsan 		number_contexts = 0;
60705d3dc4bSpaulsan 
60805d3dc4bSpaulsan 	return (number_contexts);
60905d3dc4bSpaulsan }
61005d3dc4bSpaulsan 
6111ae08745Sheppo /*
6121ae08745Sheppo  * Initalize supported page sizes information.
6131ae08745Sheppo  * Set to 0, if the page sizes mask information is absent in MD.
6141ae08745Sheppo  */
6151ae08745Sheppo static uint64_t
6161ae08745Sheppo get_cpu_pagesizes(md_t *mdp, mde_cookie_t cpu_node_cookie)
6171ae08745Sheppo {
6181ae08745Sheppo 	uint64_t mmu_page_size_list;
6197c478bd9Sstevel@tonic-gate 
6201ae08745Sheppo 	if (md_get_prop_val(mdp, cpu_node_cookie, "mmu-page-size-list",
6211ae08745Sheppo 	    &mmu_page_size_list))
6221ae08745Sheppo 		mmu_page_size_list = 0;
6231ae08745Sheppo 
6241ae08745Sheppo 	if (mmu_page_size_list == 0 || mmu_page_size_list > MAX_PAGESIZE_MASK)
6251ae08745Sheppo 		cmn_err(CE_PANIC, "Incorrect 0x%lx pagesize mask returned"
6261ae08745Sheppo 		    "by MD", mmu_page_size_list);
6271ae08745Sheppo 
6281ae08745Sheppo 	return (mmu_page_size_list);
6291ae08745Sheppo }
6301ae08745Sheppo 
6311ae08745Sheppo /*
6321ae08745Sheppo  * This routine gets the isalist information from MD and appends
6331ae08745Sheppo  * the CPU module ISA set if required.
6341ae08745Sheppo  */
6351ae08745Sheppo static char *
6361ae08745Sheppo construct_isalist(md_t *mdp, mde_cookie_t cpu_node_cookie,
6371ae08745Sheppo     char **cpu_module_isa_set)
6381ae08745Sheppo {
6391ae08745Sheppo 	extern int at_flags;
6401ae08745Sheppo 	char *md_isalist;
6411ae08745Sheppo 	int md_isalen;
6421ae08745Sheppo 	char *isabuf;
6431ae08745Sheppo 	int isalen;
6441ae08745Sheppo 	char **isa_set;
6451ae08745Sheppo 	char *p, *q;
6461ae08745Sheppo 	int cpu_module_isalen = 0, found = 0;
6471ae08745Sheppo 
6481ae08745Sheppo 	(void) md_get_prop_data(mdp, cpu_node_cookie,
6491ae08745Sheppo 	    "isalist", (uint8_t **)&isabuf, &isalen);
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	/*
6521ae08745Sheppo 	 * We support binaries for all the cpus that have shipped so far.
6531ae08745Sheppo 	 * The kernel emulates instructions that are not supported by hardware.
6547c478bd9Sstevel@tonic-gate 	 */
6551ae08745Sheppo 	at_flags = EF_SPARC_SUN_US3 | EF_SPARC_32PLUS | EF_SPARC_SUN_US1;
6567c478bd9Sstevel@tonic-gate 
6571ae08745Sheppo 	/*
6581ae08745Sheppo 	 * Construct the space separated isa_list.
6591ae08745Sheppo 	 */
6601ae08745Sheppo 	if (cpu_module_isa_set != NULL) {
6611ae08745Sheppo 		for (isa_set = cpu_module_isa_set; *isa_set != NULL;
6621ae08745Sheppo 		    isa_set++) {
6631ae08745Sheppo 			cpu_module_isalen += strlen(*isa_set);
6641ae08745Sheppo 			cpu_module_isalen++;	/* for space character */
6651ae08745Sheppo 		}
6661ae08745Sheppo 	}
6677c478bd9Sstevel@tonic-gate 
6681ae08745Sheppo 	/*
6691ae08745Sheppo 	 * Allocate the buffer of MD isa buffer length + CPU module
6701ae08745Sheppo 	 * isa buffer length.
6711ae08745Sheppo 	 */
6721ae08745Sheppo 	md_isalen = isalen + cpu_module_isalen + 2;
6731ae08745Sheppo 	md_isalist = (char *)prom_alloc((caddr_t)0, md_isalen, 0);
6741ae08745Sheppo 	if (md_isalist == NULL)
6751ae08745Sheppo 		cmn_err(CE_PANIC, "construct_isalist: Allocation failed for "
6761ae08745Sheppo 		    "md_isalist");
6771ae08745Sheppo 
6781ae08745Sheppo 	md_isalist[0] = '\0'; /* create an empty string to start */
6791ae08745Sheppo 	for (p = isabuf, q = p + isalen; p < q; p += strlen(p) + 1) {
6801ae08745Sheppo 		(void) strlcat(md_isalist, p, md_isalen);
6811ae08745Sheppo 		(void) strcat(md_isalist, " ");
6821ae08745Sheppo 	}
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	/*
6851ae08745Sheppo 	 * Check if the isa_set is present in isalist returned by MD.
6861ae08745Sheppo 	 * If yes, then no need to append it, if no then append it to
6871ae08745Sheppo 	 * isalist returned by MD.
6887c478bd9Sstevel@tonic-gate 	 */
6891ae08745Sheppo 	if (cpu_module_isa_set != NULL) {
6901ae08745Sheppo 		for (isa_set = cpu_module_isa_set; *isa_set != NULL;
6911ae08745Sheppo 		    isa_set++) {
6921ae08745Sheppo 			found = 0;
6931ae08745Sheppo 			for (p = isabuf, q = p + isalen; p < q;
6941ae08745Sheppo 			    p += strlen(p) + 1) {
6951ae08745Sheppo 				if (strcmp(p, *isa_set) == 0) {
6961ae08745Sheppo 					found = 1;
6971ae08745Sheppo 					break;
6981ae08745Sheppo 				}
6991ae08745Sheppo 			}
7001ae08745Sheppo 			if (!found) {
7011ae08745Sheppo 				(void) strlcat(md_isalist, *isa_set, md_isalen);
7021ae08745Sheppo 				(void) strcat(md_isalist, " ");
7031ae08745Sheppo 			}
7041ae08745Sheppo 		}
7051ae08745Sheppo 	}
7061ae08745Sheppo 
7071ae08745Sheppo 	/* Get rid of any trailing white spaces */
7081ae08745Sheppo 	md_isalist[strlen(md_isalist) - 1] = '\0';
7091ae08745Sheppo 
7101ae08745Sheppo 	return (md_isalist);
7117c478bd9Sstevel@tonic-gate }
7127c478bd9Sstevel@tonic-gate 
7132f0fcb93SJason Beloro static void
7142f0fcb93SJason Beloro get_hwcaps(md_t *mdp, mde_cookie_t cpu_node_cookie)
7152f0fcb93SJason Beloro {
7162f0fcb93SJason Beloro 	char *hwcapbuf;
7172f0fcb93SJason Beloro 	int hwcaplen;
7182f0fcb93SJason Beloro 
7192f0fcb93SJason Beloro 	if (md_get_prop_data(mdp, cpu_node_cookie,
7202f0fcb93SJason Beloro 	    "hwcap-list", (uint8_t **)&hwcapbuf, &hwcaplen)) {
7212f0fcb93SJason Beloro 		/* Property not found */
7222f0fcb93SJason Beloro 		return;
7232f0fcb93SJason Beloro 	}
7242f0fcb93SJason Beloro 
7252f0fcb93SJason Beloro 	cpu_hwcap_flags |= names2bits(hwcapbuf, hwcaplen, FMT_AV_SPARC,
7262f0fcb93SJason Beloro 	    "unrecognized token: %s");
7272f0fcb93SJason Beloro }
7282f0fcb93SJason Beloro 
7292c5124a1SPrashanth Sreenivasa static void
7302c5124a1SPrashanth Sreenivasa get_weakest_mem_model(md_t *mdp, mde_cookie_t cpu_node_cookie)
7312c5124a1SPrashanth Sreenivasa {
7322c5124a1SPrashanth Sreenivasa 	char *mmbuf;
7332c5124a1SPrashanth Sreenivasa 	int mmlen;
7342c5124a1SPrashanth Sreenivasa 	uint_t wmm;
7352c5124a1SPrashanth Sreenivasa 	char *p, *q;
7362c5124a1SPrashanth Sreenivasa 
7372c5124a1SPrashanth Sreenivasa 	if (md_get_prop_data(mdp, cpu_node_cookie,
7382c5124a1SPrashanth Sreenivasa 	    "memory-model-list", (uint8_t **)&mmbuf, &mmlen)) {
7392c5124a1SPrashanth Sreenivasa 		/* Property not found */
7402c5124a1SPrashanth Sreenivasa 		return;
7412c5124a1SPrashanth Sreenivasa 	}
7422c5124a1SPrashanth Sreenivasa 
7432c5124a1SPrashanth Sreenivasa 	wmm = TSTATE_MM_TSO;
7442c5124a1SPrashanth Sreenivasa 	for (p = mmbuf, q = p + mmlen; p < q; p += strlen(p) + 1) {
7452c5124a1SPrashanth Sreenivasa 		if (strcmp(p, "wc") == 0)
7462c5124a1SPrashanth Sreenivasa 			wmm = TSTATE_MM_WC;
7472c5124a1SPrashanth Sreenivasa 	}
7482c5124a1SPrashanth Sreenivasa 	weakest_mem_model = wmm;
7492c5124a1SPrashanth Sreenivasa }
7502f0fcb93SJason Beloro 
7512f0fcb93SJason Beloro /*
7522f0fcb93SJason Beloro  * Does the opposite of cmn_err(9f) "%b" conversion specification:
7532f0fcb93SJason Beloro  * Given a list of strings, converts them to a bit-vector.
7542f0fcb93SJason Beloro  *
7552f0fcb93SJason Beloro  *  tokens - is a buffer of [NUL-terminated] strings.
7562f0fcb93SJason Beloro  *  tokenslen - length of tokenbuf in bytes.
7572f0fcb93SJason Beloro  *  bit_formatter - is a %b format string, such as FMT_AV_SPARC
7582f0fcb93SJason Beloro  *    from /usr/include/sys/auxv_SPARC.h, of the form:
7592f0fcb93SJason Beloro  *    <base-char>[<bit-char><token-string>]...
7602f0fcb93SJason Beloro  *        <base-char> is ignored.
7612f0fcb93SJason Beloro  *        <bit-char>  is [1-32], as per cmn_err(9f).
7622f0fcb93SJason Beloro  *  warning - is a printf-style format string containing "%s",
7632f0fcb93SJason Beloro  *    which is used to print a warning message when an unrecognized
7642f0fcb93SJason Beloro  *    token is found.  If warning is NULL, no warning is printed.
7652f0fcb93SJason Beloro  * Returns a bit-vector corresponding to the specified tokens.
7662f0fcb93SJason Beloro  */
7672f0fcb93SJason Beloro 
7682f0fcb93SJason Beloro static unsigned long
7692f0fcb93SJason Beloro names2bits(char *tokens, size_t tokenslen, char *bit_formatter, char *warning)
7702f0fcb93SJason Beloro {
7712f0fcb93SJason Beloro 	char *cur;
7722f0fcb93SJason Beloro 	size_t  curlen;
7732f0fcb93SJason Beloro 	unsigned long ul = 0;
7742f0fcb93SJason Beloro 	char *hit;
7752f0fcb93SJason Beloro 	char *bs;
7762f0fcb93SJason Beloro 
7772f0fcb93SJason Beloro 	bit_formatter++;	/* skip base; not needed for input */
7782f0fcb93SJason Beloro 	cur = tokens;
7792f0fcb93SJason Beloro 	while (tokenslen) {
7802f0fcb93SJason Beloro 		curlen = strlen(cur);
7812f0fcb93SJason Beloro 		bs = bit_formatter;
7822f0fcb93SJason Beloro 		/*
7832f0fcb93SJason Beloro 		 * We need a complicated while loop and the >=32 check,
7842f0fcb93SJason Beloro 		 * instead of a simple "if (strstr())" so that when the
7852f0fcb93SJason Beloro 		 * token is "vis", we don't match on "vis2" (for example).
7862f0fcb93SJason Beloro 		 */
7872f0fcb93SJason Beloro 		/* LINTED E_EQUALITY_NOT_ASSIGNMENT */
7882f0fcb93SJason Beloro 		while ((hit = strstr(bs, cur)) &&
7892f0fcb93SJason Beloro 		    *(hit + curlen) >= 32) {
7902f0fcb93SJason Beloro 			/*
7912f0fcb93SJason Beloro 			 * We're still in the middle of a word, i.e., not
7922f0fcb93SJason Beloro 			 * pointing at a <bit-char>.  So advance ptr
7932f0fcb93SJason Beloro 			 * to ensure forward progress.
7942f0fcb93SJason Beloro 			 */
7952f0fcb93SJason Beloro 			bs = hit + curlen + 1;
7962f0fcb93SJason Beloro 		}
7972f0fcb93SJason Beloro 
7982f0fcb93SJason Beloro 		if (hit != NULL) {
7992f0fcb93SJason Beloro 			ul |= (1<<(*(hit-1) - 1));
8002f0fcb93SJason Beloro 		} else {
8012f0fcb93SJason Beloro 			/* The token wasn't found in bit_formatter */
8022f0fcb93SJason Beloro 			if (warning != NULL)
8032f0fcb93SJason Beloro 				cmn_err(CE_WARN, warning, cur);
8042f0fcb93SJason Beloro 		}
8052f0fcb93SJason Beloro 		tokenslen -= curlen + 1;
8062f0fcb93SJason Beloro 		cur += curlen + 1;
8072f0fcb93SJason Beloro 	}
8082f0fcb93SJason Beloro 	return (ul);
8092f0fcb93SJason Beloro }
8102f0fcb93SJason Beloro 
8111ae08745Sheppo uint64_t
812*9853d9e8SJason Beloro get_ra_limit(md_t *mdp, mde_cookie_t cpu_node_cookie)
8131ae08745Sheppo {
814*9853d9e8SJason Beloro 	extern int ppvm_enable;
815*9853d9e8SJason Beloro 	extern int meta_alloc_enable;
8161ae08745Sheppo 	mde_cookie_t *mem_list;
8171ae08745Sheppo 	mde_cookie_t *mblock_list;
8181ae08745Sheppo 	int i;
8191ae08745Sheppo 	int memnodes;
8201ae08745Sheppo 	int nmblock;
821*9853d9e8SJason Beloro 	uint64_t r;
8221ae08745Sheppo 	uint64_t base;
8231ae08745Sheppo 	uint64_t size;
8241ae08745Sheppo 	uint64_t ra_limit = 0, new_limit = 0;
8251ae08745Sheppo 
826*9853d9e8SJason Beloro 	if (md_get_prop_val(mdp, cpu_node_cookie, "mmu-#ra-bits", &r) == 0) {
827*9853d9e8SJason Beloro 		if (r == 0 || r > RA_ADDRESS_SPACE_BITS)
828*9853d9e8SJason Beloro 			cmn_err(CE_PANIC, "Incorrect number of ra bits in MD");
829*9853d9e8SJason Beloro 		else {
830*9853d9e8SJason Beloro 			/*
831*9853d9e8SJason Beloro 			 * Enable memory DR and metadata (page_t)
832*9853d9e8SJason Beloro 			 * allocation from existing memory.
833*9853d9e8SJason Beloro 			 */
834*9853d9e8SJason Beloro 			ppvm_enable = 1;
835*9853d9e8SJason Beloro 			meta_alloc_enable = 1;
836*9853d9e8SJason Beloro 			return (1ULL << r);
837*9853d9e8SJason Beloro 		}
838*9853d9e8SJason Beloro 	}
839*9853d9e8SJason Beloro 
840*9853d9e8SJason Beloro 	cmn_err(CE_WARN, "mmu-#ra-bits property not found in MD");
841*9853d9e8SJason Beloro 	cmn_err(CE_WARN, "Memory DR disabled");
842*9853d9e8SJason Beloro 
8431ae08745Sheppo 	memnodes = md_alloc_scan_dag(mdp,
8441ae08745Sheppo 	    md_root_node(mdp), "memory", "fwd", &mem_list);
8451ae08745Sheppo 
8461ae08745Sheppo 	ASSERT(memnodes == 1);
8471ae08745Sheppo 
8481ae08745Sheppo 	nmblock = md_alloc_scan_dag(mdp,
8491ae08745Sheppo 	    mem_list[0], "mblock", "fwd", &mblock_list);
8501ae08745Sheppo 	if (nmblock < 1)
8511ae08745Sheppo 		cmn_err(CE_PANIC, "cannot find mblock nodes in MD");
8521ae08745Sheppo 
8531ae08745Sheppo 	for (i = 0; i < nmblock; i++) {
8541ae08745Sheppo 		if (md_get_prop_val(mdp, mblock_list[i], "base", &base))
8551ae08745Sheppo 			cmn_err(CE_PANIC, "base property missing from MD"
8561ae08745Sheppo 			    " mblock node");
8571ae08745Sheppo 		if (md_get_prop_val(mdp, mblock_list[i], "size", &size))
8581ae08745Sheppo 			cmn_err(CE_PANIC, "size property missing from MD"
8591ae08745Sheppo 			    " mblock node");
8601ae08745Sheppo 
8611ae08745Sheppo 		ASSERT(size != 0);
8621ae08745Sheppo 
8631ae08745Sheppo 		new_limit = base + size;
8641ae08745Sheppo 
8651ae08745Sheppo 		if (base > new_limit)
8661ae08745Sheppo 			cmn_err(CE_PANIC, "mblock in MD wrapped around");
8671ae08745Sheppo 
8681ae08745Sheppo 		if (new_limit > ra_limit)
869ad8d2eb8Szx 			ra_limit = new_limit;
8701ae08745Sheppo 	}
8711ae08745Sheppo 
8721ae08745Sheppo 	ASSERT(ra_limit != 0);
8731ae08745Sheppo 
8741ae08745Sheppo 	if (ra_limit > MAX_REAL_ADDRESS) {
8751ae08745Sheppo 		cmn_err(CE_WARN, "Highest real address in MD too large"
8761ae08745Sheppo 		    " clipping to %llx\n", MAX_REAL_ADDRESS);
8771ae08745Sheppo 		ra_limit = MAX_REAL_ADDRESS;
8781ae08745Sheppo 	}
8791ae08745Sheppo 
8801ae08745Sheppo 	md_free_scan_dag(mdp, &mblock_list);
8811ae08745Sheppo 
8821ae08745Sheppo 	md_free_scan_dag(mdp, &mem_list);
8831ae08745Sheppo 
8841ae08745Sheppo 	return (ra_limit);
8851ae08745Sheppo }
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate /*
8881ae08745Sheppo  * This routine sets the globals for CPU and DEV mondo queue entries and
8891ae08745Sheppo  * resumable and non-resumable error queue entries.
8904bac2208Snarayan  *
8914bac2208Snarayan  * First, look up the number of bits available to pass an entry number.
8924bac2208Snarayan  * This can vary by platform and may result in allocating an unreasonably
8934bac2208Snarayan  * (or impossibly) large amount of memory for the corresponding table,
894d5e8e65eSdavemq  * so we clamp it by 'max_entries'.  Finally, since the q size is used when
895d5e8e65eSdavemq  * calling contig_mem_alloc(), which expects a power of 2, clamp the q size
896d5e8e65eSdavemq  * down to a power of 2.  If the prop is missing, use 'default_entries'.
8977c478bd9Sstevel@tonic-gate  */
8981ae08745Sheppo static uint64_t
8991ae08745Sheppo get_single_q_size(md_t *mdp, mde_cookie_t cpu_node_cookie,
9004bac2208Snarayan     char *qnamep, uint64_t default_entries, uint64_t max_entries)
9011ae08745Sheppo {
9021ae08745Sheppo 	uint64_t entries;
9031ae08745Sheppo 
9044bac2208Snarayan 	if (default_entries > max_entries)
9054bac2208Snarayan 		cmn_err(CE_CONT, "!get_single_q_size: dflt %ld > "
9064bac2208Snarayan 		    "max %ld for %s\n", default_entries, max_entries, qnamep);
9074bac2208Snarayan 
9081ae08745Sheppo 	if (md_get_prop_val(mdp, cpu_node_cookie, qnamep, &entries)) {
9091ae08745Sheppo 		if (!broken_md_flag)
9101ae08745Sheppo 			cmn_err(CE_PANIC, "Missing %s property in MD cpu node",
911ad8d2eb8Szx 			    qnamep);
9121ae08745Sheppo 		entries = default_entries;
9131ae08745Sheppo 	} else {
9141ae08745Sheppo 		entries = 1 << entries;
9151ae08745Sheppo 	}
9164bac2208Snarayan 
9174bac2208Snarayan 	entries = MIN(entries, max_entries);
918d5e8e65eSdavemq 	/* If not a power of 2, truncate to a power of 2. */
919d5e8e65eSdavemq 	if ((entries & (entries - 1)) != 0) {
920d5e8e65eSdavemq 		entries = 1 << (highbit(entries) - 1);
921d5e8e65eSdavemq 	}
9224bac2208Snarayan 
9231ae08745Sheppo 	return (entries);
9241ae08745Sheppo }
9251ae08745Sheppo 
9264bac2208Snarayan /* Scaling constant used to compute size of cpu mondo queue */
9274bac2208Snarayan #define	CPU_MONDO_Q_MULTIPLIER	8
9281ae08745Sheppo 
9297c478bd9Sstevel@tonic-gate static void
9301ae08745Sheppo get_q_sizes(md_t *mdp, mde_cookie_t cpu_node_cookie)
9317c478bd9Sstevel@tonic-gate {
9324bac2208Snarayan 	uint64_t max_qsize;
9334bac2208Snarayan 	mde_cookie_t *platlist;
9344bac2208Snarayan 	int nrnode;
9354bac2208Snarayan 
9364bac2208Snarayan 	/*
9374bac2208Snarayan 	 * Compute the maximum number of entries for the cpu mondo queue.
9384bac2208Snarayan 	 * Use the appropriate property in the platform node, if it is
9394bac2208Snarayan 	 * available.  Else, base it on NCPU.
9404bac2208Snarayan 	 */
9414bac2208Snarayan 	nrnode = md_alloc_scan_dag(mdp,
9424bac2208Snarayan 	    md_root_node(mdp), "platform", "fwd", &platlist);
9434bac2208Snarayan 
9444bac2208Snarayan 	ASSERT(nrnode == 1);
9454bac2208Snarayan 
946aaa10e67Sha 	ncpu_guest_max = NCPU;
947aaa10e67Sha 	(void) md_get_prop_val(mdp, platlist[0], "max-cpus", &ncpu_guest_max);
948aaa10e67Sha 	max_qsize = ncpu_guest_max * CPU_MONDO_Q_MULTIPLIER;
9494bac2208Snarayan 
9504bac2208Snarayan 	md_free_scan_dag(mdp, &platlist);
9514bac2208Snarayan 
9521ae08745Sheppo 	cpu_q_entries = get_single_q_size(mdp, cpu_node_cookie,
9534bac2208Snarayan 	    "q-cpu-mondo-#bits", DEFAULT_CPU_Q_ENTRIES, max_qsize);
9541ae08745Sheppo 
9551ae08745Sheppo 	dev_q_entries = get_single_q_size(mdp, cpu_node_cookie,
956b0fc0e77Sgovinda 	    "q-dev-mondo-#bits", DEFAULT_DEV_Q_ENTRIES, MAXIVNUM);
9571ae08745Sheppo 
9581ae08745Sheppo 	cpu_rq_entries = get_single_q_size(mdp, cpu_node_cookie,
9594bac2208Snarayan 	    "q-resumable-#bits", CPU_RQ_ENTRIES, MAX_CPU_RQ_ENTRIES);
9601ae08745Sheppo 
9611ae08745Sheppo 	cpu_nrq_entries = get_single_q_size(mdp, cpu_node_cookie,
9624bac2208Snarayan 	    "q-nonresumable-#bits", CPU_NRQ_ENTRIES, MAX_CPU_NRQ_ENTRIES);
9631ae08745Sheppo }
9641ae08745Sheppo 
9651ae08745Sheppo 
9661ae08745Sheppo static void
9671ae08745Sheppo get_va_bits(md_t *mdp, mde_cookie_t cpu_node_cookie)
9681ae08745Sheppo {
9691ae08745Sheppo 	uint64_t value = VA_ADDRESS_SPACE_BITS;
9701ae08745Sheppo 
9711ae08745Sheppo 	if (md_get_prop_val(mdp, cpu_node_cookie, "mmu-#va-bits", &value))
9721ae08745Sheppo 		cmn_err(CE_PANIC, "mmu-#va-bits property  not found in MD");
9737c478bd9Sstevel@tonic-gate 
9747c478bd9Sstevel@tonic-gate 
9751ae08745Sheppo 	if (value == 0 || value > VA_ADDRESS_SPACE_BITS)
9761ae08745Sheppo 		cmn_err(CE_PANIC, "Incorrect number of va bits in MD");
9777c478bd9Sstevel@tonic-gate 
9781ae08745Sheppo 	/* Do not expect number of VA bits to be more than 32-bit quantity */
9797c478bd9Sstevel@tonic-gate 
9801ae08745Sheppo 	va_bits = (int)value;
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 	/*
9831ae08745Sheppo 	 * Correct the value for VA bits on UltraSPARC-T1 based systems
9841ae08745Sheppo 	 * in case of broken MD.
9857c478bd9Sstevel@tonic-gate 	 */
9861ae08745Sheppo 	if (broken_md_flag)
9871ae08745Sheppo 		va_bits = DEFAULT_VA_ADDRESS_SPACE_BITS;
9887c478bd9Sstevel@tonic-gate }
9897c478bd9Sstevel@tonic-gate 
990575a7426Spt int
991575a7426Spt l2_cache_node_count(void)
992575a7426Spt {
993575a7426Spt 	return (n_l2_caches);
994575a7426Spt }
995575a7426Spt 
996575a7426Spt /*
997575a7426Spt  * count the number of l2 caches.
998575a7426Spt  */
999575a7426Spt int
1000575a7426Spt get_l2_cache_node_count(md_t *mdp)
1001575a7426Spt {
1002575a7426Spt 	int i;
1003575a7426Spt 	mde_cookie_t *cachenodes;
1004575a7426Spt 	uint64_t level;
1005575a7426Spt 	int n_cachenodes = md_alloc_scan_dag(mdp, md_root_node(mdp),
1006575a7426Spt 	    "cache", "fwd", &cachenodes);
1007575a7426Spt 	int l2_caches = 0;
1008575a7426Spt 
1009575a7426Spt 	for (i = 0; i < n_cachenodes; i++) {
1010575a7426Spt 		if (md_get_prop_val(mdp, cachenodes[i], "level", &level) != 0) {
1011575a7426Spt 			level = 0;
1012575a7426Spt 		}
1013575a7426Spt 		if (level == 2) {
1014575a7426Spt 			l2_caches++;
1015575a7426Spt 		}
1016575a7426Spt 	}
1017575a7426Spt 	md_free_scan_dag(mdp, &cachenodes);
1018575a7426Spt 	return (l2_caches);
1019575a7426Spt }
1020575a7426Spt 
10211ae08745Sheppo /*
10221ae08745Sheppo  * This routine returns the L2 cache information such as -- associativity,
10231ae08745Sheppo  * size and linesize.
10241ae08745Sheppo  */
10251ae08745Sheppo static int
10261ae08745Sheppo get_l2_cache_info(md_t *mdp, mde_cookie_t cpu_node_cookie,
10271ae08745Sheppo 	    uint64_t *associativity, uint64_t *size, uint64_t *linesize)
10281ae08745Sheppo {
10291ae08745Sheppo 	mde_cookie_t *cachelist;
10301ae08745Sheppo 	int ncaches, i;
1031f5db7437Sae 	uint64_t cache_level = 0;
10321ae08745Sheppo 
10331ae08745Sheppo 	ncaches = md_alloc_scan_dag(mdp, cpu_node_cookie, "cache",
10341ae08745Sheppo 	    "fwd", &cachelist);
10351ae08745Sheppo 	/*
10361ae08745Sheppo 	 * The "cache" node is optional in MD, therefore ncaches can be 0.
10371ae08745Sheppo 	 */
10381ae08745Sheppo 	if (ncaches < 1) {
10391ae08745Sheppo 		return (0);
10401ae08745Sheppo 	}
10411ae08745Sheppo 
10421ae08745Sheppo 	for (i = 0; i < ncaches; i++) {
10431ae08745Sheppo 		uint64_t local_assoc;
10441ae08745Sheppo 		uint64_t local_size;
10451ae08745Sheppo 		uint64_t local_lsize;
10461ae08745Sheppo 
10471ae08745Sheppo 		if (md_get_prop_val(mdp, cachelist[i], "level", &cache_level))
10481ae08745Sheppo 			continue;
10491ae08745Sheppo 
1050f5db7437Sae 		if (cache_level != 2) continue;
10511ae08745Sheppo 
10521ae08745Sheppo 		/* If properties are missing from this cache ignore it */
10531ae08745Sheppo 
10541ae08745Sheppo 		if ((md_get_prop_val(mdp, cachelist[i],
10551ae08745Sheppo 		    "associativity", &local_assoc))) {
10561ae08745Sheppo 			continue;
10571ae08745Sheppo 		}
10581ae08745Sheppo 
10591ae08745Sheppo 		if ((md_get_prop_val(mdp, cachelist[i],
10601ae08745Sheppo 		    "size", &local_size))) {
10611ae08745Sheppo 			continue;
10621ae08745Sheppo 		}
10631ae08745Sheppo 
10641ae08745Sheppo 		if ((md_get_prop_val(mdp, cachelist[i],
10651ae08745Sheppo 		    "line-size", &local_lsize))) {
10661ae08745Sheppo 			continue;
10671ae08745Sheppo 		}
10681ae08745Sheppo 
10691ae08745Sheppo 		*associativity = local_assoc;
10701ae08745Sheppo 		*size = local_size;
10711ae08745Sheppo 		*linesize = local_lsize;
1072f5db7437Sae 		break;
10731ae08745Sheppo 	}
10747c478bd9Sstevel@tonic-gate 
10751ae08745Sheppo 	md_free_scan_dag(mdp, &cachelist);
10761ae08745Sheppo 
1077f5db7437Sae 	return ((cache_level == 2) ? 1 : 0);
10781ae08745Sheppo }
10791ae08745Sheppo 
10804bac2208Snarayan 
10811ae08745Sheppo /*
10824bac2208Snarayan  * Set the broken_md_flag to 1 if the MD doesn't have
10834bac2208Snarayan  * the domaining-enabled property in the platform node and the
10844bac2208Snarayan  * platform uses the UltraSPARC-T1 cpu. This flag is used to
10854bac2208Snarayan  * workaround some of the incorrect MD properties.
10861ae08745Sheppo  */
10871ae08745Sheppo static void
10884bac2208Snarayan init_md_broken(md_t *mdp, mde_cookie_t *cpulist)
10897c478bd9Sstevel@tonic-gate {
10901ae08745Sheppo 	int nrnode;
10911ae08745Sheppo 	mde_cookie_t *platlist, rootnode;
10921ae08745Sheppo 	uint64_t val = 0;
10934bac2208Snarayan 	char *namebuf;
10944bac2208Snarayan 	int namelen;
10951ae08745Sheppo 
10961ae08745Sheppo 	rootnode = md_root_node(mdp);
10971ae08745Sheppo 	ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE);
10984bac2208Snarayan 	ASSERT(cpulist);
10991ae08745Sheppo 
11004bac2208Snarayan 	nrnode = md_alloc_scan_dag(mdp, rootnode, "platform", "fwd",
11011ae08745Sheppo 	    &platlist);
11021ae08745Sheppo 
1103f273041fSjm 	if (nrnode < 1)
1104f273041fSjm 		cmn_err(CE_PANIC, "init_md_broken: platform node missing");
11051ae08745Sheppo 
11064bac2208Snarayan 	if (md_get_prop_data(mdp, cpulist[0],
11074bac2208Snarayan 	    "compatible", (uint8_t **)&namebuf, &namelen)) {
11084bac2208Snarayan 		cmn_err(CE_PANIC, "init_md_broken: "
11094bac2208Snarayan 		    "Cannot read 'compatible' property of 'cpu' node");
11104bac2208Snarayan 	}
11117c478bd9Sstevel@tonic-gate 
11124bac2208Snarayan 	if (md_get_prop_val(mdp, platlist[0],
1113ad8d2eb8Szx 	    "domaining-enabled", &val) == -1 &&
11144bac2208Snarayan 	    strcmp(namebuf, "SUNW,UltraSPARC-T1") == 0)
11151ae08745Sheppo 		broken_md_flag = 1;
11161ae08745Sheppo 
11171ae08745Sheppo 	md_free_scan_dag(mdp, &platlist);
11187c478bd9Sstevel@tonic-gate }
1119125be069SJason Beloro 
1120125be069SJason Beloro /*
1121125be069SJason Beloro  * This routine gets the MD properties associated with the TLB search order API
1122125be069SJason Beloro  * and compares these against the expected values for a processor which supports
1123125be069SJason Beloro  * this API. The return value is used to determine whether use the API.
1124125be069SJason Beloro  */
1125125be069SJason Beloro static int
1126125be069SJason Beloro check_mmu_pgsz_search(md_t *mdp, mde_cookie_t cpu_node_cookie)
1127125be069SJason Beloro {
1128125be069SJason Beloro 
1129125be069SJason Beloro 	uint64_t mmu_search_nshared_contexts;
1130125be069SJason Beloro 	uint64_t mmu_max_search_order;
1131125be069SJason Beloro 	uint64_t mmu_non_priv_search_unified;
1132125be069SJason Beloro 	uint64_t mmu_search_page_size_list;
1133125be069SJason Beloro 
1134125be069SJason Beloro 	if (md_get_prop_val(mdp, cpu_node_cookie,
1135125be069SJason Beloro 	    "mmu-search-#shared-contexts", &mmu_search_nshared_contexts))
1136125be069SJason Beloro 		mmu_search_nshared_contexts = 0;
1137125be069SJason Beloro 
1138125be069SJason Beloro 	if (mmu_search_nshared_contexts == 0 ||
1139125be069SJason Beloro 	    mmu_search_nshared_contexts != NSEARCH_SHCONTEXTS)
1140125be069SJason Beloro 		return (0);
1141125be069SJason Beloro 
1142125be069SJason Beloro 	if (md_get_prop_val(mdp, cpu_node_cookie, "mmu-max-search-order",
1143125be069SJason Beloro 	    &mmu_max_search_order))
1144125be069SJason Beloro 		mmu_max_search_order = 0;
1145125be069SJason Beloro 
1146125be069SJason Beloro 	if (mmu_max_search_order == 0 || mmu_max_search_order !=
1147125be069SJason Beloro 	    MAX_PGSZ_SEARCH_ORDER)
1148125be069SJason Beloro 		return (0);
1149125be069SJason Beloro 
1150125be069SJason Beloro 	if (md_get_prop_val(mdp, cpu_node_cookie,
1151125be069SJason Beloro 	    "mmu-non-priv-search-unified", &mmu_non_priv_search_unified))
1152125be069SJason Beloro 		mmu_non_priv_search_unified = -1;
1153125be069SJason Beloro 
1154125be069SJason Beloro 	if (mmu_non_priv_search_unified != 1) {
1155125be069SJason Beloro 		return (0);
1156125be069SJason Beloro 	}
1157125be069SJason Beloro 
1158125be069SJason Beloro 	if (md_get_prop_val(mdp, cpu_node_cookie,
1159125be069SJason Beloro 	    "mmu-search-page-size-list", &mmu_search_page_size_list)) {
1160125be069SJason Beloro 		mmu_search_page_size_list = 0;
1161125be069SJason Beloro 		return (0);
1162125be069SJason Beloro 	}
1163125be069SJason Beloro 
1164125be069SJason Beloro 	return (1);
1165125be069SJason Beloro }
1166