xref: /trueos/sys/compat/mach/kern/ipc_host.c (revision e1099549c883414218361efc1adc236058cd70c8)
1 /*
2  * Copyright 1991-1998 by Open Software Foundation, Inc.
3  *              All Rights Reserved
4  *
5  * Permission to use, copy, modify, and distribute this software and
6  * its documentation for any purpose and without fee is hereby granted,
7  * provided that the above copyright notice appears in all copies and
8  * that both the copyright notice and this permission notice appear in
9  * supporting documentation.
10  *
11  * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
12  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13  * FOR A PARTICULAR PURPOSE.
14  *
15  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
16  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
18  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
19  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 /*
22  * MkLinux
23  */
24 /* CMU_HIST */
25 /*
26  * Revision 2.10.3.1  92/06/24  18:05:09  jeffreyh
27  * 	Initalize host_paging_self for NORMA_IPC
28  * 	Add convert_port_to_host_paging
29  * 	[92/06/17            jeffreyh]
30  *
31  * Revision 2.10  91/08/03  18:18:50  jsb
32  * 	Removed NORMA hooks.
33  * 	[91/07/17  23:05:10  jsb]
34  *
35  * Revision 2.9  91/06/25  10:28:20  rpd
36  * 	Changed the convert_foo_to_bar functions
37  * 	to use ipc_port_t instead of mach_port_t.
38  * 	[91/05/27            rpd]
39  *
40  * Revision 2.8  91/06/17  15:46:59  jsb
41  * 	Renamed NORMA conditionals.
42  * 	[91/06/17  10:49:34  jsb]
43  *
44  * Revision 2.7  91/06/06  17:06:59  jsb
45  * 	Redid host port initialization under NORMA_IPC.
46  * 	[91/05/13  17:37:21  jsb]
47  *
48  * Revision 2.6  91/05/14  16:41:36  mrt
49  * 	Correcting copyright
50  *
51  * Revision 2.5  91/02/05  17:26:24  mrt
52  * 	Changed to new Mach copyright
53  * 	[91/02/01  16:12:32  mrt]
54  *
55  * Revision 2.4  90/09/09  14:32:08  rpd
56  * 	Don't take out extra references in ipc_pset_init.
57  * 	[90/08/30            rpd]
58  *
59  * Revision 2.3  90/06/19  22:58:46  rpd
60  * 	Changed convert_port_to_pset_name to allow
61  * 	both IKOT_PSET and IKOT_PSET_NAME ports.
62  * 	Changed convert_port_to_host to allow
63  * 	both IKOT_HOST and IKOT_HOST_PRIV ports.
64  * 	[90/06/18            rpd]
65  *
66  * 	Fixed bug in convert_processor_to_port.
67  * 	[90/06/16            rpd]
68  *
69  * Revision 2.2  90/06/02  14:53:59  rpd
70  * 	Created for new IPC.
71  * 	[90/03/26  23:46:28  rpd]
72  *
73  * 	Move includes.
74  * 	[89/08/02            dlb]
75  * 	Remove interrupt protection from pset locks.
76  * 	[89/06/14            dlb]
77  * 	Use port_alloc instead of xxx_port_allocate.
78  * 	[89/02/21            dlb]
79  * 	Reformat includes.
80  * 	[89/01/26            dlb]
81  *
82  * 	Break processor_set_default into two pieces.
83  * 	[88/12/21            dlb]
84  *
85  * 	Move host_self, host_priv_self to ipc_ptraps.c
86  * 	Rewrite processor_set_default to return both ports
87  * 	[88/11/30            dlb]
88  *
89  * 	Created.
90  * 	[88/10/29            dlb]
91  *
92  * Revision 2.4  89/12/22  15:52:20  rpd
93  * 	Take out extra reference on new processor set ports in
94  * 	ipc_pset_init for reply message; these ports are now
95  * 	returned untranslated.  Assume caller of ipc_pset_disable
96  * 	has pset locked as well as referenced.
97  * 	[89/12/15            dlb]
98  *
99  * Revision 2.3  89/10/15  02:04:29  rpd
100  * 	Minor cleanups.
101  *
102  * Revision 2.2  89/10/11  14:07:11  dlb
103  * 	Fix includes.
104  * 	Remove interrupt protection from pset locks.
105  *
106  */
107 /* CMU_ENDHIST */
108 /*
109  * Mach Operating System
110  * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
111  * All Rights Reserved.
112  *
113  * Permission to use, copy, modify and distribute this software and its
114  * documentation is hereby granted, provided that both the copyright
115  * notice and this permission notice appear in all copies of the
116  * software, derivative works or modified versions, and any portions
117  * thereof, and that both notices appear in supporting documentation.
118  *
119  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
120  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
121  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
122  *
123  * Carnegie Mellon requests users of this software to return to
124  *
125  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
126  *  School of Computer Science
127  *  Carnegie Mellon University
128  *  Pittsburgh PA 15213-3890
129  *
130  * any improvements or extensions that they make and grant Carnegie Mellon
131  * the rights to redistribute these changes.
132  */
133 /*
134  */
135 
136 /*
137  *	kern/ipc_host.c
138  *
139  *	Routines to implement host ports.
140  */
141 #include <sys/mach/message.h>
142 #include <sys/mach/mach_host_server.h>
143 #include <sys/mach/host.h>
144 #include <sys/mach/processor.h>
145 #include <sys/mach/task.h>
146 #include <sys/mach/mach_traps.h>
147 #include <sys/mach/thread.h>
148 #include <sys/mach/ipc_host.h>
149 #include <sys/mach/ipc_kobject.h>
150 #include <sys/mach/ipc/ipc_port.h>
151 #include <sys/mach/ipc/ipc_space.h>
152 
153 #include <sys/kernel.h>
154 
155 /*
156  * Forward declarations
157  */
158 
159 void
160 ipc_processor_terminate(
161 	processor_t	processor);
162 
163 void
164 ipc_processor_disable(
165 	processor_t	processor);
166 
167 boolean_t
168 ref_pset_port_locked(
169 	ipc_port_t port, boolean_t matchn, processor_set_t *ppset);
170 
171 /*
172  *	ipc_host_init: set up various things.
173  */
174 
ipc_host_init(void)175 void ipc_host_init(void)
176 {
177 	ipc_port_t	port;
178 	/*
179 	 *	Allocate and set up the two host ports.
180 	 */
181 	port = ipc_port_alloc_kernel();
182 	if (port == IP_NULL)
183 		panic("ipc_host_init");
184 
185 	ipc_kobject_set(port, (ipc_kobject_t) &realhost, IKOT_HOST);
186 	realhost.host_self = port;
187 
188 	port = ipc_port_alloc_kernel();
189 	if (port == IP_NULL)
190 		panic("ipc_host_init");
191 
192 	ipc_kobject_set(port, (ipc_kobject_t) &realhost, IKOT_HOST_PRIV);
193 	realhost.host_priv_self = port;
194 
195 	port = ipc_port_alloc_kernel();
196 	if (port == IP_NULL)
197 		panic("ipc_host_init");
198 
199 	ipc_kobject_set(port, (ipc_kobject_t) &realhost, IKOT_HOST_SECURITY);
200 	realhost.host_security_self = port;
201 	/*
202 	 *	Set up ipc for default processor set.
203 	 */
204 	ipc_pset_init(&default_pset);
205 	ipc_pset_enable(&default_pset);
206 
207 #ifdef notyet
208 	/*
209 	 *	And for master processor
210 	 */
211 	ipc_processor_init(master_processor);
212 	ipc_processor_enable(master_processor);
213 #endif
214 }
215 
216 /*
217  *	Routine:	mach_host_self [mach trap]
218  *	Purpose:
219  *		Give the caller send rights for his own host port.
220  *	Conditions:
221  *		Nothing locked.
222  *	Returns:
223  *		MACH_PORT_NULL if there are any resource failures
224  *		or other errors.
225  */
226 
227 mach_port_name_t
mach_host_self(void)228 mach_host_self(void)
229 {
230 	ipc_port_t sright;
231 
232 	sright = ipc_port_make_send(realhost.host_self);
233 	return ipc_port_copyout_send(sright, current_space());
234 }
235 
236 /*
237  *	ipc_processor_init:
238  *
239  *	Initialize ipc access to processor by allocating port.
240  */
241 
242 void
ipc_processor_init(processor_t processor)243 ipc_processor_init(
244 	processor_t	processor)
245 {
246 	ipc_port_t	port;
247 
248 	port = ipc_port_alloc_kernel();
249 	if (port == IP_NULL)
250 		panic("ipc_processor_init");
251 	processor->processor_self = port;
252 }
253 
254 /*
255  *	ipc_processor_enable:
256  *
257  *	Enable ipc control of processor by setting port object.
258  */
259 void
ipc_processor_enable(processor_t processor)260 ipc_processor_enable(
261 	processor_t	processor)
262 {
263 	ipc_port_t	myport;
264 
265 	myport = processor->processor_self;
266 	ipc_kobject_set(myport, (ipc_kobject_t) processor, IKOT_PROCESSOR);
267 }
268 
269 /*
270  *	ipc_pset_init:
271  *
272  *	Initialize ipc control of a processor set by allocating its ports.
273  */
274 
275 void
ipc_pset_init(processor_set_t pset)276 ipc_pset_init(
277 	processor_set_t		pset)
278 {
279 	ipc_port_t	port;
280 
281 	port = ipc_port_alloc_kernel();
282 	if (port == IP_NULL)
283 		panic("ipc_pset_init");
284 	pset->pset_self = port;
285 
286 	port = ipc_port_alloc_kernel();
287 	if (port == IP_NULL)
288 		panic("ipc_pset_init");
289 	pset->pset_name_self = port;
290 }
291 
292 /*
293  *	ipc_pset_enable:
294  *
295  *	Enable ipc access to a processor set.
296  */
297 void
ipc_pset_enable(processor_set_t pset)298 ipc_pset_enable(
299 	processor_set_t		pset)
300 {
301 		ipc_kobject_set(pset->pset_self,
302 				(ipc_kobject_t) pset, IKOT_PSET);
303 		ipc_kobject_set(pset->pset_name_self,
304 				(ipc_kobject_t) pset, IKOT_PSET_NAME);
305 }
306 
307 
308 /*
309  *	processor_set_default, processor_set_default_priv:
310  *
311  *	Return ports for manipulating default_processor set.  MiG code
312  *	differentiates between these two routines.
313  */
314 kern_return_t
processor_set_default(host_t host,processor_set_t * pset)315 processor_set_default(
316 	host_t			host,
317 	processor_set_t		*pset)
318 {
319 	if (host == HOST_NULL)
320 		return(KERN_INVALID_ARGUMENT);
321 
322 	*pset = &default_pset;
323 	pset_reference(*pset);
324 	return(KERN_SUCCESS);
325 }
326 
327 /*
328  *	Routine:	convert_port_to_host
329  *	Purpose:
330  *		Convert from a port to a host.
331  *		Doesn't consume the port ref; the host produced may be null.
332  *	Conditions:
333  *		Nothing locked.
334  */
335 
336 host_t
convert_port_to_host(ipc_port_t port)337 convert_port_to_host(
338 	ipc_port_t	port)
339 {
340 	host_t host = HOST_NULL;
341 
342 	if (IP_VALID(port)) {
343 		ip_lock(port);
344 		if (ip_active(port) &&
345 		    ((ip_kotype(port) == IKOT_HOST) ||
346 		     (ip_kotype(port) == IKOT_HOST_PRIV)
347 		     ))
348 			host = (host_t) port->ip_kobject;
349 		ip_unlock(port);
350 	}
351 
352 	return host;
353 }
354 
355 /*
356  *	Routine:	convert_port_to_host_priv
357  *	Purpose:
358  *		Convert from a port to a host.
359  *		Doesn't consume the port ref; the host produced may be null.
360  *	Conditions:
361  *		Nothing locked.
362  */
363 
364 host_t
convert_port_to_host_priv(ipc_port_t port)365 convert_port_to_host_priv(
366 	ipc_port_t	port)
367 {
368 	host_t host = HOST_NULL;
369 
370 	if (IP_VALID(port)) {
371 		ip_lock(port);
372 		if (ip_active(port) &&
373 		    (ip_kotype(port) == IKOT_HOST_PRIV))
374 			host = (host_t) port->ip_kobject;
375 		ip_unlock(port);
376 	}
377 
378 	return host;
379 }
380 
381 /*
382  *	Routine:	convert_port_to_processor
383  *	Purpose:
384  *		Convert from a port to a processor.
385  *		Doesn't consume the port ref;
386  *		the processor produced may be null.
387  *	Conditions:
388  *		Nothing locked.
389  */
390 
391 processor_t
convert_port_to_processor(ipc_port_t port)392 convert_port_to_processor(
393 	ipc_port_t	port)
394 {
395 	processor_t processor = PROCESSOR_NULL;
396 
397 	if (IP_VALID(port)) {
398 		ip_lock(port);
399 		if (ip_active(port) &&
400 		    (ip_kotype(port) == IKOT_PROCESSOR))
401 			processor = (processor_t) port->ip_kobject;
402 		ip_unlock(port);
403 	}
404 
405 	return processor;
406 }
407 
408 /*
409  *	Routine:	convert_port_to_pset
410  *	Purpose:
411  *		Convert from a port to a pset.
412  *		Doesn't consume the port ref; produces a pset ref,
413  *		which may be null.
414  *	Conditions:
415  *		Nothing locked.
416  */
417 
418 processor_set_t
convert_port_to_pset(ipc_port_t port)419 convert_port_to_pset(
420 	ipc_port_t	port)
421 {
422 	boolean_t r;
423 	processor_set_t pset = PROCESSOR_SET_NULL;
424 
425 	r = FALSE;
426 	while (!r && IP_VALID(port)) {
427 		ip_lock(port);
428 		r = ref_pset_port_locked(port, FALSE, &pset);
429 		/* port unlocked */
430 	}
431 	return pset;
432 }
433 
434 /*
435  *	Routine:	convert_port_to_pset_name
436  *	Purpose:
437  *		Convert from a port to a pset.
438  *		Doesn't consume the port ref; produces a pset ref,
439  *		which may be null.
440  *	Conditions:
441  *		Nothing locked.
442  */
443 
444 processor_set_t
convert_port_to_pset_name(ipc_port_t port)445 convert_port_to_pset_name(
446 	ipc_port_t	port)
447 {
448 	boolean_t r;
449 	processor_set_t pset = PROCESSOR_SET_NULL;
450 
451 	r = FALSE;
452 	while (!r && IP_VALID(port)) {
453 		ip_lock(port);
454 		r = ref_pset_port_locked(port, TRUE, &pset);
455 		/* port unlocked */
456 	}
457 	return pset;
458 }
459 
460 boolean_t
ref_pset_port_locked(ipc_port_t port,boolean_t matchn,processor_set_t * ppset)461 ref_pset_port_locked(ipc_port_t port, boolean_t matchn, processor_set_t *ppset)
462 {
463 	processor_set_t pset;
464 
465 	pset = PROCESSOR_SET_NULL;
466 	if (ip_active(port) &&
467 		((ip_kotype(port) == IKOT_PSET) ||
468 		 (matchn && (ip_kotype(port) == IKOT_PSET_NAME)))) {
469 		pset = (processor_set_t) port->ip_kobject;
470 	}
471 	*ppset = pset;
472 	ip_unlock(port);
473 	return (TRUE);
474 }
475 
476 /*
477  *	Routine:	convert_host_to_port
478  *	Purpose:
479  *		Convert from a host to a port.
480  *		Produces a naked send right which may be invalid.
481  *	Conditions:
482  *		Nothing locked.
483  */
484 
485 ipc_port_t
convert_host_to_port(host_t host)486 convert_host_to_port(
487 	host_t		host)
488 {
489 	ipc_port_t port;
490 
491 	port = ipc_port_make_send(host->host_self);
492 
493 	return port;
494 }
495 
496 /*
497  *	Routine:	convert_processor_to_port
498  *	Purpose:
499  *		Convert from a processor to a port.
500  *		Produces a naked send right which may be invalid.
501  *	Conditions:
502  *		Nothing locked.
503  */
504 
505 ipc_port_t
convert_processor_to_port(processor_t processor)506 convert_processor_to_port(
507 	processor_t		processor)
508 {
509 	ipc_port_t port;
510 
511 	if (processor->processor_self != IP_NULL)
512 		port = ipc_port_make_send(processor->processor_self);
513 	else
514 		port = IP_NULL;
515 
516 	return port;
517 }
518 
519 /*
520  *	Routine:	convert_pset_to_port
521  *	Purpose:
522  *		Convert from a pset to a port.
523  *		Consumes a pset ref; produces a naked send right
524  *		which may be invalid.
525  *	Conditions:
526  *		Nothing locked.
527  */
528 
529 ipc_port_t
convert_pset_to_port(processor_set_t pset)530 convert_pset_to_port(
531 	processor_set_t		pset)
532 {
533 	ipc_port_t port;
534 
535 	pset_lock(pset);
536 	if (pset->active)
537 		port = ipc_port_make_send(pset->pset_self);
538 	else
539 		port = IP_NULL;
540 	pset_unlock(pset);
541 
542 	pset_deallocate(pset);
543 	return port;
544 }
545 
546 /*
547  *	Routine:	convert_pset_name_to_port
548  *	Purpose:
549  *		Convert from a pset to a port.
550  *		Consumes a pset ref; produces a naked send right
551  *		which may be invalid.
552  *	Conditions:
553  *		Nothing locked.
554  */
555 
556 ipc_port_t
convert_pset_name_to_port(processor_set_t pset)557 convert_pset_name_to_port(
558 	processor_set_t		pset)
559 {
560 	ipc_port_t port;
561 
562 	pset_lock(pset);
563 	if (pset->active)
564 		port = ipc_port_make_send(pset->pset_name_self);
565 	else
566 		port = IP_NULL;
567 	pset_unlock(pset);
568 
569 	pset_deallocate(pset);
570 	return port;
571 }
572 
573 /*
574  *	Routine:	convert_port_to_host_security
575  *	Purpose:
576  *		Convert from a port to a host security.
577  *		Doesn't consume the port ref; the port produced may be null.
578  *	Conditions:
579  *		Nothing locked.
580  */
581 
582 host_t
convert_port_to_host_security(ipc_port_t port)583 convert_port_to_host_security(
584 	ipc_port_t port)
585 {
586 	host_t host = HOST_NULL;
587 
588 	if (IP_VALID(port)) {
589 		ip_lock(port);
590 		if (ip_active(port) &&
591 		    (ip_kotype(port) == IKOT_HOST_SECURITY))
592 			host = (host_t) port->ip_kobject;
593 		ip_unlock(port);
594 	}
595 
596 	return host;
597 }
598 
599 static void
ipc_host_sysinit(void * arg __unused)600 ipc_host_sysinit(void *arg __unused)
601 {
602 
603 	ipc_host_init();
604 }
605 
606 /* before SI_SUB_INTRINSIC and after SI_SUB_KLD where zones are initialized */
607 SYSINIT(ipc_host, SI_SUB_CPU, SI_ORDER_ANY, ipc_host_sysinit, NULL);
608 
609