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 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 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 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 * 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 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 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 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 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 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