1*1ae08745Sheppo /* 2*1ae08745Sheppo * CDDL HEADER START 3*1ae08745Sheppo * 4*1ae08745Sheppo * The contents of this file are subject to the terms of the 5*1ae08745Sheppo * Common Development and Distribution License (the "License"). 6*1ae08745Sheppo * You may not use this file except in compliance with the License. 7*1ae08745Sheppo * 8*1ae08745Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1ae08745Sheppo * or http://www.opensolaris.org/os/licensing. 10*1ae08745Sheppo * See the License for the specific language governing permissions 11*1ae08745Sheppo * and limitations under the License. 12*1ae08745Sheppo * 13*1ae08745Sheppo * When distributing Covered Code, include this CDDL HEADER in each 14*1ae08745Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1ae08745Sheppo * If applicable, add the following below this CDDL HEADER, with the 16*1ae08745Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 17*1ae08745Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 18*1ae08745Sheppo * 19*1ae08745Sheppo * CDDL HEADER END 20*1ae08745Sheppo */ 21*1ae08745Sheppo 22*1ae08745Sheppo /* 23*1ae08745Sheppo * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*1ae08745Sheppo * Use is subject to license terms. 25*1ae08745Sheppo */ 26*1ae08745Sheppo 27*1ae08745Sheppo #pragma ident "%Z%%M% %I% %E% SMI" 28*1ae08745Sheppo 29*1ae08745Sheppo #include <sys/promif_impl.h> 30*1ae08745Sheppo #include <sys/machsystm.h> 31*1ae08745Sheppo #include <sys/lpad.h> 32*1ae08745Sheppo #include <sys/vmsystm.h> 33*1ae08745Sheppo #include <sys/prom_plat.h> 34*1ae08745Sheppo #include <sys/ldoms.h> 35*1ae08745Sheppo #include <sys/kobj.h> 36*1ae08745Sheppo #include <sys/reboot.h> 37*1ae08745Sheppo #include <sys/hypervisor_api.h> 38*1ae08745Sheppo 39*1ae08745Sheppo #ifndef _KMDB 40*1ae08745Sheppo static processorid_t cif_cpu; 41*1ae08745Sheppo static struct translation *cif_prom_trans; 42*1ae08745Sheppo static size_t cif_prom_ntrans; 43*1ae08745Sheppo 44*1ae08745Sheppo int cif_cpu_mp_ready; 45*1ae08745Sheppo int (*prom_cif_handler)(void *) = NULL; 46*1ae08745Sheppo #endif 47*1ae08745Sheppo 48*1ae08745Sheppo #ifdef DEBUG 49*1ae08745Sheppo uint_t cif_debug; 50*1ae08745Sheppo #endif /* DEBUG */ 51*1ae08745Sheppo 52*1ae08745Sheppo extern int (*cif_handler)(void *); 53*1ae08745Sheppo 54*1ae08745Sheppo typedef struct { 55*1ae08745Sheppo char *name; 56*1ae08745Sheppo cif_func_t func; 57*1ae08745Sheppo } cif_callback_t; 58*1ae08745Sheppo 59*1ae08745Sheppo static cif_callback_t cb_table[] = { 60*1ae08745Sheppo { "getprop", promif_getprop }, 61*1ae08745Sheppo { "getproplen", promif_getproplen }, 62*1ae08745Sheppo { "nextprop", promif_nextprop }, 63*1ae08745Sheppo { "peer", promif_nextnode }, 64*1ae08745Sheppo { "child", promif_childnode }, 65*1ae08745Sheppo { "parent", promif_parentnode }, 66*1ae08745Sheppo { "enter", promif_enter_mon }, 67*1ae08745Sheppo { "exit", promif_exit_to_mon }, 68*1ae08745Sheppo { "boot", promif_reboot }, 69*1ae08745Sheppo { "write", promif_write }, 70*1ae08745Sheppo { "read", promif_read }, 71*1ae08745Sheppo { "interpret", promif_interpret }, 72*1ae08745Sheppo { "finddevice", promif_finddevice }, 73*1ae08745Sheppo { "instance-to-package", promif_instance_to_package }, 74*1ae08745Sheppo #ifndef _KMDB 75*1ae08745Sheppo { "setprop", promif_setprop }, 76*1ae08745Sheppo { "test", promif_test }, 77*1ae08745Sheppo { "instance-to-path", promif_instance_to_path }, 78*1ae08745Sheppo { "SUNW,power-off", promif_power_off }, 79*1ae08745Sheppo { "SUNW,asr-list-keys-len", promif_asr_list_keys_len }, 80*1ae08745Sheppo { "SUNW,asr-list-keys", promif_asr_list_keys }, 81*1ae08745Sheppo { "SUNW,asr-export-len", promif_asr_export_len }, 82*1ae08745Sheppo { "SUNW,asr-export", promif_asr_export }, 83*1ae08745Sheppo { "SUNW,set-security-key", promif_set_security_key }, 84*1ae08745Sheppo { "SUNW,get-security-key", promif_get_security_key }, 85*1ae08745Sheppo { "SUNW,start-cpu-by-cpuid", promif_start_cpu }, 86*1ae08745Sheppo { "SUNW,set-trap-table", promif_set_mmfsa_traptable }, 87*1ae08745Sheppo { "SUNW,set-sun4v-api-version", promif_set_sun4v_api_version }, 88*1ae08745Sheppo { "SUNW,get-sun4v-api-version", promif_get_sun4v_api_version }, 89*1ae08745Sheppo #endif 90*1ae08745Sheppo { NULL, NULL } 91*1ae08745Sheppo }; 92*1ae08745Sheppo 93*1ae08745Sheppo cif_func_t 94*1ae08745Sheppo promif_find_cif_callback(char *opname) 95*1ae08745Sheppo { 96*1ae08745Sheppo cif_callback_t *cb; 97*1ae08745Sheppo 98*1ae08745Sheppo if (opname == NULL) 99*1ae08745Sheppo return (NULL); 100*1ae08745Sheppo 101*1ae08745Sheppo for (cb = cb_table; cb->name; cb++) { 102*1ae08745Sheppo if (prom_strcmp(cb->name, opname) == 0) 103*1ae08745Sheppo break; 104*1ae08745Sheppo } 105*1ae08745Sheppo 106*1ae08745Sheppo return (cb->func); 107*1ae08745Sheppo } 108*1ae08745Sheppo 109*1ae08745Sheppo static int 110*1ae08745Sheppo kern_cif_handler(void *p) 111*1ae08745Sheppo { 112*1ae08745Sheppo cell_t *ci = (cell_t *)p; 113*1ae08745Sheppo char *opname; 114*1ae08745Sheppo cif_func_t func; 115*1ae08745Sheppo int rv; 116*1ae08745Sheppo 117*1ae08745Sheppo ASSERT(cif_handler == kern_cif_handler); 118*1ae08745Sheppo 119*1ae08745Sheppo #ifndef _KMDB 120*1ae08745Sheppo cif_cpu = getprocessorid(); 121*1ae08745Sheppo #endif 122*1ae08745Sheppo 123*1ae08745Sheppo opname = p1275_cell2ptr(ci[0]); 124*1ae08745Sheppo 125*1ae08745Sheppo /* lookup the callback for the desired operation */ 126*1ae08745Sheppo func = promif_find_cif_callback(opname); 127*1ae08745Sheppo 128*1ae08745Sheppo if (func == NULL) { 129*1ae08745Sheppo #ifdef _KMDB 130*1ae08745Sheppo prom_fatal_error("sun4v unsupported CIFs\n"); 131*1ae08745Sheppo #else 132*1ae08745Sheppo cmn_err(CE_CONT, "!sun4v unsupported CIF: %s\n", opname); 133*1ae08745Sheppo return (-1); 134*1ae08745Sheppo #endif 135*1ae08745Sheppo } 136*1ae08745Sheppo 137*1ae08745Sheppo /* callback found, execute it */ 138*1ae08745Sheppo rv = func(p); 139*1ae08745Sheppo 140*1ae08745Sheppo #ifndef _KMDB 141*1ae08745Sheppo cif_cpu = -1; 142*1ae08745Sheppo #endif 143*1ae08745Sheppo 144*1ae08745Sheppo return (rv); 145*1ae08745Sheppo } 146*1ae08745Sheppo 147*1ae08745Sheppo #ifdef _KMDB 148*1ae08745Sheppo 149*1ae08745Sheppo void 150*1ae08745Sheppo cif_init(char *pgmname, caddr_t root, ihandle_t in, ihandle_t out, 151*1ae08745Sheppo phandle_t pin, phandle_t pout, pnode_t chosen, pnode_t options) 152*1ae08745Sheppo { 153*1ae08745Sheppo /* initialize pointer to a copy of OBP device tree */ 154*1ae08745Sheppo promif_stree_setroot(root); 155*1ae08745Sheppo 156*1ae08745Sheppo promif_set_nodes(chosen, options); 157*1ae08745Sheppo 158*1ae08745Sheppo /* initialize io parameters */ 159*1ae08745Sheppo promif_io_init(in, out, pin, pout); 160*1ae08745Sheppo 161*1ae08745Sheppo /* 162*1ae08745Sheppo * Switch CIF handler to the kernel. 163*1ae08745Sheppo */ 164*1ae08745Sheppo if (pgmname != NULL) 165*1ae08745Sheppo prom_init(pgmname, (void *)kern_cif_handler); 166*1ae08745Sheppo else 167*1ae08745Sheppo cif_handler = kern_cif_handler; 168*1ae08745Sheppo } 169*1ae08745Sheppo 170*1ae08745Sheppo #else 171*1ae08745Sheppo 172*1ae08745Sheppo static void cache_prom_data(void); 173*1ae08745Sheppo 174*1ae08745Sheppo /* 175*1ae08745Sheppo * This function returns 1 if the current thread is executing in 176*1ae08745Sheppo * the CIF and 0 otherwise. This is useful information to know 177*1ae08745Sheppo * since code that implements CIF handlers can assume that it has 178*1ae08745Sheppo * gone through the kern_preprom() entry point, implying it is 179*1ae08745Sheppo * running single threaded, has preemption disabled, etc. 180*1ae08745Sheppo */ 181*1ae08745Sheppo int 182*1ae08745Sheppo promif_in_cif(void) 183*1ae08745Sheppo { 184*1ae08745Sheppo int mycpuid = getprocessorid(); 185*1ae08745Sheppo 186*1ae08745Sheppo return ((cif_cpu == mycpuid) ? 1 : 0); 187*1ae08745Sheppo } 188*1ae08745Sheppo 189*1ae08745Sheppo void 190*1ae08745Sheppo cif_init(void) 191*1ae08745Sheppo { 192*1ae08745Sheppo void (*kmdb_cb)(void); 193*1ae08745Sheppo uint64_t rtba; 194*1ae08745Sheppo uint64_t rv; 195*1ae08745Sheppo 196*1ae08745Sheppo /* 197*1ae08745Sheppo * Check if domaining is enabled. If not, do not 198*1ae08745Sheppo * initialize the kernel CIF handler. 199*1ae08745Sheppo */ 200*1ae08745Sheppo if (!domaining_enabled) 201*1ae08745Sheppo return; 202*1ae08745Sheppo 203*1ae08745Sheppo /* 204*1ae08745Sheppo * Cache PROM data that is needed later, e.g. a shadow 205*1ae08745Sheppo * copy of the device tree, IO mappings, etc. 206*1ae08745Sheppo */ 207*1ae08745Sheppo cache_prom_data(); 208*1ae08745Sheppo 209*1ae08745Sheppo /* 210*1ae08745Sheppo * Prepare to take over the get/set of environmental variables. 211*1ae08745Sheppo */ 212*1ae08745Sheppo promif_prop_init(); 213*1ae08745Sheppo 214*1ae08745Sheppo /* 215*1ae08745Sheppo * Switch CIF handler to the kernel. 216*1ae08745Sheppo */ 217*1ae08745Sheppo prom_cif_handler = cif_handler; 218*1ae08745Sheppo 219*1ae08745Sheppo promif_preprom(); 220*1ae08745Sheppo cif_handler = kern_cif_handler; 221*1ae08745Sheppo 222*1ae08745Sheppo /* 223*1ae08745Sheppo * Take over rtba for the boot CPU. The rtba for 224*1ae08745Sheppo * all other CPUs are set as they enter the system. 225*1ae08745Sheppo */ 226*1ae08745Sheppo rtba = va_to_pa(&trap_table); 227*1ae08745Sheppo if ((rv = hv_cpu_set_rtba(&rtba)) != H_EOK) 228*1ae08745Sheppo panic("hv_cpu_set_rtba failed: %ld\n", rv); 229*1ae08745Sheppo 230*1ae08745Sheppo promif_postprom(); 231*1ae08745Sheppo 232*1ae08745Sheppo /* 233*1ae08745Sheppo * If the system has been booted with kmdb we need kmdb to 234*1ae08745Sheppo * use the kernel cif handler instead of the PROM cif handler. 235*1ae08745Sheppo */ 236*1ae08745Sheppo if (boothowto & RB_KMDB) { 237*1ae08745Sheppo kmdb_cb = (void (*)(void))modlookup("misc/kmdbmod", 238*1ae08745Sheppo "kctl_switch_promif"); 239*1ae08745Sheppo ASSERT(kmdb_cb != NULL); 240*1ae08745Sheppo (*kmdb_cb)(); 241*1ae08745Sheppo } 242*1ae08745Sheppo } 243*1ae08745Sheppo 244*1ae08745Sheppo static void 245*1ae08745Sheppo cache_prom_data(void) 246*1ae08745Sheppo { 247*1ae08745Sheppo /* initialize copy of OBP device tree */ 248*1ae08745Sheppo promif_stree_init(); 249*1ae08745Sheppo 250*1ae08745Sheppo /* initialize io parameters */ 251*1ae08745Sheppo promif_io_init(); 252*1ae08745Sheppo } 253*1ae08745Sheppo 254*1ae08745Sheppo 255*1ae08745Sheppo /* 256*1ae08745Sheppo * Platform-specific actions to be taken when all cpus are running 257*1ae08745Sheppo * in the OS. 258*1ae08745Sheppo */ 259*1ae08745Sheppo void 260*1ae08745Sheppo cpu_mp_init(void) 261*1ae08745Sheppo { 262*1ae08745Sheppo if (!domaining_enabled) 263*1ae08745Sheppo return; 264*1ae08745Sheppo 265*1ae08745Sheppo cif_cpu_mp_ready = 1; 266*1ae08745Sheppo } 267*1ae08745Sheppo 268*1ae08745Sheppo #endif /* _KMDB */ 269