Annotation of XNU/osfmk/kern/norma_task.c, revision 1.1.1.1

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:34  wsanchez
                     29:  * Import of Mac OS X kernel (~semeria)
                     30:  *
                     31:  * Revision 1.2  1998/04/29 17:36:06  mburg
                     32:  * MK7.3 merger
                     33:  *
                     34:  * Revision 1.1.24.1  1998/02/03  09:28:42  gdt
                     35:  *     Merge up to MK7.3
                     36:  *     [1998/02/03  09:13:51  gdt]
                     37:  *
                     38:  * Revision 1.1.22.1  1997/06/17  02:57:54  devrcs
                     39:  *     Add node incarnation number to uid definition.
                     40:  *     [1996/09/03  19:31:17  watkins]
                     41:  * 
                     42:  * Revision 1.1.7.3  1995/10/09  17:15:22  devrcs
                     43:  *     Added ETAP argument to `mutex_init()' call.
                     44:  *     [1995/09/13  16:04:48  joe]
                     45:  * 
                     46:  * Revision 1.1.7.2  1995/09/18  19:15:00  devrcs
                     47:  *     Added ETAP argument to `mutex_init()' call.
                     48:  *     [1995/09/13  16:04:48  joe]
                     49:  * 
                     50:  * Revision 1.1.7.1  1995/02/23  17:31:49  alanl
                     51:  *     DIPC:  Merge from nmk17b2 to nmk18b8.
                     52:  *     [95/01/05            alanl]
                     53:  * 
                     54:  * Revision 1.1.4.4  1994/12/06  20:11:26  alanl
                     55:  *     Include norma_protos.h.
                     56:  *     [94/12/05            mmp]
                     57:  * 
                     58:  * Revision 1.1.4.3  1994/09/09  23:12:57  alanl
                     59:  *     Merge up to NMK17.3.  Note:  chose to preserve most of
                     60:  *     the mmp task_set_inherited_ports solution, with small
                     61:  *     modifications from the paire solution.
                     62:  * 
                     63:  *     Revision 1.4.15.3  1994/08/31  14:13:44  paire
                     64:  *             In task_set_inherited_ports routine, the ipc_port_release_send
                     65:  *             routine must not be called while holding the task simple lock.
                     66:  *             [94/08/26            paire]
                     67:  *     [94/09/07            alanl]
                     68:  * 
                     69:  * Revision 1.1.4.2  1994/09/01  12:52:22  alanl
                     70:  *     Fix task_set_inherited_ports to drop ports after releasing the
                     71:  *     task lock.  (With mmp.)
                     72:  *     [94/08/29            alanl]
                     73:  * 
                     74:  * Revision 1.1.4.1  1994/08/04  02:25:24  mmp
                     75:  *     DIPC:  Merge up from NMK16.
                     76:  *     DIPC:  replace use of norma_get_special_port with
                     77:  *     dipc_host_priv_port.  Eliminate norma_ipc.h.
                     78:  *     [1994/04/27  23:52:52  alanl]
                     79:  * 
                     80:  *     DIPC:  separated out from NORMA_IPC.  Include
                     81:  *     <dipc/dipc_funcs.h> rather than <norma/ipc_node.h>.
                     82:  *     NORMA_TASK must presuppose DIPC.
                     83:  *     [1994/04/20  18:31:04  alanl]
                     84:  * 
                     85:  * Revision 1.4.21.4  1994/09/23  02:49:55  ezf
                     86:  *     change marker to not FREE
                     87:  *     [1994/09/22  21:46:48  ezf]
                     88:  * 
                     89:  * Revision 1.4.21.3  1994/09/10  21:47:13  bolinger
                     90:  *     Merge up to NMK17.3
                     91:  *     [1994/09/08  19:58:01  bolinger]
                     92:  * 
                     93:  * Revision 1.4.21.2  1994/06/21  19:43:02  dlb
                     94:  *     Use mutex_init to initialize new task's lock.
                     95:  *     Add additional argument to task_create_local().
                     96:  *     [94/06/16            dlb]
                     97:  * 
                     98:  * Revision 1.4.21.1  1994/06/14  22:39:26  robert
                     99:  *     merge forward
                    100:  *     [1994/06/14  22:04:58  robert]
                    101:  * 
                    102:  * Revision 1.4.19.2  1994/06/14  13:29:35  dswartz
                    103:  *     Preemption merge
                    104:  * 
                    105:  * Revision 1.4.15.3  1994/08/31  14:13:44  paire
                    106:  *     In task_set_inherited_ports routine, the ipc_port_release_send
                    107:  *     routine must not be called while holding the task simple lock.
                    108:  *     [94/08/26            paire]
                    109:  * 
                    110:  * Revision 1.4.15.2  1994/03/11  15:27:17  bernadat
                    111:  *     Fixed misordered parameters in norma_task_common().
                    112:  *     Fixed test against TASK_PORT_REGISTER_MAX in
                    113:  *             task_set_inherited_ports().
                    114:  *     [94/03/11            bernadat]
                    115:  * 
                    116:  * Revision 1.4.15.1  1994/03/07  16:52:36  paire
                    117:  *     Implemented new exception ports.
                    118:  *     [94/02/22            paire]
                    119:  * 
                    120:  *     Added ANSI prototypes.
                    121:  *     [94/02/15            paire]
                    122:  * 
                    123:  *     Added mcmsg.h (machine dependent, needs to be fixed)
                    124:  *     Change from NMK16.1 [93/12/03            bernadat]
                    125:  * 
                    126:  *     Added init. of new_task->itk_lock_data in norma_task_common().
                    127:  *     Fixed a typo from last merge.
                    128:  *     In task_[sg]et_inherited_ports(), task_[sg]et_special_port()
                    129:  *     must be called without any lock held.
                    130:  *     Change from NMK16.1 [93/11/30            paire]
                    131:  * 
                    132:  *     Added missing semicolon preventing sequent MP build.
                    133:  *     Change from NMK16.1 [93/08/18            bernadat]
                    134:  * 
                    135:  *     Fixes for ANSI C
                    136:  *     Change from NMK16.1 [93/07/20            bernadat]
                    137:  * 
                    138:  *     [Joseph Barerra:[email protected]] Added norma_task_teleport
                    139:  *     call for task migration.
                    140:  *     Change from NORMA_MK14.6 [93/03/08            sjs]
                    141:  *     [94/02/04            paire]
                    142:  * 
                    143:  * Revision 1.4.2.2  1993/06/09  02:46:16  gm
                    144:  *     Added to OSF/1 R1.3 from NMK15.0.
                    145:  *     [1993/06/02  21:21:05  jeffc]
                    146:  * 
                    147:  * Revision 1.4  1993/04/19  16:57:22  devrcs
                    148:  *     Use task_{set,get}_special_port for norma_task_create
                    149:  *     instead of referencing itk_exception which does not exist
                    150:  *     anymore. For the final solution (transfering all exception
                    151:  *     ports) we need to change the internal MIG stub and probably
                    152:  *     and need also to split the exception_action structure to pass
                    153:  *     it through mig.
                    154:  *     [93/03/02            bernadat]
                    155:  * 
                    156:  * Revision 1.3  1992/12/07  21:30:14  robert
                    157:  *     integrate any changes below for 14.0 (branch from 13.16 base)
                    158:  * 
                    159:  *     Dave Mitchell (dwm) at Open Software Foundation 23-Oct-92
                    160:  *     Rearrange task_create() et al. to prevent user code from
                    161:  *     being able to pass in a null parent.    (#478)
                    162:  * 
                    163:  *     Joseph Barrera (jsb) at Carnegie-Mellon University 11-Sep-92
                    164:  *     This version now supports VM_INHERIT_SHARE.
                    165:  *     Added norma_task_clone to support task migration.
                    166:  *     Use norma_get_special_port() instead of remote_host().
                    167:  *     Moved task_copy_vm to norma/vm_copy.c. Removed babble routine.
                    168:  *     Placed task_create_remote_node feature under TASK_CREATE_USE_REMOTE
                    169:  *     conditional. Folded task initialization calls into norma_task_allocate.
                    170:  *     Removed norma_task_server and associated lock. Check for null parent
                    171:  *     task in task_create. Terminate task upon address space copy failure.
                    172:  *     [1992/12/06  20:51:48  robert]
                    173:  * 
                    174:  * Revision 1.2  1992/11/25  01:15:11  robert
                    175:  *     fix history
                    176:  *     [1992/11/09  21:58:59  robert]
                    177:  * 
                    178:  *     integrate changes below for norma_14
                    179:  *     [1992/11/09  16:47:47  robert]
                    180:  * 
                    181:  * Revision 1.1  1992/11/05  21:00:06  robert
                    182:  *     Initial revision
                    183:  *     [92/10/23            dwm]
                    184:  * 
                    185:  * Revision 0.0  92/10/23            dwm
                    186:  *     Terminate remote_task in norma_task_create() error path,
                    187:  *     to avoid leaving remote orphans hanging around, and avoid
                    188:  *     returning random MiG errors.  (#471, 475).
                    189:  *     Rearrange task_create() et al. to prevent user code from
                    190:  *     being able to pass in a null parent.    (#478)
                    191:  * 
                    192:  * $EndLog$
                    193:  */
                    194: /* CMU_HIST */
                    195: /*
                    196:  * Revision 2.7.2.7  92/09/15  17:34:52  jeffreyh
                    197:  *     When inheriting memory in task_copy_vm, set protection in
                    198:  *     locally forked map to max.  This deals with regions that are
                    199:  *             currently unreadable but could become readable in the future.
                    200:  *     Don't set up cross node copy logic for permanently unreadable
                    201:  *     regions.  Don't copy read-only regions.
                    202:  *     [92/08/14            dlb]
                    203:  * 
                    204:  *     Add bounds checking on the node to task_set_child_node
                    205:  *     and norma_task_create.
                    206:  *     [92/07/23            jeffreyh]
                    207:  * 
                    208:  * Revision 2.7.2.6  92/05/28  18:20:32  jeffreyh
                    209:  *     Add new type argument to remote_host call
                    210:  * 
                    211:  * Revision 2.7.2.5  92/05/27  00:53:43  jeffreyh
                    212:  *     norma_task_create inits mcmsg_task in MCMSG ifdef
                    213:  *     [[email protected]]
                    214:  * 
                    215:  * Revision 2.7.2.4  92/03/04  16:07:16  jeffreyh
                    216:  *     Converted to use out-of-line forms of task_{get,set}_emulation_vector.
                    217:  *     [92/03/04  14:55:51  jsb]
                    218:  * 
                    219:  * Revision 2.7.2.3  92/02/21  11:25:15  jsb
                    220:  *     Release send right to memory_object after mapping it in remote task
                    221:  *     in task_copy_vm.
                    222:  *     [92/02/20  10:29:45  jsb]
                    223:  * 
                    224:  *     Set copy flag TRUE in r_vm_map call in task_copy_vm.
                    225:  *     This is now practical due to smarter copy strategy management
                    226:  *     in xmm_svm (compared to when it always used MEMORY_OBJECT_COPY_NONE).
                    227:  *     It also keeps xmm_copy from having to deal with data writes without
                    228:  *     having to use an xmm_shadow layer.
                    229:  *     [92/02/11  11:39:23  jsb]
                    230:  * 
                    231:  *     Release map reference in task_copy_vm.
                    232:  *     [92/01/22  10:29:57  jsb]
                    233:  * 
                    234:  * Revision 2.7.2.2  92/01/09  18:46:08  jsb
                    235:  *     Added logic in task_create to alternate task creation between local
                    236:  *     node and a patchable remote node. For testing purposes only.
                    237:  *     [92/01/08  16:41:27  jsb]
                    238:  * 
                    239:  *     Use varargs for debugging printfs.
                    240:  *     [92/01/08  10:22:12  jsb]
                    241:  * 
                    242:  *     Use remote_host() instead of norma_get_special_port().
                    243:  *     [92/01/04  18:17:46  jsb]
                    244:  * 
                    245:  * Revision 2.7.2.1  92/01/03  16:38:29  jsb
                    246:  *     Removed unused routine ipc_task_reinit.
                    247:  *     [91/12/28  17:59:18  jsb]
                    248:  * 
                    249:  * Revision 2.7  91/12/13  13:53:22  jsb
                    250:  *     Changed name of task_create_remote to norma_task_create.
                    251:  *     Added check for local case in norma_task_create.
                    252:  * 
                    253:  * Revision 2.6  91/12/10  13:26:19  jsb
                    254:  *     Changed printfs to frets.
                    255:  *     [91/12/10  11:34:35  jsb]
                    256:  * 
                    257:  * Revision 2.5  91/11/14  16:51:51  rpd
                    258:  *     Use new child_node task field in place of task_server_node to decide
                    259:  *     upon what node to create child task. Also add task_set_child_node().
                    260:  *     [91/09/23  09:22:18  jsb]
                    261:  * 
                    262:  * Revision 2.4  91/08/28  11:16:18  jsb
                    263:  *     Turned off remaining printf.
                    264:  *     [91/08/26  11:16:11  jsb]
                    265:  * 
                    266:  *     Added support for remote task creation with inherited memory.
                    267:  *     Remove task creation is accessible either via task_create_remote,
                    268:  *     or task_create with task_server_node patched to some reasonable value.
                    269:  *     [91/08/15  13:55:54  jsb]
                    270:  * 
                    271:  * Revision 2.3  91/06/17  15:48:07  jsb
                    272:  *     Moved routines here from kern/ipc_tt.c and kern/task.c.
                    273:  *     [91/06/17  11:01:51  jsb]
                    274:  * 
                    275:  * Revision 2.2  91/06/06  17:08:15  jsb
                    276:  *     First checkin.
                    277:  *     [91/05/25  11:47:39  jsb]
                    278:  * 
                    279:  */
                    280: /* CMU_ENDHIST */
                    281: /* 
                    282:  * Mach Operating System
                    283:  * Copyright (c) 1991 Carnegie Mellon University
                    284:  * All Rights Reserved.
                    285:  * 
                    286:  * Permission to use, copy, modify and distribute this software and its
                    287:  * documentation is hereby granted, provided that both the copyright
                    288:  * notice and this permission notice appear in all copies of the
                    289:  * software, derivative works or modified versions, and any portions
                    290:  * thereof, and that both notices appear in supporting documentation.
                    291:  * 
                    292:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                    293:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                    294:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                    295:  * 
                    296:  * Carnegie Mellon requests users of this software to return to
                    297:  * 
                    298:  *  Software Distribution Coordinator  or  [email protected]
                    299:  *  School of Computer Science
                    300:  *  Carnegie Mellon University
                    301:  *  Pittsburgh PA 15213-3890
                    302:  * 
                    303:  * any improvements or extensions that they make and grant Carnegie Mellon
                    304:  * the rights to redistribute these changes.
                    305:  */
                    306: /*
                    307:  */
                    308: /*
                    309:  *     File:   norma/kern_task.c
                    310:  *     Author: Joseph S. Barrera III
                    311:  *
                    312:  *     NORMA task support.
                    313:  */
                    314: 
                    315: #include <dipc.h>
                    316: #include <norma_vm.h>
                    317: #include <norma_task.h>
                    318: 
                    319: #include <mach/machine/vm_types.h>
                    320: #include <mach/vm_param.h>
                    321: #include <mach/mach_norma_server.h>
                    322: #include <mach/task_server.h>
                    323: #include <mach/thread_act_server.h>
                    324: #include <mach/vm_task_server.h>
                    325: #include <kern/norma_task_server.h>
                    326: #include <xmm/xmm_internal.h>
                    327: #include <mach/task_info.h>
                    328: #include <mach/task_special_ports.h>
                    329: #include <mach/norma_special_ports.h>
                    330: #include <ipc/ipc_space.h>
                    331: #include <kern/mach_param.h>
                    332: #include <kern/task.h>
                    333: #include <kern/host.h>
                    334: #include <kern/thread.h>
                    335: #include <kern/zalloc.h>
                    336: #include <kern/kalloc.h>
                    337: #include <kern/processor.h>
                    338: #include <kern/ipc_tt.h>
                    339: #include <kern/misc_protos.h>
                    340: #include <kern/norma_protos.h>
                    341: #include <kern/norma_task.h>           /* mig-generated */
                    342: #if    DIPC
                    343: #include <dipc/dipc_funcs.h>
                    344: #include <dipc/special_ports.h>
                    345: #endif
                    346: 
                    347: 
                    348: /*
                    349:  * XXX This definition should be elsewhere
                    350:  */
                    351: kern_return_t
                    352: norma_node_self(
                    353:        host_t host,
                    354:        int *node)
                    355: {
                    356: #if    DIPC
                    357:        *node = dipc_node_self();
                    358:        return KERN_SUCCESS;
                    359: #else
                    360:        panic("norma_node_self:  no transport");
                    361:        return KERN_INVALID_ARGUMENT;
                    362: #endif
                    363: }
                    364: 
                    365: #if    NORMA_TASK
                    366: 
                    367: /*
                    368:  * Forward.
                    369:  */
                    370: kern_return_t  task_get_inherited_ports(
                    371:                        task_t                          task,
                    372:                        ipc_port_t                      *bootstrap,
                    373:                        norma_registered_port_array_t   registered,
                    374:                        unsigned                        *count,
                    375:                        exception_mask_array_t          exc_masks,
                    376:                        unsigned                        *exc_count,
                    377:                        exception_port_array_t          exc_ports,
                    378:                        exception_behavior_array_t      exc_behaviors,
                    379:                        exception_flavor_array_t        exc_flavors);
                    380: 
                    381: kern_return_t  task_set_inherited_ports(
                    382:                        task_t                          task,
                    383:                        ipc_port_t                      bootstrap,
                    384:                        norma_registered_port_array_t   registered,
                    385:                        unsigned                        count,
                    386:                        exception_mask_array_t          exc_masks,
                    387:                        unsigned                        exc_count,
                    388:                        exception_port_array_t          exc_ports,
                    389:                        exception_behavior_array_t      exc_behaviors,
                    390:                        exception_flavor_array_t        exc_flavors);
                    391: 
                    392: kern_return_t  norma_task_common(
                    393:                        task_t          parent_task,
                    394:                        boolean_t       inherit_memory,
                    395:                        boolean_t       clone,
                    396:                        boolean_t       kill_parent,
                    397:                        int             child_node,
                    398:                        task_t          *child_task);
                    399: 
                    400: extern zone_t task_zone;
                    401: 
                    402: /*
                    403:  * This is a debugging/testing hack to allow a system with an unmodified
                    404:  * server to run tasks automatically alternately on local node and some
                    405:  * remote node specified by a patchable variable (task_create_remote_node).
                    406:  */
                    407: #define        TASK_CREATE_USE_REMOTE  1
                    408: #if    TASK_CREATE_USE_REMOTE
                    409: int task_create_remote_node = -1;
                    410: boolean_t task_create_use_remote = FALSE;
                    411: #endif /* TASK_CREATE_USE_REMOTE */
                    412: 
                    413: kern_return_t
                    414: task_create(
                    415:        task_t          parent_task,
                    416:         ledger_port_array_t ledger_ports,
                    417:         mach_msg_type_number_t ledger_portsCnt,
                    418:        boolean_t       inherit_memory,
                    419:        task_t          *child_task)            /* OUT */
                    420: {
                    421: #if    TASK_CREATE_USE_REMOTE
                    422:        if (task_create_remote_node != -1) {
                    423:                task_create_use_remote = ! task_create_use_remote;
                    424:                if (task_create_use_remote) {
                    425:                        return norma_task_create(parent_task, inherit_memory,
                    426:                                                 task_create_remote_node,
                    427:                                                 child_task);
                    428:                } else {
                    429:                        return task_create_local(parent_task, inherit_memory,
                    430:                                                 FALSE, child_task);
                    431:                }
                    432:        }
                    433: #endif /* TASK_CREATE_USE_REMOTE */
                    434:        if (! parent_task || parent_task->child_node == -1) {
                    435:                return task_create_local(parent_task, inherit_memory,
                    436:                                         FALSE, child_task);
                    437:        } else {
                    438:                return norma_task_create(parent_task, inherit_memory,
                    439:                                         (int) parent_task->child_node,
                    440:                                         child_task);
                    441:        }
                    442: }
                    443: 
                    444: kern_return_t
                    445: task_set_child_node(
                    446:        task_t  task,
                    447:        int     child_node)
                    448: {
                    449: #if    DIPC
                    450:        if (task == TASK_NULL || !dipc_node_is_valid (child_node)) {
                    451:                return KERN_INVALID_ARGUMENT;
                    452:        } else {
                    453:                task->child_node = child_node;
                    454:                return KERN_SUCCESS;
                    455:        }
                    456: #else  /* DIPC */
                    457:        printf("task_set_child_node:  no underlying transport!\n");
                    458:        return KERN_INVALID_ARGUMENT;
                    459: #endif /* DIPC */
                    460: }
                    461: 
                    462: /*
                    463:  * This allows us to create a task without providing a parent.
                    464:  *
                    465:  * XXX
                    466:  * Should deallocate resouces upon failure
                    467:  */
                    468: kern_return_t
                    469: norma_task_allocate(
                    470:        host_t                          host,
                    471:        int                             vector_start,
                    472:        emulation_vector_t              entry_vector,
                    473:        unsigned int                    entry_vector_count,
                    474:        ipc_port_t                      bootstrap,
                    475:        norma_registered_port_array_t   registered,
                    476:        unsigned                        count,
                    477:        exception_mask_array_t          exc_masks,
                    478:        unsigned                        exc_count,
                    479:        exception_port_array_t          exc_ports,
                    480:        exception_behavior_array_t      exc_behaviors,
                    481:        exception_flavor_array_t        exc_flavors,
                    482:        task_t                          *result)        /* OUT */
                    483: {
                    484:        kern_return_t kr;
                    485:        task_t task;
                    486: 
                    487:        if (host == HOST_NULL) {
                    488:                return KERN_INVALID_ARGUMENT;
                    489:        }
                    490:        kr = task_create_local(TASK_NULL, FALSE, FALSE, &task);
                    491:        if (kr != KERN_SUCCESS) {
                    492:                return kr;
                    493:        }
                    494:        kr = task_set_emulation_vector(task, vector_start, entry_vector,
                    495:                                       entry_vector_count);
                    496:        if (kr != KERN_SUCCESS) {
                    497:                return kr;
                    498:        }
                    499:        kr = task_set_inherited_ports(task, bootstrap, registered, count,
                    500:                                      exc_masks, exc_count, exc_ports,
                    501:                                      exc_behaviors, exc_flavors);
                    502:        if (kr != KERN_SUCCESS) {
                    503:                printf("task_set_inherited_ports failed: kr %d %x\n", kr, kr);
                    504:                return kr;
                    505:        }
                    506:        *result = task;
                    507:        return KERN_SUCCESS;
                    508: }
                    509: 
                    510: kern_return_t
                    511: task_get_inherited_ports(
                    512:        task_t                          task,
                    513:        ipc_port_t                      *bootstrap,
                    514:        norma_registered_port_array_t   registered,
                    515:        unsigned                        *count,
                    516:        exception_mask_array_t          exc_masks,
                    517:        unsigned                        *exc_count,
                    518:        exception_port_array_t          exc_ports,
                    519:        exception_behavior_array_t      exc_behaviors,
                    520:        exception_flavor_array_t        exc_flavors)
                    521: {
                    522:        unsigned i;
                    523:        unsigned j;
                    524:        unsigned n;
                    525: 
                    526:        if (task == TASK_NULL) {
                    527:                return KERN_INVALID_ARGUMENT;
                    528:        }
                    529: 
                    530:        itk_lock(task);
                    531:        *bootstrap = ipc_port_copy_send(task->itk_bootstrap);
                    532: 
                    533:        for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
                    534:                registered[i] = ipc_port_copy_send(task->itk_registered[i]);
                    535:        *count = TASK_PORT_REGISTER_MAX;
                    536: 
                    537:        n = 0;
                    538:        for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) {
                    539:                for (j = 0; j < n; j++) {
                    540:                        /*
                    541:                         * Search for an identical entry, if found
                    542:                         * set corresponding mask for this exception.
                    543:                         */
                    544:                        if (task->exc_actions[i].port == exc_ports[j] &&
                    545:                            task->exc_actions[i].behavior == exc_behaviors[j] &&
                    546:                            task->exc_actions[i].flavor == exc_flavors[j]) {
                    547:                                exc_masks[j] |= (1 << i);
                    548:                                break;
                    549:                        }
                    550:                }
                    551:                if (j == n) {
                    552:                        exc_masks[j] = (1 << i);
                    553:                        exc_ports[j] =
                    554:                                ipc_port_copy_send(task->exc_actions[i].port);
                    555:                        exc_behaviors[j] = task->exc_actions[i].behavior;
                    556:                        exc_flavors[j] = task->exc_actions[i].flavor;
                    557:                        n++;
                    558:                }
                    559:        }
                    560:        *exc_count = n;
                    561:        itk_unlock(task);
                    562: 
                    563:        return KERN_SUCCESS;
                    564: }
                    565: 
                    566: 
                    567: /*
                    568:  *     It's not a good idea to be releasing send rights to ports
                    569:  *     while holding the task lock -- the send rights could get
                    570:  *     deallocated or could result in message traffic (at least
                    571:  *     in the DIPC case).  So save pointers to all the ports we
                    572:  *     would deallocate, and drop them at the end.
                    573:  *
                    574:  *     Possible ports to deallocate:
                    575:  *             itk_bootstrap (per-task)
                    576:  *             itk_registered[TASK_PORT_REGISTER_MAX] (per-task)
                    577:  *             exc_actions[EXC_TYPES_COUNT] (per-task)
                    578:  *             exc_ports[EXC_TYPES_COUNT] (passed in by caller)
                    579:  */
                    580: #define        TSIP_DROP_MAX   (1 + TASK_PORT_REGISTER_MAX + (EXC_TYPES_COUNT * 2))
                    581: 
                    582: kern_return_t
                    583: task_set_inherited_ports(
                    584:        task_t                          task,
                    585:        ipc_port_t                      bootstrap,
                    586:        norma_registered_port_array_t   registered,
                    587:        unsigned                        count,
                    588:        exception_mask_array_t          exc_masks,
                    589:        unsigned                        exc_count,
                    590:        exception_port_array_t          exc_ports,
                    591:        exception_behavior_array_t      exc_behaviors,
                    592:        exception_flavor_array_t        exc_flavors)
                    593: {
                    594:        exception_mask_t mask;
                    595:        ipc_port_t      drop_ports[TSIP_DROP_MAX];
                    596:        unsigned int    drop_port_count = 0;
                    597:        unsigned i;
                    598:        unsigned j;
                    599: 
                    600:        if (task == TASK_NULL)
                    601:                return KERN_INVALID_ARGUMENT;
                    602: 
                    603:        if (count > TASK_PORT_REGISTER_MAX+1)
                    604:                return KERN_INVALID_ARGUMENT;
                    605: 
                    606:        mask = 0;
                    607:        for (i = 0; i < exc_count; i++) {
                    608:                if ((exc_masks[i] & ~EXC_MASK_ALL) || (mask & exc_masks[i]))
                    609:                        return KERN_INVALID_ARGUMENT;
                    610:                mask |= exc_masks[i];
                    611:        }
                    612: 
                    613:        if (exc_count >= EXC_TYPES_COUNT)
                    614:                return KERN_INVALID_ARGUMENT;
                    615: 
                    616:        itk_lock(task);
                    617:        /*
                    618:         * First, set up bootstrap port.
                    619:         */
                    620:        if (IP_VALID(task->itk_bootstrap)) {
                    621:                assert(drop_port_count < TSIP_DROP_MAX);
                    622:                drop_ports[drop_port_count++] = task->itk_bootstrap;
                    623:        }
                    624:        task->itk_bootstrap = bootstrap;
                    625: 
                    626:        /*
                    627:         * Next, set up registered ports.
                    628:         */
                    629:        for (i = 0; i < count; i++) {
                    630:                if (IP_VALID(task->itk_registered[i])) {
                    631:                        assert(drop_port_count < TSIP_DROP_MAX);
                    632:                        drop_ports[drop_port_count++] = task->itk_registered[i];
                    633:                }
                    634:                task->itk_registered[i] = registered[i];
                    635:        }
                    636: 
                    637:        /*
                    638:         * Finally, set up exception ports.
                    639:         */
                    640:        for (i = 0; i < exc_count; i++) {
                    641:                mask = exc_masks[i] & ~EXC_MASK_ALL;
                    642:                j = 0;
                    643:                while (mask) {
                    644:                        if (mask & 1) {
                    645:                                if (IP_VALID(task->exc_actions[j].port)) {
                    646:                                        assert(drop_port_count < TSIP_DROP_MAX);
                    647:                                        drop_ports[drop_port_count++] =
                    648:                                                task->exc_actions[j].port;
                    649:                                }
                    650:                                task->exc_actions[j].port =
                    651:                                        ipc_port_copy_send(exc_ports[i]);
                    652:                                task->exc_actions[j].behavior =
                    653:                                        exc_behaviors[i];
                    654:                                task->exc_actions[j].flavor = exc_flavors[i];
                    655:                        }
                    656:                        mask >>= 1;
                    657:                        j++;
                    658:                }
                    659:                if (IP_VALID(exc_ports[i])) {   /* consume send right */
                    660:                        assert(drop_port_count < TSIP_DROP_MAX);
                    661:                        drop_ports[drop_port_count++] = exc_ports[i];
                    662:                }
                    663:        }
                    664:        itk_unlock(task);
                    665: 
                    666:        for (i = 0; i < drop_port_count; ++i)
                    667:                ipc_port_release_send(drop_ports[i]);
                    668: 
                    669:        return KERN_SUCCESS;
                    670: }
                    671: 
                    672: kern_return_t
                    673: norma_task_common(
                    674:        task_t          parent_task,
                    675:        boolean_t       inherit_memory,
                    676:        boolean_t       clone,
                    677:        boolean_t       kill_parent,
                    678:        int             child_node,
                    679:        task_t          *child_task)
                    680: {
                    681:        ipc_port_t remote_task, remote_host;
                    682:        task_t new_task;
                    683:        kern_return_t kr;
                    684:        int vector_start;
                    685:        unsigned int entry_vector_count;
                    686:        ipc_port_t bootstrap;
                    687:        emulation_vector_t entry_vector;
                    688:        ipc_port_t registered[TASK_PORT_REGISTER_MAX];
                    689:        exception_mask_t exc_masks[EXC_TYPES_COUNT];
                    690:        ipc_port_t exc_ports[EXC_TYPES_COUNT];
                    691:        exception_behavior_t exc_behaviors[EXC_TYPES_COUNT];
                    692:        thread_state_flavor_t exc_flavors[EXC_TYPES_COUNT];
                    693:        unsigned count, exc_count;
                    694: 
                    695: #if    DIPC
                    696:        if (!dipc_node_is_valid (child_node)) {
                    697:                return KERN_INVALID_ARGUMENT;
                    698:        }
                    699: 
                    700:        if (child_node == dipc_node_self()) {
                    701:                if (clone) {
                    702:                        /*
                    703:                         * Cloning: easy if kill_parent;
                    704:                         * (currently) impossible otherwise.
                    705:                         */
                    706:                        if (kill_parent) {
                    707:                                /*
                    708:                                 * Just return the parent -- nothing says that
                    709:                                 * the clone has to be a different task.
                    710:                                 */
                    711:                                *child_task = parent_task;
                    712:                                return KERN_SUCCESS;
                    713:                        } else {
                    714:                                /*
                    715:                                 * XXX
                    716:                                 * There is no local call we can use with the
                    717:                                 * same memory semantics -- we'd have to
                    718:                                 * modify task_create_local, and vm_map_fork.
                    719:                                 * Not hard, just probably unnecessary except
                    720:                                 * for orthogonality.
                    721:                                 */
                    722:                                return KERN_INVALID_ARGUMENT;
                    723:                        }
                    724:                } else {
                    725:                        /*
                    726:                         * Not cloning: just use task_create_local,
                    727:                         * and task_terminate if appropriate.
                    728:                         */
                    729:                        kr = task_create_local(parent_task, inherit_memory,
                    730:                                               FALSE, child_task);
                    731:                        if (kr != KERN_SUCCESS) {
                    732:                                return kr;
                    733:                        }
                    734:                        if (kill_parent) {
                    735:                                kr = task_terminate(parent_task);
                    736:                                if (kr != KERN_SUCCESS) {
                    737:                                        /* cleanup */
                    738:                                        (void) task_terminate(*child_task);
                    739:                                        return kr;
                    740:                                }
                    741:                        }
                    742:                        return KERN_SUCCESS;
                    743:                }
                    744:        }
                    745: 
                    746:        kr = task_get_emulation_vector(parent_task, &vector_start,
                    747:                                       &entry_vector, &entry_vector_count);
                    748:        if (kr != KERN_SUCCESS) {
                    749:                printf("task_get_emulation_vector failed: kr %d %x\n", kr, kr);
                    750:                return kr;
                    751:        }
                    752: 
                    753:        kr = task_get_inherited_ports(parent_task, &bootstrap, registered,
                    754:                                      &count, exc_masks, &exc_count,
                    755:                                      exc_ports, exc_behaviors, exc_flavors);
                    756:        if (kr != KERN_SUCCESS) {
                    757:                printf("task_get_inherited_ports failed: kr %d %x\n", kr, kr);
                    758:                return kr;
                    759:        }
                    760: 
                    761:        remote_host = dipc_host_priv_port(child_node);
                    762:        if (remote_host == IP_NULL) {
                    763:                panic("norma_task_create:  no priv port for node %d\n",
                    764:                      child_node);
                    765:                return KERN_INVALID_ARGUMENT;
                    766:        }
                    767: 
                    768:        kr = r_norma_task_allocate(remote_host, vector_start, entry_vector,
                    769:                                   entry_vector_count, bootstrap,
                    770:                                   registered, count, exc_masks, exc_count,
                    771:                                   exc_ports, exc_behaviors, exc_flavors,
                    772:                                   &remote_task);
                    773:        if (kr != KERN_SUCCESS) {
                    774:                return kr;
                    775:        }
                    776: 
                    777:        if (inherit_memory) {
                    778:                task_copy_vm(remote_host, parent_task->map, clone,
                    779:                             kill_parent, remote_task);
                    780:        }
                    781: 
                    782:        if (kill_parent) {
                    783:                (void) task_terminate(parent_task);
                    784:        }
                    785: 
                    786:        /*
                    787:         * Create a placeholder task for the benefit of convert_task_to_port.
                    788:         * Set new_task->map to VM_MAP_NULL so that task_deallocate will
                    789:         * know that this is only a placeholder task.
                    790:         */
                    791:        new_task = (task_t) zalloc(task_zone);
                    792:        if (new_task == TASK_NULL) {
                    793:                panic("task_create: no memory for task structure");
                    794:        }
                    795: 
                    796: #if     MCMSG
                    797:        new_task->mcmsg_task = 0;
                    798: #endif  /* MCMSG */
                    799: 
                    800:        /* only one ref, for our caller */
                    801:        new_task->ref_count = 1;
                    802: 
                    803:        new_task->map = VM_MAP_NULL;
                    804:        new_task->itk_self = remote_task;
                    805:        mutex_init(&new_task->lock, ETAP_NORMA_TASK);
                    806:        itk_lock_init(new_task);
                    807: 
                    808:        *child_task = new_task;
                    809:        return(KERN_SUCCESS);
                    810: #else  /* DIPC */
                    811:        printf("norma_task_common:  no underlying transport!\n");
                    812:        return KERN_INVALID_ARGUMENT;
                    813: #endif /* DIPC */
                    814: }
                    815: 
                    816: 
                    817: #if    !NORMA_VM
                    818: /*
                    819:  *     task_vm_copy
                    820:  *
                    821:  *     Provide a stub for task_copy_vm when we have norma_task but not
                    822:  *     norma_vm. This allows us to build and link kernels which support
                    823:  *     dipc and norma_node_self without turning on norma_vm.
                    824:  *
                    825:  *     XXX We need to rearrange things so we can have a dipc subset and
                    826:  *         basic node information system calls without turning EITHER
                    827:  *         norma_task or norma_vm on. This is needed for RFT ports.
                    828:  */
                    829: void
                    830: task_copy_vm(
                    831:         ipc_port_t      host,
                    832:         vm_map_t        old_map,
                    833:         boolean_t       clone,
                    834:         boolean_t       kill_parent,
                    835:         ipc_port_t      to)
                    836: {
                    837: 
                    838:        panic("task_copy_vm: norma_vm option not turned on");   
                    839: 
                    840: }
                    841: #endif /* !NORMA_VM */
                    842: 
                    843: kern_return_t
                    844: norma_task_create(
                    845:        task_t          parent_task,
                    846:        boolean_t       inherit_memory,
                    847:        int             child_node,
                    848:        task_t          *child_task)            /* OUT */
                    849: {
                    850:        return norma_task_common(parent_task, inherit_memory, FALSE,
                    851:                                 FALSE, child_node, child_task);
                    852: }
                    853: 
                    854: kern_return_t
                    855: norma_task_clone(
                    856:        task_t          parent_task,
                    857:        boolean_t       inherit_memory,
                    858:        int             child_node,
                    859:        task_t          *child_task)            /* OUT */
                    860: {
                    861:        return norma_task_common(parent_task, inherit_memory, TRUE,
                    862:                                 FALSE, child_node, child_task);
                    863: }
                    864: 
                    865: kern_return_t
                    866: norma_task_teleport(
                    867:        task_t          parent_task,
                    868:        boolean_t       inherit_memory,
                    869:        int             child_node,
                    870:        task_t          *child_task)            /* OUT */
                    871: {
                    872:        return norma_task_common(parent_task, inherit_memory, TRUE,
                    873:                                 TRUE, child_node, child_task);
                    874: }
                    875: 
                    876: #else  /* NORMA_TASK */
                    877: 
                    878: /*ARGSUSED*/
                    879: kern_return_t
                    880: norma_task_allocate(
                    881:        host_t                          host,
                    882:        int                             vector_start,
                    883:        emulation_vector_t              entry_vector,
                    884:        unsigned int                    entry_vector_count,
                    885:        ipc_port_t                      bootstrap,
                    886:        norma_registered_port_array_t   registered,
                    887:        exception_mask_array_t          exc_masks,
                    888:        unsigned                        count,
                    889:        exception_port_array_t          exc_ports,
                    890:        exception_behavior_array_t      exc_behaviors,
                    891:        exception_flavor_array_t        exc_flavors
                    892:        task_t                          *result)
                    893: {
                    894:        return KERN_FAILURE;
                    895: }
                    896: 
                    897: /*ARGSUSED*/
                    898: kern_return_t
                    899: norma_task_create(
                    900:        task_t          parent_task,
                    901:        boolean_t       inherit_memory,
                    902:        int             child_node,
                    903:        task_t          *child_task)            /* OUT */
                    904: {
                    905:        return KERN_FAILURE;
                    906: }
                    907: 
                    908: /*ARGSUSED*/
                    909: kern_return_t
                    910: norma_task_clone(
                    911:        task_t          parent_task,
                    912:        boolean_t       inherit_memory,
                    913:        int             child_node,
                    914:        task_t          *child_task)            /* OUT */
                    915: {
                    916:        return KERN_FAILURE;
                    917: }
                    918: 
                    919: /*ARGSUSED*/
                    920: kern_return_t
                    921: norma_task_teleport(
                    922:        task_t          parent_task,
                    923:        boolean_t       inherit_memory,
                    924:        int             child_node,
                    925:        task_t          *child_task)            /* OUT */
                    926: {
                    927:        return KERN_FAILURE;
                    928: }
                    929: #endif /* NORMA_TASK */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.