|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26:
27: #include <norma_vm.h>
28:
29: #include <mach/boolean.h>
30: #include <mach/port.h>
31: #include <mach/message.h>
32: #include <mach/thread_status.h>
33: #include <kern/ast.h>
34: #include <kern/ipc_tt.h>
35: #include <kern/thread.h>
36: #include <kern/task.h>
37: #include <kern/ipc_kobject.h>
38: #include <vm/vm_map.h>
39: #include <vm/vm_user.h>
40: #include <ipc/port.h>
41: #include <ipc/ipc_kmsg.h>
42: #include <ipc/ipc_entry.h>
43: #include <ipc/ipc_object.h>
44: #include <ipc/ipc_mqueue.h>
45: #include <ipc/ipc_space.h>
46: #include <ipc/ipc_port.h>
47: #include <ipc/ipc_pset.h>
48: #include <ipc/ipc_thread.h>
49: #include <device/device_types.h>
50:
51:
52: /*
53: * Routine: mach_msg_send_from_kernel
54: * Purpose:
55: * Send a message from the kernel.
56: *
57: * This is used by the client side of KernelUser interfaces
58: * to implement SimpleRoutines. Currently, this includes
59: * device_reply and memory_object messages.
60: * Conditions:
61: * Nothing locked.
62: * Returns:
63: * MACH_MSG_SUCCESS Sent the message.
64: * MACH_SEND_INVALID_DATA Bad destination port.
65: */
66:
67: mach_msg_return_t
68: mach_msg_send_from_kernel(
69: mach_msg_header_t *msg,
70: mach_msg_size_t send_size)
71: {
72: ipc_kmsg_t kmsg;
73: mach_msg_return_t mr;
74:
75: if (!MACH_PORT_VALID(msg->msgh_remote_port))
76: return MACH_SEND_INVALID_DEST;
77:
78: mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
79: if (mr != MACH_MSG_SUCCESS)
80: panic("mach_msg_send_from_kernel");
81:
82: ipc_kmsg_copyin_from_kernel(kmsg);
83: ipc_mqueue_send_always(kmsg);
84:
85: return MACH_MSG_SUCCESS;
86: }
87:
88: mach_msg_return_t
89: mach_msg_rpc_from_kernel(msg, send_size, reply_size)
90: mach_msg_header_t *msg;
91: mach_msg_size_t send_size;
92: mach_msg_size_t reply_size;
93: {
94: panic("mach_msg_rpc_from_kernel"); /*XXX*/
95: }
96:
97: #if NORMA_VM
98: /*
99: * Routine: mach_msg_rpc_from_kernel
100: * Purpose:
101: * Send a message from the kernel and receive a reply.
102: * Uses ith_rpc_reply for the reply port.
103: *
104: * This is used by the client side of KernelUser interfaces
105: * to implement Routines.
106: * Conditions:
107: * Nothing locked.
108: * Returns:
109: * MACH_MSG_SUCCESS Sent the message.
110: * MACH_RCV_PORT_DIED The reply port was deallocated.
111: */
112:
113: mach_msg_return_t
114: mach_msg_rpc_from_kernel(
115: mach_msg_header_t *msg,
116: mach_msg_size_t send_size,
117: mach_msg_size_t rcv_size)
118: {
119: ipc_thread_t self = current_thread();
120: ipc_port_t reply;
121: ipc_kmsg_t kmsg;
122: mach_port_seqno_t seqno;
123: mach_msg_return_t mr;
124:
125: assert(MACH_PORT_VALID(msg->msgh_remote_port));
126: assert(msg->msgh_local_port == MACH_PORT_NULL);
127:
128: mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
129: if (mr != MACH_MSG_SUCCESS)
130: panic("mach_msg_rpc_from_kernel");
131:
132: ipc_kmsg_copyin_from_kernel(kmsg);
133:
134: ith_lock(self);
135: assert(self->ith_self != IP_NULL);
136:
137: reply = self->ith_rpc_reply;
138: if (reply == IP_NULL) {
139: ith_unlock(self);
140: reply = ipc_port_alloc_reply();
141: ith_lock(self);
142: if ((reply == IP_NULL) ||
143: (self->ith_rpc_reply != IP_NULL))
144: panic("mach_msg_rpc_from_kernel");
145: self->ith_rpc_reply = reply;
146: }
147:
148: /* insert send-once right for the reply port */
149: kmsg->ikm_header.msgh_local_port =
150: (mach_port_t) ipc_port_make_sonce(reply);
151:
152: ipc_port_reference(reply);
153: ith_unlock(self);
154:
155: ipc_mqueue_send_always(kmsg);
156:
157: for (;;) {
158: ipc_mqueue_t mqueue;
159:
160: ip_lock(reply);
161: if (!ip_active(reply)) {
162: ip_unlock(reply);
163: ipc_port_release(reply);
164: return MACH_RCV_PORT_DIED;
165: }
166:
167: assert(reply->ip_pset == IPS_NULL);
168: mqueue = &reply->ip_messages;
169: imq_lock(mqueue);
170: ip_unlock(reply);
171:
172: mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
173: MACH_MSG_SIZE_MAX,
174: MACH_MSG_TIMEOUT_NONE,
175: FALSE, IMQ_NULL_CONTINUE,
176: &kmsg, &seqno);
177: /* mqueue is unlocked */
178: if (mr == MACH_MSG_SUCCESS)
179: break;
180:
181: assert((mr == MACH_RCV_INTERRUPTED) ||
182: (mr == MACH_RCV_PORT_DIED));
183:
184: while (thread_should_halt(self)) {
185: /* don't terminate while holding a reference */
186: if (self->ast & AST_TERMINATE)
187: ipc_port_release(reply);
188: thread_halt_self();
189: }
190: }
191: ipc_port_release(reply);
192:
193: kmsg->ikm_header.msgh_seqno = seqno;
194:
195: if (rcv_size < kmsg->ikm_header.msgh_size) {
196: ipc_kmsg_copyout_dest(kmsg, ipc_space_reply);
197: ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
198: return MACH_RCV_TOO_LARGE;
199: }
200:
201: /*
202: * We want to preserve rights and memory in reply!
203: * We don't have to put them anywhere; just leave them
204: * as they are.
205: */
206:
207: ipc_kmsg_copyout_to_kernel(kmsg, ipc_space_reply);
208: ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
209: return MACH_MSG_SUCCESS;
210: }
211: #endif /* NORMA_VM */
212:
213: /*
214: * Routine: mach_msg_abort_rpc
215: * Purpose:
216: * Destroy the thread's ith_rpc_reply port.
217: * This will interrupt a mach_msg_rpc_from_kernel
218: * with a MACH_RCV_PORT_DIED return code.
219: * Conditions:
220: * Nothing locked.
221: */
222:
223: void
224: mach_msg_abort_rpc(thread)
225: ipc_thread_t thread;
226: {
227: ipc_port_t reply = IP_NULL;
228:
229: ith_lock(thread);
230: if (thread->ith_self != IP_NULL) {
231: reply = thread->ith_rpc_reply;
232: thread->ith_rpc_reply = IP_NULL;
233: }
234: ith_unlock(thread);
235:
236: if (reply != IP_NULL)
237: ipc_port_dealloc_reply(reply);
238: }
239:
240: /*
241: * Routine: mach_msg
242: * Purpose:
243: * Like mach_msg_trap except that message buffers
244: * live in kernel space. Doesn't handle any options.
245: *
246: * This is used by in-kernel server threads to make
247: * kernel calls, to receive request messages, and
248: * to send reply messages.
249: * Conditions:
250: * Nothing locked.
251: * Returns:
252: */
253:
254: mach_msg_return_t
255: mach_msg(msg, option, send_size, rcv_size, rcv_name, time_out, notify)
256: mach_msg_header_t *msg;
257: mach_msg_option_t option;
258: mach_msg_size_t send_size;
259: mach_msg_size_t rcv_size;
260: mach_port_t rcv_name;
261: mach_msg_timeout_t time_out;
262: mach_port_t notify;
263: {
264: ipc_space_t space = current_space();
265: vm_map_t map = current_map();
266: ipc_kmsg_t kmsg;
267: mach_port_seqno_t seqno;
268: mach_msg_return_t mr;
269:
270: if (option & MACH_SEND_MSG) {
271: mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
272: if (mr != MACH_MSG_SUCCESS)
273: panic("mach_msg");
274:
275: mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL);
276: if (mr != MACH_MSG_SUCCESS) {
277: ikm_free(kmsg);
278: return mr;
279: }
280:
281: do
282: mr = ipc_mqueue_send(kmsg, MACH_MSG_OPTION_NONE,
283: MACH_MSG_TIMEOUT_NONE);
284: while (mr == MACH_SEND_INTERRUPTED);
285: assert(mr == MACH_MSG_SUCCESS);
286: }
287:
288: if (option & MACH_RCV_MSG) {
289: do {
290: ipc_object_t object;
291: ipc_mqueue_t mqueue;
292:
293: mr = ipc_mqueue_copyin(space, rcv_name,
294: &mqueue, &object);
295: if (mr != MACH_MSG_SUCCESS)
296: return mr;
297: /* hold ref for object; mqueue is locked */
298:
299: mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
300: MACH_MSG_SIZE_MAX,
301: MACH_MSG_TIMEOUT_NONE,
302: FALSE, IMQ_NULL_CONTINUE,
303: &kmsg, &seqno);
304: /* mqueue is unlocked */
305: ipc_object_release(object);
306: } while (mr == MACH_RCV_INTERRUPTED);
307: if (mr != MACH_MSG_SUCCESS)
308: return mr;
309:
310: kmsg->ikm_header.msgh_seqno = seqno;
311:
312: if (rcv_size < kmsg->ikm_header.msgh_size) {
313: ipc_kmsg_copyout_dest(kmsg, space);
314: ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
315: return MACH_RCV_TOO_LARGE;
316: }
317:
318: mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
319: if (mr != MACH_MSG_SUCCESS) {
320: if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
321: ipc_kmsg_put_to_kernel(msg, kmsg,
322: kmsg->ikm_header.msgh_size);
323: } else {
324: ipc_kmsg_copyout_dest(kmsg, space);
325: ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
326: }
327:
328: return mr;
329: }
330:
331: ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
332: }
333:
334: return MACH_MSG_SUCCESS;
335: }
336:
337: /*
338: * Routine: mig_get_reply_port
339: * Purpose:
340: * Called by client side interfaces living in the kernel
341: * to get a reply port. This port is used for
342: * mach_msg() calls which are kernel calls.
343: */
344:
345: mach_port_t
346: mig_get_reply_port(void)
347: {
348: ipc_thread_t self = current_thread();
349:
350: if (self->ith_mig_reply == MACH_PORT_NULL)
351: self->ith_mig_reply = mach_reply_port();
352:
353: return self->ith_mig_reply;
354: }
355:
356: /*
357: * Routine: mig_dealloc_reply_port
358: * Purpose:
359: * Called by client side interfaces to get rid of a reply port.
360: * Shouldn't ever be called inside the kernel, because
361: * kernel calls shouldn't prompt Mig to call it.
362: */
363:
364: void
365: mig_dealloc_reply_port(
366: mach_port_t reply_port)
367: {
368: panic("mig_dealloc_reply_port");
369: }
370:
371: /*
372: * Routine: mig_put_reply_port
373: * Purpose:
374: * Called by client side interfaces after each RPC to
375: * let the client recycle the reply port if it wishes.
376: */
377: void
378: mig_put_reply_port(
379: mach_port_t reply_port)
380: {
381: }
382:
383: /*
384: * mig_strncpy.c - by Joshua Block
385: *
386: * mig_strncp -- Bounded string copy. Does what the library routine strncpy
387: * OUGHT to do: Copies the (null terminated) string in src into dest, a
388: * buffer of length len. Assures that the copy is still null terminated
389: * and doesn't overflow the buffer, truncating the copy if necessary.
390: *
391: * Parameters:
392: *
393: * dest - Pointer to destination buffer.
394: *
395: * src - Pointer to source string.
396: *
397: * len - Length of destination buffer.
398: */
399: void mig_strncpy(dest, src, len)
400: char *dest, *src;
401: int len;
402: {
403: int i;
404:
405: if (len <= 0)
406: return;
407:
408: for (i=1; i<len; i++)
409: if (! (*dest++ = *src++))
410: return;
411:
412: *dest = '\0';
413: return;
414: }
415:
416: #define fast_send_right_lookup(name, port, abort) \
417: MACRO_BEGIN \
418: register ipc_space_t space = current_space(); \
419: register ipc_entry_t entry; \
420: register mach_port_index_t index = MACH_PORT_INDEX(name); \
421: \
422: is_read_lock(space); \
423: assert(space->is_active); \
424: \
425: if ((index >= space->is_table_size) || \
426: (((entry = &space->is_table[index])->ie_bits & \
427: (IE_BITS_GEN_MASK|MACH_PORT_TYPE_SEND)) != \
428: (MACH_PORT_GEN(name) | MACH_PORT_TYPE_SEND))) { \
429: is_read_unlock(space); \
430: abort; \
431: } \
432: \
433: port = (ipc_port_t) entry->ie_object; \
434: assert(port != IP_NULL); \
435: \
436: ip_lock(port); \
437: /* can safely unlock space now that port is locked */ \
438: is_read_unlock(space); \
439: MACRO_END
440:
441: device_t
442: port_name_to_device(name)
443: mach_port_t name;
444: {
445: register ipc_port_t port;
446: register device_t device;
447:
448: fast_send_right_lookup(name, port, goto abort);
449: /* port is locked */
450:
451: /*
452: * Now map the port object to a device object.
453: * This is an inline version of dev_port_lookup().
454: */
455: if (ip_active(port) && (ip_kotype(port) == IKOT_DEVICE)) {
456: device = (device_t) port->ip_kobject;
457: device_reference(device);
458: ip_unlock(port);
459: return device;
460: }
461:
462: ip_unlock(port);
463: return DEVICE_NULL;
464:
465: /*
466: * The slow case. The port wasn't easily accessible.
467: */
468: abort: {
469: ipc_port_t kern_port;
470: kern_return_t kr;
471:
472: kr = ipc_object_copyin(current_space(), name,
473: MACH_MSG_TYPE_COPY_SEND,
474: (ipc_object_t *) &kern_port);
475: if (kr != KERN_SUCCESS)
476: return DEVICE_NULL;
477:
478: device = dev_port_lookup(kern_port);
479: if (IP_VALID(kern_port))
480: ipc_port_release_send(kern_port);
481: return device;
482: }
483: }
484:
485: thread_t
486: port_name_to_thread(name)
487: mach_port_t name;
488: {
489: register ipc_port_t port;
490:
491: fast_send_right_lookup(name, port, goto abort);
492: /* port is locked */
493:
494: if (ip_active(port) &&
495: (ip_kotype(port) == IKOT_THREAD)) {
496: register thread_t thread;
497:
498: thread = (thread_t) port->ip_kobject;
499: assert(thread != THREAD_NULL);
500:
501: /* thread referencing is a bit complicated,
502: so don't bother to expand inline */
503: thread_reference(thread);
504: ip_unlock(port);
505:
506: return thread;
507: }
508:
509: ip_unlock(port);
510: return THREAD_NULL;
511:
512: abort: {
513: thread_t thread;
514: ipc_port_t kern_port;
515: kern_return_t kr;
516:
517: kr = ipc_object_copyin(current_space(), name,
518: MACH_MSG_TYPE_COPY_SEND,
519: (ipc_object_t *) &kern_port);
520: if (kr != KERN_SUCCESS)
521: return THREAD_NULL;
522:
523: thread = convert_port_to_thread(kern_port);
524: if (IP_VALID(kern_port))
525: ipc_port_release_send(kern_port);
526:
527: return thread;
528: }
529: }
530:
531: task_t
532: port_name_to_task(name)
533: mach_port_t name;
534: {
535: register ipc_port_t port;
536:
537: fast_send_right_lookup(name, port, goto abort);
538: /* port is locked */
539:
540: if (ip_active(port) &&
541: (ip_kotype(port) == IKOT_TASK)) {
542: register task_t task;
543:
544: task = (task_t) port->ip_kobject;
545: assert(task != TASK_NULL);
546:
547: task_lock(task);
548: /* can safely unlock port now that task is locked */
549: ip_unlock(port);
550:
551: task->ref_count++;
552: task_unlock(task);
553:
554: return task;
555: }
556:
557: ip_unlock(port);
558: return TASK_NULL;
559:
560: abort: {
561: task_t task;
562: ipc_port_t kern_port;
563: kern_return_t kr;
564:
565: kr = ipc_object_copyin(current_space(), name,
566: MACH_MSG_TYPE_COPY_SEND,
567: (ipc_object_t *) &kern_port);
568: if (kr != KERN_SUCCESS)
569: return TASK_NULL;
570:
571: task = convert_port_to_task(kern_port);
572: if (IP_VALID(kern_port))
573: ipc_port_release_send(kern_port);
574:
575: return task;
576: }
577: }
578:
579: vm_map_t
580: port_name_to_map(
581: mach_port_t name)
582: {
583: register ipc_port_t port;
584:
585: fast_send_right_lookup(name, port, goto abort);
586: /* port is locked */
587:
588: if (ip_active(port) &&
589: (ip_kotype(port) == IKOT_TASK)) {
590: register vm_map_t map;
591:
592: map = ((task_t) port->ip_kobject)->map;
593: assert(map != VM_MAP_NULL);
594:
595: simple_lock(&map->ref_lock);
596: /* can safely unlock port now that map is locked */
597: ip_unlock(port);
598:
599: map->ref_count++;
600: simple_unlock(&map->ref_lock);
601:
602: return map;
603: }
604:
605: ip_unlock(port);
606: return VM_MAP_NULL;
607:
608: abort: {
609: vm_map_t map;
610: ipc_port_t kern_port;
611: kern_return_t kr;
612:
613: kr = ipc_object_copyin(current_space(), name,
614: MACH_MSG_TYPE_COPY_SEND,
615: (ipc_object_t *) &kern_port);
616: if (kr != KERN_SUCCESS)
617: return VM_MAP_NULL;
618:
619: map = convert_port_to_map(kern_port);
620: if (IP_VALID(kern_port))
621: ipc_port_release_send(kern_port);
622:
623: return map;
624: }
625: }
626:
627: ipc_space_t
628: port_name_to_space(name)
629: mach_port_t name;
630: {
631: register ipc_port_t port;
632:
633: fast_send_right_lookup(name, port, goto abort);
634: /* port is locked */
635:
636: if (ip_active(port) &&
637: (ip_kotype(port) == IKOT_TASK)) {
638: register ipc_space_t space;
639:
640: space = ((task_t) port->ip_kobject)->itk_space;
641: assert(space != IS_NULL);
642:
643: simple_lock(&space->is_ref_lock_data);
644: /* can safely unlock port now that space is locked */
645: ip_unlock(port);
646:
647: space->is_references++;
648: simple_unlock(&space->is_ref_lock_data);
649:
650: return space;
651: }
652:
653: ip_unlock(port);
654: return IS_NULL;
655:
656: abort: {
657: ipc_space_t space;
658: ipc_port_t kern_port;
659: kern_return_t kr;
660:
661: kr = ipc_object_copyin(current_space(), name,
662: MACH_MSG_TYPE_COPY_SEND,
663: (ipc_object_t *) &kern_port);
664: if (kr != KERN_SUCCESS)
665: return IS_NULL;
666:
667: space = convert_port_to_space(kern_port);
668: if (IP_VALID(kern_port))
669: ipc_port_release_send(kern_port);
670:
671: return space;
672: }
673: }
674:
675: /*
676: * Hack to translate a thread port to a thread pointer for calling
677: * thread_get_state and thread_set_state. This is only necessary
678: * because the IPC message for these two operations overflows the
679: * kernel stack.
680: *
681: * AARGH!
682: */
683:
684: kern_return_t thread_get_state_KERNEL(thread_port, flavor,
685: old_state, old_state_count)
686: mach_port_t thread_port; /* port right for thread */
687: int flavor;
688: thread_state_t old_state; /* pointer to OUT array */
689: natural_t *old_state_count; /* IN/OUT */
690: {
691: thread_t thread;
692: kern_return_t result;
693:
694: thread = port_name_to_thread(thread_port);
695: result = thread_get_state(thread, flavor, old_state, old_state_count);
696: thread_deallocate(thread);
697:
698: return result;
699: }
700:
701: kern_return_t thread_set_state_KERNEL(thread_port, flavor,
702: new_state, new_state_count)
703: mach_port_t thread_port; /* port right for thread */
704: int flavor;
705: thread_state_t new_state;
706: natural_t new_state_count;
707: {
708: thread_t thread;
709: kern_return_t result;
710:
711: thread = port_name_to_thread(thread_port);
712: result = thread_set_state(thread, flavor, new_state, new_state_count);
713: thread_deallocate(thread);
714:
715: return result;
716: }
717:
718: /*
719: * Things to keep in mind:
720: *
721: * The idea here is to duplicate the semantics of the true kernel RPC.
722: * The destination port/object should be checked first, before anything
723: * that the user might notice (like ipc_object_copyin). Return
724: * MACH_SEND_INTERRUPTED if it isn't correct, so that the user stub
725: * knows to fall back on an RPC. For other return values, it won't
726: * retry with an RPC. The retry might get a different (incorrect) rc.
727: * Return values are only set (and should only be set, with copyout)
728: * on successfull calls.
729: */
730:
731: kern_return_t
732: syscall_vm_map(
733: mach_port_t target_map,
734: vm_offset_t *address,
735: vm_size_t size,
736: vm_offset_t mask,
737: boolean_t anywhere,
738: mach_port_t memory_object,
739: vm_offset_t offset,
740: boolean_t copy,
741: vm_prot_t cur_protection,
742: vm_prot_t max_protection,
743: vm_inherit_t inheritance)
744: {
745: vm_map_t map;
746: ipc_port_t port;
747: vm_offset_t addr;
748: kern_return_t result;
749:
750: map = port_name_to_map(target_map);
751: if (map == VM_MAP_NULL)
752: return MACH_SEND_INTERRUPTED;
753:
754: if (MACH_PORT_VALID(memory_object)) {
755: result = ipc_object_copyin(current_space(), memory_object,
756: MACH_MSG_TYPE_COPY_SEND,
757: (ipc_object_t *) &port);
758: if (result != KERN_SUCCESS) {
759: vm_map_deallocate(map);
760: return result;
761: }
762: } else
763: port = (ipc_port_t) memory_object;
764:
765: copyin((char *)address, (char *)&addr, sizeof(vm_offset_t));
766: result = vm_map(map, &addr, size, mask, anywhere,
767: port, offset, copy,
768: cur_protection, max_protection, inheritance);
769: if (result == KERN_SUCCESS)
770: copyout((char *)&addr, (char *)address, sizeof(vm_offset_t));
771: if (IP_VALID(port))
772: ipc_port_release_send(port);
773: vm_map_deallocate(map);
774:
775: return result;
776: }
777:
778: kern_return_t syscall_vm_allocate(target_map, address, size, anywhere)
779: mach_port_t target_map;
780: vm_offset_t *address;
781: vm_size_t size;
782: boolean_t anywhere;
783: {
784: vm_map_t map;
785: vm_offset_t addr;
786: kern_return_t result;
787:
788: map = port_name_to_map(target_map);
789: if (map == VM_MAP_NULL)
790: return MACH_SEND_INTERRUPTED;
791:
792: copyin((char *)address, (char *)&addr, sizeof(vm_offset_t));
793: result = vm_allocate(map, &addr, size, anywhere);
794: if (result == KERN_SUCCESS)
795: copyout((char *)&addr, (char *)address, sizeof(vm_offset_t));
796: vm_map_deallocate(map);
797:
798: return result;
799: }
800:
801: kern_return_t syscall_vm_deallocate(target_map, start, size)
802: mach_port_t target_map;
803: vm_offset_t start;
804: vm_size_t size;
805: {
806: vm_map_t map;
807: kern_return_t result;
808:
809: map = port_name_to_map(target_map);
810: if (map == VM_MAP_NULL)
811: return MACH_SEND_INTERRUPTED;
812:
813: result = vm_deallocate(map, start, size);
814: vm_map_deallocate(map);
815:
816: return result;
817: }
818:
819: kern_return_t syscall_task_create(parent_task, inherit_memory, child_task)
820: mach_port_t parent_task;
821: boolean_t inherit_memory;
822: mach_port_t *child_task; /* OUT */
823: {
824: task_t t, c;
825: ipc_port_t port;
826: mach_port_t name;
827: kern_return_t result;
828:
829: t = port_name_to_task(parent_task);
830: if (t == TASK_NULL)
831: return MACH_SEND_INTERRUPTED;
832:
833: result = task_create(t, inherit_memory, &c);
834: if (result == KERN_SUCCESS) {
835: port = (ipc_port_t) convert_task_to_port(c);
836: /* always returns a name, even for non-success return codes */
837: (void) ipc_kmsg_copyout_object(current_space(),
838: (ipc_object_t) port,
839: MACH_MSG_TYPE_PORT_SEND, &name);
840: copyout((char *)&name, (char *)child_task,
841: sizeof(mach_port_t));
842: }
843: task_deallocate(t);
844:
845: return result;
846: }
847:
848: kern_return_t syscall_task_terminate(task)
849: mach_port_t task;
850: {
851: task_t t;
852: kern_return_t result;
853:
854: t = port_name_to_task(task);
855: if (t == TASK_NULL)
856: return MACH_SEND_INTERRUPTED;
857:
858: result = task_terminate(t);
859: task_deallocate(t);
860:
861: return result;
862: }
863:
864: kern_return_t syscall_task_suspend(task)
865: mach_port_t task;
866: {
867: task_t t;
868: kern_return_t result;
869:
870: t = port_name_to_task(task);
871: if (t == TASK_NULL)
872: return MACH_SEND_INTERRUPTED;
873:
874: result = task_suspend(t);
875: task_deallocate(t);
876:
877: return result;
878: }
879:
880: kern_return_t syscall_task_set_special_port(task, which_port, port_name)
881: mach_port_t task;
882: int which_port;
883: mach_port_t port_name;
884: {
885: task_t t;
886: ipc_port_t port;
887: kern_return_t result;
888:
889: t = port_name_to_task(task);
890: if (t == TASK_NULL)
891: return MACH_SEND_INTERRUPTED;
892:
893: if (MACH_PORT_VALID(port_name)) {
894: result = ipc_object_copyin(current_space(), port_name,
895: MACH_MSG_TYPE_COPY_SEND,
896: (ipc_object_t *) &port);
897: if (result != KERN_SUCCESS) {
898: task_deallocate(t);
899: return result;
900: }
901: } else
902: port = (ipc_port_t) port_name;
903:
904: result = task_set_special_port(t, which_port, port);
905: if ((result != KERN_SUCCESS) && IP_VALID(port))
906: ipc_port_release_send(port);
907: task_deallocate(t);
908:
909: return result;
910: }
911:
912: kern_return_t
913: syscall_mach_port_allocate(task, right, namep)
914: mach_port_t task;
915: mach_port_right_t right;
916: mach_port_t *namep;
917: {
918: ipc_space_t space;
919: mach_port_t name;
920: kern_return_t kr;
921:
922: space = port_name_to_space(task);
923: if (space == IS_NULL)
924: return MACH_SEND_INTERRUPTED;
925:
926: kr = mach_port_allocate(space, right, &name);
927: if (kr == KERN_SUCCESS)
928: copyout((char *)&name, (char *)namep, sizeof(mach_port_t));
929: is_release(space);
930:
931: return kr;
932: }
933:
934: kern_return_t
935: syscall_mach_port_allocate_name(task, right, name)
936: mach_port_t task;
937: mach_port_right_t right;
938: mach_port_t name;
939: {
940: ipc_space_t space;
941: kern_return_t kr;
942:
943: space = port_name_to_space(task);
944: if (space == IS_NULL)
945: return MACH_SEND_INTERRUPTED;
946:
947: kr = mach_port_allocate_name(space, right, name);
948: is_release(space);
949:
950: return kr;
951: }
952:
953: kern_return_t
954: syscall_mach_port_deallocate(task, name)
955: mach_port_t task;
956: mach_port_t name;
957: {
958: ipc_space_t space;
959: kern_return_t kr;
960:
961: space = port_name_to_space(task);
962: if (space == IS_NULL)
963: return MACH_SEND_INTERRUPTED;
964:
965: kr = mach_port_deallocate(space, name);
966: is_release(space);
967:
968: return kr;
969: }
970:
971: kern_return_t
972: syscall_mach_port_insert_right(task, name, right, rightType)
973: mach_port_t task;
974: mach_port_t name;
975: mach_port_t right;
976: mach_msg_type_name_t rightType;
977: {
978: ipc_space_t space;
979: ipc_object_t object;
980: mach_msg_type_name_t newtype;
981: kern_return_t kr;
982:
983: space = port_name_to_space(task);
984: if (space == IS_NULL)
985: return MACH_SEND_INTERRUPTED;
986:
987: if (!MACH_MSG_TYPE_PORT_ANY(rightType)) {
988: is_release(space);
989: return KERN_INVALID_VALUE;
990: }
991:
992: if (MACH_PORT_VALID(right)) {
993: kr = ipc_object_copyin(current_space(), right, rightType,
994: &object);
995: if (kr != KERN_SUCCESS) {
996: is_release(space);
997: return kr;
998: }
999: } else
1000: object = (ipc_object_t) right;
1001: newtype = ipc_object_copyin_type(rightType);
1002:
1003: kr = mach_port_insert_right(space, name, (ipc_port_t) object, newtype);
1004: if ((kr != KERN_SUCCESS) && IO_VALID(object))
1005: ipc_object_destroy(object, newtype);
1006: is_release(space);
1007:
1008: return kr;
1009: }
1010:
1011: kern_return_t syscall_thread_depress_abort(thread)
1012: mach_port_t thread;
1013: {
1014: thread_t t;
1015: kern_return_t result;
1016:
1017: t = port_name_to_thread(thread);
1018: if (t == THREAD_NULL)
1019: return MACH_SEND_INTERRUPTED;
1020:
1021: result = thread_depress_abort(t);
1022: thread_deallocate(t);
1023:
1024: return result;
1025: }
1026:
1027: /*
1028: * Device traps -- these are way experimental.
1029: */
1030:
1031: extern io_return_t ds_device_write_trap();
1032: extern io_return_t ds_device_writev_trap();
1033:
1034: io_return_t
1035: syscall_device_write_request(mach_port_t device_name,
1036: mach_port_t reply_name,
1037: dev_mode_t mode,
1038: recnum_t recnum,
1039: vm_offset_t data,
1040: vm_size_t data_count)
1041: {
1042: device_t dev;
1043: ipc_port_t reply_port;
1044: io_return_t res;
1045:
1046: /*
1047: * First try to translate the device name.
1048: *
1049: * If this fails, return KERN_INVALID_CAPABILITY.
1050: * Caller knows that this most likely means that
1051: * device is not local to node and IPC should be used.
1052: *
1053: * If kernel doesn't do device traps, kern_invalid()
1054: * will be called instead of this function which will
1055: * return KERN_INVALID_ARGUMENT.
1056: */
1057: dev = port_name_to_device(device_name);
1058: if (dev == DEVICE_NULL)
1059: return KERN_INVALID_CAPABILITY;
1060:
1061: /*
1062: * Translate reply port.
1063: */
1064: if (reply_name == MACH_PORT_NULL)
1065: reply_port = IP_NULL;
1066: else {
1067: /* Homey don't play that. */
1068: device_deallocate(dev);
1069: return KERN_INVALID_RIGHT;
1070: }
1071:
1072: /* note: doesn't take reply_port arg yet. */
1073: res = ds_device_write_trap(dev, /*reply_port,*/
1074: mode, recnum,
1075: data, data_count);
1076:
1077: /*
1078: * Give up reference from port_name_to_device.
1079: */
1080: device_deallocate(dev);
1081: return res;
1082: }
1083:
1084: io_return_t
1085: syscall_device_writev_request(mach_port_t device_name,
1086: mach_port_t reply_name,
1087: dev_mode_t mode,
1088: recnum_t recnum,
1089: io_buf_vec_t *iovec,
1090: vm_size_t iocount)
1091: {
1092: device_t dev;
1093: ipc_port_t reply_port;
1094: io_return_t res;
1095:
1096: /*
1097: * First try to translate the device name.
1098: *
1099: * If this fails, return KERN_INVALID_CAPABILITY.
1100: * Caller knows that this most likely means that
1101: * device is not local to node and IPC should be used.
1102: *
1103: * If kernel doesn't do device traps, kern_invalid()
1104: * will be called instead of this function which will
1105: * return KERN_INVALID_ARGUMENT.
1106: */
1107: dev = port_name_to_device(device_name);
1108: if (dev == DEVICE_NULL)
1109: return KERN_INVALID_CAPABILITY;
1110:
1111: /*
1112: * Translate reply port.
1113: */
1114: if (reply_name == MACH_PORT_NULL)
1115: reply_port = IP_NULL;
1116: else {
1117: /* Homey don't play that. */
1118: device_deallocate(dev);
1119: return KERN_INVALID_RIGHT;
1120: }
1121:
1122: /* note: doesn't take reply_port arg yet. */
1123: res = ds_device_writev_trap(dev, /*reply_port,*/
1124: mode, recnum,
1125: iovec, iocount);
1126:
1127: /*
1128: * Give up reference from port_name_to_device.
1129: */
1130: device_deallocate(dev);
1131: return res;
1132: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.