xref: /onnv-gate/usr/src/uts/sun4v/promif/promif_emul.c (revision 11185:f0c31008e395)
11991Sheppo /*
21991Sheppo  * CDDL HEADER START
31991Sheppo  *
41991Sheppo  * The contents of this file are subject to the terms of the
51991Sheppo  * Common Development and Distribution License (the "License").
61991Sheppo  * You may not use this file except in compliance with the License.
71991Sheppo  *
81991Sheppo  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91991Sheppo  * or http://www.opensolaris.org/os/licensing.
101991Sheppo  * See the License for the specific language governing permissions
111991Sheppo  * and limitations under the License.
121991Sheppo  *
131991Sheppo  * When distributing Covered Code, include this CDDL HEADER in each
141991Sheppo  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151991Sheppo  * If applicable, add the following below this CDDL HEADER, with the
161991Sheppo  * fields enclosed by brackets "[]" replaced with your own identifying
171991Sheppo  * information: Portions Copyright [yyyy] [name of copyright owner]
181991Sheppo  *
191991Sheppo  * CDDL HEADER END
201991Sheppo  */
211991Sheppo 
221991Sheppo /*
2310106SJason.Beloro@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
241991Sheppo  * Use is subject to license terms.
251991Sheppo  */
261991Sheppo 
271991Sheppo #include <sys/promif_impl.h>
281991Sheppo #include <sys/machsystm.h>
291991Sheppo #include <sys/lpad.h>
301991Sheppo #include <sys/vmsystm.h>
311991Sheppo #include <sys/prom_plat.h>
321991Sheppo #include <sys/ldoms.h>
331991Sheppo #include <sys/kobj.h>
341991Sheppo #include <sys/reboot.h>
351991Sheppo #include <sys/hypervisor_api.h>
362531Snarayan #include <sys/mdesc.h>
372531Snarayan #include <sys/mach_descrip.h>
3810106SJason.Beloro@Sun.COM #include <sys/cpu_module.h>
39*11185SSean.McEnroe@Sun.COM #include <vm/seg_kmem.h>
401991Sheppo 
411991Sheppo #ifndef _KMDB
4210106SJason.Beloro@Sun.COM #include <sys/pte.h>
4310106SJason.Beloro@Sun.COM #include <vm/hat_sfmmu.h>
4410106SJason.Beloro@Sun.COM #include <sys/memlist_impl.h>
4510106SJason.Beloro@Sun.COM 
461991Sheppo static processorid_t cif_cpu;
471991Sheppo static struct translation *cif_prom_trans;
481991Sheppo static size_t cif_prom_ntrans;
491991Sheppo 
501991Sheppo int cif_cpu_mp_ready;
511991Sheppo int (*prom_cif_handler)(void *) = NULL;
5210106SJason.Beloro@Sun.COM 
5310106SJason.Beloro@Sun.COM extern struct memlist *phys_avail;
54*11185SSean.McEnroe@Sun.COM extern struct vnode promvp;
5510106SJason.Beloro@Sun.COM extern void kdi_tlb_page_unlock(caddr_t, int);
5610106SJason.Beloro@Sun.COM 
5710106SJason.Beloro@Sun.COM #define	COMBINE(hi, lo) (((uint64_t)(uint32_t)(hi) << 32) | (uint32_t)(lo))
5810106SJason.Beloro@Sun.COM #define	OFW_PT_START_ADDR	0xfffffffc00000000	/* OBP PT start */
5910106SJason.Beloro@Sun.COM #define	OFW_PT_END_ADDR		0xffffffffffffffff	/* OBP PT end */
6010106SJason.Beloro@Sun.COM 
6110106SJason.Beloro@Sun.COM #define	PROM_ADDR(a)	(((a) >= OFW_START_ADDR && (a) <= OFW_END_ADDR) || \
6210106SJason.Beloro@Sun.COM 			((a) >= OFW_PT_START_ADDR && (a) <= OFW_PT_END_ADDR))
631991Sheppo #endif
641991Sheppo 
651991Sheppo #ifdef DEBUG
661991Sheppo uint_t cif_debug;
6710106SJason.Beloro@Sun.COM int prom_free_debug;
6810106SJason.Beloro@Sun.COM #define	PMFREE_DEBUG(args...) if (prom_free_debug) printf(args)
6910106SJason.Beloro@Sun.COM #else
7010106SJason.Beloro@Sun.COM #define	PMFREE_DEBUG(args...)
7110106SJason.Beloro@Sun.COM #endif
721991Sheppo 
731991Sheppo extern int (*cif_handler)(void *);
741991Sheppo 
751991Sheppo typedef struct {
761991Sheppo 	char		*name;
771991Sheppo 	cif_func_t	func;
781991Sheppo } cif_callback_t;
791991Sheppo 
801991Sheppo static cif_callback_t cb_table[] = {
811991Sheppo 	{ "getprop",			promif_getprop		    },
821991Sheppo 	{ "getproplen",			promif_getproplen	    },
831991Sheppo 	{ "nextprop",			promif_nextprop		    },
841991Sheppo 	{ "peer",			promif_nextnode		    },
851991Sheppo 	{ "child",			promif_childnode	    },
861991Sheppo 	{ "parent",			promif_parentnode	    },
871991Sheppo 	{ "enter",			promif_enter_mon	    },
881991Sheppo 	{ "exit",			promif_exit_to_mon	    },
891991Sheppo 	{ "boot",			promif_reboot		    },
901991Sheppo 	{ "write",			promif_write		    },
911991Sheppo 	{ "read",			promif_read		    },
921991Sheppo 	{ "interpret",			promif_interpret	    },
931991Sheppo 	{ "finddevice",			promif_finddevice	    },
941991Sheppo 	{ "instance-to-package",	promif_instance_to_package  },
951991Sheppo #ifndef _KMDB
961991Sheppo 	{ "setprop",			promif_setprop		    },
971991Sheppo 	{ "test",			promif_test		    },
981991Sheppo 	{ "instance-to-path",		promif_instance_to_path	    },
991991Sheppo 	{ "SUNW,power-off",		promif_power_off	    },
1001991Sheppo 	{ "SUNW,asr-list-keys-len",	promif_asr_list_keys_len    },
1011991Sheppo 	{ "SUNW,asr-list-keys",		promif_asr_list_keys	    },
1021991Sheppo 	{ "SUNW,asr-export-len",	promif_asr_export_len	    },
1031991Sheppo 	{ "SUNW,asr-export",		promif_asr_export	    },
1041991Sheppo 	{ "SUNW,set-security-key",	promif_set_security_key	    },
1051991Sheppo 	{ "SUNW,get-security-key",	promif_get_security_key	    },
1061991Sheppo 	{ "SUNW,start-cpu-by-cpuid",	promif_start_cpu	    },
1071991Sheppo 	{ "SUNW,set-trap-table",	promif_set_mmfsa_traptable  },
1081991Sheppo 	{ "SUNW,set-sun4v-api-version",	promif_set_sun4v_api_version },
1091991Sheppo 	{ "SUNW,get-sun4v-api-version",	promif_get_sun4v_api_version },
1101991Sheppo #endif
1111991Sheppo 	{ NULL,				NULL			    }
1121991Sheppo };
1131991Sheppo 
1141991Sheppo cif_func_t
promif_find_cif_callback(char * opname)1151991Sheppo promif_find_cif_callback(char *opname)
1161991Sheppo {
1171991Sheppo 	cif_callback_t	*cb;
1181991Sheppo 
1191991Sheppo 	if (opname == NULL)
1201991Sheppo 		return (NULL);
1211991Sheppo 
1221991Sheppo 	for (cb = cb_table; cb->name; cb++) {
1231991Sheppo 		if (prom_strcmp(cb->name, opname) == 0)
1241991Sheppo 			break;
1251991Sheppo 	}
1261991Sheppo 
1271991Sheppo 	return (cb->func);
1281991Sheppo }
1291991Sheppo 
1301991Sheppo static int
kern_cif_handler(void * p)1311991Sheppo kern_cif_handler(void *p)
1321991Sheppo {
1331991Sheppo 	cell_t		*ci = (cell_t *)p;
1341991Sheppo 	char		*opname;
1351991Sheppo 	cif_func_t	func;
1361991Sheppo 	int		rv;
1371991Sheppo 
1381991Sheppo 	ASSERT(cif_handler == kern_cif_handler);
1391991Sheppo 
1401991Sheppo #ifndef _KMDB
1411991Sheppo 	cif_cpu = getprocessorid();
1421991Sheppo #endif
1431991Sheppo 
1441991Sheppo 	opname = p1275_cell2ptr(ci[0]);
1451991Sheppo 
1461991Sheppo 	/* lookup the callback for the desired operation */
1471991Sheppo 	func = promif_find_cif_callback(opname);
1481991Sheppo 
1491991Sheppo 	if (func == NULL) {
1501991Sheppo #ifdef _KMDB
1511991Sheppo 		prom_fatal_error("sun4v unsupported CIFs\n");
1521991Sheppo #else
1531991Sheppo 		cmn_err(CE_CONT, "!sun4v unsupported CIF: %s\n", opname);
1541991Sheppo 		return (-1);
1551991Sheppo #endif
1561991Sheppo 	}
1571991Sheppo 
1581991Sheppo 	/* callback found, execute it */
1591991Sheppo 	rv = func(p);
1601991Sheppo 
1611991Sheppo #ifndef _KMDB
1621991Sheppo 	cif_cpu = -1;
1631991Sheppo #endif
1641991Sheppo 
1651991Sheppo 	return (rv);
1661991Sheppo }
1671991Sheppo 
1681991Sheppo #ifdef _KMDB
1691991Sheppo 
1701991Sheppo void
cif_init(char * pgmname,caddr_t root,ihandle_t in,ihandle_t out,phandle_t pin,phandle_t pout,pnode_t chosen,pnode_t options)1711991Sheppo cif_init(char *pgmname, caddr_t root, ihandle_t in, ihandle_t out,
1721991Sheppo     phandle_t pin, phandle_t pout, pnode_t chosen, pnode_t options)
1731991Sheppo {
1741991Sheppo 	/* initialize pointer to a copy of OBP device tree */
1751991Sheppo 	promif_stree_setroot(root);
1761991Sheppo 
1771991Sheppo 	promif_set_nodes(chosen, options);
1781991Sheppo 
1791991Sheppo 	/* initialize io parameters */
1801991Sheppo 	promif_io_init(in, out, pin, pout);
1811991Sheppo 
1821991Sheppo 	/*
1831991Sheppo 	 * Switch CIF handler to the kernel.
1841991Sheppo 	 */
1851991Sheppo 	if (pgmname != NULL)
1861991Sheppo 		prom_init(pgmname, (void *)kern_cif_handler);
1871991Sheppo 	else
1881991Sheppo 		cif_handler = kern_cif_handler;
1891991Sheppo }
1901991Sheppo 
1911991Sheppo #else
1921991Sheppo 
19310106SJason.Beloro@Sun.COM static struct translation *
read_prom_mappings(size_t * ntransp)19410106SJason.Beloro@Sun.COM read_prom_mappings(size_t *ntransp)
19510106SJason.Beloro@Sun.COM {
19610106SJason.Beloro@Sun.COM 	char *prop = "translations";
19710106SJason.Beloro@Sun.COM 	pnode_t node;
19810106SJason.Beloro@Sun.COM 	size_t translen;
19910106SJason.Beloro@Sun.COM 	ihandle_t immu;
20010106SJason.Beloro@Sun.COM 	struct translation *transroot;
20110106SJason.Beloro@Sun.COM 
20210106SJason.Beloro@Sun.COM 	*ntransp = 0;
20310106SJason.Beloro@Sun.COM 
20410106SJason.Beloro@Sun.COM 	/*
20510106SJason.Beloro@Sun.COM 	 * the "translations" property is associated with the mmu node
20610106SJason.Beloro@Sun.COM 	 */
20710106SJason.Beloro@Sun.COM 	if ((immu = prom_mmu_ihandle()) == (ihandle_t)-1) {
20810106SJason.Beloro@Sun.COM 		PMFREE_DEBUG("no mmu ihandle");
20910106SJason.Beloro@Sun.COM 		return (NULL);
21010106SJason.Beloro@Sun.COM 	}
21110106SJason.Beloro@Sun.COM 	node = (pnode_t)prom_getphandle(immu);
21210106SJason.Beloro@Sun.COM 	if (node == OBP_NONODE || node == OBP_BADNODE) {
21310106SJason.Beloro@Sun.COM 		PMFREE_DEBUG("no mmu node");
21410106SJason.Beloro@Sun.COM 		return (NULL);
21510106SJason.Beloro@Sun.COM 	}
21610106SJason.Beloro@Sun.COM 
21710106SJason.Beloro@Sun.COM 	if ((translen = prom_getproplen(node, prop)) == -1) {
21810106SJason.Beloro@Sun.COM 		PMFREE_DEBUG("no translations property");
21910106SJason.Beloro@Sun.COM 		return (NULL);
22010106SJason.Beloro@Sun.COM 	}
22110106SJason.Beloro@Sun.COM 	transroot = (struct translation *)kmem_zalloc(translen, KM_SLEEP);
22210106SJason.Beloro@Sun.COM 
22310106SJason.Beloro@Sun.COM 	if (prom_getprop(node, prop, (caddr_t)transroot) == -1) {
22410106SJason.Beloro@Sun.COM 		PMFREE_DEBUG("translations getprop failed");
22510106SJason.Beloro@Sun.COM 		kmem_free(transroot, translen);
22610106SJason.Beloro@Sun.COM 		return (NULL);
22710106SJason.Beloro@Sun.COM 	}
22810106SJason.Beloro@Sun.COM 	*ntransp = translen / sizeof (*transroot);
22910106SJason.Beloro@Sun.COM 
23010106SJason.Beloro@Sun.COM 	return (transroot);
23110106SJason.Beloro@Sun.COM }
23210106SJason.Beloro@Sun.COM 
23310106SJason.Beloro@Sun.COM static void
unmap_prom_mappings(struct translation * transroot,size_t ntransroot)23410106SJason.Beloro@Sun.COM unmap_prom_mappings(struct translation *transroot, size_t ntransroot)
23510106SJason.Beloro@Sun.COM {
23610106SJason.Beloro@Sun.COM 	int i, j, rv;
23710292Sbijan.mottahedeh@sun.com 	int npgs, nunmapped, nfreed, nskipped, nskipped_io;
23810106SJason.Beloro@Sun.COM 	char *p;
23910106SJason.Beloro@Sun.COM 	tte_t tte;
24010106SJason.Beloro@Sun.COM 	pfn_t pfn;
24110106SJason.Beloro@Sun.COM 	page_t *pp;
24210106SJason.Beloro@Sun.COM 	uint64_t vaddr;
24310106SJason.Beloro@Sun.COM 	struct translation *promt;
24410106SJason.Beloro@Sun.COM 	cpuset_t other_cpus;
24510106SJason.Beloro@Sun.COM 
24610106SJason.Beloro@Sun.COM 	/*
24710106SJason.Beloro@Sun.COM 	 * During startup isa_list is allocated in OBP address space
24810106SJason.Beloro@Sun.COM 	 * so it needs to be re-allocated in kernel address space
24910106SJason.Beloro@Sun.COM 	 * before OBP memory is unmapped.
25010106SJason.Beloro@Sun.COM 	 *
25110106SJason.Beloro@Sun.COM 	 * see cpu_setup_common().
25210106SJason.Beloro@Sun.COM 	 */
25310106SJason.Beloro@Sun.COM 	p = kmem_zalloc(strlen(isa_list) + 1, KM_SLEEP);
25410106SJason.Beloro@Sun.COM 	(void) strcpy(p, isa_list);
25510106SJason.Beloro@Sun.COM 	isa_list = p;
25610106SJason.Beloro@Sun.COM 
25710106SJason.Beloro@Sun.COM 	nfreed = 0;
25810106SJason.Beloro@Sun.COM 	nunmapped = 0;
25910106SJason.Beloro@Sun.COM 	nskipped = 0;
26010292Sbijan.mottahedeh@sun.com 	nskipped_io = 0;
26110106SJason.Beloro@Sun.COM 
26210106SJason.Beloro@Sun.COM 	for (i = 0, promt = transroot; i < ntransroot; i++, promt++) {
26310106SJason.Beloro@Sun.COM 		ASSERT(promt->tte_hi != 0);
26410106SJason.Beloro@Sun.COM 		ASSERT32(promt->virt_hi == 0 && promt->size_hi == 0);
26510106SJason.Beloro@Sun.COM 
26610106SJason.Beloro@Sun.COM 		vaddr = COMBINE(promt->virt_hi, promt->virt_lo);
26710106SJason.Beloro@Sun.COM 
26810106SJason.Beloro@Sun.COM 		if (!PROM_ADDR(vaddr)) {
26910106SJason.Beloro@Sun.COM 			nskipped++;
27010106SJason.Beloro@Sun.COM 			continue;
27110106SJason.Beloro@Sun.COM 		}
27210106SJason.Beloro@Sun.COM 
27310106SJason.Beloro@Sun.COM 		npgs = mmu_btopr(COMBINE(promt->size_hi, promt->size_lo));
27410106SJason.Beloro@Sun.COM 
27510106SJason.Beloro@Sun.COM 		if (npgs > 1) {
27610106SJason.Beloro@Sun.COM 			PMFREE_DEBUG("large trans vaddr=0x%lx, npgs=%d\n",
27710106SJason.Beloro@Sun.COM 			    vaddr, npgs);
27810106SJason.Beloro@Sun.COM 		}
27910106SJason.Beloro@Sun.COM 		for (j = 0; j < npgs; j++) {
28010106SJason.Beloro@Sun.COM 
28110106SJason.Beloro@Sun.COM 			pfn = sfmmu_vatopfn((caddr_t)vaddr, KHATID, &tte);
28210106SJason.Beloro@Sun.COM 
28310106SJason.Beloro@Sun.COM 			if (pfn == PFN_INVALID) {
28410106SJason.Beloro@Sun.COM 				tte.tte_inthi = promt->tte_hi;
28510106SJason.Beloro@Sun.COM 				tte.tte_intlo = promt->tte_lo;
28610106SJason.Beloro@Sun.COM 				pfn = TTE_TO_PFN((caddr_t)COMBINE(
28710106SJason.Beloro@Sun.COM 				    promt->virt_hi, promt->virt_lo), &tte);
28810106SJason.Beloro@Sun.COM 				PMFREE_DEBUG(
28910106SJason.Beloro@Sun.COM 				    "no mapping for vaddr=0x%lx (opfn=0x%lx)\n",
29010106SJason.Beloro@Sun.COM 				    vaddr, pfn);
29110106SJason.Beloro@Sun.COM 				break;
29210106SJason.Beloro@Sun.COM 			}
29310106SJason.Beloro@Sun.COM 			ASSERT(!TTE_IS_LOCKED(&tte));
29410106SJason.Beloro@Sun.COM 			ASSERT(TTE_IS_8K(&tte));
29510106SJason.Beloro@Sun.COM 
29610106SJason.Beloro@Sun.COM 			/*
29710292Sbijan.mottahedeh@sun.com 			 * Unload the current mapping for the pfn and
29810292Sbijan.mottahedeh@sun.com 			 * if it is the last mapping for a memory page,
29910292Sbijan.mottahedeh@sun.com 			 * free the page.
30010106SJason.Beloro@Sun.COM 			 */
30110292Sbijan.mottahedeh@sun.com 			PMFREE_DEBUG("unmap vaddr=0x%lx pfn=0x%lx", vaddr, pfn);
30210106SJason.Beloro@Sun.COM 
30310106SJason.Beloro@Sun.COM 			hat_unload(kas.a_hat, (caddr_t)vaddr, PAGESIZE,
30410106SJason.Beloro@Sun.COM 			    HAT_UNLOAD_UNLOCK);
30510106SJason.Beloro@Sun.COM 
30610292Sbijan.mottahedeh@sun.com 			if (pf_is_memory(pfn)) {
30710292Sbijan.mottahedeh@sun.com 				pp = page_numtopp_nolock(pfn);
30810292Sbijan.mottahedeh@sun.com 				PMFREE_DEBUG(" pp=0x%p", (void *)pp);
30910292Sbijan.mottahedeh@sun.com 				ASSERT(pp);
31010292Sbijan.mottahedeh@sun.com 				ASSERT(PAGE_EXCL(pp));
31110292Sbijan.mottahedeh@sun.com 				ASSERT(PP_ISNORELOC(pp));
31210292Sbijan.mottahedeh@sun.com 				ASSERT(!PP_ISFREE(pp));
313*11185SSean.McEnroe@Sun.COM 				ASSERT(page_find(&promvp, pfn));
31410292Sbijan.mottahedeh@sun.com 				ASSERT(page_get_pagecnt(pp->p_szc) == 1);
31510292Sbijan.mottahedeh@sun.com 
31610292Sbijan.mottahedeh@sun.com 				if (pp->p_mapping) {
31710292Sbijan.mottahedeh@sun.com 					PMFREE_DEBUG(" skip\n");
31810292Sbijan.mottahedeh@sun.com 				} else {
31910292Sbijan.mottahedeh@sun.com 					PP_CLRNORELOC(pp);
32010292Sbijan.mottahedeh@sun.com 					page_destroy(pp, 0);
32110292Sbijan.mottahedeh@sun.com 					memlist_write_lock();
32210292Sbijan.mottahedeh@sun.com 					rv = memlist_add_span(pfn << PAGESHIFT,
32310292Sbijan.mottahedeh@sun.com 					    PAGESIZE, &phys_avail);
32410292Sbijan.mottahedeh@sun.com 					ASSERT(rv == MEML_SPANOP_OK);
32510292Sbijan.mottahedeh@sun.com 					memlist_write_unlock();
32610292Sbijan.mottahedeh@sun.com 					PMFREE_DEBUG(" free\n");
32710292Sbijan.mottahedeh@sun.com 					nfreed++;
32810292Sbijan.mottahedeh@sun.com 				}
32910106SJason.Beloro@Sun.COM 			} else {
33010292Sbijan.mottahedeh@sun.com 				nskipped_io++;
33110292Sbijan.mottahedeh@sun.com 				PMFREE_DEBUG(" skip IO\n");
33210106SJason.Beloro@Sun.COM 			}
33310106SJason.Beloro@Sun.COM 			nunmapped++;
33410106SJason.Beloro@Sun.COM 			vaddr += PAGESIZE;
33510106SJason.Beloro@Sun.COM 		}
33610106SJason.Beloro@Sun.COM 	}
33710106SJason.Beloro@Sun.COM 
33810106SJason.Beloro@Sun.COM 	if (transroot) {
33910292Sbijan.mottahedeh@sun.com 		PMFREE_DEBUG(
34010292Sbijan.mottahedeh@sun.com 		    "nunmapped=%d nfreed=%d nskipped=%d nskipped_io=%d\n",
34110292Sbijan.mottahedeh@sun.com 		    nunmapped, nfreed, nskipped, nskipped_io);
34210106SJason.Beloro@Sun.COM 		kmem_free(transroot, ntransroot * sizeof (*transroot));
34310106SJason.Beloro@Sun.COM 	}
34410106SJason.Beloro@Sun.COM 
34510106SJason.Beloro@Sun.COM 	/*
34610106SJason.Beloro@Sun.COM 	 * Unload OBP permanent mappings.
34710106SJason.Beloro@Sun.COM 	 */
34810106SJason.Beloro@Sun.COM 	kdi_tlb_page_unlock((caddr_t)OFW_START_ADDR, 1);
34910106SJason.Beloro@Sun.COM 	kpreempt_disable();
35010106SJason.Beloro@Sun.COM 	other_cpus = cpu_ready_set;
35110106SJason.Beloro@Sun.COM 	CPUSET_DEL(other_cpus, CPU->cpu_id);
35210106SJason.Beloro@Sun.COM 	xt_some(other_cpus, vtag_unmap_perm_tl1, (uint64_t)OFW_START_ADDR,
35310106SJason.Beloro@Sun.COM 	    KCONTEXT);
35410106SJason.Beloro@Sun.COM 	kpreempt_enable();
35510106SJason.Beloro@Sun.COM }
35610106SJason.Beloro@Sun.COM 
3571991Sheppo static void cache_prom_data(void);
3581991Sheppo 
3591991Sheppo /*
3601991Sheppo  * This function returns 1 if the current thread is executing in
3611991Sheppo  * the CIF and 0 otherwise. This is useful information to know
3621991Sheppo  * since code that implements CIF handlers can assume that it has
3631991Sheppo  * gone through the kern_preprom() entry point, implying it is
3641991Sheppo  * running single threaded, has preemption disabled, etc.
3651991Sheppo  */
3661991Sheppo int
promif_in_cif(void)3671991Sheppo promif_in_cif(void)
3681991Sheppo {
3691991Sheppo 	int	mycpuid = getprocessorid();
3701991Sheppo 
3711991Sheppo 	return ((cif_cpu == mycpuid) ? 1 : 0);
3721991Sheppo }
3731991Sheppo 
3742531Snarayan /*
3752531Snarayan  * Check that all cpus in the MD are within range (< NCPU).  Attempt
3762531Snarayan  * to stop any that aren't.
3772531Snarayan  */
3782531Snarayan static void
cif_check_cpus(void)3792531Snarayan cif_check_cpus(void)
3802531Snarayan {
3812531Snarayan 	md_t		*mdp;
3822531Snarayan 	mde_cookie_t	rootnode;
3832531Snarayan 	size_t		listsz;
3842531Snarayan 	int		i;
3852531Snarayan 	mde_cookie_t	*listp = NULL;
3862531Snarayan 	int		num_nodes;
3872531Snarayan 	uint64_t	cpuid;
3882531Snarayan 	int		status;
3892531Snarayan 
3902531Snarayan 	mdp = md_get_handle();
3912531Snarayan 	ASSERT(mdp);
3922531Snarayan 
3932531Snarayan 	rootnode = md_root_node(mdp);
3942531Snarayan 	ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE);
3952531Snarayan 
3962531Snarayan 	num_nodes = md_node_count(mdp);
3972531Snarayan 	ASSERT(num_nodes > 0);
3982531Snarayan 
3992531Snarayan 	listsz = num_nodes * sizeof (mde_cookie_t);
4002531Snarayan 	listp = kmem_zalloc(listsz, KM_SLEEP);
4012531Snarayan 
4022531Snarayan 	num_nodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "cpu"),
4032531Snarayan 	    md_find_name(mdp, "fwd"), listp);
4042531Snarayan 
4052531Snarayan 	if (num_nodes <= 0)
4062531Snarayan 		goto done;
4072531Snarayan 
4082531Snarayan 	for (i = 0; i < num_nodes; i++) {
4092531Snarayan 		if (md_get_prop_val(mdp, listp[i], "id", &cpuid)) {
4102531Snarayan 			cmn_err(CE_WARN, "cif_check_cpus: "
4112531Snarayan 			    "CPU instance %d has no 'id' property", i);
4122531Snarayan 			continue;
4132531Snarayan 		}
4142531Snarayan 
4152531Snarayan 		mutex_enter(&cpu_lock);
4162531Snarayan 
4172531Snarayan 		if (cpuid >= NCPU) {
4182531Snarayan 			status = stopcpu_bycpuid(cpuid);
4192531Snarayan 			if (status != 0 && status != ENOTSUP)
4202531Snarayan 				cmn_err(CE_PANIC, "failed to stop cpu %lu (%d)",
4212531Snarayan 				    cpuid, status);
4222531Snarayan 		}
4232531Snarayan 
4242531Snarayan 		mutex_exit(&cpu_lock);
4252531Snarayan 	}
4262531Snarayan 
4272531Snarayan done:
4282531Snarayan 	kmem_free(listp, listsz);
4293069Sjm22469 	(void) md_fini_handle(mdp);
4302531Snarayan }
4312531Snarayan 
4321991Sheppo void
cif_init(void)4331991Sheppo cif_init(void)
4341991Sheppo {
4351991Sheppo 	void (*kmdb_cb)(void);
4361991Sheppo 	uint64_t rtba;
4371991Sheppo 	uint64_t rv;
43810106SJason.Beloro@Sun.COM 	size_t ntransroot;
43910106SJason.Beloro@Sun.COM 	struct translation *transroot;
4401991Sheppo 
4411991Sheppo 	/*
4421991Sheppo 	 * Check if domaining is enabled. If not, do not
4431991Sheppo 	 * initialize the kernel CIF handler.
4441991Sheppo 	 */
4454776Sjm22469 	if (!domaining_enabled())
4461991Sheppo 		return;
4471991Sheppo 
44810106SJason.Beloro@Sun.COM 	transroot = read_prom_mappings(&ntransroot);
44910106SJason.Beloro@Sun.COM 
4501991Sheppo 	/*
4511991Sheppo 	 * Cache PROM data that is needed later, e.g. a shadow
4521991Sheppo 	 * copy of the device tree, IO mappings, etc.
4531991Sheppo 	 */
4541991Sheppo 	cache_prom_data();
4551991Sheppo 
4561991Sheppo 	/*
4571991Sheppo 	 * Prepare to take over the get/set of environmental variables.
4581991Sheppo 	 */
4591991Sheppo 	promif_prop_init();
4601991Sheppo 
4611991Sheppo 	/*
4621991Sheppo 	 * Switch CIF handler to the kernel.
4631991Sheppo 	 */
4641991Sheppo 	prom_cif_handler = cif_handler;
4651991Sheppo 
4661991Sheppo 	promif_preprom();
4671991Sheppo 	cif_handler = kern_cif_handler;
4681991Sheppo 
4691991Sheppo 	/*
4701991Sheppo 	 * Take over rtba for the boot CPU. The rtba for
4711991Sheppo 	 * all other CPUs are set as they enter the system.
4721991Sheppo 	 */
4731991Sheppo 	rtba = va_to_pa(&trap_table);
4741991Sheppo 	if ((rv = hv_cpu_set_rtba(&rtba)) != H_EOK)
4751991Sheppo 		panic("hv_cpu_set_rtba failed: %ld\n", rv);
4761991Sheppo 
4771991Sheppo 	promif_postprom();
4781991Sheppo 
4791991Sheppo 	/*
4801991Sheppo 	 * If the system has been booted with kmdb we need kmdb to
4811991Sheppo 	 * use the kernel cif handler instead of the PROM cif handler.
4821991Sheppo 	 */
4831991Sheppo 	if (boothowto & RB_KMDB) {
4841991Sheppo 		kmdb_cb = (void (*)(void))modlookup("misc/kmdbmod",
4851991Sheppo 		    "kctl_switch_promif");
4861991Sheppo 		ASSERT(kmdb_cb != NULL);
4871991Sheppo 		(*kmdb_cb)();
4881991Sheppo 	}
4892531Snarayan 
4902531Snarayan 	cif_check_cpus();
49110106SJason.Beloro@Sun.COM 
49210106SJason.Beloro@Sun.COM 	if (transroot != NULL)
49310106SJason.Beloro@Sun.COM 		unmap_prom_mappings(transroot, ntransroot);
4941991Sheppo }
4951991Sheppo 
4961991Sheppo static void
cache_prom_data(void)4971991Sheppo cache_prom_data(void)
4981991Sheppo {
4991991Sheppo 	/* initialize copy of OBP device tree */
5001991Sheppo 	promif_stree_init();
5011991Sheppo 
5021991Sheppo 	/* initialize io parameters */
5031991Sheppo 	promif_io_init();
5041991Sheppo }
5051991Sheppo 
5061991Sheppo #endif	/* _KMDB */
507