|
|
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: * HISTORY ! 27: * ! 28: * Revision 1.1.1.1 1998/09/22 21:05:32 wsanchez ! 29: * Import of Mac OS X kernel (~semeria) ! 30: * ! 31: * Revision 1.2 1998/04/29 17:36:19 mburg ! 32: * MK7.3 merger ! 33: * ! 34: * Revision 1.1.18.1 1998/02/03 09:30:24 gdt ! 35: * Merge up to MK7.3 ! 36: * [1998/02/03 09:15:10 gdt] ! 37: * ! 38: * Revision 1.1.16.1 1997/06/17 02:59:23 devrcs ! 39: * Added call to `ipc_subsystem_terminate()' to `subsystem_deallocate()' ! 40: * to close port leak. ! 41: * [1997/03/18 18:25:55 rkc] ! 42: * ! 43: * Revision 1.1.7.4 1995/01/10 05:14:19 devrcs ! 44: * mk6 CR801 - merge up from nmk18b4 to nmk18b7 ! 45: * * Rev 1.1.7.3 1994/10/19 16:24:57 watkins ! 46: * Define subsystem_print if mach_debug. ! 47: * [1994/12/09 21:01:02 dwm] ! 48: * ! 49: * mk6 CR668 - 1.3b26 merge ! 50: * splx is void. ! 51: * [1994/11/04 09:32:40 dwm] ! 52: * ! 53: * Revision 1.1.7.2 1994/09/23 02:27:05 ezf ! 54: * change marker to not FREE ! 55: * [1994/09/22 21:36:22 ezf] ! 56: * ! 57: * Revision 1.1.7.1 1994/09/16 15:30:10 emcmanus ! 58: * Implement "show subsystem" command. ! 59: * [1994/09/16 15:29:11 emcmanus] ! 60: * ! 61: * Revision 1.1.3.4 1994/06/02 01:53:14 bolinger ! 62: * mk6 CR125: Initialize subsystem_lock(). ! 63: * [1994/06/01 22:30:18 bolinger] ! 64: * ! 65: * Revision 1.1.3.3 1994/01/21 01:22:58 condict ! 66: * Fix too stringent error checking. Change subsys from ool to in-line. ! 67: * [1994/01/21 01:19:32 condict] ! 68: * ! 69: * Revision 1.1.3.2 1994/01/20 16:25:29 condict ! 70: * Testing bsubmit. ! 71: * [1994/01/20 16:24:32 condict] ! 72: * ! 73: * Revision 1.1.3.1 1994/01/20 11:09:26 emcmanus ! 74: * Copied for submission. ! 75: * [1994/01/20 11:08:20 emcmanus] ! 76: * ! 77: * Revision 1.1.1.4 1994/01/20 02:45:10 condict ! 78: * Make user subsystem point at containing system subsytem struct. ! 79: * ! 80: * Revision 1.1.1.3 1994/01/15 22:01:19 condict ! 81: * Validate user subsystem data, convert user ptrs to kernel ptrs. ! 82: * ! 83: * Revision 1.1.1.2 1994/01/13 02:39:58 condict ! 84: * Implementation of RPC subsystem object, for server co-location. ! 85: * ! 86: * $EndLog$ ! 87: */ ! 88: /* ! 89: * Functions to manipulate RPC subsystem descriptions. ! 90: */ ! 91: ! 92: #include <mach/port.h> ! 93: #include <mach/kern_return.h> ! 94: #include <kern/task.h> ! 95: #include <kern/lock.h> ! 96: #include <kern/spl.h> ! 97: #include <kern/zalloc.h> ! 98: #include <kern/ipc_subsystem.h> ! 99: #include <kern/subsystem.h> ! 100: #include <kern/misc_protos.h> ! 101: ! 102: #define SUBSYSTEM_MIN_SIZE 12 ! 103: #define SUBSYSTEM_MAX_SIZE (2*1024*1024) /* What value is correct? */ ! 104: ! 105: void ! 106: subsystem_init( ! 107: void) ! 108: { ! 109: /* Nothing to do on bootstrap, at the moment. */ ! 110: } ! 111: ! 112: /* ! 113: * Routine: mach_subsystem_create ! 114: * Purpose: ! 115: * Create a new RPC subsystem. ! 116: * Conditions: ! 117: * Nothing locked. If successful, the subsystem is returned ! 118: * unlocked. (The caller has a reference.) ! 119: * Returns: ! 120: * KERN_SUCCESS The subsystem is allocated. ! 121: * KERN_INVALID_TASK The task is dead. ! 122: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 123: */ ! 124: ! 125: kern_return_t ! 126: mach_subsystem_create( ! 127: register task_t parent_task, ! 128: user_subsystem_t user_subsys, ! 129: mach_msg_type_number_t user_subsysCount, ! 130: subsystem_t *subsystem_p) ! 131: { ! 132: int i; ! 133: subsystem_t new_subsystem; ! 134: kern_return_t kr; ! 135: boolean_t deallocate = FALSE; ! 136: vm_size_t size; ! 137: vm_offset_t offset; ! 138: int num_routines; ! 139: boolean_t bad_arg = FALSE; ! 140: ! 141: if (parent_task == TASK_NULL) ! 142: return(KERN_INVALID_ARGUMENT); ! 143: ! 144: if (user_subsysCount < SUBSYSTEM_MIN_SIZE || ! 145: user_subsysCount > SUBSYSTEM_MAX_SIZE) ! 146: return(KERN_INVALID_ARGUMENT); ! 147: ! 148: /* ! 149: * Allocate a subsystem and initialize: ! 150: */ ! 151: ! 152: size = (vm_size_t)user_subsysCount + sizeof(struct subsystem) - ! 153: sizeof(struct rpc_subsystem); ! 154: new_subsystem = (subsystem_t) kalloc(size); ! 155: ! 156: if (new_subsystem == 0) ! 157: return(KERN_RESOURCE_SHORTAGE); ! 158: ! 159: new_subsystem->task = parent_task; ! 160: new_subsystem->ref_count = 1; /* A reference for our caller */ ! 161: new_subsystem->size = size; ! 162: subsystem_lock_init(new_subsystem); ! 163: ! 164: /* Copy the user subsystem data to a permanent place: */ ! 165: bcopy((char *)user_subsys, (char *)&(new_subsystem->user), ! 166: (int)user_subsysCount); ! 167: ! 168: /* Validate the user-specified fields of the subsystem: */ ! 169: ! 170: num_routines = new_subsystem->user.end - new_subsystem->user.start; ! 171: if (num_routines < 0 || ! 172: (char *)&new_subsystem->user.routine[num_routines] > ! 173: (char *)&new_subsystem->user + (int)user_subsysCount ! 174: ) { ! 175: kfree((vm_offset_t)new_subsystem, size); ! 176: return(KERN_INVALID_ADDRESS); ! 177: } ! 178: ! 179: /* The following is for converting the user pointers in the ! 180: * subsystem struct to kernel pointers: ! 181: */ ! 182: offset = (char *)&new_subsystem->user - ! 183: (char *)new_subsystem->user.base_addr; /* The user addr */ ! 184: ! 185: for (i = 0; i < num_routines; i++) { ! 186: routine_descriptor_t routine = &new_subsystem->user.routine[i]; ! 187: ! 188: /* If this is a "skip" routine, ignore it: */ ! 189: if (!routine->impl_routine) ! 190: continue; ! 191: ! 192: /* Convert the user arg_descr pointer to a kernel pointer: */ ! 193: routine->arg_descr = (routine_arg_descriptor_t) ! 194: ((char *)routine->arg_descr + offset); ! 195: ! 196: if (routine->argc > 1000000 || ! 197: routine->argc < routine->descr_count) { ! 198: bad_arg = TRUE; ! 199: break; ! 200: } ! 201: /* Validate that the arg_descr field is within the part of ! 202: * the struct that follows the routine array: */ ! 203: if ((char *)&routine->arg_descr[0] < ! 204: (char *)&new_subsystem->user.routine[num_routines] ! 205: || ! 206: (char *)&routine->arg_descr[routine->descr_count] > ! 207: (char *)&new_subsystem->user + (int)user_subsysCount ! 208: ) { ! 209: printf("Arg descr out of bounds: arg_descr=%x, &routine.num_routines=%x\n", ! 210: &routine->arg_descr[0], &new_subsystem->user.routine[num_routines]); ! 211: printf(" new_subsys->user + subsysCount = %x\n", ! 212: (char *)&new_subsystem->user + (int)user_subsysCount); ! 213: #if MACH_DEBUG && MACH_KDB ! 214: subsystem_print(new_subsystem); ! 215: /* Not all of the arg_descr pointers have necessarily ! 216: been corrected, but this just means that we print ! 217: the arg_descr from the user's input subsystem ! 218: instead of the copy we are building. */ ! 219: #endif /* MACH_DEBUG && MACH_KDB */ ! 220: bad_arg = TRUE; ! 221: break; ! 222: } ! 223: } ! 224: if (bad_arg) { ! 225: kfree((vm_offset_t)new_subsystem, size); ! 226: return(KERN_INVALID_ADDRESS); ! 227: } ! 228: ! 229: /* Convert the user base address to a kernel address: */ ! 230: new_subsystem->user.base_addr = (vm_address_t)&new_subsystem->user; ! 231: ! 232: /* Make the user subsystem point at the containing system data ! 233: * structure, so we can get from a port (which points to the user ! 234: * subsystem data) to the system subsystem struct: ! 235: */ ! 236: new_subsystem->user.subsystem = new_subsystem; ! 237: ! 238: ipc_subsystem_init(new_subsystem); ! 239: ! 240: task_lock(parent_task); ! 241: if (parent_task->active) { ! 242: parent_task->subsystem_count++; ! 243: queue_enter(&parent_task->subsystem_list, new_subsystem, ! 244: subsystem_t, subsystem_list); ! 245: } else ! 246: deallocate = TRUE; ! 247: task_unlock(parent_task); ! 248: ! 249: if (deallocate) { ! 250: /* release ref we would have given our caller */ ! 251: subsystem_deallocate(new_subsystem); ! 252: return(KERN_INVALID_TASK); ! 253: } ! 254: ! 255: ipc_subsystem_enable(new_subsystem); ! 256: ! 257: *subsystem_p = new_subsystem; ! 258: return(KERN_SUCCESS); ! 259: } ! 260: ! 261: /* ! 262: * Routine: subsystem_reference ! 263: * Purpose: ! 264: * Increments the reference count on a subsystem. ! 265: * Conditions: ! 266: * Nothing is locked. ! 267: */ ! 268: void ! 269: subsystem_reference( ! 270: register subsystem_t subsystem) ! 271: { ! 272: spl_t s; ! 273: ! 274: if (subsystem == SUBSYSTEM_NULL) ! 275: return; ! 276: ! 277: s = splsched(); ! 278: subsystem_lock(subsystem); ! 279: subsystem->ref_count++; ! 280: subsystem_unlock(subsystem); ! 281: splx(s); ! 282: } ! 283: ! 284: ! 285: ! 286: /* ! 287: * Routine: subsystem_deallocate ! 288: * Purpose: ! 289: * Decrements the reference count on a subsystem. If 0, ! 290: * destroys the subsystem. Must have no ports registered on it ! 291: * when it is destroyed. ! 292: * Conditions: ! 293: * The subsystem is locked, and ! 294: * the caller has a reference, which is consumed. ! 295: */ ! 296: ! 297: void ! 298: subsystem_deallocate( ! 299: subsystem_t subsystem) ! 300: { ! 301: task_t task; ! 302: spl_t s; ! 303: ! 304: if (subsystem == SUBSYSTEM_NULL) ! 305: return; ! 306: ! 307: s = splsched(); ! 308: subsystem_lock(subsystem); ! 309: if (--subsystem->ref_count > 0) { ! 310: subsystem_unlock(subsystem); ! 311: splx(s); ! 312: return; ! 313: } ! 314: ! 315: /* ! 316: * Count is 0, so destroy the subsystem. Need to restore the ! 317: * reference temporarily, and lock the task first: ! 318: */ ! 319: ipc_subsystem_disable(subsystem); ! 320: ! 321: subsystem->ref_count = 1; ! 322: subsystem_unlock(subsystem); ! 323: splx(s); ! 324: ! 325: task = subsystem->task; ! 326: task_lock(task); ! 327: s = splsched(); ! 328: subsystem_lock(subsystem); ! 329: ! 330: /* Check again, since we temporarily unlocked the subsystem: */ ! 331: if (--subsystem->ref_count == 0) { ! 332: ! 333: task->subsystem_count--; ! 334: queue_remove(&task->subsystem_list, subsystem, subsystem_t, ! 335: subsystem_list); ! 336: ipc_subsystem_terminate(subsystem); ! 337: subsystem_unlock(subsystem); ! 338: splx(s); ! 339: kfree((vm_offset_t) subsystem, subsystem->size); ! 340: task_unlock(task); ! 341: return; ! 342: } ! 343: ! 344: ipc_subsystem_enable(subsystem); ! 345: ! 346: subsystem_unlock(subsystem); ! 347: splx(s); ! 348: task_unlock(task); ! 349: } ! 350: ! 351: ! 352: #include <mach_kdb.h> ! 353: #if MACH_KDB ! 354: ! 355: #include <ddb/db_output.h> ! 356: #include <ddb/db_sym.h> ! 357: #include <ddb/db_print.h> ! 358: #include <ddb/db_command.h> ! 359: ! 360: #define printf kdbprintf ! 361: ! 362: /* ! 363: * Routine: subsystem_print ! 364: * Purpose: ! 365: * Pretty-print a subsystem for kdb. ! 366: */ ! 367: ! 368: void rpc_subsystem_print(rpc_subsystem_t subsys); ! 369: ! 370: void ! 371: subsystem_print( ! 372: subsystem_t subsystem) ! 373: { ! 374: extern int db_indent; ! 375: ! 376: iprintf("subsystem 0x%x\n", subsystem); ! 377: ! 378: db_indent += 2; ! 379: ! 380: iprintf("ref %d size %x task %x port %x\n", subsystem->ref_count, ! 381: subsystem->size, subsystem->task, subsystem->ipc_self); ! 382: rpc_subsystem_print(&subsystem->user); ! 383: ! 384: /* ipc_object_print(&port->ip_object); ! 385: * iprintf("receiver=0x%x", port->ip_receiver); ! 386: * printf(", receiver_name=0x%x\n", port->ip_receiver_name); ! 387: */ ! 388: db_indent -=2; ! 389: } ! 390: ! 391: struct flagnames { ! 392: char *name; ! 393: int bit; ! 394: } arg_type_names[] = { ! 395: "port", MACH_RPC_PORT, "array", MACH_RPC_ARRAY, ! 396: "variable", MACH_RPC_VARIABLE, "in", MACH_RPC_IN, "out", MACH_RPC_OUT, ! 397: "pointer", MACH_RPC_POINTER, "phys_copy", MACH_RPC_PHYSICAL_COPY, ! 398: "virt_copy", MACH_RPC_VIRTUAL_COPY, "deallocate", MACH_RPC_DEALLOCATE, ! 399: "onstack", MACH_RPC_ONSTACK, "bounded", MACH_RPC_BOUND, ! 400: }; ! 401: ! 402: void ! 403: rpc_subsystem_print( ! 404: rpc_subsystem_t subsys) ! 405: { ! 406: int i, num_routines; ! 407: ! 408: iprintf("rpc_subsystem 0x%x\n", subsys); ! 409: ! 410: db_indent += 2; ! 411: ! 412: num_routines = subsys->end - subsys->start; ! 413: iprintf("start %d end %d (%d routines) maxsize %x base %x\n", ! 414: subsys->start, subsys->end, num_routines, subsys->maxsize, ! 415: subsys->base_addr); ! 416: for (i = 0; i < num_routines; i++) { ! 417: routine_descriptor_t routine = subsys->routine + i; ! 418: routine_arg_descriptor_t args = routine->arg_descr; ! 419: int j, type, disposition; ! 420: struct flagnames *n; ! 421: char *sep; ! 422: ! 423: iprintf("%x #%d:", routine, subsys->start + i); ! 424: if (routine->impl_routine == 0) { ! 425: printf(" skip\n"); ! 426: continue; ! 427: } ! 428: printf("\n"); ! 429: db_indent += 2; ! 430: iprintf("impl "); ! 431: db_printsym((db_expr_t) routine->impl_routine, DB_STGY_PROC); ! 432: printf("\n"); ! 433: iprintf("stub "); ! 434: db_printsym((db_expr_t) routine->stub_routine, DB_STGY_PROC); ! 435: printf("\n"); ! 436: iprintf("argc %d descr_count %d max_reply %x\n", ! 437: routine->argc, routine->descr_count, routine->max_reply_msg); ! 438: for (j = 0; j < routine->descr_count; j++) { ! 439: iprintf("%x desc %d: size %d count %d offset %x type", &args[j], j, ! 440: args[j].size, args[j].count, args[j].offset); ! 441: sep = " "; ! 442: type = args[j].type; ! 443: for (n = arg_type_names; n->name != 0; n++) { ! 444: if (type & n->bit) { ! 445: printf("%s%s", sep, n->name); ! 446: sep = "|"; ! 447: type &= ~n->bit; /* Might have an alias */ ! 448: } ! 449: } ! 450: #define NAME_MASK (3 << NAME_SHIFT) /* XXX magic numbers */ ! 451: #define ACTION_MASK (3 << ACTION_SHIFT) ! 452: #define DISPOSITION_MASK (NAME_MASK | ACTION_MASK) ! 453: disposition = type & DISPOSITION_MASK; ! 454: type &= ~DISPOSITION_MASK; ! 455: if (sep[0] != '|' || type != 0) ! 456: printf("%s%x", sep, type); ! 457: switch (disposition & ACTION_MASK) { ! 458: case MACH_RPC_MOVE: printf(" move"); break; ! 459: case MACH_RPC_COPY: printf(" copy"); break; ! 460: case MACH_RPC_MAKE: printf(" make"); break; ! 461: } ! 462: switch (disposition & NAME_MASK) { ! 463: case MACH_RPC_RECEIVE: printf(" receive"); break; ! 464: case MACH_RPC_SEND: printf(" send"); break; ! 465: case MACH_RPC_SEND_ONCE: printf(" send-once"); break; ! 466: } ! 467: printf("\n"); ! 468: } ! 469: db_indent -= 2; ! 470: } ! 471: ! 472: db_indent -= 2; ! 473: } ! 474: ! 475: void ! 476: db_show_subsystem( ! 477: db_expr_t addr, ! 478: boolean_t have_addr, ! 479: db_expr_t count, ! 480: char *modif) ! 481: { ! 482: if (!have_addr || addr == 0) { ! 483: db_printf("No subsystem\n"); ! 484: return; ! 485: } ! 486: if (db_option(modif, 'r')) ! 487: rpc_subsystem_print((rpc_subsystem_t) addr); ! 488: else ! 489: subsystem_print((subsystem_t) addr); ! 490: } ! 491: ! 492: #endif /* MACH_KDB || MACH_DEBUG */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.