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