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 /*
239853d9e8SJason 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>
389853d9e8SJason Beloro #include <sys/cpu_module.h>
39*af4c679fSSean McEnroe #include <vm/seg_kmem.h>
401ae08745Sheppo
411ae08745Sheppo #ifndef _KMDB
429853d9e8SJason Beloro #include <sys/pte.h>
439853d9e8SJason Beloro #include <vm/hat_sfmmu.h>
449853d9e8SJason Beloro #include <sys/memlist_impl.h>
459853d9e8SJason Beloro
461ae08745Sheppo static processorid_t cif_cpu;
471ae08745Sheppo static struct translation *cif_prom_trans;
481ae08745Sheppo static size_t cif_prom_ntrans;
491ae08745Sheppo
501ae08745Sheppo int cif_cpu_mp_ready;
511ae08745Sheppo int (*prom_cif_handler)(void *) = NULL;
529853d9e8SJason Beloro
539853d9e8SJason Beloro extern struct memlist *phys_avail;
54*af4c679fSSean McEnroe extern struct vnode promvp;
559853d9e8SJason Beloro extern void kdi_tlb_page_unlock(caddr_t, int);
569853d9e8SJason Beloro
579853d9e8SJason Beloro #define COMBINE(hi, lo) (((uint64_t)(uint32_t)(hi) << 32) | (uint32_t)(lo))
589853d9e8SJason Beloro #define OFW_PT_START_ADDR 0xfffffffc00000000 /* OBP PT start */
599853d9e8SJason Beloro #define OFW_PT_END_ADDR 0xffffffffffffffff /* OBP PT end */
609853d9e8SJason Beloro
619853d9e8SJason Beloro #define PROM_ADDR(a) (((a) >= OFW_START_ADDR && (a) <= OFW_END_ADDR) || \
629853d9e8SJason Beloro ((a) >= OFW_PT_START_ADDR && (a) <= OFW_PT_END_ADDR))
631ae08745Sheppo #endif
641ae08745Sheppo
651ae08745Sheppo #ifdef DEBUG
661ae08745Sheppo uint_t cif_debug;
679853d9e8SJason Beloro int prom_free_debug;
689853d9e8SJason Beloro #define PMFREE_DEBUG(args...) if (prom_free_debug) printf(args)
699853d9e8SJason Beloro #else
709853d9e8SJason Beloro #define PMFREE_DEBUG(args...)
719853d9e8SJason Beloro #endif
721ae08745Sheppo
731ae08745Sheppo extern int (*cif_handler)(void *);
741ae08745Sheppo
751ae08745Sheppo typedef struct {
761ae08745Sheppo char *name;
771ae08745Sheppo cif_func_t func;
781ae08745Sheppo } cif_callback_t;
791ae08745Sheppo
801ae08745Sheppo static cif_callback_t cb_table[] = {
811ae08745Sheppo { "getprop", promif_getprop },
821ae08745Sheppo { "getproplen", promif_getproplen },
831ae08745Sheppo { "nextprop", promif_nextprop },
841ae08745Sheppo { "peer", promif_nextnode },
851ae08745Sheppo { "child", promif_childnode },
861ae08745Sheppo { "parent", promif_parentnode },
871ae08745Sheppo { "enter", promif_enter_mon },
881ae08745Sheppo { "exit", promif_exit_to_mon },
891ae08745Sheppo { "boot", promif_reboot },
901ae08745Sheppo { "write", promif_write },
911ae08745Sheppo { "read", promif_read },
921ae08745Sheppo { "interpret", promif_interpret },
931ae08745Sheppo { "finddevice", promif_finddevice },
941ae08745Sheppo { "instance-to-package", promif_instance_to_package },
951ae08745Sheppo #ifndef _KMDB
961ae08745Sheppo { "setprop", promif_setprop },
971ae08745Sheppo { "test", promif_test },
981ae08745Sheppo { "instance-to-path", promif_instance_to_path },
991ae08745Sheppo { "SUNW,power-off", promif_power_off },
1001ae08745Sheppo { "SUNW,asr-list-keys-len", promif_asr_list_keys_len },
1011ae08745Sheppo { "SUNW,asr-list-keys", promif_asr_list_keys },
1021ae08745Sheppo { "SUNW,asr-export-len", promif_asr_export_len },
1031ae08745Sheppo { "SUNW,asr-export", promif_asr_export },
1041ae08745Sheppo { "SUNW,set-security-key", promif_set_security_key },
1051ae08745Sheppo { "SUNW,get-security-key", promif_get_security_key },
1061ae08745Sheppo { "SUNW,start-cpu-by-cpuid", promif_start_cpu },
1071ae08745Sheppo { "SUNW,set-trap-table", promif_set_mmfsa_traptable },
1081ae08745Sheppo { "SUNW,set-sun4v-api-version", promif_set_sun4v_api_version },
1091ae08745Sheppo { "SUNW,get-sun4v-api-version", promif_get_sun4v_api_version },
1101ae08745Sheppo #endif
1111ae08745Sheppo { NULL, NULL }
1121ae08745Sheppo };
1131ae08745Sheppo
1141ae08745Sheppo cif_func_t
promif_find_cif_callback(char * opname)1151ae08745Sheppo promif_find_cif_callback(char *opname)
1161ae08745Sheppo {
1171ae08745Sheppo cif_callback_t *cb;
1181ae08745Sheppo
1191ae08745Sheppo if (opname == NULL)
1201ae08745Sheppo return (NULL);
1211ae08745Sheppo
1221ae08745Sheppo for (cb = cb_table; cb->name; cb++) {
1231ae08745Sheppo if (prom_strcmp(cb->name, opname) == 0)
1241ae08745Sheppo break;
1251ae08745Sheppo }
1261ae08745Sheppo
1271ae08745Sheppo return (cb->func);
1281ae08745Sheppo }
1291ae08745Sheppo
1301ae08745Sheppo static int
kern_cif_handler(void * p)1311ae08745Sheppo kern_cif_handler(void *p)
1321ae08745Sheppo {
1331ae08745Sheppo cell_t *ci = (cell_t *)p;
1341ae08745Sheppo char *opname;
1351ae08745Sheppo cif_func_t func;
1361ae08745Sheppo int rv;
1371ae08745Sheppo
1381ae08745Sheppo ASSERT(cif_handler == kern_cif_handler);
1391ae08745Sheppo
1401ae08745Sheppo #ifndef _KMDB
1411ae08745Sheppo cif_cpu = getprocessorid();
1421ae08745Sheppo #endif
1431ae08745Sheppo
1441ae08745Sheppo opname = p1275_cell2ptr(ci[0]);
1451ae08745Sheppo
1461ae08745Sheppo /* lookup the callback for the desired operation */
1471ae08745Sheppo func = promif_find_cif_callback(opname);
1481ae08745Sheppo
1491ae08745Sheppo if (func == NULL) {
1501ae08745Sheppo #ifdef _KMDB
1511ae08745Sheppo prom_fatal_error("sun4v unsupported CIFs\n");
1521ae08745Sheppo #else
1531ae08745Sheppo cmn_err(CE_CONT, "!sun4v unsupported CIF: %s\n", opname);
1541ae08745Sheppo return (-1);
1551ae08745Sheppo #endif
1561ae08745Sheppo }
1571ae08745Sheppo
1581ae08745Sheppo /* callback found, execute it */
1591ae08745Sheppo rv = func(p);
1601ae08745Sheppo
1611ae08745Sheppo #ifndef _KMDB
1621ae08745Sheppo cif_cpu = -1;
1631ae08745Sheppo #endif
1641ae08745Sheppo
1651ae08745Sheppo return (rv);
1661ae08745Sheppo }
1671ae08745Sheppo
1681ae08745Sheppo #ifdef _KMDB
1691ae08745Sheppo
1701ae08745Sheppo 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)1711ae08745Sheppo cif_init(char *pgmname, caddr_t root, ihandle_t in, ihandle_t out,
1721ae08745Sheppo phandle_t pin, phandle_t pout, pnode_t chosen, pnode_t options)
1731ae08745Sheppo {
1741ae08745Sheppo /* initialize pointer to a copy of OBP device tree */
1751ae08745Sheppo promif_stree_setroot(root);
1761ae08745Sheppo
1771ae08745Sheppo promif_set_nodes(chosen, options);
1781ae08745Sheppo
1791ae08745Sheppo /* initialize io parameters */
1801ae08745Sheppo promif_io_init(in, out, pin, pout);
1811ae08745Sheppo
1821ae08745Sheppo /*
1831ae08745Sheppo * Switch CIF handler to the kernel.
1841ae08745Sheppo */
1851ae08745Sheppo if (pgmname != NULL)
1861ae08745Sheppo prom_init(pgmname, (void *)kern_cif_handler);
1871ae08745Sheppo else
1881ae08745Sheppo cif_handler = kern_cif_handler;
1891ae08745Sheppo }
1901ae08745Sheppo
1911ae08745Sheppo #else
1921ae08745Sheppo
1939853d9e8SJason Beloro static struct translation *
read_prom_mappings(size_t * ntransp)1949853d9e8SJason Beloro read_prom_mappings(size_t *ntransp)
1959853d9e8SJason Beloro {
1969853d9e8SJason Beloro char *prop = "translations";
1979853d9e8SJason Beloro pnode_t node;
1989853d9e8SJason Beloro size_t translen;
1999853d9e8SJason Beloro ihandle_t immu;
2009853d9e8SJason Beloro struct translation *transroot;
2019853d9e8SJason Beloro
2029853d9e8SJason Beloro *ntransp = 0;
2039853d9e8SJason Beloro
2049853d9e8SJason Beloro /*
2059853d9e8SJason Beloro * the "translations" property is associated with the mmu node
2069853d9e8SJason Beloro */
2079853d9e8SJason Beloro if ((immu = prom_mmu_ihandle()) == (ihandle_t)-1) {
2089853d9e8SJason Beloro PMFREE_DEBUG("no mmu ihandle");
2099853d9e8SJason Beloro return (NULL);
2109853d9e8SJason Beloro }
2119853d9e8SJason Beloro node = (pnode_t)prom_getphandle(immu);
2129853d9e8SJason Beloro if (node == OBP_NONODE || node == OBP_BADNODE) {
2139853d9e8SJason Beloro PMFREE_DEBUG("no mmu node");
2149853d9e8SJason Beloro return (NULL);
2159853d9e8SJason Beloro }
2169853d9e8SJason Beloro
2179853d9e8SJason Beloro if ((translen = prom_getproplen(node, prop)) == -1) {
2189853d9e8SJason Beloro PMFREE_DEBUG("no translations property");
2199853d9e8SJason Beloro return (NULL);
2209853d9e8SJason Beloro }
2219853d9e8SJason Beloro transroot = (struct translation *)kmem_zalloc(translen, KM_SLEEP);
2229853d9e8SJason Beloro
2239853d9e8SJason Beloro if (prom_getprop(node, prop, (caddr_t)transroot) == -1) {
2249853d9e8SJason Beloro PMFREE_DEBUG("translations getprop failed");
2259853d9e8SJason Beloro kmem_free(transroot, translen);
2269853d9e8SJason Beloro return (NULL);
2279853d9e8SJason Beloro }
2289853d9e8SJason Beloro *ntransp = translen / sizeof (*transroot);
2299853d9e8SJason Beloro
2309853d9e8SJason Beloro return (transroot);
2319853d9e8SJason Beloro }
2329853d9e8SJason Beloro
2339853d9e8SJason Beloro static void
unmap_prom_mappings(struct translation * transroot,size_t ntransroot)2349853d9e8SJason Beloro unmap_prom_mappings(struct translation *transroot, size_t ntransroot)
2359853d9e8SJason Beloro {
2369853d9e8SJason Beloro int i, j, rv;
2370a9b4b43SBijan Mottahedeh int npgs, nunmapped, nfreed, nskipped, nskipped_io;
2389853d9e8SJason Beloro char *p;
2399853d9e8SJason Beloro tte_t tte;
2409853d9e8SJason Beloro pfn_t pfn;
2419853d9e8SJason Beloro page_t *pp;
2429853d9e8SJason Beloro uint64_t vaddr;
2439853d9e8SJason Beloro struct translation *promt;
2449853d9e8SJason Beloro cpuset_t other_cpus;
2459853d9e8SJason Beloro
2469853d9e8SJason Beloro /*
2479853d9e8SJason Beloro * During startup isa_list is allocated in OBP address space
2489853d9e8SJason Beloro * so it needs to be re-allocated in kernel address space
2499853d9e8SJason Beloro * before OBP memory is unmapped.
2509853d9e8SJason Beloro *
2519853d9e8SJason Beloro * see cpu_setup_common().
2529853d9e8SJason Beloro */
2539853d9e8SJason Beloro p = kmem_zalloc(strlen(isa_list) + 1, KM_SLEEP);
2549853d9e8SJason Beloro (void) strcpy(p, isa_list);
2559853d9e8SJason Beloro isa_list = p;
2569853d9e8SJason Beloro
2579853d9e8SJason Beloro nfreed = 0;
2589853d9e8SJason Beloro nunmapped = 0;
2599853d9e8SJason Beloro nskipped = 0;
2600a9b4b43SBijan Mottahedeh nskipped_io = 0;
2619853d9e8SJason Beloro
2629853d9e8SJason Beloro for (i = 0, promt = transroot; i < ntransroot; i++, promt++) {
2639853d9e8SJason Beloro ASSERT(promt->tte_hi != 0);
2649853d9e8SJason Beloro ASSERT32(promt->virt_hi == 0 && promt->size_hi == 0);
2659853d9e8SJason Beloro
2669853d9e8SJason Beloro vaddr = COMBINE(promt->virt_hi, promt->virt_lo);
2679853d9e8SJason Beloro
2689853d9e8SJason Beloro if (!PROM_ADDR(vaddr)) {
2699853d9e8SJason Beloro nskipped++;
2709853d9e8SJason Beloro continue;
2719853d9e8SJason Beloro }
2729853d9e8SJason Beloro
2739853d9e8SJason Beloro npgs = mmu_btopr(COMBINE(promt->size_hi, promt->size_lo));
2749853d9e8SJason Beloro
2759853d9e8SJason Beloro if (npgs > 1) {
2769853d9e8SJason Beloro PMFREE_DEBUG("large trans vaddr=0x%lx, npgs=%d\n",
2779853d9e8SJason Beloro vaddr, npgs);
2789853d9e8SJason Beloro }
2799853d9e8SJason Beloro for (j = 0; j < npgs; j++) {
2809853d9e8SJason Beloro
2819853d9e8SJason Beloro pfn = sfmmu_vatopfn((caddr_t)vaddr, KHATID, &tte);
2829853d9e8SJason Beloro
2839853d9e8SJason Beloro if (pfn == PFN_INVALID) {
2849853d9e8SJason Beloro tte.tte_inthi = promt->tte_hi;
2859853d9e8SJason Beloro tte.tte_intlo = promt->tte_lo;
2869853d9e8SJason Beloro pfn = TTE_TO_PFN((caddr_t)COMBINE(
2879853d9e8SJason Beloro promt->virt_hi, promt->virt_lo), &tte);
2889853d9e8SJason Beloro PMFREE_DEBUG(
2899853d9e8SJason Beloro "no mapping for vaddr=0x%lx (opfn=0x%lx)\n",
2909853d9e8SJason Beloro vaddr, pfn);
2919853d9e8SJason Beloro break;
2929853d9e8SJason Beloro }
2939853d9e8SJason Beloro ASSERT(!TTE_IS_LOCKED(&tte));
2949853d9e8SJason Beloro ASSERT(TTE_IS_8K(&tte));
2959853d9e8SJason Beloro
2969853d9e8SJason Beloro /*
2970a9b4b43SBijan Mottahedeh * Unload the current mapping for the pfn and
2980a9b4b43SBijan Mottahedeh * if it is the last mapping for a memory page,
2990a9b4b43SBijan Mottahedeh * free the page.
3009853d9e8SJason Beloro */
3010a9b4b43SBijan Mottahedeh PMFREE_DEBUG("unmap vaddr=0x%lx pfn=0x%lx", vaddr, pfn);
3020a9b4b43SBijan Mottahedeh
3030a9b4b43SBijan Mottahedeh hat_unload(kas.a_hat, (caddr_t)vaddr, PAGESIZE,
3040a9b4b43SBijan Mottahedeh HAT_UNLOAD_UNLOCK);
3050a9b4b43SBijan Mottahedeh
3060a9b4b43SBijan Mottahedeh if (pf_is_memory(pfn)) {
3079853d9e8SJason Beloro pp = page_numtopp_nolock(pfn);
3080a9b4b43SBijan Mottahedeh PMFREE_DEBUG(" pp=0x%p", (void *)pp);
3099853d9e8SJason Beloro ASSERT(pp);
3109853d9e8SJason Beloro ASSERT(PAGE_EXCL(pp));
3119853d9e8SJason Beloro ASSERT(PP_ISNORELOC(pp));
3129853d9e8SJason Beloro ASSERT(!PP_ISFREE(pp));
313*af4c679fSSean McEnroe ASSERT(page_find(&promvp, pfn));
3149853d9e8SJason Beloro ASSERT(page_get_pagecnt(pp->p_szc) == 1);
3159853d9e8SJason Beloro
3169853d9e8SJason Beloro if (pp->p_mapping) {
3179853d9e8SJason Beloro PMFREE_DEBUG(" skip\n");
3189853d9e8SJason Beloro } else {
3199853d9e8SJason Beloro PP_CLRNORELOC(pp);
3209853d9e8SJason Beloro page_destroy(pp, 0);
3219853d9e8SJason Beloro memlist_write_lock();
3229853d9e8SJason Beloro rv = memlist_add_span(pfn << PAGESHIFT,
3239853d9e8SJason Beloro PAGESIZE, &phys_avail);
3249853d9e8SJason Beloro ASSERT(rv == MEML_SPANOP_OK);
3259853d9e8SJason Beloro memlist_write_unlock();
3269853d9e8SJason Beloro PMFREE_DEBUG(" free\n");
3279853d9e8SJason Beloro nfreed++;
3289853d9e8SJason Beloro }
3290a9b4b43SBijan Mottahedeh } else {
3300a9b4b43SBijan Mottahedeh nskipped_io++;
3310a9b4b43SBijan Mottahedeh PMFREE_DEBUG(" skip IO\n");
3320a9b4b43SBijan Mottahedeh }
3339853d9e8SJason Beloro nunmapped++;
3349853d9e8SJason Beloro vaddr += PAGESIZE;
3359853d9e8SJason Beloro }
3369853d9e8SJason Beloro }
3379853d9e8SJason Beloro
3389853d9e8SJason Beloro if (transroot) {
3390a9b4b43SBijan Mottahedeh PMFREE_DEBUG(
3400a9b4b43SBijan Mottahedeh "nunmapped=%d nfreed=%d nskipped=%d nskipped_io=%d\n",
3410a9b4b43SBijan Mottahedeh nunmapped, nfreed, nskipped, nskipped_io);
3429853d9e8SJason Beloro kmem_free(transroot, ntransroot * sizeof (*transroot));
3439853d9e8SJason Beloro }
3449853d9e8SJason Beloro
3459853d9e8SJason Beloro /*
3469853d9e8SJason Beloro * Unload OBP permanent mappings.
3479853d9e8SJason Beloro */
3489853d9e8SJason Beloro kdi_tlb_page_unlock((caddr_t)OFW_START_ADDR, 1);
3499853d9e8SJason Beloro kpreempt_disable();
3509853d9e8SJason Beloro other_cpus = cpu_ready_set;
3519853d9e8SJason Beloro CPUSET_DEL(other_cpus, CPU->cpu_id);
3529853d9e8SJason Beloro xt_some(other_cpus, vtag_unmap_perm_tl1, (uint64_t)OFW_START_ADDR,
3539853d9e8SJason Beloro KCONTEXT);
3549853d9e8SJason Beloro kpreempt_enable();
3559853d9e8SJason Beloro }
3569853d9e8SJason Beloro
3571ae08745Sheppo static void cache_prom_data(void);
3581ae08745Sheppo
3591ae08745Sheppo /*
3601ae08745Sheppo * This function returns 1 if the current thread is executing in
3611ae08745Sheppo * the CIF and 0 otherwise. This is useful information to know
3621ae08745Sheppo * since code that implements CIF handlers can assume that it has
3631ae08745Sheppo * gone through the kern_preprom() entry point, implying it is
3641ae08745Sheppo * running single threaded, has preemption disabled, etc.
3651ae08745Sheppo */
3661ae08745Sheppo int
promif_in_cif(void)3671ae08745Sheppo promif_in_cif(void)
3681ae08745Sheppo {
3691ae08745Sheppo int mycpuid = getprocessorid();
3701ae08745Sheppo
3711ae08745Sheppo return ((cif_cpu == mycpuid) ? 1 : 0);
3721ae08745Sheppo }
3731ae08745Sheppo
3744bac2208Snarayan /*
3754bac2208Snarayan * Check that all cpus in the MD are within range (< NCPU). Attempt
3764bac2208Snarayan * to stop any that aren't.
3774bac2208Snarayan */
3784bac2208Snarayan static void
cif_check_cpus(void)3794bac2208Snarayan cif_check_cpus(void)
3804bac2208Snarayan {
3814bac2208Snarayan md_t *mdp;
3824bac2208Snarayan mde_cookie_t rootnode;
3834bac2208Snarayan size_t listsz;
3844bac2208Snarayan int i;
3854bac2208Snarayan mde_cookie_t *listp = NULL;
3864bac2208Snarayan int num_nodes;
3874bac2208Snarayan uint64_t cpuid;
3884bac2208Snarayan int status;
3894bac2208Snarayan
3904bac2208Snarayan mdp = md_get_handle();
3914bac2208Snarayan ASSERT(mdp);
3924bac2208Snarayan
3934bac2208Snarayan rootnode = md_root_node(mdp);
3944bac2208Snarayan ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE);
3954bac2208Snarayan
3964bac2208Snarayan num_nodes = md_node_count(mdp);
3974bac2208Snarayan ASSERT(num_nodes > 0);
3984bac2208Snarayan
3994bac2208Snarayan listsz = num_nodes * sizeof (mde_cookie_t);
4004bac2208Snarayan listp = kmem_zalloc(listsz, KM_SLEEP);
4014bac2208Snarayan
4024bac2208Snarayan num_nodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "cpu"),
4034bac2208Snarayan md_find_name(mdp, "fwd"), listp);
4044bac2208Snarayan
4054bac2208Snarayan if (num_nodes <= 0)
4064bac2208Snarayan goto done;
4074bac2208Snarayan
4084bac2208Snarayan for (i = 0; i < num_nodes; i++) {
4094bac2208Snarayan if (md_get_prop_val(mdp, listp[i], "id", &cpuid)) {
4104bac2208Snarayan cmn_err(CE_WARN, "cif_check_cpus: "
4114bac2208Snarayan "CPU instance %d has no 'id' property", i);
4124bac2208Snarayan continue;
4134bac2208Snarayan }
4144bac2208Snarayan
4154bac2208Snarayan mutex_enter(&cpu_lock);
4164bac2208Snarayan
4174bac2208Snarayan if (cpuid >= NCPU) {
4184bac2208Snarayan status = stopcpu_bycpuid(cpuid);
4194bac2208Snarayan if (status != 0 && status != ENOTSUP)
4204bac2208Snarayan cmn_err(CE_PANIC, "failed to stop cpu %lu (%d)",
4214bac2208Snarayan cpuid, status);
4224bac2208Snarayan }
4234bac2208Snarayan
4244bac2208Snarayan mutex_exit(&cpu_lock);
4254bac2208Snarayan }
4264bac2208Snarayan
4274bac2208Snarayan done:
4284bac2208Snarayan kmem_free(listp, listsz);
429a3f75865Sjm22469 (void) md_fini_handle(mdp);
4304bac2208Snarayan }
4314bac2208Snarayan
4321ae08745Sheppo void
cif_init(void)4331ae08745Sheppo cif_init(void)
4341ae08745Sheppo {
4351ae08745Sheppo void (*kmdb_cb)(void);
4361ae08745Sheppo uint64_t rtba;
4371ae08745Sheppo uint64_t rv;
4389853d9e8SJason Beloro size_t ntransroot;
4399853d9e8SJason Beloro struct translation *transroot;
4401ae08745Sheppo
4411ae08745Sheppo /*
4421ae08745Sheppo * Check if domaining is enabled. If not, do not
4431ae08745Sheppo * initialize the kernel CIF handler.
4441ae08745Sheppo */
44522e19ac1Sjm22469 if (!domaining_enabled())
4461ae08745Sheppo return;
4471ae08745Sheppo
4489853d9e8SJason Beloro transroot = read_prom_mappings(&ntransroot);
4499853d9e8SJason Beloro
4501ae08745Sheppo /*
4511ae08745Sheppo * Cache PROM data that is needed later, e.g. a shadow
4521ae08745Sheppo * copy of the device tree, IO mappings, etc.
4531ae08745Sheppo */
4541ae08745Sheppo cache_prom_data();
4551ae08745Sheppo
4561ae08745Sheppo /*
4571ae08745Sheppo * Prepare to take over the get/set of environmental variables.
4581ae08745Sheppo */
4591ae08745Sheppo promif_prop_init();
4601ae08745Sheppo
4611ae08745Sheppo /*
4621ae08745Sheppo * Switch CIF handler to the kernel.
4631ae08745Sheppo */
4641ae08745Sheppo prom_cif_handler = cif_handler;
4651ae08745Sheppo
4661ae08745Sheppo promif_preprom();
4671ae08745Sheppo cif_handler = kern_cif_handler;
4681ae08745Sheppo
4691ae08745Sheppo /*
4701ae08745Sheppo * Take over rtba for the boot CPU. The rtba for
4711ae08745Sheppo * all other CPUs are set as they enter the system.
4721ae08745Sheppo */
4731ae08745Sheppo rtba = va_to_pa(&trap_table);
4741ae08745Sheppo if ((rv = hv_cpu_set_rtba(&rtba)) != H_EOK)
4751ae08745Sheppo panic("hv_cpu_set_rtba failed: %ld\n", rv);
4761ae08745Sheppo
4771ae08745Sheppo promif_postprom();
4781ae08745Sheppo
4791ae08745Sheppo /*
4801ae08745Sheppo * If the system has been booted with kmdb we need kmdb to
4811ae08745Sheppo * use the kernel cif handler instead of the PROM cif handler.
4821ae08745Sheppo */
4831ae08745Sheppo if (boothowto & RB_KMDB) {
4841ae08745Sheppo kmdb_cb = (void (*)(void))modlookup("misc/kmdbmod",
4851ae08745Sheppo "kctl_switch_promif");
4861ae08745Sheppo ASSERT(kmdb_cb != NULL);
4871ae08745Sheppo (*kmdb_cb)();
4881ae08745Sheppo }
4894bac2208Snarayan
4904bac2208Snarayan cif_check_cpus();
4919853d9e8SJason Beloro
4929853d9e8SJason Beloro if (transroot != NULL)
4939853d9e8SJason Beloro unmap_prom_mappings(transroot, ntransroot);
4941ae08745Sheppo }
4951ae08745Sheppo
4961ae08745Sheppo static void
cache_prom_data(void)4971ae08745Sheppo cache_prom_data(void)
4981ae08745Sheppo {
4991ae08745Sheppo /* initialize copy of OBP device tree */
5001ae08745Sheppo promif_stree_init();
5011ae08745Sheppo
5021ae08745Sheppo /* initialize io parameters */
5031ae08745Sheppo promif_io_init();
5041ae08745Sheppo }
5051ae08745Sheppo
5061ae08745Sheppo #endif /* _KMDB */
507