xref: /illumos-gate/usr/src/uts/sun4v/promif/promif_emul.c (revision 1ae0874509b6811fdde1dfd46f0d93fd09867a3f)
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