|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: */ ! 52: ! 53: #include <norma_vm.h> ! 54: #include <mach_rt.h> ! 55: #include <dipc.h> ! 56: ! 57: #include <mach/boolean.h> ! 58: #include <mach/port.h> ! 59: #include <mach/thread_status.h> ! 60: #include <mach/mig_errors.h> ! 61: #include <mach/mach_types.h> ! 62: #include <mach/mach_traps.h> ! 63: #include <kern/ast.h> ! 64: #include <kern/ipc_mig.h> ! 65: #include <kern/task.h> ! 66: #include <kern/thread.h> ! 67: #include <kern/ipc_kobject.h> ! 68: #include <kern/misc_protos.h> ! 69: #include <vm/vm_map.h> ! 70: #include <vm/vm_user.h> ! 71: #include <ipc/port.h> ! 72: #include <ipc/ipc_kmsg.h> ! 73: #include <ipc/ipc_entry.h> ! 74: #include <ipc/ipc_object.h> ! 75: #include <ipc/ipc_mqueue.h> ! 76: #include <ipc/ipc_space.h> ! 77: #include <ipc/ipc_port.h> ! 78: #include <ipc/ipc_pset.h> ! 79: ! 80: /* Default (zeroed) template for qos */ ! 81: ! 82: static mach_port_qos_t qos_template; ! 83: ! 84: /* ! 85: * Routine: mach_msg_send_from_kernel ! 86: * Purpose: ! 87: * Send a message from the kernel. ! 88: * ! 89: * This is used by the client side of KernelUser interfaces ! 90: * to implement SimpleRoutines. Currently, this includes ! 91: * memory_object messages. ! 92: * Conditions: ! 93: * Nothing locked. ! 94: * Returns: ! 95: * MACH_MSG_SUCCESS Sent the message. ! 96: * MACH_SEND_INVALID_DATA Bad destination port. ! 97: */ ! 98: ! 99: mach_msg_return_t ! 100: mach_msg_send_from_kernel( ! 101: mach_msg_header_t *msg, ! 102: mach_msg_size_t send_size) ! 103: { ! 104: ipc_kmsg_t kmsg; ! 105: mach_msg_return_t mr; ! 106: ! 107: if (!MACH_PORT_VALID((mach_port_name_t)msg->msgh_remote_port)) ! 108: return MACH_SEND_INVALID_DEST; ! 109: ! 110: mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg); ! 111: if (mr != MACH_MSG_SUCCESS) ! 112: panic("mach_msg_send_from_kernel"); ! 113: ! 114: ipc_kmsg_copyin_from_kernel(kmsg); ! 115: ipc_kmsg_send_always(kmsg); ! 116: ! 117: return MACH_MSG_SUCCESS; ! 118: } ! 119: ! 120: /* ! 121: * Routine: mach_msg_rpc_from_kernel ! 122: * Purpose: ! 123: * Send a message from the kernel and receive a reply. ! 124: * Uses ith_rpc_reply for the reply port. ! 125: * ! 126: * This is used by the client side of KernelUser interfaces ! 127: * to implement Routines. ! 128: * Conditions: ! 129: * Nothing locked. ! 130: * Returns: ! 131: * MACH_MSG_SUCCESS Sent the message. ! 132: * MACH_RCV_PORT_DIED The reply port was deallocated. ! 133: */ ! 134: ! 135: mach_msg_return_t ! 136: mach_msg_rpc_from_kernel( ! 137: mach_msg_header_t *msg, ! 138: mach_msg_size_t send_size, ! 139: mach_msg_size_t rcv_size) ! 140: { ! 141: thread_t self = current_thread(); ! 142: ipc_port_t reply; ! 143: ipc_kmsg_t kmsg; ! 144: mach_port_seqno_t seqno; ! 145: mach_msg_return_t mr; ! 146: ! 147: assert(MACH_PORT_VALID((mach_port_name_t)msg->msgh_remote_port)); ! 148: assert(msg->msgh_local_port == MACH_PORT_NULL); ! 149: ! 150: self->ith_scatter_list = MACH_MSG_BODY_NULL; ! 151: ! 152: mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg); ! 153: if (mr != MACH_MSG_SUCCESS) ! 154: panic("mach_msg_rpc_from_kernel"); ! 155: ! 156: rpc_lock(self); ! 157: ! 158: reply = self->ith_rpc_reply; ! 159: if (reply == IP_NULL) { ! 160: rpc_unlock(self); ! 161: reply = ipc_port_alloc_reply(); ! 162: rpc_lock(self); ! 163: if ((reply == IP_NULL) || ! 164: (self->ith_rpc_reply != IP_NULL)) ! 165: panic("mach_msg_rpc_from_kernel"); ! 166: self->ith_rpc_reply = reply; ! 167: } ! 168: ! 169: /* insert send-once right for the reply port */ ! 170: kmsg->ikm_header.msgh_local_port = reply; ! 171: kmsg->ikm_header.msgh_bits |= ! 172: MACH_MSGH_BITS(0, MACH_MSG_TYPE_MAKE_SEND_ONCE); ! 173: ! 174: ipc_port_reference(reply); ! 175: rpc_unlock(self); ! 176: ! 177: ipc_kmsg_copyin_from_kernel(kmsg); ! 178: ! 179: ipc_kmsg_send_always(kmsg); ! 180: ! 181: for (;;) { ! 182: ipc_mqueue_t mqueue; ! 183: ! 184: ip_lock(reply); ! 185: if ( !ip_active(reply)) { ! 186: ip_unlock(reply); ! 187: ipc_port_release(reply); ! 188: return MACH_RCV_PORT_DIED; ! 189: } ! 190: if (!self->top_act || !self->top_act->active) { ! 191: ip_unlock(reply); ! 192: ipc_port_release(reply); ! 193: return MACH_RCV_INTERRUPTED; ! 194: } ! 195: ! 196: assert(reply->ip_pset_count == 0); ! 197: mqueue = &reply->ip_messages; ! 198: ip_unlock(reply); ! 199: ! 200: mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE, ! 201: MACH_MSG_SIZE_MAX, ! 202: MACH_MSG_TIMEOUT_NONE, ! 203: THREAD_INTERRUPTIBLE, ! 204: &kmsg, &seqno); ! 205: if (mr == MACH_MSG_SUCCESS) ! 206: { ! 207: break; ! 208: } ! 209: ! 210: assert(mr == MACH_RCV_INTERRUPTED); ! 211: ! 212: if (self->top_act && self->top_act->handlers) { ! 213: ipc_port_release(reply); ! 214: return(mr); ! 215: } ! 216: } ! 217: ipc_port_release(reply); ! 218: ! 219: /* ! 220: * XXXXX Set manually for now ... ! 221: * No, why even bother, since the effort is wasted? ! 222: * ! 223: { mach_msg_format_0_trailer_t *trailer = (mach_msg_format_0_trailer_t *) ! 224: ((vm_offset_t)&kmsg->ikm_header + kmsg->ikm_header.msgh_size); ! 225: trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0; ! 226: trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE; ! 227: } ! 228: *****/ ! 229: ! 230: if (rcv_size < kmsg->ikm_header.msgh_size) { ! 231: ipc_kmsg_copyout_dest(kmsg, ipc_space_reply); ! 232: ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size); ! 233: return MACH_RCV_TOO_LARGE; ! 234: } ! 235: ! 236: /* ! 237: * We want to preserve rights and memory in reply! ! 238: * We don't have to put them anywhere; just leave them ! 239: * as they are. ! 240: */ ! 241: ! 242: ipc_kmsg_copyout_to_kernel(kmsg, ipc_space_reply); ! 243: ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size); ! 244: return MACH_MSG_SUCCESS; ! 245: } ! 246: ! 247: ! 248: /************** These Calls are set up for kernel-loaded tasks **************/ ! 249: /************** Apple does not plan on supporting that. These **************/ ! 250: /************** need to be reworked to deal with the kernel **************/ ! 251: /************** proper to eliminate the kernel specific code MIG **************/ ! 252: /************** must generate. **************/ ! 253: ! 254: ! 255: /* ! 256: * Routine: mach_msg ! 257: * Purpose: ! 258: * Like mach_msg_overwrite_trap except that message buffers ! 259: * live in kernel space. Doesn't handle any options. ! 260: * ! 261: * This is used by in-kernel server threads to make ! 262: * kernel calls, to receive request messages, and ! 263: * to send reply messages. ! 264: * Conditions: ! 265: * Nothing locked. ! 266: * Returns: ! 267: */ ! 268: ! 269: mach_msg_return_t ! 270: mach_msg_overwrite( ! 271: mach_msg_header_t *msg, ! 272: mach_msg_option_t option, ! 273: mach_msg_size_t send_size, ! 274: mach_msg_size_t rcv_size, ! 275: mach_port_name_t rcv_name, ! 276: mach_msg_timeout_t timeout, ! 277: mach_port_name_t notify, ! 278: mach_msg_header_t *rcv_msg, ! 279: mach_msg_size_t rcv_msg_size) ! 280: { ! 281: ipc_space_t space = current_space(); ! 282: vm_map_t map = current_map(); ! 283: ipc_kmsg_t kmsg; ! 284: mach_port_seqno_t seqno; ! 285: mach_msg_return_t mr; ! 286: mach_msg_format_0_trailer_t *trailer; ! 287: ! 288: if (option & MACH_SEND_MSG) { ! 289: mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg); ! 290: if (mr != MACH_MSG_SUCCESS) ! 291: panic("mach_msg"); ! 292: ! 293: mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL); ! 294: if (mr != MACH_MSG_SUCCESS) { ! 295: ikm_free(kmsg); ! 296: return mr; ! 297: } ! 298: ! 299: do ! 300: mr = ipc_kmsg_send(kmsg, MACH_MSG_OPTION_NONE, ! 301: MACH_MSG_TIMEOUT_NONE); ! 302: while (mr == MACH_SEND_INTERRUPTED); ! 303: assert(mr == MACH_MSG_SUCCESS); ! 304: } ! 305: ! 306: if (option & MACH_RCV_MSG) { ! 307: thread_t self = current_thread(); ! 308: ! 309: self->ith_scatter_list = MACH_MSG_BODY_NULL; ! 310: do { ! 311: ipc_object_t object; ! 312: ipc_mqueue_t mqueue; ! 313: ! 314: mr = ipc_mqueue_copyin(space, rcv_name, ! 315: &mqueue, &object); ! 316: if (mr != MACH_MSG_SUCCESS) ! 317: return mr; ! 318: /* hold ref for object */ ! 319: ! 320: mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE, ! 321: MACH_MSG_SIZE_MAX, ! 322: MACH_MSG_TIMEOUT_NONE, ! 323: THREAD_ABORTSAFE, ! 324: &kmsg, &seqno); ! 325: ipc_object_release(object); ! 326: ! 327: } while (mr == MACH_RCV_INTERRUPTED); ! 328: if (mr != MACH_MSG_SUCCESS) ! 329: return mr; ! 330: ! 331: trailer = (mach_msg_format_0_trailer_t *) ! 332: ((vm_offset_t)&kmsg->ikm_header + kmsg->ikm_header.msgh_size); ! 333: if (option & MACH_RCV_TRAILER_MASK) { ! 334: trailer->msgh_seqno = seqno; ! 335: trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(option); ! 336: } ! 337: ! 338: if (rcv_size < (kmsg->ikm_header.msgh_size + trailer->msgh_trailer_size)) { ! 339: ipc_kmsg_copyout_dest(kmsg, space); ! 340: ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg); ! 341: return MACH_RCV_TOO_LARGE; ! 342: } ! 343: ! 344: mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL, ! 345: MACH_MSG_BODY_NULL); ! 346: if (mr != MACH_MSG_SUCCESS) { ! 347: if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) { ! 348: ipc_kmsg_put_to_kernel(msg, kmsg, ! 349: kmsg->ikm_header.msgh_size + trailer->msgh_trailer_size); ! 350: } else { ! 351: ipc_kmsg_copyout_dest(kmsg, space); ! 352: ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg); ! 353: } ! 354: ! 355: return mr; ! 356: } ! 357: ! 358: ipc_kmsg_put_to_kernel(msg, kmsg, ! 359: kmsg->ikm_header.msgh_size + trailer->msgh_trailer_size); ! 360: } ! 361: ! 362: return MACH_MSG_SUCCESS; ! 363: } ! 364: ! 365: /* ! 366: * Routine: mig_get_reply_port ! 367: * Purpose: ! 368: * Called by client side interfaces living in the kernel ! 369: * to get a reply port. This port is used for ! 370: * mach_msg() calls which are kernel calls. ! 371: */ ! 372: mach_port_t ! 373: mig_get_reply_port(void) ! 374: { ! 375: thread_t self = current_thread(); ! 376: ! 377: assert(self->ith_mig_reply == (mach_port_t)0); ! 378: ! 379: /* ! 380: * JMM - for now we have no real clients of this under the kernel ! 381: * loaded server model because we only have one of those. In order ! 382: * to avoid MIG changes, we just return null here - and return] ! 383: * references to ipc_port_t's instead of names. ! 384: * ! 385: * if (self->ith_mig_reply == MACH_PORT_NULL) ! 386: * self->ith_mig_reply = mach_reply_port(); ! 387: */ ! 388: return self->ith_mig_reply; ! 389: } ! 390: ! 391: /* ! 392: * Routine: mig_dealloc_reply_port ! 393: * Purpose: ! 394: * Called by client side interfaces to get rid of a reply port. ! 395: * Shouldn't ever be called inside the kernel, because ! 396: * kernel calls shouldn't prompt Mig to call it. ! 397: */ ! 398: ! 399: void ! 400: mig_dealloc_reply_port( ! 401: mach_port_t reply_port) ! 402: { ! 403: panic("mig_dealloc_reply_port"); ! 404: } ! 405: ! 406: /* ! 407: * Routine: mig_put_reply_port ! 408: * Purpose: ! 409: * Called by client side interfaces after each RPC to ! 410: * let the client recycle the reply port if it wishes. ! 411: */ ! 412: void ! 413: mig_put_reply_port( ! 414: mach_port_t reply_port) ! 415: { ! 416: } ! 417: ! 418: /* ! 419: * mig_strncpy.c - by Joshua Block ! 420: * ! 421: * mig_strncp -- Bounded string copy. Does what the library routine strncpy ! 422: * OUGHT to do: Copies the (null terminated) string in src into dest, a ! 423: * buffer of length len. Assures that the copy is still null terminated ! 424: * and doesn't overflow the buffer, truncating the copy if necessary. ! 425: * ! 426: * Parameters: ! 427: * ! 428: * dest - Pointer to destination buffer. ! 429: * ! 430: * src - Pointer to source string. ! 431: * ! 432: * len - Length of destination buffer. ! 433: */ ! 434: int ! 435: mig_strncpy( ! 436: char *dest, ! 437: char *src, ! 438: int len) ! 439: { ! 440: int i; ! 441: ! 442: if (len <= 0) ! 443: return 0; ! 444: ! 445: for (i=1; i<len; i++) ! 446: if (! (*dest++ = *src++)) ! 447: return i; ! 448: ! 449: *dest = '\0'; ! 450: return i; ! 451: } ! 452: ! 453: char * ! 454: mig_user_allocate( ! 455: vm_size_t size) ! 456: { ! 457: return (char *)kalloc(size); ! 458: } ! 459: ! 460: void ! 461: mig_user_deallocate( ! 462: char *data, ! 463: vm_size_t size) ! 464: { ! 465: kfree((vm_offset_t)data, size); ! 466: } ! 467: ! 468: thread_act_t ! 469: port_name_to_act( ! 470: mach_port_name_t name) ! 471: { ! 472: thread_act_t thr_act; ! 473: ipc_port_t kern_port; ! 474: kern_return_t kr; ! 475: ! 476: if (MACH_PORT_VALID(name)) { ! 477: kr = ipc_object_copyin(current_space(), name, ! 478: MACH_MSG_TYPE_COPY_SEND, ! 479: (ipc_object_t *) &kern_port); ! 480: if (kr != KERN_SUCCESS) ! 481: return THR_ACT_NULL; ! 482: ! 483: thr_act = convert_port_to_act(kern_port); ! 484: ! 485: if (IP_VALID(kern_port)) ! 486: ipc_port_release_send(kern_port); ! 487: } ! 488: return thr_act; ! 489: } ! 490: ! 491: task_t ! 492: port_name_to_task( ! 493: mach_port_name_t name) ! 494: { ! 495: ipc_port_t kern_port; ! 496: kern_return_t kr; ! 497: task_t task = TASK_NULL; ! 498: ! 499: if (MACH_PORT_VALID(name)) { ! 500: kr = ipc_object_copyin(current_space(), name, ! 501: MACH_MSG_TYPE_COPY_SEND, ! 502: (ipc_object_t *) &kern_port); ! 503: if (kr != KERN_SUCCESS) ! 504: return TASK_NULL; ! 505: ! 506: task = convert_port_to_task(kern_port); ! 507: ! 508: if (IP_VALID(kern_port)) ! 509: ipc_port_release_send(kern_port); ! 510: } ! 511: return task; ! 512: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.