xref: /titanic_52/usr/src/uts/sun4v/os/fillsysinfo.c (revision 1ae0874509b6811fdde1dfd46f0d93fd09867a3f)
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
5*1ae08745Sheppo  * Common Development and Distribution License (the "License").
6*1ae08745Sheppo  * 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*1ae08745Sheppo  * Copyright 2006 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/errno.h>
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <sys/param.h>
317c478bd9Sstevel@tonic-gate #include <sys/cpu.h>
327c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
337c478bd9Sstevel@tonic-gate #include <sys/clock.h>
347c478bd9Sstevel@tonic-gate #include <sys/promif.h>
357c478bd9Sstevel@tonic-gate #include <sys/promimpl.h>
367c478bd9Sstevel@tonic-gate #include <sys/systm.h>
377c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
387c478bd9Sstevel@tonic-gate #include <sys/debug.h>
397c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
407c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
417c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h>
427c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
437c478bd9Sstevel@tonic-gate #include <sys/cmp.h>
447c478bd9Sstevel@tonic-gate #include <sys/async.h>
457c478bd9Sstevel@tonic-gate #include <vm/page.h>
46*1ae08745Sheppo #include <vm/hat_sfmmu.h>
47*1ae08745Sheppo #include <sys/sysmacros.h>
48*1ae08745Sheppo #include <sys/mach_descrip.h>
49*1ae08745Sheppo #include <sys/mdesc.h>
50*1ae08745Sheppo #include <sys/archsystm.h>
51*1ae08745Sheppo #include <sys/error.h>
52*1ae08745Sheppo #include <sys/mmu.h>
53*1ae08745Sheppo #include <sys/bitmap.h>
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate int ncpunode;
567c478bd9Sstevel@tonic-gate struct cpu_node cpunodes[NCPU];
577c478bd9Sstevel@tonic-gate 
58*1ae08745Sheppo uint64_t cpu_q_entries;
59*1ae08745Sheppo uint64_t dev_q_entries;
60*1ae08745Sheppo uint64_t cpu_rq_entries;
61*1ae08745Sheppo uint64_t cpu_nrq_entries;
62*1ae08745Sheppo 
63*1ae08745Sheppo void fill_cpu(md_t *, mde_cookie_t);
64*1ae08745Sheppo 
65*1ae08745Sheppo static uint64_t get_mmu_ctx_bits(md_t *, mde_cookie_t);
66*1ae08745Sheppo static uint64_t get_cpu_pagesizes(md_t *, mde_cookie_t);
67*1ae08745Sheppo static char *construct_isalist(md_t *, mde_cookie_t, char **);
68*1ae08745Sheppo static void set_at_flags(char *, int, char **);
69*1ae08745Sheppo static void init_md_broken(md_t *);
70*1ae08745Sheppo static int get_l2_cache_info(md_t *, mde_cookie_t, uint64_t *, uint64_t *,
71*1ae08745Sheppo     uint64_t *);
72*1ae08745Sheppo static id_t get_exec_unit_mapping(md_t *, mde_cookie_t, mde_cookie_t *);
73*1ae08745Sheppo static int find_exec_unit_id(mde_cookie_t, mde_cookie_t *);
74*1ae08745Sheppo static void get_q_sizes(md_t *, mde_cookie_t);
75*1ae08745Sheppo static void get_va_bits(md_t *, mde_cookie_t);
76*1ae08745Sheppo static size_t get_ra_limit(md_t *);
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate uint64_t	system_clock_freq;
797c478bd9Sstevel@tonic-gate int		niobus = 0;
807c478bd9Sstevel@tonic-gate uint_t		niommu_tsbs = 0;
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate void
837c478bd9Sstevel@tonic-gate map_wellknown_devices()
847c478bd9Sstevel@tonic-gate {
85*1ae08745Sheppo }
86*1ae08745Sheppo 
87*1ae08745Sheppo #define	S_VAC_SIZE	MMU_PAGESIZE
88*1ae08745Sheppo #define	S_VAC_SHIFT	MMU_PAGESHIFT
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate /*
91*1ae08745Sheppo  * For backward compatibility we need to verify that we can handle
92*1ae08745Sheppo  * running on platforms which shipped with missing MD properties.
937c478bd9Sstevel@tonic-gate  */
94*1ae08745Sheppo #define	ONTARIO_PLATNAME1	"SUNW,Sun-Fire-T200"
95*1ae08745Sheppo #define	ONTARIO_PLATNAME2	"SUNW,Sun-Fire-T2000"
96*1ae08745Sheppo #define	ERIE_PLATNAME1		"SUNW,Sun-Fire-T100"
97*1ae08745Sheppo #define	ERIE_PLATNAME2		"SUNW,Sun-Fire-T1000"
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate void
100*1ae08745Sheppo fill_cpu(md_t *mdp, mde_cookie_t cpuc)
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate 	struct cpu_node *cpunode;
103*1ae08745Sheppo 	uint64_t cpuid;
104*1ae08745Sheppo 	uint64_t clk_freq;
105*1ae08745Sheppo 	char *namebuf;
1067c478bd9Sstevel@tonic-gate 	char *namebufp;
107*1ae08745Sheppo 	int namelen;
108*1ae08745Sheppo 	uint64_t associativity = 0, linesize = 0, size = 0;
109*1ae08745Sheppo 	int status;
1107c478bd9Sstevel@tonic-gate 
111*1ae08745Sheppo 	if (md_get_prop_val(mdp, cpuc, "id", &cpuid)) {
112*1ae08745Sheppo 		return;
1137c478bd9Sstevel@tonic-gate 	}
1147c478bd9Sstevel@tonic-gate 
115*1ae08745Sheppo 	if (cpuid >= NCPU) {
116*1ae08745Sheppo 		cmn_err(CE_CONT, "fill_cpu: out of range cpuid %ld - "
117*1ae08745Sheppo 		    "cpu excluded from configuration", cpuid);
118*1ae08745Sheppo 
119*1ae08745Sheppo 		mutex_enter(&cpu_lock);
120*1ae08745Sheppo 
121*1ae08745Sheppo 		/*
122*1ae08745Sheppo 		 * Since the CPU cannot be used, make sure it
123*1ae08745Sheppo 		 * is in a safe place. If the firmware does not
124*1ae08745Sheppo 		 * support CPU stop, this is known to be true.
125*1ae08745Sheppo 		 * If it fails to stop for any other reason, the
126*1ae08745Sheppo 		 * system is in an inconsistent state and cannot
127*1ae08745Sheppo 		 * be allowed to continue.
128*1ae08745Sheppo 		 */
129*1ae08745Sheppo 		status = stopcpu_bycpuid(cpuid);
130*1ae08745Sheppo 
131*1ae08745Sheppo 		if ((status != 0) && (status != ENOTSUP)) {
132*1ae08745Sheppo 			cmn_err(CE_PANIC, "failed to stop cpu %lu (%d)",
133*1ae08745Sheppo 			    cpuid, status);
134*1ae08745Sheppo 		}
135*1ae08745Sheppo 
136*1ae08745Sheppo 		mutex_exit(&cpu_lock);
1377c478bd9Sstevel@tonic-gate 		return;
1387c478bd9Sstevel@tonic-gate 	}
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	cpunode = &cpunodes[cpuid];
141*1ae08745Sheppo 	cpunode->cpuid = (int)cpuid;
1427c478bd9Sstevel@tonic-gate 	cpunode->device_id = cpuid;
1437c478bd9Sstevel@tonic-gate 
144*1ae08745Sheppo 	if (sizeof (cpunode->fru_fmri) > strlen(CPU_FRU_FMRI))
145*1ae08745Sheppo 		(void) strcpy(cpunode->fru_fmri, CPU_FRU_FMRI);
146*1ae08745Sheppo 
147*1ae08745Sheppo 	if (md_get_prop_data(mdp, cpuc,
148*1ae08745Sheppo 	    "compatible", (uint8_t **)&namebuf, &namelen)) {
149*1ae08745Sheppo 		cmn_err(CE_PANIC, "fill_cpu: Cannot read compatible "
150*1ae08745Sheppo 		    "property");
151*1ae08745Sheppo 	}
1527c478bd9Sstevel@tonic-gate 	namebufp = namebuf;
1537c478bd9Sstevel@tonic-gate 	if (strncmp(namebufp, "SUNW,", 5) == 0)
1547c478bd9Sstevel@tonic-gate 		namebufp += 5;
155*1ae08745Sheppo 	if (strlen(namebufp) > sizeof (cpunode->name))
156*1ae08745Sheppo 		cmn_err(CE_PANIC, "Compatible property too big to "
157*1ae08745Sheppo 		    "fit into the cpunode name buffer");
1587c478bd9Sstevel@tonic-gate 	(void) strcpy(cpunode->name, namebufp);
1597c478bd9Sstevel@tonic-gate 
160*1ae08745Sheppo 	if (md_get_prop_val(mdp, cpuc,
161*1ae08745Sheppo 	    "clock-frequency", &clk_freq)) {
1627c478bd9Sstevel@tonic-gate 			clk_freq = 0;
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 	cpunode->clock_freq = clk_freq;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	ASSERT(cpunode->clock_freq != 0);
1677c478bd9Sstevel@tonic-gate 	/*
1687c478bd9Sstevel@tonic-gate 	 * Compute scaling factor based on rate of %tick. This is used
1697c478bd9Sstevel@tonic-gate 	 * to convert from ticks derived from %tick to nanoseconds. See
1707c478bd9Sstevel@tonic-gate 	 * comment in sun4u/sys/clock.h for details.
1717c478bd9Sstevel@tonic-gate 	 */
1727c478bd9Sstevel@tonic-gate 	cpunode->tick_nsec_scale = (uint_t)(((uint64_t)NANOSEC <<
1737c478bd9Sstevel@tonic-gate 	    (32 - TICK_NSEC_SHIFT)) / cpunode->clock_freq);
1747c478bd9Sstevel@tonic-gate 
175*1ae08745Sheppo 	/*
176*1ae08745Sheppo 	 * The nodeid is not used in sun4v at all. Setting it
177*1ae08745Sheppo 	 * to positive value to make starting of slave CPUs
178*1ae08745Sheppo 	 * code happy.
179*1ae08745Sheppo 	 */
180*1ae08745Sheppo 	cpunode->nodeid = cpuid + 1;
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	/*
183*1ae08745Sheppo 	 * Obtain the L2 cache information from MD.
184*1ae08745Sheppo 	 * If "Cache" node exists, then set L2 cache properties
185*1ae08745Sheppo 	 * as read from MD.
186*1ae08745Sheppo 	 * If node does not exists, then set the L2 cache properties
187*1ae08745Sheppo 	 * in individual CPU module.
1887c478bd9Sstevel@tonic-gate 	 */
189*1ae08745Sheppo 	if ((!get_l2_cache_info(mdp, cpuc,
190*1ae08745Sheppo 	    &associativity, &size, &linesize)) ||
191*1ae08745Sheppo 	    associativity == 0 || size == 0 || linesize == 0) {
1927c478bd9Sstevel@tonic-gate 		cpu_fiximp(cpunode);
193*1ae08745Sheppo 	} else {
194*1ae08745Sheppo 		/*
195*1ae08745Sheppo 		 * Do not expect L2 cache properties to be bigger
196*1ae08745Sheppo 		 * than 32-bit quantity.
197*1ae08745Sheppo 		 */
198*1ae08745Sheppo 		cpunode->ecache_associativity = (int)associativity;
199*1ae08745Sheppo 		cpunode->ecache_size = (int)size;
200*1ae08745Sheppo 		cpunode->ecache_linesize = (int)linesize;
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 
203*1ae08745Sheppo 	cpunode->ecache_setsize =
204*1ae08745Sheppo 	    cpunode->ecache_size / cpunode->ecache_associativity;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 		/*
207*1ae08745Sheppo 		 * Start off by assigning the cpu id as the default
208*1ae08745Sheppo 		 * mapping index.
209*1ae08745Sheppo 		 */
210*1ae08745Sheppo 
211*1ae08745Sheppo 	cpunode->exec_unit_mapping = NO_EU_MAPPING_FOUND;
212*1ae08745Sheppo 
213*1ae08745Sheppo 	if (ecache_setsize == 0)
214*1ae08745Sheppo 		ecache_setsize = cpunode->ecache_setsize;
215*1ae08745Sheppo 	if (ecache_alignsize == 0)
216*1ae08745Sheppo 		ecache_alignsize = cpunode->ecache_linesize;
217*1ae08745Sheppo 
218*1ae08745Sheppo 	ncpunode++;
219*1ae08745Sheppo }
220*1ae08745Sheppo 
221*1ae08745Sheppo void
222*1ae08745Sheppo empty_cpu(int cpuid)
223*1ae08745Sheppo {
224*1ae08745Sheppo 	bzero(&cpunodes[cpuid], sizeof (struct cpu_node));
225*1ae08745Sheppo 	ncpunode--;
226*1ae08745Sheppo }
227*1ae08745Sheppo 
228*1ae08745Sheppo void
229*1ae08745Sheppo setup_exec_unit_mappings(md_t *mdp)
230*1ae08745Sheppo {
231*1ae08745Sheppo 	uint64_t num, num_eunits;
232*1ae08745Sheppo 	mde_cookie_t cpus_node;
233*1ae08745Sheppo 	mde_cookie_t *node, *eunit;
234*1ae08745Sheppo 	int idx, i, j;
235*1ae08745Sheppo 	processorid_t cpuid;
236*1ae08745Sheppo 	char *eunit_name = broken_md_flag ? "exec_unit" : "exec-unit";
237*1ae08745Sheppo 
238*1ae08745Sheppo 	/*
239*1ae08745Sheppo 	 * Find the cpu integer exec units - and
240*1ae08745Sheppo 	 * setup the mappings appropriately.
241*1ae08745Sheppo 	 */
242*1ae08745Sheppo 	num = md_alloc_scan_dag(mdp, md_root_node(mdp), "cpus", "fwd", &node);
243*1ae08745Sheppo 	if (num < 1)
244*1ae08745Sheppo 		cmn_err(CE_PANIC, "No cpus node in machine desccription");
245*1ae08745Sheppo 	if (num > 1)
246*1ae08745Sheppo 		cmn_err(CE_PANIC, "More than 1 cpus node in machine"
247*1ae08745Sheppo 		    " description");
248*1ae08745Sheppo 
249*1ae08745Sheppo 	cpus_node = node[0];
250*1ae08745Sheppo 	md_free_scan_dag(mdp, &node);
251*1ae08745Sheppo 
252*1ae08745Sheppo 	num_eunits = md_alloc_scan_dag(mdp, cpus_node, eunit_name,
253*1ae08745Sheppo 	    "fwd", &eunit);
254*1ae08745Sheppo 	if (num_eunits > 0) {
255*1ae08745Sheppo 		char *match_type = broken_md_flag ? "int" : "integer";
256*1ae08745Sheppo 
257*1ae08745Sheppo 		/* Spin through and find all the integer exec units */
258*1ae08745Sheppo 		for (i = 0; i < num_eunits; i++) {
259*1ae08745Sheppo 			char *p;
260*1ae08745Sheppo 			char *val;
261*1ae08745Sheppo 			int vallen;
262*1ae08745Sheppo 			uint64_t lcpuid;
263*1ae08745Sheppo 
264*1ae08745Sheppo 				/* ignore nodes with no type */
265*1ae08745Sheppo 			if (md_get_prop_data(mdp, eunit[i], "type",
266*1ae08745Sheppo 				(uint8_t **)&val, &vallen)) continue;
267*1ae08745Sheppo 
268*1ae08745Sheppo 			for (p = val; *p != '\0'; p += strlen(p) + 1) {
269*1ae08745Sheppo 				if (strcmp(p, match_type) == 0)
270*1ae08745Sheppo 					goto found;
271*1ae08745Sheppo 			}
272*1ae08745Sheppo 
273*1ae08745Sheppo 			continue;
274*1ae08745Sheppo found:
275*1ae08745Sheppo 			idx = NCPU + i;
276*1ae08745Sheppo 			/*
277*1ae08745Sheppo 			 * find the cpus attached to this EU and
278*1ae08745Sheppo 			 * update their mapping indices
279*1ae08745Sheppo 			 */
280*1ae08745Sheppo 			num = md_alloc_scan_dag(mdp, eunit[i], "cpu",
281*1ae08745Sheppo 			    "back", &node);
282*1ae08745Sheppo 
283*1ae08745Sheppo 			if (num < 1)
284*1ae08745Sheppo 				cmn_err(CE_PANIC, "exec-unit node in MD"
285*1ae08745Sheppo 				    " not attached to a cpu node");
286*1ae08745Sheppo 
287*1ae08745Sheppo 			for (j = 0; j < num; j++) {
288*1ae08745Sheppo 				if (md_get_prop_val(mdp, node[j], "id",
289*1ae08745Sheppo 				    &lcpuid))
290*1ae08745Sheppo 					continue;
291*1ae08745Sheppo 				if (lcpuid >= NCPU)
292*1ae08745Sheppo 					continue;
293*1ae08745Sheppo 				cpuid = (processorid_t)lcpuid;
294*1ae08745Sheppo 				cpunodes[cpuid].exec_unit_mapping = idx;
295*1ae08745Sheppo 			}
296*1ae08745Sheppo 			md_free_scan_dag(mdp, &node);
297*1ae08745Sheppo 		}
298*1ae08745Sheppo 
299*1ae08745Sheppo 
300*1ae08745Sheppo 		md_free_scan_dag(mdp, &eunit);
301*1ae08745Sheppo 	}
302*1ae08745Sheppo }
303*1ae08745Sheppo 
304*1ae08745Sheppo /*
305*1ae08745Sheppo  * All the common setup of sun4v CPU modules is done by this routine.
306*1ae08745Sheppo  */
307*1ae08745Sheppo void
308*1ae08745Sheppo cpu_setup_common(char **cpu_module_isa_set)
309*1ae08745Sheppo {
310*1ae08745Sheppo 	extern int disable_delay_tlb_flush, delay_tlb_flush;
311*1ae08745Sheppo 	extern int mmu_exported_pagesize_mask;
312*1ae08745Sheppo 	extern int vac_size, vac_shift;
313*1ae08745Sheppo 	extern uint_t vac_mask;
314*1ae08745Sheppo 	int nocpus, i;
315*1ae08745Sheppo 	size_t ra_limit;
316*1ae08745Sheppo 	mde_cookie_t *cpulist;
317*1ae08745Sheppo 	md_t *mdp;
318*1ae08745Sheppo 
319*1ae08745Sheppo 	if ((mdp = md_get_handle()) == NULL)
320*1ae08745Sheppo 		cmn_err(CE_PANIC, "Unable to initialize machine description");
321*1ae08745Sheppo 
322*1ae08745Sheppo 	init_md_broken(mdp);
323*1ae08745Sheppo 
324*1ae08745Sheppo 	nocpus = md_alloc_scan_dag(mdp,
325*1ae08745Sheppo 	    md_root_node(mdp), "cpu", "fwd", &cpulist);
326*1ae08745Sheppo 	if (nocpus < 1) {
327*1ae08745Sheppo 		cmn_err(CE_PANIC, "cpu_common_setup: cpulist allocation "
328*1ae08745Sheppo 		    "failed or incorrect number of CPUs in MD");
329*1ae08745Sheppo 	}
330*1ae08745Sheppo 
331*1ae08745Sheppo 	if (use_page_coloring) {
332*1ae08745Sheppo 		do_pg_coloring = 1;
333*1ae08745Sheppo 		if (use_virtual_coloring) {
334*1ae08745Sheppo 			/*
335*1ae08745Sheppo 			 * XXX Sun4v cpus don't have virtual caches
336*1ae08745Sheppo 			 */
337*1ae08745Sheppo 			do_virtual_coloring = 1;
338*1ae08745Sheppo 		}
339*1ae08745Sheppo 	}
340*1ae08745Sheppo 
341*1ae08745Sheppo 	/*
342*1ae08745Sheppo 	 * Get the valid contexts, mmu page sizes mask, Q sizes and isalist/r
343*1ae08745Sheppo 	 * from the MD for the first available CPU in cpulist.
344*1ae08745Sheppo 	 */
345*1ae08745Sheppo 
346*1ae08745Sheppo 	if (nctxs == 0)
347*1ae08745Sheppo 		nctxs = (uint_t)(1 << get_mmu_ctx_bits(mdp, cpulist[0]));
348*1ae08745Sheppo 
349*1ae08745Sheppo 	if (nctxs > MAX_NCTXS)
350*1ae08745Sheppo 		nctxs = MAX_NCTXS;
351*1ae08745Sheppo 
352*1ae08745Sheppo 	/* Do not expect the MMU page sizes mask to be more than 32-bit. */
353*1ae08745Sheppo 	mmu_exported_pagesize_mask = (int)get_cpu_pagesizes(mdp, cpulist[0]);
354*1ae08745Sheppo 
355*1ae08745Sheppo 	for (i = 0; i < nocpus; i++)
356*1ae08745Sheppo 		fill_cpu(mdp, cpulist[i]);
357*1ae08745Sheppo 
358*1ae08745Sheppo 	setup_exec_unit_mappings(mdp);
359*1ae08745Sheppo 
360*1ae08745Sheppo 	vac_size = S_VAC_SIZE;
361*1ae08745Sheppo 	vac_mask = MMU_PAGEMASK & (vac_size - 1);
362*1ae08745Sheppo 	vac_shift = S_VAC_SHIFT;
363*1ae08745Sheppo 	shm_alignment = vac_size;
364*1ae08745Sheppo 	vac = 0;
365*1ae08745Sheppo 
366*1ae08745Sheppo 	/*
367*1ae08745Sheppo 	 * If MD is broken then append the passed ISA set,
368*1ae08745Sheppo 	 * otherwise trust the MD.
369*1ae08745Sheppo 	 */
370*1ae08745Sheppo 
371*1ae08745Sheppo 	if (broken_md_flag)
372*1ae08745Sheppo 		isa_list = construct_isalist(mdp, cpulist[0],
373*1ae08745Sheppo 		    cpu_module_isa_set);
374*1ae08745Sheppo 	else
375*1ae08745Sheppo 		isa_list = construct_isalist(mdp, cpulist[0], NULL);
376*1ae08745Sheppo 
377*1ae08745Sheppo 	get_q_sizes(mdp, cpulist[0]);
378*1ae08745Sheppo 
379*1ae08745Sheppo 	get_va_bits(mdp, cpulist[0]);
380*1ae08745Sheppo 
381*1ae08745Sheppo 	/*
382*1ae08745Sheppo 	 * ra_limit is the highest real address in the machine.
383*1ae08745Sheppo 	 */
384*1ae08745Sheppo 	ra_limit = get_ra_limit(mdp);
385*1ae08745Sheppo 
386*1ae08745Sheppo 	md_free_scan_dag(mdp, &cpulist);
387*1ae08745Sheppo 
388*1ae08745Sheppo 	(void) md_fini_handle(mdp);
389*1ae08745Sheppo 
390*1ae08745Sheppo 	/*
391*1ae08745Sheppo 	 * Block stores invalidate all pages of the d$ so pagecopy
392*1ae08745Sheppo 	 * et. al. do not need virtual translations with virtual
393*1ae08745Sheppo 	 * coloring taken into consideration.
394*1ae08745Sheppo 	 */
395*1ae08745Sheppo 	pp_consistent_coloring = 0;
396*1ae08745Sheppo 
397*1ae08745Sheppo 	/*
398*1ae08745Sheppo 	 * The kpm mapping window.
399*1ae08745Sheppo 	 * kpm_size:
400*1ae08745Sheppo 	 *	The size of a single kpm range.
401*1ae08745Sheppo 	 *	The overall size will be: kpm_size * vac_colors.
402*1ae08745Sheppo 	 * kpm_vbase:
403*1ae08745Sheppo 	 *	The virtual start address of the kpm range within the kernel
404*1ae08745Sheppo 	 *	virtual address space. kpm_vbase has to be kpm_size aligned.
405*1ae08745Sheppo 	 */
406*1ae08745Sheppo 
407*1ae08745Sheppo 	/*
408*1ae08745Sheppo 	 * Make kpm_vbase, kpm_size aligned to kpm_size_shift.
409*1ae08745Sheppo 	 * To do this find the nearest power of 2 size that the
410*1ae08745Sheppo 	 * actual ra_limit fits within.
411*1ae08745Sheppo 	 * If it is an even power of two use that, otherwise use the
412*1ae08745Sheppo 	 * next power of two larger than ra_limit.
413*1ae08745Sheppo 	 */
414*1ae08745Sheppo 
415*1ae08745Sheppo 	ASSERT(ra_limit != 0);
416*1ae08745Sheppo 
417*1ae08745Sheppo 	kpm_size_shift = (ra_limit & (ra_limit - 1)) != 0 ?
418*1ae08745Sheppo 		highbit(ra_limit) : highbit(ra_limit) - 1;
419*1ae08745Sheppo 
420*1ae08745Sheppo 	/*
421*1ae08745Sheppo 	 * No virtual caches on sun4v so size matches size shift
422*1ae08745Sheppo 	 */
423*1ae08745Sheppo 	kpm_size = 1ul << kpm_size_shift;
424*1ae08745Sheppo 
425*1ae08745Sheppo 	if (va_bits < VA_ADDRESS_SPACE_BITS) {
426*1ae08745Sheppo 		/*
427*1ae08745Sheppo 		 * In case of VA hole
428*1ae08745Sheppo 		 * kpm_base = hole_end + 1TB
429*1ae08745Sheppo 		 * Starting 1TB beyond where VA hole ends because on Niagara
430*1ae08745Sheppo 		 * processor software must not use pages within 4GB of the
431*1ae08745Sheppo 		 * VA hole as instruction pages to avoid problems with
432*1ae08745Sheppo 		 * prefetching into the VA hole.
433*1ae08745Sheppo 		 */
434*1ae08745Sheppo 		kpm_vbase = (caddr_t)((0ull - (1ull << (va_bits - 1))) +
435*1ae08745Sheppo 		    (1ull << 40));
436*1ae08745Sheppo 	} else {		/* Number of VA bits 64 ... no VA hole */
437*1ae08745Sheppo 		kpm_vbase = (caddr_t)0x8000000000000000ull;	/* 8 EB */
438*1ae08745Sheppo 	}
439*1ae08745Sheppo 
440*1ae08745Sheppo 	/*
441*1ae08745Sheppo 	 * The traptrace code uses either %tick or %stick for
442*1ae08745Sheppo 	 * timestamping.  The sun4v require use of %stick.
443*1ae08745Sheppo 	 */
444*1ae08745Sheppo 	traptrace_use_stick = 1;
445*1ae08745Sheppo 
446*1ae08745Sheppo 	/*
447*1ae08745Sheppo 	 * sun4v provides demap_all
448*1ae08745Sheppo 	 */
449*1ae08745Sheppo 	if (!disable_delay_tlb_flush)
450*1ae08745Sheppo 		delay_tlb_flush = 1;
451*1ae08745Sheppo }
452*1ae08745Sheppo 
453*1ae08745Sheppo /*
454*1ae08745Sheppo  * Get the nctxs from MD. If absent panic.
455*1ae08745Sheppo  */
456*1ae08745Sheppo static uint64_t
457*1ae08745Sheppo get_mmu_ctx_bits(md_t *mdp, mde_cookie_t cpu_node_cookie)
458*1ae08745Sheppo {
459*1ae08745Sheppo 	uint64_t ctx_bits;
460*1ae08745Sheppo 
461*1ae08745Sheppo 	if (md_get_prop_val(mdp, cpu_node_cookie, "mmu-#context-bits",
462*1ae08745Sheppo 	    &ctx_bits))
463*1ae08745Sheppo 		ctx_bits = 0;
464*1ae08745Sheppo 
465*1ae08745Sheppo 	if (ctx_bits < MIN_NCTXS_BITS || ctx_bits > MAX_NCTXS_BITS)
466*1ae08745Sheppo 		cmn_err(CE_PANIC, "Incorrect %ld number of contexts bits "
467*1ae08745Sheppo 		    "returned by MD", ctx_bits);
468*1ae08745Sheppo 
469*1ae08745Sheppo 	return (ctx_bits);
470*1ae08745Sheppo }
471*1ae08745Sheppo 
472*1ae08745Sheppo /*
473*1ae08745Sheppo  * Initalize supported page sizes information.
474*1ae08745Sheppo  * Set to 0, if the page sizes mask information is absent in MD.
475*1ae08745Sheppo  */
476*1ae08745Sheppo static uint64_t
477*1ae08745Sheppo get_cpu_pagesizes(md_t *mdp, mde_cookie_t cpu_node_cookie)
478*1ae08745Sheppo {
479*1ae08745Sheppo 	uint64_t mmu_page_size_list;
480*1ae08745Sheppo 
481*1ae08745Sheppo 	if (md_get_prop_val(mdp, cpu_node_cookie, "mmu-page-size-list",
482*1ae08745Sheppo 	    &mmu_page_size_list))
483*1ae08745Sheppo 		mmu_page_size_list = 0;
484*1ae08745Sheppo 
485*1ae08745Sheppo 	if (mmu_page_size_list == 0 || mmu_page_size_list > MAX_PAGESIZE_MASK)
486*1ae08745Sheppo 		cmn_err(CE_PANIC, "Incorrect 0x%lx pagesize mask returned"
487*1ae08745Sheppo 		    "by MD", mmu_page_size_list);
488*1ae08745Sheppo 
489*1ae08745Sheppo 	return (mmu_page_size_list);
490*1ae08745Sheppo }
491*1ae08745Sheppo 
492*1ae08745Sheppo /*
493*1ae08745Sheppo  * This routine gets the isalist information from MD and appends
494*1ae08745Sheppo  * the CPU module ISA set if required.
495*1ae08745Sheppo  */
496*1ae08745Sheppo static char *
497*1ae08745Sheppo construct_isalist(md_t *mdp, mde_cookie_t cpu_node_cookie,
498*1ae08745Sheppo     char **cpu_module_isa_set)
499*1ae08745Sheppo {
500*1ae08745Sheppo 	extern int at_flags;
501*1ae08745Sheppo 	char *md_isalist;
502*1ae08745Sheppo 	int md_isalen;
503*1ae08745Sheppo 	char *isabuf;
504*1ae08745Sheppo 	int isalen;
505*1ae08745Sheppo 	char **isa_set;
506*1ae08745Sheppo 	char *p, *q;
507*1ae08745Sheppo 	int cpu_module_isalen = 0, found = 0;
508*1ae08745Sheppo 
509*1ae08745Sheppo 	(void) md_get_prop_data(mdp, cpu_node_cookie,
510*1ae08745Sheppo 	    "isalist", (uint8_t **)&isabuf, &isalen);
511*1ae08745Sheppo 
512*1ae08745Sheppo 	/*
513*1ae08745Sheppo 	 * We support binaries for all the cpus that have shipped so far.
514*1ae08745Sheppo 	 * The kernel emulates instructions that are not supported by hardware.
515*1ae08745Sheppo 	 */
516*1ae08745Sheppo 	at_flags = EF_SPARC_SUN_US3 | EF_SPARC_32PLUS | EF_SPARC_SUN_US1;
517*1ae08745Sheppo 
518*1ae08745Sheppo 	/*
519*1ae08745Sheppo 	 * Construct the space separated isa_list.
520*1ae08745Sheppo 	 */
521*1ae08745Sheppo 	if (cpu_module_isa_set != NULL) {
522*1ae08745Sheppo 		for (isa_set = cpu_module_isa_set; *isa_set != NULL;
523*1ae08745Sheppo 		    isa_set++) {
524*1ae08745Sheppo 			cpu_module_isalen += strlen(*isa_set);
525*1ae08745Sheppo 			cpu_module_isalen++;	/* for space character */
526*1ae08745Sheppo 		}
527*1ae08745Sheppo 	}
528*1ae08745Sheppo 
529*1ae08745Sheppo 	/*
530*1ae08745Sheppo 	 * Allocate the buffer of MD isa buffer length + CPU module
531*1ae08745Sheppo 	 * isa buffer length.
532*1ae08745Sheppo 	 */
533*1ae08745Sheppo 	md_isalen = isalen + cpu_module_isalen + 2;
534*1ae08745Sheppo 	md_isalist = (char *)prom_alloc((caddr_t)0, md_isalen, 0);
535*1ae08745Sheppo 	if (md_isalist == NULL)
536*1ae08745Sheppo 		cmn_err(CE_PANIC, "construct_isalist: Allocation failed for "
537*1ae08745Sheppo 		    "md_isalist");
538*1ae08745Sheppo 
539*1ae08745Sheppo 	md_isalist[0] = '\0'; /* create an empty string to start */
540*1ae08745Sheppo 	for (p = isabuf, q = p + isalen; p < q; p += strlen(p) + 1) {
541*1ae08745Sheppo 		(void) strlcat(md_isalist, p, md_isalen);
542*1ae08745Sheppo 		(void) strcat(md_isalist, " ");
543*1ae08745Sheppo 	}
544*1ae08745Sheppo 
545*1ae08745Sheppo 	/*
546*1ae08745Sheppo 	 * Check if the isa_set is present in isalist returned by MD.
547*1ae08745Sheppo 	 * If yes, then no need to append it, if no then append it to
548*1ae08745Sheppo 	 * isalist returned by MD.
549*1ae08745Sheppo 	 */
550*1ae08745Sheppo 	if (cpu_module_isa_set != NULL) {
551*1ae08745Sheppo 		for (isa_set = cpu_module_isa_set; *isa_set != NULL;
552*1ae08745Sheppo 		    isa_set++) {
553*1ae08745Sheppo 			found = 0;
554*1ae08745Sheppo 			for (p = isabuf, q = p + isalen; p < q;
555*1ae08745Sheppo 			    p += strlen(p) + 1) {
556*1ae08745Sheppo 				if (strcmp(p, *isa_set) == 0) {
557*1ae08745Sheppo 					found = 1;
558*1ae08745Sheppo 					break;
559*1ae08745Sheppo 				}
560*1ae08745Sheppo 			}
561*1ae08745Sheppo 			if (!found) {
562*1ae08745Sheppo 				(void) strlcat(md_isalist, *isa_set, md_isalen);
563*1ae08745Sheppo 				(void) strcat(md_isalist, " ");
564*1ae08745Sheppo 			}
565*1ae08745Sheppo 		}
566*1ae08745Sheppo 	}
567*1ae08745Sheppo 
568*1ae08745Sheppo 	/* Get rid of any trailing white spaces */
569*1ae08745Sheppo 	md_isalist[strlen(md_isalist) - 1] = '\0';
570*1ae08745Sheppo 
571*1ae08745Sheppo 	return (md_isalist);
572*1ae08745Sheppo }
573*1ae08745Sheppo 
574*1ae08745Sheppo uint64_t
575*1ae08745Sheppo get_ra_limit(md_t *mdp)
576*1ae08745Sheppo {
577*1ae08745Sheppo 	mde_cookie_t *mem_list;
578*1ae08745Sheppo 	mde_cookie_t *mblock_list;
579*1ae08745Sheppo 	int i;
580*1ae08745Sheppo 	int memnodes;
581*1ae08745Sheppo 	int nmblock;
582*1ae08745Sheppo 	uint64_t base;
583*1ae08745Sheppo 	uint64_t size;
584*1ae08745Sheppo 	uint64_t ra_limit = 0, new_limit = 0;
585*1ae08745Sheppo 
586*1ae08745Sheppo 	memnodes = md_alloc_scan_dag(mdp,
587*1ae08745Sheppo 	    md_root_node(mdp), "memory", "fwd", &mem_list);
588*1ae08745Sheppo 
589*1ae08745Sheppo 	ASSERT(memnodes == 1);
590*1ae08745Sheppo 
591*1ae08745Sheppo 	nmblock = md_alloc_scan_dag(mdp,
592*1ae08745Sheppo 	    mem_list[0], "mblock", "fwd", &mblock_list);
593*1ae08745Sheppo 	if (nmblock < 1)
594*1ae08745Sheppo 		cmn_err(CE_PANIC, "cannot find mblock nodes in MD");
595*1ae08745Sheppo 
596*1ae08745Sheppo 	for (i = 0; i < nmblock; i++) {
597*1ae08745Sheppo 		if (md_get_prop_val(mdp, mblock_list[i], "base", &base))
598*1ae08745Sheppo 			cmn_err(CE_PANIC, "base property missing from MD"
599*1ae08745Sheppo 			    " mblock node");
600*1ae08745Sheppo 		if (md_get_prop_val(mdp, mblock_list[i], "size", &size))
601*1ae08745Sheppo 			cmn_err(CE_PANIC, "size property missing from MD"
602*1ae08745Sheppo 			    " mblock node");
603*1ae08745Sheppo 
604*1ae08745Sheppo 		ASSERT(size != 0);
605*1ae08745Sheppo 
606*1ae08745Sheppo 		new_limit = base + size;
607*1ae08745Sheppo 
608*1ae08745Sheppo 		if (base > new_limit)
609*1ae08745Sheppo 			cmn_err(CE_PANIC, "mblock in MD wrapped around");
610*1ae08745Sheppo 
611*1ae08745Sheppo 		if (new_limit > ra_limit)
612*1ae08745Sheppo 		    ra_limit = new_limit;
613*1ae08745Sheppo 	}
614*1ae08745Sheppo 
615*1ae08745Sheppo 	ASSERT(ra_limit != 0);
616*1ae08745Sheppo 
617*1ae08745Sheppo 	if (ra_limit > MAX_REAL_ADDRESS) {
618*1ae08745Sheppo 		cmn_err(CE_WARN, "Highest real address in MD too large"
619*1ae08745Sheppo 		    " clipping to %llx\n", MAX_REAL_ADDRESS);
620*1ae08745Sheppo 		ra_limit = MAX_REAL_ADDRESS;
621*1ae08745Sheppo 	}
622*1ae08745Sheppo 
623*1ae08745Sheppo 	md_free_scan_dag(mdp, &mblock_list);
624*1ae08745Sheppo 
625*1ae08745Sheppo 	md_free_scan_dag(mdp, &mem_list);
626*1ae08745Sheppo 
627*1ae08745Sheppo 	return (ra_limit);
628*1ae08745Sheppo }
629*1ae08745Sheppo 
630*1ae08745Sheppo /*
631*1ae08745Sheppo  * This routine sets the globals for CPU and DEV mondo queue entries and
632*1ae08745Sheppo  * resumable and non-resumable error queue entries.
633*1ae08745Sheppo  */
634*1ae08745Sheppo static uint64_t
635*1ae08745Sheppo get_single_q_size(md_t *mdp, mde_cookie_t cpu_node_cookie,
636*1ae08745Sheppo     char *qnamep, uint64_t default_entries)
637*1ae08745Sheppo {
638*1ae08745Sheppo 	uint64_t entries;
639*1ae08745Sheppo 
640*1ae08745Sheppo 	if (md_get_prop_val(mdp, cpu_node_cookie, qnamep, &entries)) {
641*1ae08745Sheppo 		if (!broken_md_flag)
642*1ae08745Sheppo 			cmn_err(CE_PANIC, "Missing %s property in MD cpu node",
643*1ae08745Sheppo 				qnamep);
644*1ae08745Sheppo 		entries = default_entries;
645*1ae08745Sheppo 	} else {
646*1ae08745Sheppo 		entries = 1 << entries;
647*1ae08745Sheppo 	}
648*1ae08745Sheppo 	return (entries);
649*1ae08745Sheppo }
650*1ae08745Sheppo 
651*1ae08745Sheppo 
652*1ae08745Sheppo static void
653*1ae08745Sheppo get_q_sizes(md_t *mdp, mde_cookie_t cpu_node_cookie)
654*1ae08745Sheppo {
655*1ae08745Sheppo 	cpu_q_entries = get_single_q_size(mdp, cpu_node_cookie,
656*1ae08745Sheppo 	    "q-cpu-mondo-#bits", DEFAULT_CPU_Q_ENTRIES);
657*1ae08745Sheppo 
658*1ae08745Sheppo 	dev_q_entries = get_single_q_size(mdp, cpu_node_cookie,
659*1ae08745Sheppo 	    "q-dev-mondo-#bits", DEFAULT_DEV_Q_ENTRIES);
660*1ae08745Sheppo 
661*1ae08745Sheppo 	cpu_rq_entries = get_single_q_size(mdp, cpu_node_cookie,
662*1ae08745Sheppo 	    "q-resumable-#bits", CPU_RQ_ENTRIES);
663*1ae08745Sheppo 
664*1ae08745Sheppo 	cpu_nrq_entries = get_single_q_size(mdp, cpu_node_cookie,
665*1ae08745Sheppo 		"q-nonresumable-#bits", CPU_NRQ_ENTRIES);
666*1ae08745Sheppo }
667*1ae08745Sheppo 
668*1ae08745Sheppo 
669*1ae08745Sheppo static void
670*1ae08745Sheppo get_va_bits(md_t *mdp, mde_cookie_t cpu_node_cookie)
671*1ae08745Sheppo {
672*1ae08745Sheppo 	uint64_t value = VA_ADDRESS_SPACE_BITS;
673*1ae08745Sheppo 
674*1ae08745Sheppo 	if (md_get_prop_val(mdp, cpu_node_cookie, "mmu-#va-bits", &value))
675*1ae08745Sheppo 		cmn_err(CE_PANIC, "mmu-#va-bits property  not found in MD");
676*1ae08745Sheppo 
677*1ae08745Sheppo 
678*1ae08745Sheppo 	if (value == 0 || value > VA_ADDRESS_SPACE_BITS)
679*1ae08745Sheppo 		cmn_err(CE_PANIC, "Incorrect number of va bits in MD");
680*1ae08745Sheppo 
681*1ae08745Sheppo 	/* Do not expect number of VA bits to be more than 32-bit quantity */
682*1ae08745Sheppo 
683*1ae08745Sheppo 	va_bits = (int)value;
684*1ae08745Sheppo 
685*1ae08745Sheppo 	/*
686*1ae08745Sheppo 	 * Correct the value for VA bits on UltraSPARC-T1 based systems
687*1ae08745Sheppo 	 * in case of broken MD.
688*1ae08745Sheppo 	 */
689*1ae08745Sheppo 	if (broken_md_flag)
690*1ae08745Sheppo 		va_bits = DEFAULT_VA_ADDRESS_SPACE_BITS;
691*1ae08745Sheppo }
692*1ae08745Sheppo 
693*1ae08745Sheppo /*
694*1ae08745Sheppo  * This routine returns the L2 cache information such as -- associativity,
695*1ae08745Sheppo  * size and linesize.
696*1ae08745Sheppo  */
697*1ae08745Sheppo static int
698*1ae08745Sheppo get_l2_cache_info(md_t *mdp, mde_cookie_t cpu_node_cookie,
699*1ae08745Sheppo 	    uint64_t *associativity, uint64_t *size, uint64_t *linesize)
700*1ae08745Sheppo {
701*1ae08745Sheppo 	mde_cookie_t *cachelist;
702*1ae08745Sheppo 	int ncaches, i;
703*1ae08745Sheppo 	uint64_t max_level;
704*1ae08745Sheppo 
705*1ae08745Sheppo 	ncaches = md_alloc_scan_dag(mdp, cpu_node_cookie, "cache",
706*1ae08745Sheppo 	    "fwd", &cachelist);
707*1ae08745Sheppo 	/*
708*1ae08745Sheppo 	 * The "cache" node is optional in MD, therefore ncaches can be 0.
709*1ae08745Sheppo 	 */
710*1ae08745Sheppo 	if (ncaches < 1) {
711*1ae08745Sheppo 		return (0);
712*1ae08745Sheppo 	}
713*1ae08745Sheppo 
714*1ae08745Sheppo 	max_level = 0;
715*1ae08745Sheppo 	for (i = 0; i < ncaches; i++) {
716*1ae08745Sheppo 		uint64_t cache_level;
717*1ae08745Sheppo 		uint64_t local_assoc;
718*1ae08745Sheppo 		uint64_t local_size;
719*1ae08745Sheppo 		uint64_t local_lsize;
720*1ae08745Sheppo 
721*1ae08745Sheppo 		if (md_get_prop_val(mdp, cachelist[i], "level", &cache_level))
722*1ae08745Sheppo 			continue;
723*1ae08745Sheppo 
724*1ae08745Sheppo 		if (cache_level <= max_level) continue;
725*1ae08745Sheppo 
726*1ae08745Sheppo 		/* If properties are missing from this cache ignore it */
727*1ae08745Sheppo 
728*1ae08745Sheppo 		if ((md_get_prop_val(mdp, cachelist[i],
729*1ae08745Sheppo 		    "associativity", &local_assoc))) {
730*1ae08745Sheppo 			continue;
731*1ae08745Sheppo 		}
732*1ae08745Sheppo 
733*1ae08745Sheppo 		if ((md_get_prop_val(mdp, cachelist[i],
734*1ae08745Sheppo 		    "size", &local_size))) {
735*1ae08745Sheppo 			continue;
736*1ae08745Sheppo 		}
737*1ae08745Sheppo 
738*1ae08745Sheppo 		if ((md_get_prop_val(mdp, cachelist[i],
739*1ae08745Sheppo 		    "line-size", &local_lsize))) {
740*1ae08745Sheppo 			continue;
741*1ae08745Sheppo 		}
742*1ae08745Sheppo 
743*1ae08745Sheppo 		max_level = cache_level;
744*1ae08745Sheppo 		*associativity = local_assoc;
745*1ae08745Sheppo 		*size = local_size;
746*1ae08745Sheppo 		*linesize = local_lsize;
747*1ae08745Sheppo 	}
748*1ae08745Sheppo 
749*1ae08745Sheppo 	md_free_scan_dag(mdp, &cachelist);
750*1ae08745Sheppo 
751*1ae08745Sheppo 	return ((max_level > 0) ? 1 : 0);
752*1ae08745Sheppo }
753*1ae08745Sheppo 
754*1ae08745Sheppo /*
755*1ae08745Sheppo  * The broken_md_flag is set to 1, if the MD doesn't have
756*1ae08745Sheppo  * the domaining-enabled property in the platform node and the platforms
757*1ae08745Sheppo  * are Ontario and Erie. This flag is used to workaround some of the
758*1ae08745Sheppo  * incorrect MD properties.
7597c478bd9Sstevel@tonic-gate  */
7607c478bd9Sstevel@tonic-gate static void
761*1ae08745Sheppo init_md_broken(md_t *mdp)
7627c478bd9Sstevel@tonic-gate {
763*1ae08745Sheppo 	int nrnode;
764*1ae08745Sheppo 	mde_cookie_t *platlist, rootnode;
765*1ae08745Sheppo 	char *vbuf;
766*1ae08745Sheppo 	uint64_t val = 0;
7677c478bd9Sstevel@tonic-gate 
768*1ae08745Sheppo 	rootnode = md_root_node(mdp);
769*1ae08745Sheppo 	ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE);
7707c478bd9Sstevel@tonic-gate 
771*1ae08745Sheppo 	nrnode = md_alloc_scan_dag(mdp, md_root_node(mdp), "platform", "fwd",
772*1ae08745Sheppo 	    &platlist);
7737c478bd9Sstevel@tonic-gate 
774*1ae08745Sheppo 	ASSERT(nrnode == 1);
7757c478bd9Sstevel@tonic-gate 
776*1ae08745Sheppo 	if (md_get_prop_str(mdp, platlist[0], "name", &vbuf) != 0)
777*1ae08745Sheppo 		panic("platform name not found in machine description");
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 	/*
780*1ae08745Sheppo 	 * If domaining-enable prop doesn't exist and the platform name is
781*1ae08745Sheppo 	 * Ontario or Erie the md is broken.
7827c478bd9Sstevel@tonic-gate 	 */
7837c478bd9Sstevel@tonic-gate 
784*1ae08745Sheppo 	if (md_get_prop_val(mdp, platlist[0], "domaining-enabled", &val) != 0 &&
785*1ae08745Sheppo 	    ((strcmp(vbuf, ONTARIO_PLATNAME1) == 0) ||
786*1ae08745Sheppo 	    (strcmp(vbuf, ONTARIO_PLATNAME2) == 0) ||
787*1ae08745Sheppo 	    (strcmp(vbuf, ERIE_PLATNAME1) == 0) ||
788*1ae08745Sheppo 	    (strcmp(vbuf, ERIE_PLATNAME2) == 0)))
789*1ae08745Sheppo 		broken_md_flag = 1;
790*1ae08745Sheppo 
791*1ae08745Sheppo 	md_free_scan_dag(mdp, &platlist);
7927c478bd9Sstevel@tonic-gate }
793