Annotation of kernel/kernserv/kern_server.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* 
                     26:  * Copyright (c) 1989 NeXT, Inc.
                     27:  *
                     28:  * HISTORY
                     29:  *  4-Jun-91  Gregg Kellogg (gk) at NeXT
                     30:  *     Abort server_thread before calling thread_dowait when trying to
                     31:  *     service callouts.
                     32:  *
                     33:  * 27-Aug-90  Gregg Kellogg (gk) at NeXT
                     34:  *     Fixed bugs in kern_serv_callout.
                     35:  *     Remove compatibility for servers < version 2.
                     36:  *
                     37:  * 12-Jul-90  Gregg Kellogg (gk) at NeXT
                     38:  *     Don't allocate MSG_SIZE_MAX for in and out messages.  Only allocate
                     39:  *     a minimal amount fo input message and use RCV_TOO_LARGE logic
                     40:  *     to allocate more.  Output message is only allocated for servers
                     41:  *     and older style handlers.
                     42:  *
                     43:  * 23-May-90  Gregg kellogg (gk) at NeXT
                     44:  *     Changed to use thread_reply port instead of bootstrap port.
                     45:  *     Checks to see if it's running in the kernel_task and uses
                     46:  *     kernel_ipc_space accordingly.
                     47:  *     Terminates on shutdown, doesn't suspend.
                     48:  *     Doesn't depend on being in a separate task now.
                     49:  *
                     50:  * 06-Feb-89  Gregg Kellogg (gk) at NeXT
                     51:  *     Created.
                     52:  *
                     53:  */ 
                     54: 
                     55: /*
                     56:  * Generic Kernel Server for loaded server tasks.
                     57:  *
                     58:  * This code is run by dynamically loaded Mach kernel servers.  It recieves
                     59:  * instructions from it's boot port server to set up it's local environment
                     60:  * and enter the server loop to do per-server processing.
                     61:  *
                     62:  * The server basically exists to dispatch messages recieved on ports
                     63:  * to procedures.  Any un-handled messages are either thrown away or handled
                     64:  * directly by the server.  Handled messages are either acked, or not acked.
                     65:  * If the return status is > 0, then any resources passed (other than ports)
                     66:  * are deallocated from the message as well.
                     67:  */
                     68: 
                     69: #import <mach/mig_errors.h>
                     70: #import <sys/callout.h>
                     71: #import <mach/notify.h>
                     72: #import <kern/kern_port.h>
                     73: #import <kern/sched_prim.h>
                     74: #import <mach/mach_traps.h>
                     75: #import <kern/kalloc.h>
                     76: #import <kernserv/kern_notify.h>
                     77: #import <mach/vm_param.h>
                     78: #import "kernobjc.h"
                     79: #import <kern/thread_call.h>
                     80: 
                     81: #import <machine/spl.h>
                     82: 
                     83: #import <kernserv/kern_server_handler.h>
                     84: #import <kernserv/kern_server_reply.h>
                     85: 
                     86: #define panic(s) (curipl() == 0 ? kern_serv_panic(ksp->bootstrap_port, s) \
                     87:                                : printf("can't panic: %s\n", s))
                     88: 
                     89: /* Now a per server static port_t kernel_port; */
                     90: 
                     91: /*
                     92:  * Use internal version of thread_terminate.
                     93:  */
                     94: #undef thread_terminate
                     95: 
                     96: /*
                     97:  * Locally used functions
                     98:  */
                     99: static kern_return_t kern_serv_dispatch (
                    100:        msg_header_t *in_msg,
                    101:        kern_server_t ksp);
                    102: 
                    103: static void kern_serv_send_log(void *arg);
                    104: static void kern_serv_log_init (       // initialize server's log buffer
                    105:        log_t   *log,                   // uninitialized log struct
                    106:        int     num_entries);           // size of log
                    107: 
                    108: static void kern_serv_log_free (log_t *log); // deallocate log structure
                    109: static void kern_serv_interrupt_server(thread_t thread);
                    110: 
                    111: const kern_serv_t kern_serv_proto = {
                    112:        0,              // arg to be filled in
                    113:        0,              // don't wait for message to be sent
                    114:        kern_serv_instance_loc,
                    115:        kern_serv_boot_port,
                    116:        kern_serv_wire_range,
                    117:        kern_serv_unwire_range,
                    118:        kern_serv_port_proc,
                    119:        kern_serv_port_death_proc,
                    120:        kern_serv_call_proc,
                    121:        kern_serv_shutdown,
                    122:        kern_serv_log_level,
                    123:        kern_serv_get_log,
                    124:        kern_serv_port_serv,
                    125:        kern_serv_version,
                    126:        kern_serv_load_objc};
                    127: 
                    128: /*
                    129:  * Prototypes for kernel functions not yet prototyped.
                    130:  */
                    131: int bcopy(void *to, void *from, int size);
                    132: int curipl(void);
                    133: kern_return_t vm_map_pageable(
                    134:        vm_map_t        map,
                    135:        vm_offset_t     start,
                    136:        vm_offset_t     end,
                    137:        boolean_t       new_pageable);
                    138: #if    DEBUG
                    139: void xpr(char *msg, ...);
                    140: #endif DEBUG
                    141: 
                    142: #if    DEBUG
                    143: static boolean_t kserv_debug = TRUE;
                    144: #define ks_log(s) {if (kserv_debug) XPR(XPR_LDD, s); }
                    145: #define ks_log2(s) ks_log(s)
                    146: void kern_server_main1(void);
                    147: void kern_server_main2(void);
                    148: #else  DEBUG
                    149: #define ks_log(s)
                    150: #define ks_log2(s)
                    151: #endif DEBUG
                    152: 
                    153: /*
                    154:  * Entry point to kernel server, set up task environment.
                    155:  */
                    156: void kern_server_main(void)
                    157: {
                    158: #if    DEBUG
                    159:        int foo[10];
                    160:        kern_server_main1();
                    161: }
                    162: void kern_server_main1(void)
                    163: {
                    164:        int foo[10];
                    165:        kern_server_main2();
                    166: }
                    167: void kern_server_main2(void)
                    168: {
                    169: #endif DEBUG
                    170:        kern_return_t   r;
                    171:        kern_server_t   ksp = (kern_server_t)kalloc(sizeof *ksp);
                    172:        port_t          boot_listener_port;
                    173:        port_t          reply_port;
                    174:        port_set_name_t port_set;
                    175:        msg_header_t    *in_msg;
                    176:        int             error;
                    177:        register int    i, s;
                    178:        kern_serv_t kern_serv = kern_serv_proto;
                    179: 
                    180: #if    0
                    181:        volatile int instr;
                    182: 
                    183:        /*
                    184:         * Write to the loaded text so that the debugger can set break-points.
                    185:         */
                    186:        instr = *(int *)&kern_server_main2;
                    187:        *(int *)&kern_server_main2 = instr;
                    188: #endif 0
                    189: 
                    190:        kern_serv.arg = (void *)&ksp;
                    191: 
                    192:        /*
                    193:         *      Find out who we are.
                    194:         */
                    195: 
                    196:        if (current_task() != kernel_task) {
                    197:                current_task()->kernel_vm_space = TRUE;
                    198:        }
                    199: 
                    200:        bzero((char *)ksp, sizeof(*ksp));
                    201:        ksp->version = -1;
                    202: 
                    203:        /*
                    204:         * Our task port.
                    205:         */
                    206:        ksp->task_port = task_self();
                    207: 
                    208:        /*
                    209:         * Our thread structure.
                    210:         */
                    211:        ksp->server_thread = current_thread();
                    212:        simple_lock_init(&ksp->slock);
                    213: 
                    214:        /*
                    215:         * Initialize message send queue.
                    216:         */
                    217:        queue_init(&ksp->msg_callout_q);
                    218:        queue_init(&ksp->msg_callout_fq);
                    219:        queue_init(&ksp->notify_q);
                    220:        for (  i = sizeof(ksp->msg_send_array)/sizeof(ksp->msg_send_array[0])-1
                    221:             ; i >= 0
                    222:             ; i--)
                    223:        {
                    224:                queue_enter(&ksp->msg_callout_fq, &ksp->msg_send_array[i],
                    225:                        struct msg_send_entry *, link);
                    226:        }
                    227: 
                    228:        /*
                    229:         * Use our thread_reply port as the bootstrap port.  This is
                    230:         * claimed by the kern_loader before we startup, so there's no
                    231:         * race condition.
                    232:         */
                    233:        r = thread_get_special_port(thread_self(), THREAD_REPLY_PORT,
                    234:                &boot_listener_port);
                    235:        if (r != KERN_SUCCESS || boot_listener_port == PORT_NULL) {
                    236:                printf("k_server: can't find listener port..terminating\n");
                    237:                thread_terminate(current_thread());
                    238:                thread_halt_self();
                    239:        }
                    240:        ksp->boot_listener_port = boot_listener_port;
                    241: 
                    242:        /*
                    243:         * Allocate a new reply port.
                    244:         */
                    245:        r = port_allocate(task_self(), &reply_port);
                    246:        if (r != KERN_SUCCESS) {
                    247:                printf("k_server: can't allocate reply port..terminating\n");
                    248:                thread_terminate(current_thread());
                    249:                thread_halt_self();
                    250:        }
                    251:        
                    252:        r = thread_set_special_port(thread_self(), THREAD_REPLY_PORT,
                    253:                reply_port);
                    254:        if (r != KERN_SUCCESS) {
                    255:                printf("k_server: can't set reply port..terminating\n");
                    256:                thread_terminate(current_thread());
                    257:                thread_halt_self();
                    258:        }
                    259: 
                    260:        /*
                    261:         * Forget the reply_port we were using so that it isn't
                    262:         * cached anymore.
                    263:         */
                    264: 
                    265:        /*
                    266:         * Allocate the basic set of ports we need for communication
                    267:         * (notify port).
                    268:         */
                    269:        r = port_set_allocate(task_self(), &port_set);
                    270:        if (r != KERN_SUCCESS) {
                    271:                printf("k_server: can't allocate port set..terminating\n");
                    272:                thread_terminate(current_thread());
                    273:                thread_halt_self();
                    274:        }
                    275:        ksp->port_set = port_set;
                    276: 
                    277:        /*
                    278:         * Add boot listener port to the port set.
                    279:         */
                    280:        if (   port_set_add(task_self(), port_set, boot_listener_port)
                    281:            != KERN_SUCCESS)
                    282:        {
                    283:                printf("k_server: can't add listener port\n");
                    284:                thread_terminate(current_thread());
                    285:                thread_halt_self();
                    286:        }
                    287: 
                    288:        /*
                    289:         * Allocate and set up the notify port.
                    290:         */
                    291:        r = port_allocate(ksp->task_port, &ksp->notify_port);
                    292:        if (r == KERN_SUCCESS)
                    293:                (void) port_set_add(ksp->task_port, ksp->port_set,
                    294:                        ksp->notify_port);
                    295:        else
                    296:                kern_serv_panic(ksp->bootstrap_port,
                    297:                        "k_server: can't get notify port");
                    298: 
                    299:        if (current_task() != kernel_task) {
                    300:                /*
                    301:                 * Set this port as our task's notify port.
                    302:                 */
                    303:                (void) task_set_special_port(task_self(),
                    304:                        TASK_NOTIFY_PORT, ksp->notify_port);
                    305:        }
                    306: 
                    307:        kern_serv_notify(&ksp, ksp->notify_port, ksp->bootstrap_port);
                    308: 
                    309:        /*
                    310:         * The kernel's task port.
                    311:         */
                    312:        ksp->kernel_port = kern_serv_kernel_task_port();
                    313: 
                    314:        /*
                    315:         *      Service loop... receive messages and process them.
                    316:         */
                    317: 
                    318:        in_msg = (msg_header_t *)kalloc(kern_servMaxRequestSize);
                    319:        ksp->msg = in_msg;
                    320:        ksp->msg_size = kern_servMaxRequestSize;
                    321:        for (;;) {
                    322:                /*
                    323:                 * Look for things to do that need to be done
                    324:                 * from this task/thread.
                    325:                 * Send messages.
                    326:                 */
                    327:                s = splhigh();
                    328:                simple_lock(&ksp->slock);
                    329: 
                    330:                while (!queue_empty(&ksp->msg_callout_q)) {
                    331:                        struct msg_send_entry *msep;
                    332: 
                    333:                        queue_remove_first(&ksp->msg_callout_q,
                    334:                                msep, struct msg_send_entry *, link);
                    335: 
                    336:                        simple_unlock(&ksp->slock);
                    337:                        splx(s);
                    338: 
                    339:                        ks_log(("kern_server_main: qed callout func 0x%x\n",
                    340:                                msep->func));
                    341:                        (*msep->func)(msep->arg);
                    342: 
                    343:                        s = splhigh();
                    344:                        simple_lock(&ksp->slock);
                    345: 
                    346:                        queue_enter(&ksp->msg_callout_fq, msep,
                    347:                                struct msg_send_entry *, link);
                    348:                }
                    349: 
                    350:                simple_unlock(&ksp->slock);
                    351:                splx(s);
                    352: 
                    353:                /*
                    354:                 * Wait for the next request.
                    355:                 */
                    356:            receive:
                    357:                in_msg->msg_local_port = port_set;
                    358:                in_msg->msg_size = ksp->msg_size;
                    359:                r = msg_receive(in_msg, RCV_TIMEOUT|RCV_INTERRUPT|RCV_LARGE,
                    360:                                1000);
                    361: 
                    362:                /*
                    363:                 * If our receive was interrupted, go back to it.
                    364:                 */
                    365:                switch (r) {
                    366:                case RCV_INTERRUPTED:
                    367:                        break;
                    368:                case RCV_TIMED_OUT:
                    369:                        continue;
                    370:                case RCV_TOO_LARGE:
                    371:                {
                    372:                        vm_size_t       new_msg_size = ksp->msg->msg_size;
                    373:                        /*
                    374:                         * We need to allocate a larger message to return.
                    375:                         */
                    376:                        kfree(ksp->msg, ksp->msg_size);
                    377:                        ksp->msg_size = new_msg_size;
                    378:                        ksp->msg = (void *)kalloc(ksp->msg_size);
                    379:                        in_msg = ksp->msg;
                    380:                        goto receive;
                    381:                }
                    382: 
                    383:                case KERN_SUCCESS:
                    384:                        break;
                    385:                default:
                    386:                        kern_serv_panic(ksp->bootstrap_port,
                    387:                                "kern_server_main: received return bad return"
                    388:                                " from msg_receive");
                    389:                        break;
                    390:                }
                    391: 
                    392:                ks_log(("kern_server_main: received msgid %d "
                    393:                        "on port %d\n", in_msg->msg_id,
                    394:                        in_msg->msg_local_port));
                    395: 
                    396:                /*
                    397:                 * Dispatch the message based on it's port.
                    398:                 */
                    399:                if (in_msg->msg_local_port == ksp->notify_port) {
                    400:                        notification_t  *n = (notification_t *) in_msg;
                    401:                        switch(in_msg->msg_id) {
                    402:                        case NOTIFY_PORT_DELETED:
                    403:                                /*
                    404:                                 * Give loaded code a chance to handle it
                    405:                                 */
                    406:                                if (ksp->pd_proc) {
                    407:                                        if ((*ksp->pd_proc)(n->notify_port))
                    408:                                                break;
                    409:                                } else if (ksp->pn_proc)
                    410:                                        (*ksp->pn_proc)(n->notify_port,
                    411:                                                in_msg->msg_id);
                    412:                                kern_serv_port_gone(&ksp, n->notify_port);
                    413:                                break;
                    414:                        default:
                    415:                                if (ksp->pn_proc)
                    416:                                        (*ksp->pn_proc)(n->notify_port,
                    417:                                                        in_msg->msg_id);
                    418:                                break;
                    419:                        }
                    420:                        continue;
                    421:                } else if (   in_msg->msg_id >= NOTIFY_FIRST
                    422:                           && in_msg->msg_id < NOTIFY_LAST)
                    423:                {
                    424:                        notification_t  *n = (notification_t *) in_msg;
                    425:                        ks_notify_t *np;
                    426: 
                    427:                        /*
                    428:                         * If we have a notify request on this port, forward
                    429:                         * the message to the requested port.
                    430:                         */
                    431:                        for (  np = (ks_notify_t *)queue_first(&ksp->notify_q)
                    432:                             ; !queue_end(&ksp->notify_q, (queue_entry_t)np)
                    433:                             ; np = (ks_notify_t *)queue_next(&np->link))
                    434:                                if (np->req_port == n->notify_port) {
                    435:                                        in_msg->msg_remote_port =
                    436:                                                np->reply_port;
                    437:                                        ks_log2(("kern_server_main: "
                    438:                                                 "forwarding notification "
                    439:                                                 "request to port %d\n",
                    440:                                                 np->reply_port));
                    441:                                        msg_send(in_msg, MSG_OPTION_NONE, 0);
                    442:                                        queue_remove(&ksp->notify_q, np,
                    443:                                                ks_notify_t *, link);
                    444:                                        kfree(np, sizeof(*np));
                    445:                                        continue;
                    446:                                }
                    447:                }
                    448: 
                    449:                ksp->local_port = in_msg->msg_local_port;
                    450: 
                    451:                error = kern_serv_dispatch(in_msg, ksp);
                    452:                ks_log2(("kern_server_main: return from ks_disp %d\n",
                    453:                        error));
                    454: 
                    455:                if (   error == MIG_BAD_ID
                    456:                    && in_msg->msg_local_port == boot_listener_port)
                    457:                {
                    458:                        error = kern_serv_handler(in_msg, &kern_serv);
                    459:                        ks_log2(("kern_server_main: "
                    460:                                "return from ks_server %d\n",
                    461:                                error));
                    462:                }
                    463:        }
                    464: }
                    465: 
                    466: typedef struct {
                    467:        msg_header_t Head;
                    468:        msg_type_t RetCodeType;
                    469:        kern_return_t RetCode;
                    470: } Reply;
                    471: 
                    472: static kern_return_t kern_serv_port_proc_call (
                    473:        msg_header_t *in_msg,
                    474:        port_proc_map_t *pp)
                    475: {
                    476:        Reply *out_msg;
                    477:        kern_return_t ret_code;
                    478:        port_t local_port;
                    479: 
                    480:        if (pp->type == PP_handler)
                    481:                return (*pp->proc)(in_msg, pp->uarg);
                    482: 
                    483:        out_msg = (Reply *)kalloc(MSG_SIZE_MAX);
                    484:        local_port = in_msg->msg_local_port;
                    485:        in_msg->msg_local_port = (port_t)pp->uarg;
                    486: 
                    487:        (*((port_map_serv_t)pp->proc))(in_msg, (msg_header_t *)out_msg);
                    488:        ret_code = out_msg->RetCode;
                    489: 
                    490:        if (out_msg->RetCode == MIG_NO_REPLY)
                    491:                ret_code = KERN_SUCCESS;
                    492:        else
                    493:                ret_code = msg_send(&out_msg->Head, MSG_OPTION_NONE, 0);
                    494: 
                    495:        kfree(out_msg, MSG_SIZE_MAX);
                    496: 
                    497:        return ret_code;
                    498: }
                    499: 
                    500: #define RCV_IN_PROGRESS                RCV_ERRORS_START
                    501: /*
                    502:  * Call a proc indirectly based on the port.
                    503:  */
                    504: static kern_return_t kern_serv_dispatch (
                    505:        msg_header_t *in_msg,
                    506:        kern_server_t ksp)
                    507: {
                    508:        int i = ksp->last_rec_index;
                    509:        kern_return_t r = RCV_IN_PROGRESS;
                    510: 
                    511:        if (!ksp)
                    512:                return MIG_BAD_ID;
                    513: 
                    514:        if (in_msg->msg_local_port == ksp->last_unrec_port) {
                    515:                ks_log2(("kern_serv_dispatch: port %d was unrec\n",
                    516:                        in_msg->msg_local_port));
                    517:                r = MIG_BAD_ID;
                    518:        } else if (in_msg->msg_local_port == ksp->last_rec_port) {
                    519:                ks_log2(("kern_serv_dispatch: port %d was rec(%d), "
                    520:                        "proc 0x%x(%d)\n",
                    521:                        in_msg->msg_local_port, i, ksp->port_proc[i].proc,
                    522:                        ksp->port_proc[i].uarg));
                    523:                r = kern_serv_port_proc_call(in_msg, &ksp->port_proc[i]);
                    524:        } else {
                    525:                for (   i = 0
                    526:                     ;    i < KERN_SERVER_NPORTPROC
                    527:                       && ksp->port_proc[i].port != in_msg->msg_local_port
                    528:                     ; i++)
                    529:                        ;
                    530: 
                    531:                if (i != KERN_SERVER_NPORTPROC) {
                    532:                        ksp->last_rec_port = in_msg->msg_local_port;
                    533:                        ksp->last_rec_index = i;
                    534:                        ks_log2(("kern_serv_dispatch: port %d now rec(%d), "
                    535:                                "proc 0x%x(%d)\n",
                    536:                                in_msg->msg_local_port, i,
                    537:                                ksp->port_proc[i].proc,
                    538:                                ksp->port_proc[i].uarg));
                    539:                        r = kern_serv_port_proc_call(in_msg,
                    540:                                &ksp->port_proc[i]);
                    541:                }
                    542:        }
                    543: 
                    544:        if (r == RCV_IN_PROGRESS) {
                    545:                ks_log2(("kern_serv_dispatch: port %d now unrec\n",
                    546:                        in_msg->msg_local_port));
                    547:                ksp->last_unrec_port = in_msg->msg_local_port;
                    548:                r = MIG_BAD_ID;
                    549:        }
                    550: 
                    551:        return r;
                    552: }
                    553: 
                    554: /*
                    555:  * Got notification that port we have send rights on has gone away, clean up.
                    556:  */
                    557: void kern_serv_port_gone (
                    558:        kern_server_t   *kspp,
                    559:        port_name_t     port)
                    560: {
                    561:        kern_server_t   ksp = *kspp;
                    562:        register int i;
                    563: 
                    564:        if (ksp == 0)
                    565:                return;
                    566: 
                    567:        if (ksp->last_rec_port == port)
                    568:                ksp->last_rec_port = PORT_NULL;
                    569: 
                    570:        /*
                    571:         * If this is the log port, don't try to send anything to it.
                    572:         */
                    573:        if (ksp->log_port && port == ksp->log_port)
                    574:                ksp->log_port == PORT_NULL;
                    575:                
                    576:        /*
                    577:         * Free up port/proc pairs
                    578:         */
                    579:        for (i = 0; i < KERN_SERVER_NPORTPROC; i++)
                    580:                if (ksp->port_proc[i].port == port) {
                    581:                        ksp->port_proc[i].port = PORT_NULL;
                    582:                        ksp->port_proc[i].proc = 0;
                    583:                        break;
                    584:                }
                    585:        return;
                    586: }
                    587: 
                    588: kern_return_t kern_serv_instance_loc (
                    589:        void            *arg,
                    590:        vm_address_t    instance_loc)
                    591: {
                    592:        kern_server_t ksp = *((kern_server_t *)arg);
                    593:        kern_server_t *kspp = (kern_server_t *)instance_loc;
                    594: 
                    595:        ks_log(("kern_serv_instance_loc: 0x%x\n", instance_loc));
                    596:        *kspp = ksp;
                    597: 
                    598:        return KERN_SUCCESS;
                    599: }
                    600: 
                    601: /*
                    602:  * Specify user's version of system user compiled with.
                    603:  */
                    604: kern_return_t kern_serv_version (
                    605:        void            *arg,
                    606:        int             version)
                    607: {
                    608:        kern_server_t ksp = *((kern_server_t *)arg);
                    609: 
                    610:        if (version < KS_COMPAT)
                    611:                return KERN_SERVER_BAD_VERSION;
                    612:        ksp->version = version;
                    613: 
                    614:        return KERN_SUCCESS;
                    615: }
                    616: kern_return_t kern_serv_load_objc(
                    617:        void            *arg,
                    618:        vm_address_t    header)
                    619: {
                    620:        kern_server_t ksp = *((kern_server_t *)arg);
                    621:        int             error;
                    622: 
                    623: #if    KERNOBJC
                    624:        ksp->mach_header = (struct mach_header *) header;
                    625:        error = objc_registerModule (ksp->mach_header, 0);
                    626: #endif KERNOBJC
                    627:        return KERN_SUCCESS;
                    628: }
                    629: 
                    630:                                  
                    631: kern_return_t kern_serv_boot_port (    // how to talk to loader
                    632:        void            *arg,
                    633:        port_t          boot_port)
                    634: {
                    635:        kern_server_t ksp = *((kern_server_t *)arg);
                    636: 
                    637:        ksp->bootstrap_port = boot_port;
                    638:        return KERN_SUCCESS;
                    639: }
                    640: 
                    641: /*
                    642:  * Kernel version of kern_serv_notify, doesn't contact kern_loader, uses
                    643:  * internal port_request_notification facility.
                    644:  */
                    645: kern_return_t kern_serv_notify (
                    646:        kern_server_t   *kspp,
                    647:        port_t          reply_port,
                    648:        port_t          req_port)
                    649: {
                    650:        kern_server_t ksp;
                    651:        port_t  bootstrap_port;
                    652:        kern_return_t r;
                    653:        kern_port_t rp, np;
                    654: 
                    655:        ksp = *kspp;
                    656:        bootstrap_port = ksp->bootstrap_port;
                    657: 
                    658:        if (current_task() != kernel_task) {
                    659:                ks_notify_t *np;
                    660: 
                    661:                if (reply_port == ksp->notify_port)
                    662:                        /*
                    663:                         * Notification will happen automatically.
                    664:                         */
                    665:                        return KERN_SUCCESS;
                    666: 
                    667:                /*
                    668:                 * Make sure that an entry doesn't already exist for this
                    669:                 * pair.
                    670:                 */
                    671:                for (  np = (ks_notify_t *)queue_first(&ksp->notify_q)
                    672:                     ; !queue_end(&ksp->notify_q, (queue_entry_t)np)
                    673:                     ; np = (ks_notify_t *)queue_next(&np->link))
                    674:                        if (   np->reply_port == reply_port
                    675:                            && np->req_port == req_port)
                    676:                                return KERN_FAILURE;
                    677: 
                    678:                np = (kern_port_t)kalloc(sizeof *np);
                    679:                np->reply_port = reply_port;
                    680:                np->req_port = req_port;
                    681:                queue_enter(&ksp->notify_q, np, ks_notify_t *, link);
                    682: 
                    683:                /*
                    684:                 * Notification will be forwarded from kern_server.
                    685:                 */
                    686:                return KERN_SUCCESS;
                    687:        }
                    688: 
                    689:        r = get_kern_port(current_task(), req_port, &rp);
                    690:        if (r != KERN_SUCCESS)
                    691:                return r;
                    692:        r = get_kern_port(current_task(), reply_port, &np);
                    693:        if (r != KERN_SUCCESS)
                    694:                return r;
                    695:        port_request_notification(rp, np);
                    696:        return KERN_SUCCESS;
                    697: }
                    698: 
                    699: kern_return_t kern_serv_wire_range (   // wire the specified range or memory
                    700:        void            *arg,
                    701:        vm_address_t    addr,
                    702:        vm_size_t       size)
                    703: {
                    704:        kern_server_t ksp = *((kern_server_t *)arg);
                    705: 
                    706:        ks_log(("kern_serv_wire_range: addr 0x%x for 0x%x bytes\n",
                    707:                addr, size));
                    708: #if    DIAGNOSTIC
                    709:        printf("kern_server: wiring 0x%x to 0x%x\n", trunc_page(addr),
                    710:                round_page(addr+size));
                    711: #endif
                    712:        return vm_map_pageable(kernel_task->map, trunc_page(addr),
                    713:                round_page(addr+size), FALSE);
                    714: }
                    715: 
                    716: kern_return_t kern_serv_unwire_range ( // unwire the specified range or memory
                    717:        void            *arg,
                    718:        vm_address_t    addr,
                    719:        vm_size_t       size)
                    720: {
                    721:        kern_server_t ksp = *((kern_server_t *)arg);
                    722: 
                    723:        ks_log(("kern_serv_unwire_range: addr 0x%x for 0x%x bytes\n",
                    724:                addr, size));
                    725: #if    DIAGNOSTIC
                    726:        printf("kern_server: unwiring 0x%x to 0x%x\n", trunc_page(addr),
                    727:                round_page(addr+size));
                    728: #endif
                    729:        return vm_map_pageable(kernel_task->map, trunc_page(addr),
                    730:                round_page(addr+size), TRUE);
                    731: }
                    732: 
                    733: /*
                    734:  * Map messages coming on on the specified port to call the specified proc.
                    735:  * If this mapping can't be made FALSE is returned.
                    736:  * The port is added to the portset for this server.
                    737:  */
                    738: kern_return_t kern_serv_port_proc (    // map a message on port to proc/arg
                    739:        void            *arg,           // record into structure
                    740:        port_all_t      port,           // port to map (all rights passed)
                    741:        port_map_proc_t proc,           // proc to call
                    742:        int             uarg)           // replace local_port with uarg
                    743: {
                    744:        register int i;
                    745:        kern_return_t r;
                    746:        kern_server_t ksp = *((kern_server_t *)arg);
                    747: 
                    748:        ks_log(("kern_serv_port_proc: port %d proc 0x%x uarg %d\n",
                    749:                port, proc, uarg));
                    750: 
                    751:        if (ksp->last_unrec_port == port)
                    752:                ksp->last_unrec_port = PORT_NULL;
                    753: 
                    754:        for (i = 0; i < KERN_SERVER_NPORTPROC; i++)
                    755:                if (ksp->port_proc[i].port == port)
                    756:                        ksp->port_proc[i].port = PORT_NULL;
                    757: 
                    758:        for (i = 0; i < KERN_SERVER_NPORTPROC; i++)
                    759:                if (ksp->port_proc[i].port == PORT_NULL)
                    760:                        break;
                    761: 
                    762:        r = KERN_RESOURCE_SHORTAGE;
                    763:        if (   i == KERN_SERVER_NPORTPROC
                    764:            || (r = port_set_add(ksp->task_port, ksp->port_set, port))
                    765:                != KERN_SUCCESS)
                    766:                return r;
                    767: 
                    768:        ksp->port_proc[i].port = port;
                    769:        ksp->port_proc[i].proc = proc;
                    770:        ksp->port_proc[i].uarg = (void *)uarg;
                    771:        ksp->port_proc[i].type = PP_handler;
                    772: 
                    773:        return KERN_SUCCESS;
                    774: }
                    775: 
                    776: /*
                    777:  * Map messages coming on on the specified port to call the specified proc.
                    778:  * If this mapping can't be made FALSE is returned.
                    779:  * The port is added to the portset for this server.
                    780:  */
                    781: kern_return_t kern_serv_port_serv (    // map a message on port to proc/arg
                    782:        void            *arg,           // record into structure
                    783:        port_all_t      port,           // port to map (all rights passed)
                    784:        port_map_proc_t proc,           // proc to call
                    785:        int             uarg)           // replace local_port with uarg
                    786: {
                    787:        register int i;
                    788:        kern_return_t r;
                    789:        kern_server_t ksp = *((kern_server_t *)arg);
                    790: 
                    791:        ks_log(("kern_serv_port_serv: port %d proc 0x%x uarg %d\n",
                    792:                port, proc, uarg));
                    793: 
                    794:        if (ksp->last_unrec_port == port)
                    795:                ksp->last_unrec_port = PORT_NULL;
                    796: 
                    797:        for (i = 0; i < KERN_SERVER_NPORTPROC; i++)
                    798:                if (ksp->port_proc[i].port == port)
                    799:                        ksp->port_proc[i].port = PORT_NULL;
                    800: 
                    801:        for (i = 0; i < KERN_SERVER_NPORTPROC; i++)
                    802:                if (ksp->port_proc[i].port == PORT_NULL)
                    803:                        break;
                    804: 
                    805:        r = KERN_RESOURCE_SHORTAGE;
                    806:        if (   i == KERN_SERVER_NPORTPROC
                    807:            || (r = port_set_add(ksp->task_port, ksp->port_set, port))
                    808:                != KERN_SUCCESS)
                    809:                return r;
                    810: 
                    811:        ksp->port_proc[i].port = port;
                    812:        ksp->port_proc[i].proc = proc;
                    813:        ksp->port_proc[i].uarg = (void *)uarg;
                    814:        ksp->port_proc[i].type = PP_server;
                    815: 
                    816:        return KERN_SUCCESS;
                    817: }
                    818: 
                    819: kern_return_t kern_serv_port_death_proc ( // specify port death handler
                    820:        void                    *arg,   // record into structure
                    821:        port_death_proc_t       proc)   // record into structure
                    822: {
                    823:        kern_server_t ksp = *((kern_server_t *)arg);
                    824: 
                    825:        ksp->pd_proc = proc;
                    826:        return KERN_SUCCESS;
                    827: }
                    828: 
                    829: kern_return_t kern_serv_call_proc (    // call procedure with argument
                    830:        void            *arg,           // record into structure
                    831:        call_proc_t     proc,           // record into structure
                    832:        int             uarg)           // arg to supply
                    833: {
                    834:        kern_server_t ksp = *((kern_server_t *)arg);
                    835: 
                    836:        ks_log(("kern_serv_call_proc: proc 0x%x uarg %d\n",
                    837:                proc, uarg));
                    838: 
                    839:        if (proc) {
                    840:                (*proc)(uarg);
                    841:                return KERN_SUCCESS;
                    842:        }
                    843:        return KERN_SERVER_ERROR;
                    844: }
                    845: 
                    846: kern_return_t kern_serv_shutdown (
                    847:        void            *arg)
                    848: {
                    849:        kern_server_t ksp = *((kern_server_t *)arg);
                    850:        int i;
                    851: 
                    852:        ks_log(("kern_serv_shutdown\n"));
                    853: 
                    854: #if    KERNOBJC
                    855:        /*
                    856:         * Detach from Objective-C runtime.
                    857:         */
                    858:        if (ksp->mach_header)
                    859:                objc_unregisterModule (ksp->mach_header, 0);
                    860: #endif KERNOBJC
                    861: 
                    862:        /*
                    863:         * Stop logging and free the data
                    864:         * if we were logging.
                    865:         */
                    866:        if (ksp->log.level) {
                    867:                kern_serv_log_free(&ksp->log);
                    868:                ksp->log.level = 0;
                    869:        }
                    870: 
                    871:        /*
                    872:         * Deallocate all the port mappings we have.
                    873:         */
                    874:        for (i = 0; i < KERN_SERVER_NPORTPROC; i++)
                    875:                if (ksp->port_proc[i].port != PORT_NULL) {
                    876:                        port_deallocate(ksp->task_port,
                    877:                                ksp->port_proc[i].port);
                    878:                        ksp->port_proc[i].port = PORT_NULL;
                    879:                        ksp->port_proc[i].proc = 0;
                    880:                }
                    881: 
                    882:        /*
                    883:         * Deallocate our boot_listener and notify ports.
                    884:         */
                    885:        port_deallocate(ksp->task_port, ksp->boot_listener_port);
                    886:        port_deallocate(ksp->task_port, ksp->notify_port);
                    887: 
                    888:        /*
                    889:         * Deallocate our port_set
                    890:         */
                    891:        port_set_deallocate(ksp->task_port, ksp->port_set);
                    892: 
                    893:        /*
                    894:         * Deallocate our message frame.
                    895:         */
                    896:        kfree(ksp->msg, ksp->msg_size);
                    897:        kfree(ksp, sizeof *ksp);
                    898:        thread_terminate(current_thread());
                    899:        while (1)
                    900:                /*
                    901:                 * Wait to be killed.
                    902:                 */
                    903:                thread_halt_self();
                    904: 
                    905:        return KERN_SUCCESS;
                    906: }
                    907: 
                    908: // log level from message on port
                    909: kern_return_t kern_serv_log_level (
                    910:        void            *arg,
                    911:        int             log_level)
                    912: {
                    913:        kern_server_t ksp = *((kern_server_t *)arg);
                    914:        int old_level = ksp->log.level;
                    915: 
                    916:        ksp->log.level = log_level;
                    917: 
                    918:        /*
                    919:         * Only keep space around for the log
                    920:         * if we need it.
                    921:         */
                    922:        if (old_level == 0 && ksp->log.level)
                    923:                kern_serv_log_init(&ksp->log,
                    924:                        KERN_SERVER_LOG_SIZE);
                    925:        else if (ksp->log.level == 0 && old_level)
                    926:                kern_serv_log_free(&ksp->log);
                    927: 
                    928:        return KERN_SUCCESS;
                    929: }
                    930: 
                    931: kern_return_t kern_serv_get_log (
                    932:        void            *arg,
                    933:        port_t          reply_port)     // port to send log information to
                    934: {
                    935:        int s, n;
                    936:        kern_server_t ksp = *((kern_server_t *)arg);
                    937: 
                    938:        if (ksp->log.level == 0) {
                    939:                port_deallocate(ksp->task_port, reply_port);
                    940:                return KERN_SERVER_NOTLOGGING;
                    941:        }
                    942: 
                    943:        if (ksp->log.ptr == ksp->log.base) {
                    944:                ksp->log_port = reply_port;
                    945:                return KERN_SUCCESS;
                    946:        } else {
                    947:                vm_size_t size =
                    948:                    round_page((char *)ksp->log.ptr - (char *)ksp->log.base);
                    949:                pointer_t ldata;
                    950:                unsigned int ldata_count;
                    951:                kern_return_t r;
                    952: 
                    953:                ASSERT(    (void *)ksp->log.base
                    954:                        == (void *)round_page(ksp->log.base));
                    955:                r = vm_read(ksp->kernel_port,
                    956:                        (vm_address_t)ksp->log.base, size, &ldata,
                    957:                        &ldata_count);
                    958:                ASSERT(r == KERN_SUCCESS);
                    959:                kern_serv_log_data(reply_port,
                    960:                        (log_entry_t *)ldata,
                    961:                        ksp->log.ptr - ksp->log.base);
                    962: 
                    963:                port_deallocate(ksp->task_port, reply_port);
                    964:                vm_deallocate(ksp->task_port, ldata, size);
                    965:        }
                    966: 
                    967:        s = splhigh();
                    968:        simple_lock(&ksp->slock);
                    969:        ksp->log.ptr = ksp->log.base;
                    970:        simple_unlock(&ksp->slock);
                    971:        splx(s);
                    972: 
                    973:        return KERN_SUCCESS;
                    974: }
                    975: 
                    976: void kern_serv_log (                   // log a message
                    977:        kern_server_t   *kspp,          // kern_server instance vars
                    978:        int             log_level,      // level to log at
                    979:        char            *msg,           // what to log (followed by args)
                    980:        int             arg1,
                    981:        int             arg2,
                    982:        int             arg3,
                    983:        int             arg4,
                    984:        int             arg5)
                    985: {
                    986:        kern_server_t ksp = *kspp;
                    987:        register int s;
                    988:        log_entry_t *x;
                    989: 
                    990:        if (log_level > ksp->log.level || ksp->log.base == 0)
                    991:                return;
                    992: 
                    993:        s = splhigh();
                    994:        simple_lock(&ksp->slock);
                    995: 
                    996:        x = ksp->log.ptr++;
                    997:        if (ksp->log.ptr == ksp->log.last) {
                    998:                ksp->log.ptr--;
                    999:                simple_unlock(&ksp->slock);
                   1000:                splx(s);
                   1001:                return;
                   1002:        }
                   1003:        simple_unlock(&ksp->slock);
                   1004:        splx(s);
                   1005: 
                   1006:        x->msg = msg;
                   1007:        x->arg1 = arg1;
                   1008:        x->arg2 = arg2;
                   1009:        x->arg3 = arg3;
                   1010:        x->arg4 = arg4;
                   1011:        x->arg5 = arg5;
                   1012:        x->timestamp = XPR_TIMESTAMP;
                   1013:        x->cpuinfo = log_level;
                   1014: 
                   1015:        if (ksp->log_port)
                   1016:                kern_serv_callout(kspp, kern_serv_send_log, (void *)ksp);
                   1017: }
                   1018: 
                   1019: /*
                   1020:  * Send the log back to the user.  Have to copy the log into our address
                   1021:  * space.
                   1022:  */
                   1023: static void kern_serv_send_log(void *arg)
                   1024: {
                   1025:        kern_server_t ksp = (kern_server_t)arg;
                   1026:        port_name_t log_port;
                   1027:        int s;
                   1028:        vm_size_t size =
                   1029:                round_page((char *)ksp->log.ptr - (char *)ksp->log.base);
                   1030:        pointer_t ldata;
                   1031:        unsigned int ldata_count;
                   1032:        kern_return_t r;
                   1033: 
                   1034:        s = splhigh();
                   1035:        simple_lock(&ksp->slock);
                   1036: 
                   1037:        log_port = ksp->log_port;
                   1038:        ksp->log_port = PORT_NULL;
                   1039: 
                   1040:        simple_unlock(&ksp->slock);
                   1041:        splx(s);
                   1042:        if (log_port == PORT_NULL)
                   1043:                return;
                   1044: 
                   1045:        ASSERT((void *)ksp->log.base == (void *)round_page(ksp->log.base));
                   1046:        r = vm_read(ksp->kernel_port, (vm_address_t)ksp->log.base,
                   1047:                size, &ldata, &ldata_count);
                   1048:        ASSERT(r == KERN_SUCCESS);
                   1049:        kern_serv_log_data(log_port, (log_entry_t *)ldata,
                   1050:                ksp->log.ptr - ksp->log.base);
                   1051: 
                   1052:        port_deallocate(ksp->task_port, log_port);
                   1053:        vm_deallocate(ksp->task_port, ldata, size);
                   1054: 
                   1055:        s = splhigh();
                   1056:        simple_lock(&ksp->slock);
                   1057: 
                   1058:        ksp->log.ptr = ksp->log.base;
                   1059: 
                   1060:        simple_unlock(&ksp->slock);
                   1061:        splx(s);
                   1062: 
                   1063: }
                   1064: 
                   1065: /*
                   1066:  * Ensure that the number of entries is rounded up to a page boundary.
                   1067:  */
                   1068: static void kern_serv_log_init (       // initialize server's log buffer
                   1069:        log_t   *log,                   // uninitialized log struct
                   1070:        int     num_entries)            // size of log
                   1071: {
                   1072:        vm_size_t size = round_page(sizeof(log_entry_t)*num_entries);
                   1073:        num_entries = size / sizeof(log_entry_t);
                   1074: 
                   1075:        log->base = (log_entry_t *)kalloc(size);
                   1076: 
                   1077:        log->last = log->base + num_entries;
                   1078:        log->ptr = log->base;
                   1079: #if    DIAGNOSTIC
                   1080:        printf("kern_serv_log_init: log 0x%x log.last 0x%x, log.base 0x%x\n",
                   1081:                log, log->last, log->base);
                   1082: #endif 
                   1083: }
                   1084: 
                   1085: static void kern_serv_log_free (log_t *log) // deallocate log structure
                   1086: {
                   1087:        kfree(log->base, round_page((char *)log->last - (char *)log->base));
                   1088:        log->base = log->last = log->ptr = 0;
                   1089: }
                   1090: 
                   1091: kern_return_t kern_serv_callout (
                   1092:        kern_server_t   *kspp,
                   1093:        void            (*proc)(void *arg),
                   1094:        void *          arg)
                   1095: {
                   1096:        kern_server_t ksp = *kspp;
                   1097:        struct msg_send_entry *msep;
                   1098:        int s;
                   1099: 
                   1100:        /*
                   1101:         * Just call this guy directly if the conditions are right.
                   1102:         */
                   1103:        if (
                   1104:            curipl() == 0
                   1105:            && task_self() == ksp->task_port) {
                   1106:                (*proc)(arg);
                   1107:                return KERN_SUCCESS;
                   1108:        }
                   1109: 
                   1110:        s = splhigh();
                   1111:        simple_lock(&ksp->slock);
                   1112: 
                   1113:        if (queue_empty(&ksp->msg_callout_fq)) {
                   1114: #if    DIAGNOSTIC
                   1115:                printf("kern_serv_callout: no free messages");
                   1116: #endif
                   1117:                simple_unlock(&ksp->slock);
                   1118:                splx(s);
                   1119:                return KERN_RESOURCE_SHORTAGE;
                   1120:        }
                   1121: 
                   1122:        queue_remove_first(&ksp->msg_callout_fq, msep, struct msg_send_entry *,
                   1123:                link);
                   1124:        ks_log(("kern_serv_send: (queue) proc 0x%x\n", proc));
                   1125: 
                   1126:        msep->func = proc;
                   1127:        msep->arg = arg;
                   1128:        queue_enter(&ksp->msg_callout_q, msep, struct msg_send_entry *, link);
                   1129: 
                   1130:        simple_unlock(&ksp->slock);
                   1131:        splx(s);
                   1132: 
                   1133:        /*
                   1134:         * Interrupt the server thread to that it'll look at this sucker.
                   1135:         */
                   1136:        thread_call_func(
                   1137:                (thread_call_func_t)kern_serv_interrupt_server,
                   1138:                (thread_call_spec_t)ksp->server_thread, TRUE);
                   1139: 
                   1140:        return KERN_SUCCESS;
                   1141: }
                   1142: 
                   1143: static void kern_serv_interrupt_server(thread_t thread)
                   1144: {
                   1145:        /*
                   1146:         * Sending the guy a message sounds like the best way to ensure
                   1147:         * that he see's that there's something to do.
                   1148:         */
                   1149:        send_notification(thread->task, NOTIFY_MSG_ACCEPTED, PORT_NULL);
                   1150: }
                   1151: 
                   1152: /*
                   1153:  * Structure access functions.
                   1154:  */
                   1155: port_t kern_serv_local_port(kern_server_t *ksp)
                   1156: {
                   1157:        return (*ksp)->local_port;
                   1158: }
                   1159: 
                   1160: port_t kern_serv_bootstrap_port(kern_server_t *ksp)
                   1161: {
                   1162:        return (*ksp)->bootstrap_port;
                   1163: }
                   1164: 
                   1165: port_t kern_serv_notify_port(kern_server_t *ksp)
                   1166: {
                   1167:        return (*ksp)->notify_port;
                   1168: }
                   1169: 
                   1170: port_set_name_t kern_serv_port_set(kern_server_t *ksp)
                   1171: {
                   1172:        return (*ksp)->port_set;
                   1173: }
                   1174: 
                   1175: /* Get the kernel task port. */
                   1176: port_t kern_serv_kernel_task_port(void)
                   1177: {
                   1178:        extern task_t kernel_task;      // global kernel variable.
                   1179:        port_t my_kernel_port;
                   1180: 
                   1181:        task_reference(kernel_task);
                   1182:        my_kernel_port = convert_task_to_port(kernel_task);
                   1183:        if (my_kernel_port == PORT_NULL)
                   1184:                return PORT_NULL;
                   1185: 
                   1186:        object_copyout(current_task(), my_kernel_port, MSG_TYPE_PORT,
                   1187:                &my_kernel_port);
                   1188:        return my_kernel_port;
                   1189: }

unix.superglobalmegacorp.com

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