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