xref: /illumos-gate/usr/src/uts/sun4v/promif/promif_emul.c (revision 9853d9e82e7a067a2b88dae2fd257207e6be5f94)
11ae08745Sheppo /*
21ae08745Sheppo  * CDDL HEADER START
31ae08745Sheppo  *
41ae08745Sheppo  * 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.
71ae08745Sheppo  *
81ae08745Sheppo  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91ae08745Sheppo  * or http://www.opensolaris.org/os/licensing.
101ae08745Sheppo  * See the License for the specific language governing permissions
111ae08745Sheppo  * and limitations under the License.
121ae08745Sheppo  *
131ae08745Sheppo  * When distributing Covered Code, include this CDDL HEADER in each
141ae08745Sheppo  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151ae08745Sheppo  * If applicable, add the following below this CDDL HEADER, with the
161ae08745Sheppo  * fields enclosed by brackets "[]" replaced with your own identifying
171ae08745Sheppo  * information: Portions Copyright [yyyy] [name of copyright owner]
181ae08745Sheppo  *
191ae08745Sheppo  * CDDL HEADER END
201ae08745Sheppo  */
211ae08745Sheppo 
221ae08745Sheppo /*
23*9853d9e8SJason Beloro  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
241ae08745Sheppo  * Use is subject to license terms.
251ae08745Sheppo  */
261ae08745Sheppo 
271ae08745Sheppo #include <sys/promif_impl.h>
281ae08745Sheppo #include <sys/machsystm.h>
291ae08745Sheppo #include <sys/lpad.h>
301ae08745Sheppo #include <sys/vmsystm.h>
311ae08745Sheppo #include <sys/prom_plat.h>
321ae08745Sheppo #include <sys/ldoms.h>
331ae08745Sheppo #include <sys/kobj.h>
341ae08745Sheppo #include <sys/reboot.h>
351ae08745Sheppo #include <sys/hypervisor_api.h>
364bac2208Snarayan #include <sys/mdesc.h>
374bac2208Snarayan #include <sys/mach_descrip.h>
38*9853d9e8SJason Beloro #include <sys/cpu_module.h>
391ae08745Sheppo 
401ae08745Sheppo #ifndef _KMDB
41*9853d9e8SJason Beloro #include <sys/pte.h>
42*9853d9e8SJason Beloro #include <vm/hat_sfmmu.h>
43*9853d9e8SJason Beloro #include <sys/memlist_impl.h>
44*9853d9e8SJason Beloro 
451ae08745Sheppo static processorid_t cif_cpu;
461ae08745Sheppo static struct translation *cif_prom_trans;
471ae08745Sheppo static size_t cif_prom_ntrans;
481ae08745Sheppo 
491ae08745Sheppo int cif_cpu_mp_ready;
501ae08745Sheppo int (*prom_cif_handler)(void *) = NULL;
51*9853d9e8SJason Beloro 
52*9853d9e8SJason Beloro extern struct memlist *phys_avail;
53*9853d9e8SJason Beloro extern struct vnode prom_ppages;
54*9853d9e8SJason Beloro extern void kdi_tlb_page_unlock(caddr_t, int);
55*9853d9e8SJason Beloro 
56*9853d9e8SJason Beloro #define	COMBINE(hi, lo) (((uint64_t)(uint32_t)(hi) << 32) | (uint32_t)(lo))
57*9853d9e8SJason Beloro #define	OFW_PT_START_ADDR	0xfffffffc00000000	/* OBP PT start */
58*9853d9e8SJason Beloro #define	OFW_PT_END_ADDR		0xffffffffffffffff	/* OBP PT end */
59*9853d9e8SJason Beloro 
60*9853d9e8SJason Beloro #define	PROM_ADDR(a)	(((a) >= OFW_START_ADDR && (a) <= OFW_END_ADDR) || \
61*9853d9e8SJason Beloro 			((a) >= OFW_PT_START_ADDR && (a) <= OFW_PT_END_ADDR))
621ae08745Sheppo #endif
631ae08745Sheppo 
641ae08745Sheppo #ifdef DEBUG
651ae08745Sheppo uint_t cif_debug;
66*9853d9e8SJason Beloro int prom_free_debug;
67*9853d9e8SJason Beloro #define	PMFREE_DEBUG(args...) if (prom_free_debug) printf(args)
68*9853d9e8SJason Beloro #else
69*9853d9e8SJason Beloro #define	PMFREE_DEBUG(args...)
70*9853d9e8SJason Beloro #endif
711ae08745Sheppo 
721ae08745Sheppo extern int (*cif_handler)(void *);
731ae08745Sheppo 
741ae08745Sheppo typedef struct {
751ae08745Sheppo 	char		*name;
761ae08745Sheppo 	cif_func_t	func;
771ae08745Sheppo } cif_callback_t;
781ae08745Sheppo 
791ae08745Sheppo static cif_callback_t cb_table[] = {
801ae08745Sheppo 	{ "getprop",			promif_getprop		    },
811ae08745Sheppo 	{ "getproplen",			promif_getproplen	    },
821ae08745Sheppo 	{ "nextprop",			promif_nextprop		    },
831ae08745Sheppo 	{ "peer",			promif_nextnode		    },
841ae08745Sheppo 	{ "child",			promif_childnode	    },
851ae08745Sheppo 	{ "parent",			promif_parentnode	    },
861ae08745Sheppo 	{ "enter",			promif_enter_mon	    },
871ae08745Sheppo 	{ "exit",			promif_exit_to_mon	    },
881ae08745Sheppo 	{ "boot",			promif_reboot		    },
891ae08745Sheppo 	{ "write",			promif_write		    },
901ae08745Sheppo 	{ "read",			promif_read		    },
911ae08745Sheppo 	{ "interpret",			promif_interpret	    },
921ae08745Sheppo 	{ "finddevice",			promif_finddevice	    },
931ae08745Sheppo 	{ "instance-to-package",	promif_instance_to_package  },
941ae08745Sheppo #ifndef _KMDB
951ae08745Sheppo 	{ "setprop",			promif_setprop		    },
961ae08745Sheppo 	{ "test",			promif_test		    },
971ae08745Sheppo 	{ "instance-to-path",		promif_instance_to_path	    },
981ae08745Sheppo 	{ "SUNW,power-off",		promif_power_off	    },
991ae08745Sheppo 	{ "SUNW,asr-list-keys-len",	promif_asr_list_keys_len    },
1001ae08745Sheppo 	{ "SUNW,asr-list-keys",		promif_asr_list_keys	    },
1011ae08745Sheppo 	{ "SUNW,asr-export-len",	promif_asr_export_len	    },
1021ae08745Sheppo 	{ "SUNW,asr-export",		promif_asr_export	    },
1031ae08745Sheppo 	{ "SUNW,set-security-key",	promif_set_security_key	    },
1041ae08745Sheppo 	{ "SUNW,get-security-key",	promif_get_security_key	    },
1051ae08745Sheppo 	{ "SUNW,start-cpu-by-cpuid",	promif_start_cpu	    },
1061ae08745Sheppo 	{ "SUNW,set-trap-table",	promif_set_mmfsa_traptable  },
1071ae08745Sheppo 	{ "SUNW,set-sun4v-api-version",	promif_set_sun4v_api_version },
1081ae08745Sheppo 	{ "SUNW,get-sun4v-api-version",	promif_get_sun4v_api_version },
1091ae08745Sheppo #endif
1101ae08745Sheppo 	{ NULL,				NULL			    }
1111ae08745Sheppo };
1121ae08745Sheppo 
1131ae08745Sheppo cif_func_t
1141ae08745Sheppo promif_find_cif_callback(char *opname)
1151ae08745Sheppo {
1161ae08745Sheppo 	cif_callback_t	*cb;
1171ae08745Sheppo 
1181ae08745Sheppo 	if (opname == NULL)
1191ae08745Sheppo 		return (NULL);
1201ae08745Sheppo 
1211ae08745Sheppo 	for (cb = cb_table; cb->name; cb++) {
1221ae08745Sheppo 		if (prom_strcmp(cb->name, opname) == 0)
1231ae08745Sheppo 			break;
1241ae08745Sheppo 	}
1251ae08745Sheppo 
1261ae08745Sheppo 	return (cb->func);
1271ae08745Sheppo }
1281ae08745Sheppo 
1291ae08745Sheppo static int
1301ae08745Sheppo kern_cif_handler(void *p)
1311ae08745Sheppo {
1321ae08745Sheppo 	cell_t		*ci = (cell_t *)p;
1331ae08745Sheppo 	char		*opname;
1341ae08745Sheppo 	cif_func_t	func;
1351ae08745Sheppo 	int		rv;
1361ae08745Sheppo 
1371ae08745Sheppo 	ASSERT(cif_handler == kern_cif_handler);
1381ae08745Sheppo 
1391ae08745Sheppo #ifndef _KMDB
1401ae08745Sheppo 	cif_cpu = getprocessorid();
1411ae08745Sheppo #endif
1421ae08745Sheppo 
1431ae08745Sheppo 	opname = p1275_cell2ptr(ci[0]);
1441ae08745Sheppo 
1451ae08745Sheppo 	/* lookup the callback for the desired operation */
1461ae08745Sheppo 	func = promif_find_cif_callback(opname);
1471ae08745Sheppo 
1481ae08745Sheppo 	if (func == NULL) {
1491ae08745Sheppo #ifdef _KMDB
1501ae08745Sheppo 		prom_fatal_error("sun4v unsupported CIFs\n");
1511ae08745Sheppo #else
1521ae08745Sheppo 		cmn_err(CE_CONT, "!sun4v unsupported CIF: %s\n", opname);
1531ae08745Sheppo 		return (-1);
1541ae08745Sheppo #endif
1551ae08745Sheppo 	}
1561ae08745Sheppo 
1571ae08745Sheppo 	/* callback found, execute it */
1581ae08745Sheppo 	rv = func(p);
1591ae08745Sheppo 
1601ae08745Sheppo #ifndef _KMDB
1611ae08745Sheppo 	cif_cpu = -1;
1621ae08745Sheppo #endif
1631ae08745Sheppo 
1641ae08745Sheppo 	return (rv);
1651ae08745Sheppo }
1661ae08745Sheppo 
1671ae08745Sheppo #ifdef _KMDB
1681ae08745Sheppo 
1691ae08745Sheppo void
1701ae08745Sheppo cif_init(char *pgmname, caddr_t root, ihandle_t in, ihandle_t out,
1711ae08745Sheppo     phandle_t pin, phandle_t pout, pnode_t chosen, pnode_t options)
1721ae08745Sheppo {
1731ae08745Sheppo 	/* initialize pointer to a copy of OBP device tree */
1741ae08745Sheppo 	promif_stree_setroot(root);
1751ae08745Sheppo 
1761ae08745Sheppo 	promif_set_nodes(chosen, options);
1771ae08745Sheppo 
1781ae08745Sheppo 	/* initialize io parameters */
1791ae08745Sheppo 	promif_io_init(in, out, pin, pout);
1801ae08745Sheppo 
1811ae08745Sheppo 	/*
1821ae08745Sheppo 	 * Switch CIF handler to the kernel.
1831ae08745Sheppo 	 */
1841ae08745Sheppo 	if (pgmname != NULL)
1851ae08745Sheppo 		prom_init(pgmname, (void *)kern_cif_handler);
1861ae08745Sheppo 	else
1871ae08745Sheppo 		cif_handler = kern_cif_handler;
1881ae08745Sheppo }
1891ae08745Sheppo 
1901ae08745Sheppo #else
1911ae08745Sheppo 
192*9853d9e8SJason Beloro static struct translation *
193*9853d9e8SJason Beloro read_prom_mappings(size_t *ntransp)
194*9853d9e8SJason Beloro {
195*9853d9e8SJason Beloro 	char *prop = "translations";
196*9853d9e8SJason Beloro 	pnode_t node;
197*9853d9e8SJason Beloro 	size_t translen;
198*9853d9e8SJason Beloro 	ihandle_t immu;
199*9853d9e8SJason Beloro 	struct translation *transroot;
200*9853d9e8SJason Beloro 
201*9853d9e8SJason Beloro 	*ntransp = 0;
202*9853d9e8SJason Beloro 
203*9853d9e8SJason Beloro 	/*
204*9853d9e8SJason Beloro 	 * the "translations" property is associated with the mmu node
205*9853d9e8SJason Beloro 	 */
206*9853d9e8SJason Beloro 	if ((immu = prom_mmu_ihandle()) == (ihandle_t)-1) {
207*9853d9e8SJason Beloro 		PMFREE_DEBUG("no mmu ihandle");
208*9853d9e8SJason Beloro 		return (NULL);
209*9853d9e8SJason Beloro 	}
210*9853d9e8SJason Beloro 	node = (pnode_t)prom_getphandle(immu);
211*9853d9e8SJason Beloro 	if (node == OBP_NONODE || node == OBP_BADNODE) {
212*9853d9e8SJason Beloro 		PMFREE_DEBUG("no mmu node");
213*9853d9e8SJason Beloro 		return (NULL);
214*9853d9e8SJason Beloro 	}
215*9853d9e8SJason Beloro 
216*9853d9e8SJason Beloro 	if ((translen = prom_getproplen(node, prop)) == -1) {
217*9853d9e8SJason Beloro 		PMFREE_DEBUG("no translations property");
218*9853d9e8SJason Beloro 		return (NULL);
219*9853d9e8SJason Beloro 	}
220*9853d9e8SJason Beloro 	transroot = (struct translation *)kmem_zalloc(translen, KM_SLEEP);
221*9853d9e8SJason Beloro 
222*9853d9e8SJason Beloro 	if (prom_getprop(node, prop, (caddr_t)transroot) == -1) {
223*9853d9e8SJason Beloro 		PMFREE_DEBUG("translations getprop failed");
224*9853d9e8SJason Beloro 		kmem_free(transroot, translen);
225*9853d9e8SJason Beloro 		return (NULL);
226*9853d9e8SJason Beloro 	}
227*9853d9e8SJason Beloro 	*ntransp = translen / sizeof (*transroot);
228*9853d9e8SJason Beloro 
229*9853d9e8SJason Beloro 	return (transroot);
230*9853d9e8SJason Beloro }
231*9853d9e8SJason Beloro 
232*9853d9e8SJason Beloro static void
233*9853d9e8SJason Beloro unmap_prom_mappings(struct translation *transroot, size_t ntransroot)
234*9853d9e8SJason Beloro {
235*9853d9e8SJason Beloro 	int i, j, rv;
236*9853d9e8SJason Beloro 	int npgs, nunmapped, nfreed, nskipped;
237*9853d9e8SJason Beloro 	char *p;
238*9853d9e8SJason Beloro 	tte_t tte;
239*9853d9e8SJason Beloro 	pfn_t pfn;
240*9853d9e8SJason Beloro 	page_t *pp;
241*9853d9e8SJason Beloro 	uint64_t vaddr;
242*9853d9e8SJason Beloro 	struct translation *promt;
243*9853d9e8SJason Beloro 	cpuset_t other_cpus;
244*9853d9e8SJason Beloro 
245*9853d9e8SJason Beloro 	/*
246*9853d9e8SJason Beloro 	 * During startup isa_list is allocated in OBP address space
247*9853d9e8SJason Beloro 	 * so it needs to be re-allocated in kernel address space
248*9853d9e8SJason Beloro 	 * before OBP memory is unmapped.
249*9853d9e8SJason Beloro 	 *
250*9853d9e8SJason Beloro 	 * see cpu_setup_common().
251*9853d9e8SJason Beloro 	 */
252*9853d9e8SJason Beloro 	p = kmem_zalloc(strlen(isa_list) + 1, KM_SLEEP);
253*9853d9e8SJason Beloro 	(void) strcpy(p, isa_list);
254*9853d9e8SJason Beloro 	isa_list = p;
255*9853d9e8SJason Beloro 
256*9853d9e8SJason Beloro 	nfreed = 0;
257*9853d9e8SJason Beloro 	nunmapped = 0;
258*9853d9e8SJason Beloro 	nskipped = 0;
259*9853d9e8SJason Beloro 
260*9853d9e8SJason Beloro 	for (i = 0, promt = transroot; i < ntransroot; i++, promt++) {
261*9853d9e8SJason Beloro 		ASSERT(promt->tte_hi != 0);
262*9853d9e8SJason Beloro 		ASSERT32(promt->virt_hi == 0 && promt->size_hi == 0);
263*9853d9e8SJason Beloro 
264*9853d9e8SJason Beloro 		vaddr = COMBINE(promt->virt_hi, promt->virt_lo);
265*9853d9e8SJason Beloro 
266*9853d9e8SJason Beloro 		if (!PROM_ADDR(vaddr)) {
267*9853d9e8SJason Beloro 			nskipped++;
268*9853d9e8SJason Beloro 			continue;
269*9853d9e8SJason Beloro 		}
270*9853d9e8SJason Beloro 
271*9853d9e8SJason Beloro 		npgs = mmu_btopr(COMBINE(promt->size_hi, promt->size_lo));
272*9853d9e8SJason Beloro 
273*9853d9e8SJason Beloro 		if (npgs > 1) {
274*9853d9e8SJason Beloro 			PMFREE_DEBUG("large trans vaddr=0x%lx, npgs=%d\n",
275*9853d9e8SJason Beloro 			    vaddr, npgs);
276*9853d9e8SJason Beloro 		}
277*9853d9e8SJason Beloro 		for (j = 0; j < npgs; j++) {
278*9853d9e8SJason Beloro 
279*9853d9e8SJason Beloro 			pfn = sfmmu_vatopfn((caddr_t)vaddr, KHATID, &tte);
280*9853d9e8SJason Beloro 
281*9853d9e8SJason Beloro 			if (pfn == PFN_INVALID) {
282*9853d9e8SJason Beloro 				tte.tte_inthi = promt->tte_hi;
283*9853d9e8SJason Beloro 				tte.tte_intlo = promt->tte_lo;
284*9853d9e8SJason Beloro 				pfn = TTE_TO_PFN((caddr_t)COMBINE(
285*9853d9e8SJason Beloro 				    promt->virt_hi, promt->virt_lo), &tte);
286*9853d9e8SJason Beloro 				PMFREE_DEBUG(
287*9853d9e8SJason Beloro 				    "no mapping for vaddr=0x%lx (opfn=0x%lx)\n",
288*9853d9e8SJason Beloro 				    vaddr, pfn);
289*9853d9e8SJason Beloro 				break;
290*9853d9e8SJason Beloro 			}
291*9853d9e8SJason Beloro 			ASSERT(!TTE_IS_LOCKED(&tte));
292*9853d9e8SJason Beloro 			ASSERT(TTE_IS_8K(&tte));
293*9853d9e8SJason Beloro 
294*9853d9e8SJason Beloro 			/*
295*9853d9e8SJason Beloro 			 * Unload the current mapping for the page and
296*9853d9e8SJason Beloro 			 * if it is the last mapping, free the page.
297*9853d9e8SJason Beloro 			 */
298*9853d9e8SJason Beloro 			pp = page_numtopp_nolock(pfn);
299*9853d9e8SJason Beloro 			PMFREE_DEBUG("unmap vaddr=0x%lx pfn=0x%lx pp=0x%p",
300*9853d9e8SJason Beloro 			    vaddr, pfn, (void *)pp);
301*9853d9e8SJason Beloro 			ASSERT(pp);
302*9853d9e8SJason Beloro 			ASSERT(PAGE_EXCL(pp));
303*9853d9e8SJason Beloro 			ASSERT(PP_ISNORELOC(pp));
304*9853d9e8SJason Beloro 			ASSERT(!PP_ISFREE(pp));
305*9853d9e8SJason Beloro 			ASSERT(page_find(&prom_ppages, pfn));
306*9853d9e8SJason Beloro 			ASSERT(page_get_pagecnt(pp->p_szc) == 1);
307*9853d9e8SJason Beloro 
308*9853d9e8SJason Beloro 			hat_unload(kas.a_hat, (caddr_t)vaddr, PAGESIZE,
309*9853d9e8SJason Beloro 			    HAT_UNLOAD_UNLOCK);
310*9853d9e8SJason Beloro 
311*9853d9e8SJason Beloro 			if (pp->p_mapping) {
312*9853d9e8SJason Beloro 				PMFREE_DEBUG(" skip\n");
313*9853d9e8SJason Beloro 			} else {
314*9853d9e8SJason Beloro 				PP_CLRNORELOC(pp);
315*9853d9e8SJason Beloro 				page_destroy(pp, 0);
316*9853d9e8SJason Beloro 				memlist_write_lock();
317*9853d9e8SJason Beloro 				rv = memlist_add_span(pfn << PAGESHIFT,
318*9853d9e8SJason Beloro 				    PAGESIZE, &phys_avail);
319*9853d9e8SJason Beloro 				ASSERT(rv == MEML_SPANOP_OK);
320*9853d9e8SJason Beloro 				memlist_write_unlock();
321*9853d9e8SJason Beloro 				PMFREE_DEBUG(" free\n");
322*9853d9e8SJason Beloro 				nfreed++;
323*9853d9e8SJason Beloro 			}
324*9853d9e8SJason Beloro 			nunmapped++;
325*9853d9e8SJason Beloro 			vaddr += PAGESIZE;
326*9853d9e8SJason Beloro 		}
327*9853d9e8SJason Beloro 	}
328*9853d9e8SJason Beloro 
329*9853d9e8SJason Beloro 	if (transroot) {
330*9853d9e8SJason Beloro 		PMFREE_DEBUG("nunmapped=%d nfreed=%d nskipped=%d\n",
331*9853d9e8SJason Beloro 		    nunmapped, nfreed, nskipped);
332*9853d9e8SJason Beloro 		kmem_free(transroot, ntransroot * sizeof (*transroot));
333*9853d9e8SJason Beloro 	}
334*9853d9e8SJason Beloro 
335*9853d9e8SJason Beloro 	/*
336*9853d9e8SJason Beloro 	 * Unload OBP permanent mappings.
337*9853d9e8SJason Beloro 	 */
338*9853d9e8SJason Beloro 	kdi_tlb_page_unlock((caddr_t)OFW_START_ADDR, 1);
339*9853d9e8SJason Beloro 	kpreempt_disable();
340*9853d9e8SJason Beloro 	other_cpus = cpu_ready_set;
341*9853d9e8SJason Beloro 	CPUSET_DEL(other_cpus, CPU->cpu_id);
342*9853d9e8SJason Beloro 	xt_some(other_cpus, vtag_unmap_perm_tl1, (uint64_t)OFW_START_ADDR,
343*9853d9e8SJason Beloro 	    KCONTEXT);
344*9853d9e8SJason Beloro 	kpreempt_enable();
345*9853d9e8SJason Beloro }
346*9853d9e8SJason Beloro 
3471ae08745Sheppo static void cache_prom_data(void);
3481ae08745Sheppo 
3491ae08745Sheppo /*
3501ae08745Sheppo  * This function returns 1 if the current thread is executing in
3511ae08745Sheppo  * the CIF and 0 otherwise. This is useful information to know
3521ae08745Sheppo  * since code that implements CIF handlers can assume that it has
3531ae08745Sheppo  * gone through the kern_preprom() entry point, implying it is
3541ae08745Sheppo  * running single threaded, has preemption disabled, etc.
3551ae08745Sheppo  */
3561ae08745Sheppo int
3571ae08745Sheppo promif_in_cif(void)
3581ae08745Sheppo {
3591ae08745Sheppo 	int	mycpuid = getprocessorid();
3601ae08745Sheppo 
3611ae08745Sheppo 	return ((cif_cpu == mycpuid) ? 1 : 0);
3621ae08745Sheppo }
3631ae08745Sheppo 
3644bac2208Snarayan /*
3654bac2208Snarayan  * Check that all cpus in the MD are within range (< NCPU).  Attempt
3664bac2208Snarayan  * to stop any that aren't.
3674bac2208Snarayan  */
3684bac2208Snarayan static void
3694bac2208Snarayan cif_check_cpus(void)
3704bac2208Snarayan {
3714bac2208Snarayan 	md_t		*mdp;
3724bac2208Snarayan 	mde_cookie_t	rootnode;
3734bac2208Snarayan 	size_t		listsz;
3744bac2208Snarayan 	int		i;
3754bac2208Snarayan 	mde_cookie_t	*listp = NULL;
3764bac2208Snarayan 	int		num_nodes;
3774bac2208Snarayan 	uint64_t	cpuid;
3784bac2208Snarayan 	int		status;
3794bac2208Snarayan 
3804bac2208Snarayan 	mdp = md_get_handle();
3814bac2208Snarayan 	ASSERT(mdp);
3824bac2208Snarayan 
3834bac2208Snarayan 	rootnode = md_root_node(mdp);
3844bac2208Snarayan 	ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE);
3854bac2208Snarayan 
3864bac2208Snarayan 	num_nodes = md_node_count(mdp);
3874bac2208Snarayan 	ASSERT(num_nodes > 0);
3884bac2208Snarayan 
3894bac2208Snarayan 	listsz = num_nodes * sizeof (mde_cookie_t);
3904bac2208Snarayan 	listp = kmem_zalloc(listsz, KM_SLEEP);
3914bac2208Snarayan 
3924bac2208Snarayan 	num_nodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "cpu"),
3934bac2208Snarayan 	    md_find_name(mdp, "fwd"), listp);
3944bac2208Snarayan 
3954bac2208Snarayan 	if (num_nodes <= 0)
3964bac2208Snarayan 		goto done;
3974bac2208Snarayan 
3984bac2208Snarayan 	for (i = 0; i < num_nodes; i++) {
3994bac2208Snarayan 		if (md_get_prop_val(mdp, listp[i], "id", &cpuid)) {
4004bac2208Snarayan 			cmn_err(CE_WARN, "cif_check_cpus: "
4014bac2208Snarayan 			    "CPU instance %d has no 'id' property", i);
4024bac2208Snarayan 			continue;
4034bac2208Snarayan 		}
4044bac2208Snarayan 
4054bac2208Snarayan 		mutex_enter(&cpu_lock);
4064bac2208Snarayan 
4074bac2208Snarayan 		if (cpuid >= NCPU) {
4084bac2208Snarayan 			status = stopcpu_bycpuid(cpuid);
4094bac2208Snarayan 			if (status != 0 && status != ENOTSUP)
4104bac2208Snarayan 				cmn_err(CE_PANIC, "failed to stop cpu %lu (%d)",
4114bac2208Snarayan 				    cpuid, status);
4124bac2208Snarayan 		}
4134bac2208Snarayan 
4144bac2208Snarayan 		mutex_exit(&cpu_lock);
4154bac2208Snarayan 	}
4164bac2208Snarayan 
4174bac2208Snarayan done:
4184bac2208Snarayan 	kmem_free(listp, listsz);
419a3f75865Sjm22469 	(void) md_fini_handle(mdp);
4204bac2208Snarayan }
4214bac2208Snarayan 
4221ae08745Sheppo void
4231ae08745Sheppo cif_init(void)
4241ae08745Sheppo {
4251ae08745Sheppo 	void (*kmdb_cb)(void);
4261ae08745Sheppo 	uint64_t rtba;
4271ae08745Sheppo 	uint64_t rv;
428*9853d9e8SJason Beloro 	size_t ntransroot;
429*9853d9e8SJason Beloro 	struct translation *transroot;
4301ae08745Sheppo 
4311ae08745Sheppo 	/*
4321ae08745Sheppo 	 * Check if domaining is enabled. If not, do not
4331ae08745Sheppo 	 * initialize the kernel CIF handler.
4341ae08745Sheppo 	 */
43522e19ac1Sjm22469 	if (!domaining_enabled())
4361ae08745Sheppo 		return;
4371ae08745Sheppo 
438*9853d9e8SJason Beloro 	transroot = read_prom_mappings(&ntransroot);
439*9853d9e8SJason Beloro 
4401ae08745Sheppo 	/*
4411ae08745Sheppo 	 * Cache PROM data that is needed later, e.g. a shadow
4421ae08745Sheppo 	 * copy of the device tree, IO mappings, etc.
4431ae08745Sheppo 	 */
4441ae08745Sheppo 	cache_prom_data();
4451ae08745Sheppo 
4461ae08745Sheppo 	/*
4471ae08745Sheppo 	 * Prepare to take over the get/set of environmental variables.
4481ae08745Sheppo 	 */
4491ae08745Sheppo 	promif_prop_init();
4501ae08745Sheppo 
4511ae08745Sheppo 	/*
4521ae08745Sheppo 	 * Switch CIF handler to the kernel.
4531ae08745Sheppo 	 */
4541ae08745Sheppo 	prom_cif_handler = cif_handler;
4551ae08745Sheppo 
4561ae08745Sheppo 	promif_preprom();
4571ae08745Sheppo 	cif_handler = kern_cif_handler;
4581ae08745Sheppo 
4591ae08745Sheppo 	/*
4601ae08745Sheppo 	 * Take over rtba for the boot CPU. The rtba for
4611ae08745Sheppo 	 * all other CPUs are set as they enter the system.
4621ae08745Sheppo 	 */
4631ae08745Sheppo 	rtba = va_to_pa(&trap_table);
4641ae08745Sheppo 	if ((rv = hv_cpu_set_rtba(&rtba)) != H_EOK)
4651ae08745Sheppo 		panic("hv_cpu_set_rtba failed: %ld\n", rv);
4661ae08745Sheppo 
4671ae08745Sheppo 	promif_postprom();
4681ae08745Sheppo 
4691ae08745Sheppo 	/*
4701ae08745Sheppo 	 * If the system has been booted with kmdb we need kmdb to
4711ae08745Sheppo 	 * use the kernel cif handler instead of the PROM cif handler.
4721ae08745Sheppo 	 */
4731ae08745Sheppo 	if (boothowto & RB_KMDB) {
4741ae08745Sheppo 		kmdb_cb = (void (*)(void))modlookup("misc/kmdbmod",
4751ae08745Sheppo 		    "kctl_switch_promif");
4761ae08745Sheppo 		ASSERT(kmdb_cb != NULL);
4771ae08745Sheppo 		(*kmdb_cb)();
4781ae08745Sheppo 	}
4794bac2208Snarayan 
4804bac2208Snarayan 	cif_check_cpus();
481*9853d9e8SJason Beloro 
482*9853d9e8SJason Beloro 	if (transroot != NULL)
483*9853d9e8SJason Beloro 		unmap_prom_mappings(transroot, ntransroot);
4841ae08745Sheppo }
4851ae08745Sheppo 
4861ae08745Sheppo static void
4871ae08745Sheppo cache_prom_data(void)
4881ae08745Sheppo {
4891ae08745Sheppo 	/* initialize copy of OBP device tree */
4901ae08745Sheppo 	promif_stree_init();
4911ae08745Sheppo 
4921ae08745Sheppo 	/* initialize io parameters */
4931ae08745Sheppo 	promif_io_init();
4941ae08745Sheppo }
4951ae08745Sheppo 
4961ae08745Sheppo #endif	/* _KMDB */
497