Annotation of XNU/osfmk/i386/pcb.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:  * Mach Operating System
                     27:  * Copyright (c) 1991,1990 Carnegie Mellon University
                     28:  * All Rights Reserved.
                     29:  * 
                     30:  * Permission to use, copy, modify and distribute this software and its
                     31:  * documentation is hereby granted, provided that both the copyright
                     32:  * notice and this permission notice appear in all copies of the
                     33:  * software, derivative works or modified versions, and any portions
                     34:  * thereof, and that both notices appear in supporting documentation.
                     35:  * 
                     36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     39:  * 
                     40:  * Carnegie Mellon requests users of this software to return to
                     41:  * 
                     42:  *  Software Distribution Coordinator  or  [email protected]
                     43:  *  School of Computer Science
                     44:  *  Carnegie Mellon University
                     45:  *  Pittsburgh PA 15213-3890
                     46:  * 
                     47:  * any improvements or extensions that they make and grant Carnegie Mellon
                     48:  * the rights to redistribute these changes.
                     49:  */
                     50: 
                     51: #include <cpus.h>
                     52: #include <mach_rt.h>
                     53: #include <mach_debug.h>
                     54: #include <mach_ldebug.h>
                     55: 
                     56: #include <mach/kern_return.h>
                     57: #include <mach/thread_status.h>
                     58: #include <mach/vm_param.h>
                     59: #include <mach/rpc.h>
                     60: 
                     61: #include <kern/counters.h>
                     62: #include <kern/mach_param.h>
                     63: #include <kern/task.h>
                     64: #include <kern/thread.h>
                     65: #include <kern/thread_act.h>
                     66: #include <kern/thread_swap.h>
                     67: #include <kern/sched_prim.h>
                     68: #include <kern/misc_protos.h>
                     69: #include <kern/assert.h>
                     70: #include <kern/spl.h>
                     71: #include <ipc/ipc_port.h>
                     72: #include <vm/vm_kern.h>
                     73: #include <vm/pmap.h>
                     74: 
                     75: #include <i386/thread.h>
                     76: #include <i386/eflags.h>
                     77: #include <i386/proc_reg.h>
                     78: #include <i386/seg.h>
                     79: #include <i386/tss.h>
                     80: #include <i386/user_ldt.h>
                     81: #include <i386/fpu.h>
                     82: #include <i386/iopb_entries.h>
                     83: 
                     84: /*
                     85:  * Maps state flavor to number of words in the state:
                     86:  */
                     87: unsigned int state_count[] = {
                     88:        /* FLAVOR_LIST */ 0,
                     89:        i386_NEW_THREAD_STATE_COUNT,
                     90:        i386_FLOAT_STATE_COUNT,
                     91:        i386_ISA_PORT_MAP_STATE_COUNT,
                     92:        i386_V86_ASSIST_STATE_COUNT,
                     93:        i386_REGS_SEGS_STATE_COUNT,
                     94:        i386_THREAD_SYSCALL_STATE_COUNT,
                     95:        /* THREAD_STATE_NONE */ 0,
                     96:        i386_SAVED_STATE_COUNT,
                     97: };
                     98: 
                     99: /* Forward */
                    100: 
                    101: void act_machine_throughcall(thread_act_t thr_act);
                    102: extern thread_t                Switch_context(
                    103:                                thread_t                old,
                    104:                                void                    (*cont)(void),
                    105:                                thread_t                new);
                    106: extern void            Thread_continue(void);
                    107: extern void            Load_context(
                    108:                                thread_t                thread);
                    109: 
                    110: /*
                    111:  * consider_machine_collect:
                    112:  *
                    113:  *     Try to collect machine-dependent pages
                    114:  */
                    115: void
                    116: consider_machine_collect()
                    117: {
                    118: }
                    119: 
                    120: /*
                    121:  *     machine_kernel_stack_init:
                    122:  *
                    123:  *     Initialize a kernel stack which has already been
                    124:  *     attached to its thread_activation.
                    125:  */
                    126: 
                    127: void
                    128: machine_kernel_stack_init(
                    129:        thread_t        thread,
                    130:        void            (*continuation)(void))
                    131: {
                    132:        thread_act_t    thr_act = thread->top_act;
                    133:        vm_offset_t     stack;
                    134: 
                    135:        assert(thr_act);
                    136:        stack = thread->kernel_stack;
                    137:        assert(stack);
                    138: 
                    139: #if    MACH_ASSERT
                    140:        if (watchacts & WA_PCB) {
                    141:                printf("machine_kernel_stack_init(thr=%x,stk=%x,cont=%x)\n",
                    142:                                thread,stack,continuation);
                    143:                printf("\tstack_iks=%x, stack_iel=%x\n",
                    144:                        STACK_IKS(stack), STACK_IEL(stack));
                    145:        }
                    146: #endif /* MACH_ASSERT */
                    147: 
                    148:        /*
                    149:         *      We want to run continuation, giving it as an argument
                    150:         *      the return value from Load_context/Switch_context.
                    151:         *      Thread_continue takes care of the mismatch between
                    152:         *      the argument-passing/return-value conventions.
                    153:         *      This function will not return normally,
                    154:         *      so we don`t have to worry about a return address.
                    155:         */
                    156:        STACK_IKS(stack)->k_eip = (int) Thread_continue;
                    157:        STACK_IKS(stack)->k_ebx = (int) continuation;
                    158:        STACK_IKS(stack)->k_esp = (int) STACK_IEL(stack);
                    159: 
                    160:        /*
                    161:         *      Point top of kernel stack to user`s registers.
                    162:         */
                    163:        STACK_IEL(stack)->saved_state = &thr_act->mact.pcb->iss;
                    164: }
                    165: 
                    166: 
                    167: #if    NCPUS > 1
                    168: #define        curr_gdt(mycpu)         (mp_gdt[mycpu])
                    169: #define        curr_ktss(mycpu)        (mp_ktss[mycpu])
                    170: #else
                    171: #define        curr_gdt(mycpu)         (gdt)
                    172: #define        curr_ktss(mycpu)        (&ktss)
                    173: #endif
                    174: 
                    175: #define        gdt_desc_p(mycpu,sel) \
                    176:        ((struct real_descriptor *)&curr_gdt(mycpu)[sel_idx(sel)])
                    177: 
                    178: void
                    179: act_machine_switch_pcb( thread_act_t new_act )
                    180: {
                    181:        pcb_t                   pcb = new_act->mact.pcb;
                    182:        int                     mycpu;
                    183:     {
                    184:        register iopb_tss_t     tss = pcb->ims.io_tss;
                    185:        vm_offset_t             pcb_stack_top;
                    186: 
                    187:         assert(new_act->thread != NULL);
                    188:         assert(new_act->thread->kernel_stack != 0);
                    189:         STACK_IEL(new_act->thread->kernel_stack)->saved_state =
                    190:                 &new_act->mact.pcb->iss;
                    191: 
                    192:        /*
                    193:         *      Save a pointer to the top of the "kernel" stack -
                    194:         *      actually the place in the PCB where a trap into
                    195:         *      kernel mode will push the registers.
                    196:         *      The location depends on V8086 mode.  If we are
                    197:         *      not in V8086 mode, then a trap into the kernel
                    198:         *      won`t save the v86 segments, so we leave room.
                    199:         */
                    200: 
                    201:        pcb_stack_top = (pcb->iss.efl & EFL_VM)
                    202:                        ? (int) (&pcb->iss + 1)
                    203:                        : (int) (&pcb->iss.v86_segs);
                    204: 
                    205:        mp_disable_preemption();
                    206:        mycpu = cpu_number();
                    207: 
                    208:        if (tss == 0) {
                    209:            /*
                    210:             *  No per-thread IO permissions.
                    211:             *  Use standard kernel TSS.
                    212:             */
                    213:            if (!(gdt_desc_p(mycpu,KERNEL_TSS)->access & ACC_TSS_BUSY))
                    214:                set_tr(KERNEL_TSS);
                    215:            curr_ktss(mycpu)->esp0 = pcb_stack_top;
                    216:        }
                    217:        else {
                    218:            /*
                    219:             * Set the IO permissions.  Use this thread`s TSS.
                    220:             */
                    221:            *gdt_desc_p(mycpu,USER_TSS)
                    222:                = *(struct real_descriptor *)tss->iopb_desc;
                    223:            tss->tss.esp0 = pcb_stack_top;
                    224:            set_tr(USER_TSS);
                    225:            gdt_desc_p(mycpu,KERNEL_TSS)->access &= ~ ACC_TSS_BUSY;
                    226:        }
                    227:     }
                    228: 
                    229:     {
                    230:        register user_ldt_t     ldt = pcb->ims.ldt;
                    231:        /*
                    232:         * Set the thread`s LDT.
                    233:         */
                    234:        if (ldt == 0) {
                    235:            /*
                    236:             * Use system LDT.
                    237:             */
                    238:            set_ldt(KERNEL_LDT);
                    239:        }
                    240:        else {
                    241:            /*
                    242:             * Thread has its own LDT.
                    243:             */
                    244:            *gdt_desc_p(mycpu,USER_LDT) = ldt->desc;
                    245:            set_ldt(USER_LDT);
                    246:        }
                    247:     }
                    248:        mp_enable_preemption();
                    249:        /*
                    250:         * Load the floating-point context, if necessary.
                    251:         */
                    252:        fpu_load_context(pcb);
                    253: 
                    254: }
                    255: 
                    256: /*
                    257:  * flush out any lazily evaluated HW state in the
                    258:  * owning thread's context, before termination.
                    259:  */
                    260: void
                    261: thread_machine_flush( thread_act_t cur_act )
                    262: {
                    263:     fpflush(cur_act);
                    264: }
                    265: 
                    266: /*
                    267:  * Switch to the first thread on a CPU.
                    268:  */
                    269: void
                    270: load_context(
                    271:        thread_t                new)
                    272: {
                    273:        act_machine_switch_pcb(new->top_act);
                    274:        Load_context(new);
                    275: }
                    276: 
                    277: /*
                    278:  * Number of times we needed to swap an activation back in before
                    279:  * switching to it.
                    280:  */
                    281: int switch_act_swapins = 0;
                    282: 
                    283: /*
                    284:  * machine_switch_act
                    285:  *
                    286:  * Machine-dependent details of activation switching.  Called with
                    287:  * RPC locks held and preemption disabled.
                    288:  */
                    289: void
                    290: machine_switch_act( 
                    291:        thread_t        thread,
                    292:        thread_act_t    old,
                    293:        thread_act_t    new,
                    294:        int                             cpu)
                    295: {
                    296:        /*
                    297:         *      Switch the vm, ast and pcb context. 
                    298:         *      Save FP registers if in use and set TS (task switch) bit.
                    299:         */
                    300:        fpu_save_context(thread);
                    301: 
                    302:        active_stacks[cpu] = thread->kernel_stack;
                    303:        ast_context(new, cpu);
                    304: 
                    305:        PMAP_SWITCH_CONTEXT(old, new, cpu);
                    306:        act_machine_switch_pcb(new);
                    307: }
                    308: 
                    309: /*
                    310:  * Switch to a new thread.
                    311:  * Save the old thread`s kernel state or continuation,
                    312:  * and return it.
                    313:  */
                    314: thread_t
                    315: switch_context(
                    316:        thread_t                old,
                    317:        void                    (*continuation)(void),
                    318:        thread_t                new)
                    319: {
                    320:        register thread_act_t   old_act = old->top_act,
                    321:                                new_act = new->top_act;
                    322: 
                    323: #if MACH_RT
                    324:         assert(old_act->kernel_loaded ||
                    325:                active_stacks[cpu_number()] == old_act->thread->kernel_stack);
                    326:         assert (get_preemption_level() == 1);
                    327: #endif
                    328:        check_simple_locks();
                    329: 
                    330:        /*
                    331:         *      Save FP registers if in use.
                    332:         */
                    333:        fpu_save_context(old);
                    334: 
                    335: #if    MACH_ASSERT
                    336:        if (watchacts & WA_SWITCH)
                    337:                printf("\tswitch_context(old=%x con=%x new=%x)\n",
                    338:                                            old, continuation, new);
                    339: #endif /* MACH_ASSERT */
                    340: 
                    341:        /*
                    342:         *      Switch address maps if need be, even if not switching tasks.
                    343:         *      (A server activation may be "borrowing" a client map.)
                    344:         */
                    345:     {
                    346:        int     mycpu = cpu_number();
                    347: 
                    348:        PMAP_SWITCH_CONTEXT(old_act, new_act, mycpu)
                    349:     }
                    350: 
                    351:        /*
                    352:         *      Load the rest of the user state for the new thread
                    353:         */
                    354:        act_machine_switch_pcb(new_act);
                    355:        return(Switch_context(old, continuation, new));
                    356: }
                    357: 
                    358: void
                    359: pcb_module_init(void)
                    360: {
                    361:        fpu_module_init();
                    362:        iopb_init();
                    363: }
                    364: 
                    365: void
                    366: pcb_init( register thread_act_t thr_act )
                    367: {
                    368:        register pcb_t pcb;
                    369: 
                    370:        assert(thr_act->mact.pcb == (pcb_t)0);
                    371:        pcb = thr_act->mact.pcb = &thr_act->mact.xxx_pcb;
                    372: 
                    373: #if    MACH_ASSERT
                    374:        if (watchacts & WA_PCB)
                    375:                printf("pcb_init(%x) pcb=%x\n", thr_act, pcb);
                    376: #endif /* MACH_ASSERT */
                    377: 
                    378:        /*
                    379:         *      We can't let random values leak out to the user.
                    380:         * (however, act_create() zeroed the entire thr_act, mact, pcb)
                    381:         * bzero((char *) pcb, sizeof *pcb);
                    382:         */
                    383:        simple_lock_init(&pcb->lock, ETAP_MISC_PCB);
                    384: 
                    385:        /*
                    386:         *      Guarantee that the bootstrapped thread will be in user
                    387:         *      mode.
                    388:         */
                    389:        pcb->iss.cs = USER_CS;
                    390:        pcb->iss.ss = USER_DS;
                    391:        pcb->iss.ds = USER_DS;
                    392:        pcb->iss.es = USER_DS;
                    393:        pcb->iss.fs = USER_DS;
                    394:        pcb->iss.gs = USER_DS;
                    395:        pcb->iss.efl = EFL_USER_SET;
                    396: }
                    397: 
                    398: /*
                    399:  * Adjust saved register state for thread belonging to task
                    400:  * created with kernel_task_create().
                    401:  */
                    402: void
                    403: pcb_user_to_kernel(
                    404:        thread_act_t thr_act)
                    405: {
                    406:        register pcb_t pcb = thr_act->mact.pcb;
                    407: 
                    408:        pcb->iss.cs = KERNEL_CS;
                    409:        pcb->iss.ss = KERNEL_DS;
                    410:        pcb->iss.ds = KERNEL_DS;
                    411:        pcb->iss.es = KERNEL_DS;
                    412:        pcb->iss.fs = KERNEL_DS;
                    413:        pcb->iss.gs = CPU_DATA;
                    414: }
                    415: 
                    416: void
                    417: pcb_terminate(
                    418:        register thread_act_t thr_act)
                    419: {
                    420:        register pcb_t  pcb = thr_act->mact.pcb;
                    421: 
                    422:        assert(pcb);
                    423: 
                    424:        if (pcb->ims.io_tss != 0)
                    425:                iopb_destroy(pcb->ims.io_tss);
                    426:        if (pcb->ims.ifps != 0)
                    427:                fp_free(pcb->ims.ifps);
                    428:        if (pcb->ims.ldt != 0)
                    429:                user_ldt_free(pcb->ims.ldt);
                    430:        thr_act->mact.pcb = (pcb_t)0;
                    431: }
                    432: 
                    433: /*
                    434:  *     pcb_collect:
                    435:  *
                    436:  *     Attempt to free excess pcb memory.
                    437:  */
                    438: 
                    439: void
                    440: pcb_collect(
                    441:        register thread_act_t  thr_act)
                    442: {
                    443:        /* accomplishes very little */
                    444: }
                    445: 
                    446: /*
                    447:  * act_machine_sv_free
                    448:  * release saveareas associated with an act. if flag is true, release
                    449:  * user level savearea(s) too, else don't
                    450:  */
                    451: void
                    452: act_machine_sv_free(thread_act_t act, int flag)
                    453: {
                    454: 
                    455: }
                    456: 
                    457: /*
                    458:  *     act_machine_set_state:
                    459:  *
                    460:  *     Set the status of the specified thread.  Called with "appropriate"
                    461:  *     thread-related locks held (see act_lock_thread()), so
                    462:  *     thr_act->thread is guaranteed not to change.
                    463:  */
                    464: 
                    465: kern_return_t
                    466: act_machine_set_state(
                    467:        thread_act_t thr_act,
                    468:        thread_flavor_t flavor,
                    469:        thread_state_t tstate,
                    470:        mach_msg_type_number_t count)
                    471: {
                    472:        int                     kernel_act = thr_act->kernel_loading ||
                    473:                                        thr_act->kernel_loaded;
                    474: 
                    475: #if    MACH_ASSERT
                    476:        if (watchacts & WA_STATE)
                    477:            printf("act_%x act_m_set_state(thr_act=%x,flav=%x,st=%x,cnt=%x)\n",
                    478:                    current_act(), thr_act, flavor, tstate, count);
                    479: #endif /* MACH_ASSERT */
                    480: 
                    481:        switch (flavor) {
                    482:            case THREAD_SYSCALL_STATE:
                    483:            {
                    484:                register struct thread_syscall_state *state;
                    485:                register struct i386_saved_state *saved_state = USER_REGS(thr_act);
                    486: 
                    487:                state = (struct thread_syscall_state *) tstate;
                    488:                saved_state->eax = state->eax;
                    489:                saved_state->edx = state->edx;
                    490:                if (kernel_act)
                    491:                        saved_state->efl = state->efl;
                    492:                else
                    493:                        saved_state->efl = (state->efl & ~EFL_USER_CLEAR) | EFL_USER_SET;
                    494:                saved_state->eip = state->eip;
                    495:                saved_state->uesp = state->esp;
                    496:                break;
                    497:            }
                    498: 
                    499:            case i386_SAVED_STATE:
                    500:            {
                    501:                register struct i386_saved_state        *state;
                    502:                register struct i386_saved_state        *saved_state;
                    503: 
                    504:                if (count < i386_SAVED_STATE_COUNT) {
                    505:                    return(KERN_INVALID_ARGUMENT);
                    506:                }
                    507: 
                    508:                state = (struct i386_saved_state *) tstate;
                    509: 
                    510:                saved_state = USER_REGS(thr_act);
                    511: 
                    512:                /*
                    513:                 * General registers
                    514:                 */
                    515:                saved_state->edi = state->edi;
                    516:                saved_state->esi = state->esi;
                    517:                saved_state->ebp = state->ebp;
                    518:                saved_state->uesp = state->uesp;
                    519:                saved_state->ebx = state->ebx;
                    520:                saved_state->edx = state->edx;
                    521:                saved_state->ecx = state->ecx;
                    522:                saved_state->eax = state->eax;
                    523:                saved_state->eip = state->eip;
                    524:                if (kernel_act)
                    525:                        saved_state->efl = state->efl;
                    526:                else
                    527:                        saved_state->efl = (state->efl & ~EFL_USER_CLEAR)
                    528:                                                | EFL_USER_SET;
                    529: 
                    530:                /*
                    531:                 * Segment registers.  Set differently in V8086 mode.
                    532:                 */
                    533:                if (state->efl & EFL_VM) {
                    534:                    /*
                    535:                     * Set V8086 mode segment registers.
                    536:                     */
                    537:                    saved_state->cs = state->cs & 0xffff;
                    538:                    saved_state->ss = state->ss & 0xffff;
                    539:                    saved_state->v86_segs.v86_ds = state->ds & 0xffff;
                    540:                    saved_state->v86_segs.v86_es = state->es & 0xffff;
                    541:                    saved_state->v86_segs.v86_fs = state->fs & 0xffff;
                    542:                    saved_state->v86_segs.v86_gs = state->gs & 0xffff;
                    543: 
                    544:                    /*
                    545:                     * Zero protected mode segment registers.
                    546:                     */
                    547:                    saved_state->ds = 0;
                    548:                    saved_state->es = 0;
                    549:                    saved_state->fs = 0;
                    550:                    saved_state->gs = 0;
                    551: 
                    552:                    if (thr_act->mact.pcb->ims.v86s.int_table) {
                    553:                        /*
                    554:                         * Hardware assist on.
                    555:                         */
                    556:                        thr_act->mact.pcb->ims.v86s.flags =
                    557:                            state->efl & (EFL_TF | EFL_IF);
                    558:                    }
                    559:                }
                    560:                else if (!kernel_act) {
                    561:                    /*
                    562:                     * 386 mode.  Set segment registers for flat
                    563:                     * 32-bit address space.
                    564:                     */
                    565:                    saved_state->cs = USER_CS;
                    566:                    saved_state->ss = USER_DS;
                    567:                    saved_state->ds = USER_DS;
                    568:                    saved_state->es = USER_DS;
                    569:                    saved_state->fs = USER_DS;
                    570:                    saved_state->gs = USER_DS;
                    571:                }
                    572:                else {
                    573:                    /*
                    574:                     * User setting segment registers.
                    575:                     * Code and stack selectors have already been
                    576:                     * checked.  Others will be reset by 'iret'
                    577:                     * if they are not valid.
                    578:                     */
                    579:                    saved_state->cs = state->cs;
                    580:                    saved_state->ss = state->ss;
                    581:                    saved_state->ds = state->ds;
                    582:                    saved_state->es = state->es;
                    583:                    saved_state->fs = state->fs;
                    584:                    saved_state->gs = state->gs;
                    585:                }
                    586:                break;
                    587:            }
                    588: 
                    589:            case i386_NEW_THREAD_STATE:
                    590:            case i386_REGS_SEGS_STATE:
                    591:            {
                    592:                register struct i386_new_thread_state   *state;
                    593:                register struct i386_saved_state        *saved_state;
                    594: 
                    595:                if (count < i386_NEW_THREAD_STATE_COUNT) {
                    596:                    return(KERN_INVALID_ARGUMENT);
                    597:                }
                    598: 
                    599:                if (flavor == i386_REGS_SEGS_STATE) {
                    600:                    /*
                    601:                     * Code and stack selectors must not be null,
                    602:                     * and must have user protection levels.
                    603:                     * Only the low 16 bits are valid.
                    604:                     */
                    605:                    state->cs &= 0xffff;
                    606:                    state->ss &= 0xffff;
                    607:                    state->ds &= 0xffff;
                    608:                    state->es &= 0xffff;
                    609:                    state->fs &= 0xffff;
                    610:                    state->gs &= 0xffff;
                    611: 
                    612:                    if (!kernel_act &&
                    613:                        (state->cs == 0 || (state->cs & SEL_PL) != SEL_PL_U
                    614:                        || state->ss == 0 || (state->ss & SEL_PL) != SEL_PL_U))
                    615:                        return KERN_INVALID_ARGUMENT;
                    616:                }
                    617: 
                    618:                state = (struct i386_new_thread_state *) tstate;
                    619: 
                    620:                saved_state = USER_REGS(thr_act);
                    621: 
                    622:                /*
                    623:                 * General registers
                    624:                 */
                    625:                saved_state->edi = state->edi;
                    626:                saved_state->esi = state->esi;
                    627:                saved_state->ebp = state->ebp;
                    628:                saved_state->uesp = state->uesp;
                    629:                saved_state->ebx = state->ebx;
                    630:                saved_state->edx = state->edx;
                    631:                saved_state->ecx = state->ecx;
                    632:                saved_state->eax = state->eax;
                    633:                saved_state->eip = state->eip;
                    634:                if (kernel_act)
                    635:                        saved_state->efl = state->efl;
                    636:                else
                    637:                        saved_state->efl = (state->efl & ~EFL_USER_CLEAR)
                    638:                                                | EFL_USER_SET;
                    639: 
                    640:                /*
                    641:                 * Segment registers.  Set differently in V8086 mode.
                    642:                 */
                    643:                if (state->efl & EFL_VM) {
                    644:                    /*
                    645:                     * Set V8086 mode segment registers.
                    646:                     */
                    647:                    saved_state->cs = state->cs & 0xffff;
                    648:                    saved_state->ss = state->ss & 0xffff;
                    649:                    saved_state->v86_segs.v86_ds = state->ds & 0xffff;
                    650:                    saved_state->v86_segs.v86_es = state->es & 0xffff;
                    651:                    saved_state->v86_segs.v86_fs = state->fs & 0xffff;
                    652:                    saved_state->v86_segs.v86_gs = state->gs & 0xffff;
                    653: 
                    654:                    /*
                    655:                     * Zero protected mode segment registers.
                    656:                     */
                    657:                    saved_state->ds = 0;
                    658:                    saved_state->es = 0;
                    659:                    saved_state->fs = 0;
                    660:                    saved_state->gs = 0;
                    661: 
                    662:                    if (thr_act->mact.pcb->ims.v86s.int_table) {
                    663:                        /*
                    664:                         * Hardware assist on.
                    665:                         */
                    666:                        thr_act->mact.pcb->ims.v86s.flags =
                    667:                            state->efl & (EFL_TF | EFL_IF);
                    668:                    }
                    669:                }
                    670:                else if (flavor == i386_NEW_THREAD_STATE && !kernel_act) {
                    671:                    /*
                    672:                     * 386 mode.  Set segment registers for flat
                    673:                     * 32-bit address space.
                    674:                     */
                    675:                    saved_state->cs = USER_CS;
                    676:                    saved_state->ss = USER_DS;
                    677:                    saved_state->ds = USER_DS;
                    678:                    saved_state->es = USER_DS;
                    679:                    saved_state->fs = USER_DS;
                    680:                    saved_state->gs = USER_DS;
                    681:                }
                    682:                else {
                    683:                    /*
                    684:                     * User setting segment registers.
                    685:                     * Code and stack selectors have already been
                    686:                     * checked.  Others will be reset by 'iret'
                    687:                     * if they are not valid.
                    688:                     */
                    689:                    saved_state->cs = state->cs;
                    690:                    saved_state->ss = state->ss;
                    691:                    saved_state->ds = state->ds;
                    692:                    saved_state->es = state->es;
                    693:                    saved_state->fs = state->fs;
                    694:                    saved_state->gs = state->gs;
                    695:                }
                    696:                break;
                    697:            }
                    698: 
                    699:            case i386_FLOAT_STATE: {
                    700: 
                    701:                if (count < i386_FLOAT_STATE_COUNT)
                    702:                        return(KERN_INVALID_ARGUMENT);
                    703: 
                    704:                return fpu_set_state(thr_act,(struct i386_float_state*)tstate);
                    705:            }
                    706: 
                    707:            /*
                    708:             * Temporary - replace by i386_io_map
                    709:             */
                    710:            case i386_ISA_PORT_MAP_STATE: {
                    711:                register struct i386_isa_port_map_state *state;
                    712:                register iopb_tss_t     tss;
                    713: 
                    714:                if (count < i386_ISA_PORT_MAP_STATE_COUNT)
                    715:                        return(KERN_INVALID_ARGUMENT);
                    716: 
                    717:                break;
                    718:            }
                    719: 
                    720:            case i386_V86_ASSIST_STATE:
                    721:            {
                    722:                register struct i386_v86_assist_state *state;
                    723:                vm_offset_t     int_table;
                    724:                int             int_count;
                    725: 
                    726:                if (count < i386_V86_ASSIST_STATE_COUNT)
                    727:                    return KERN_INVALID_ARGUMENT;
                    728: 
                    729:                state = (struct i386_v86_assist_state *) tstate;
                    730:                int_table = state->int_table;
                    731:                int_count = state->int_count;
                    732: 
                    733:                if (int_table >= VM_MAX_ADDRESS ||
                    734:                    int_table +
                    735:                        int_count * sizeof(struct v86_interrupt_table)
                    736:                            > VM_MAX_ADDRESS)
                    737:                    return KERN_INVALID_ARGUMENT;
                    738: 
                    739:                thr_act->mact.pcb->ims.v86s.int_table = int_table;
                    740:                thr_act->mact.pcb->ims.v86s.int_count = int_count;
                    741: 
                    742:                thr_act->mact.pcb->ims.v86s.flags =
                    743:                        USER_REGS(thr_act)->efl & (EFL_TF | EFL_IF);
                    744:                break;
                    745:            }
                    746: 
                    747:        case i386_THREAD_STATE: {
                    748:                struct i386_saved_state *saved_state;
                    749:                i386_thread_state_t     *state25;
                    750: 
                    751:                saved_state = USER_REGS(thr_act);
                    752:                state25 = (i386_thread_state_t *)tstate;
                    753: 
                    754:                saved_state->eax = state25->eax;
                    755:                saved_state->ebx = state25->ebx;
                    756:                saved_state->ecx = state25->ecx;
                    757:                saved_state->edx = state25->edx;
                    758:                saved_state->edi = state25->edi;
                    759:                saved_state->esi = state25->esi;
                    760:                saved_state->ebp = state25->ebp;
                    761:                saved_state->uesp = state25->esp;
                    762:                saved_state->efl = (state25->eflags & ~EFL_USER_CLEAR)
                    763:                                                | EFL_USER_SET;
                    764:                saved_state->eip = state25->eip;
                    765:                saved_state->cs = USER_CS;      /* FIXME? */
                    766:                saved_state->ss = USER_DS;
                    767:                saved_state->ds = USER_DS;
                    768:                saved_state->es = USER_DS;
                    769:                saved_state->fs = USER_DS;
                    770:                saved_state->gs = USER_DS;
                    771:        }
                    772:                break;
                    773: 
                    774:            default:
                    775:                return(KERN_INVALID_ARGUMENT);
                    776:        }
                    777: 
                    778:        return(KERN_SUCCESS);
                    779: }
                    780: 
                    781: /*
                    782:  *     thread_getstatus:
                    783:  *
                    784:  *     Get the status of the specified thread.
                    785:  */
                    786: 
                    787: 
                    788: kern_return_t
                    789: act_machine_get_state(
                    790:        thread_act_t thr_act,
                    791:        thread_flavor_t flavor,
                    792:        thread_state_t tstate,
                    793:        mach_msg_type_number_t *count)
                    794: {
                    795: #if    MACH_ASSERT
                    796:        if (watchacts & WA_STATE)
                    797:            printf("act_%x act_m_get_state(thr_act=%x,flav=%x,st=%x,cnt@%x=%x)\n",
                    798:                current_act(), thr_act, flavor, tstate,
                    799:                count, (count ? *count : 0));
                    800: #endif /* MACH_ASSERT */
                    801: 
                    802:        switch (flavor)  {
                    803: 
                    804:            case i386_SAVED_STATE:
                    805:            {
                    806:                register struct i386_saved_state        *state;
                    807:                register struct i386_saved_state        *saved_state;
                    808: 
                    809:                if (*count < i386_SAVED_STATE_COUNT)
                    810:                    return(KERN_INVALID_ARGUMENT);
                    811: 
                    812:                state = (struct i386_saved_state *) tstate;
                    813:                saved_state = USER_REGS(thr_act);
                    814: 
                    815:                /*
                    816:                 * First, copy everything:
                    817:                 */
                    818:                *state = *saved_state;
                    819: 
                    820:                if (saved_state->efl & EFL_VM) {
                    821:                    /*
                    822:                     * V8086 mode.
                    823:                     */
                    824:                    state->ds = saved_state->v86_segs.v86_ds & 0xffff;
                    825:                    state->es = saved_state->v86_segs.v86_es & 0xffff;
                    826:                    state->fs = saved_state->v86_segs.v86_fs & 0xffff;
                    827:                    state->gs = saved_state->v86_segs.v86_gs & 0xffff;
                    828: 
                    829:                    if (thr_act->mact.pcb->ims.v86s.int_table) {
                    830:                        /*
                    831:                         * Hardware assist on
                    832:                         */
                    833:                        if ((thr_act->mact.pcb->ims.v86s.flags &
                    834:                                        (EFL_IF|V86_IF_PENDING)) == 0)
                    835:                            state->efl &= ~EFL_IF;
                    836:                    }
                    837:                }
                    838:                else {
                    839:                    /*
                    840:                     * 386 mode.
                    841:                     */
                    842:                    state->ds = saved_state->ds & 0xffff;
                    843:                    state->es = saved_state->es & 0xffff;
                    844:                    state->fs = saved_state->fs & 0xffff;
                    845:                    state->gs = saved_state->gs & 0xffff;
                    846:                }
                    847:                *count = i386_SAVED_STATE_COUNT;
                    848:                break;
                    849:            }
                    850: 
                    851:            case i386_NEW_THREAD_STATE:
                    852:            case i386_REGS_SEGS_STATE:
                    853:            {
                    854:                register struct i386_new_thread_state   *state;
                    855:                register struct i386_saved_state        *saved_state;
                    856: 
                    857:                if (*count < i386_NEW_THREAD_STATE_COUNT)
                    858:                    return(KERN_INVALID_ARGUMENT);
                    859: 
                    860:                state = (struct i386_new_thread_state *) tstate;
                    861:                saved_state = USER_REGS(thr_act);
                    862: 
                    863:                /*
                    864:                 * General registers.
                    865:                 */
                    866:                state->edi = saved_state->edi;
                    867:                state->esi = saved_state->esi;
                    868:                state->ebp = saved_state->ebp;
                    869:                state->ebx = saved_state->ebx;
                    870:                state->edx = saved_state->edx;
                    871:                state->ecx = saved_state->ecx;
                    872:                state->eax = saved_state->eax;
                    873:                state->eip = saved_state->eip;
                    874:                state->efl = saved_state->efl;
                    875:                state->uesp = saved_state->uesp;
                    876: 
                    877:                state->cs = saved_state->cs;
                    878:                state->ss = saved_state->ss;
                    879:                if (saved_state->efl & EFL_VM) {
                    880:                    /*
                    881:                     * V8086 mode.
                    882:                     */
                    883:                    state->ds = saved_state->v86_segs.v86_ds & 0xffff;
                    884:                    state->es = saved_state->v86_segs.v86_es & 0xffff;
                    885:                    state->fs = saved_state->v86_segs.v86_fs & 0xffff;
                    886:                    state->gs = saved_state->v86_segs.v86_gs & 0xffff;
                    887: 
                    888:                    if (thr_act->mact.pcb->ims.v86s.int_table) {
                    889:                        /*
                    890:                         * Hardware assist on
                    891:                         */
                    892:                        if ((thr_act->mact.pcb->ims.v86s.flags &
                    893:                                        (EFL_IF|V86_IF_PENDING)) == 0)
                    894:                            state->efl &= ~EFL_IF;
                    895:                    }
                    896:                }
                    897:                else {
                    898:                    /*
                    899:                     * 386 mode.
                    900:                     */
                    901:                    state->ds = saved_state->ds & 0xffff;
                    902:                    state->es = saved_state->es & 0xffff;
                    903:                    state->fs = saved_state->fs & 0xffff;
                    904:                    state->gs = saved_state->gs & 0xffff;
                    905:                }
                    906:                *count = i386_NEW_THREAD_STATE_COUNT;
                    907:                break;
                    908:            }
                    909: 
                    910:            case THREAD_SYSCALL_STATE:
                    911:            {
                    912:                register struct thread_syscall_state *state;
                    913:                register struct i386_saved_state *saved_state = USER_REGS(thr_act);
                    914: 
                    915:                state = (struct thread_syscall_state *) tstate;
                    916:                state->eax = saved_state->eax;
                    917:                state->edx = saved_state->edx;
                    918:                state->efl = saved_state->efl;
                    919:                state->eip = saved_state->eip;
                    920:                state->esp = saved_state->uesp;
                    921:                *count = i386_THREAD_SYSCALL_STATE_COUNT;
                    922:                break;
                    923:            }
                    924: 
                    925:            case THREAD_STATE_FLAVOR_LIST:
                    926:                if (*count < 5)
                    927:                    return (KERN_INVALID_ARGUMENT);
                    928:                tstate[0] = i386_NEW_THREAD_STATE;
                    929:                tstate[1] = i386_FLOAT_STATE;
                    930:                tstate[2] = i386_ISA_PORT_MAP_STATE;
                    931:                tstate[3] = i386_V86_ASSIST_STATE;
                    932:                tstate[4] = THREAD_SYSCALL_STATE;
                    933:                *count = 5;
                    934:                break;
                    935: 
                    936:            case i386_FLOAT_STATE: {
                    937: 
                    938:                if (*count < i386_FLOAT_STATE_COUNT)
                    939:                        return(KERN_INVALID_ARGUMENT);
                    940: 
                    941:                *count = i386_FLOAT_STATE_COUNT;
                    942:                return fpu_get_state(thr_act,(struct i386_float_state *)tstate);
                    943:            }
                    944: 
                    945:            /*
                    946:             * Temporary - replace by i386_io_map
                    947:             */
                    948:            case i386_ISA_PORT_MAP_STATE: {
                    949:                register struct i386_isa_port_map_state *state;
                    950:                register iopb_tss_t tss;
                    951: 
                    952:                if (*count < i386_ISA_PORT_MAP_STATE_COUNT)
                    953:                        return(KERN_INVALID_ARGUMENT);
                    954: 
                    955:                state = (struct i386_isa_port_map_state *) tstate;
                    956:                tss = thr_act->mact.pcb->ims.io_tss;
                    957: 
                    958:                if (tss == 0) {
                    959:                    int i;
                    960: 
                    961:                    /*
                    962:                     *  The thread has no ktss, so no IO permissions.
                    963:                     */
                    964: 
                    965:                    for (i = 0; i < sizeof state->pm; i++)
                    966:                        state->pm[i] = 0xff;
                    967:                } else {
                    968:                    /*
                    969:                     *  The thread has its own ktss.
                    970:                     */
                    971: 
                    972:                    bcopy((char *) tss->bitmap,
                    973:                          (char *) state->pm,
                    974:                          sizeof state->pm);
                    975:                }
                    976: 
                    977:                *count = i386_ISA_PORT_MAP_STATE_COUNT;
                    978:                break;
                    979:            }
                    980: 
                    981:            case i386_V86_ASSIST_STATE:
                    982:            {
                    983:                register struct i386_v86_assist_state *state;
                    984: 
                    985:                if (*count < i386_V86_ASSIST_STATE_COUNT)
                    986:                    return KERN_INVALID_ARGUMENT;
                    987: 
                    988:                state = (struct i386_v86_assist_state *) tstate;
                    989:                state->int_table = thr_act->mact.pcb->ims.v86s.int_table;
                    990:                state->int_count = thr_act->mact.pcb->ims.v86s.int_count;
                    991: 
                    992:                *count = i386_V86_ASSIST_STATE_COUNT;
                    993:                break;
                    994:            }
                    995: 
                    996:        case i386_THREAD_STATE: {
                    997:                struct i386_saved_state *saved_state;
                    998:                i386_thread_state_t     *state;
                    999: 
                   1000:                saved_state = USER_REGS(thr_act);
                   1001:                state = (i386_thread_state_t *)tstate;
                   1002: 
                   1003:                state->eax = saved_state->eax;
                   1004:                state->ebx = saved_state->ebx;
                   1005:                state->ecx = saved_state->ecx;
                   1006:                state->edx = saved_state->edx;
                   1007:                state->edi = saved_state->edi;
                   1008:                state->esi = saved_state->esi;
                   1009:                state->ebp = saved_state->ebp;
                   1010:                state->esp = saved_state->uesp;
                   1011:                state->eflags = saved_state->efl;
                   1012:                state->eip = saved_state->eip;
                   1013:                state->cs = saved_state->cs;
                   1014:                state->ss = saved_state->ss;
                   1015:                state->ds = saved_state->ds;
                   1016:                state->es = saved_state->es;
                   1017:                state->fs = saved_state->fs;
                   1018:                state->gs = saved_state->gs;
                   1019:                break;
                   1020:        }
                   1021: 
                   1022:            default:
                   1023:                return(KERN_INVALID_ARGUMENT);
                   1024:        }
                   1025: 
                   1026:        return(KERN_SUCCESS);
                   1027: }
                   1028: 
                   1029: /*
                   1030:  * Alter the thread`s state so that a following thread_exception_return
                   1031:  * will make the thread return 'retval' from a syscall.
                   1032:  */
                   1033: void
                   1034: thread_set_syscall_return(
                   1035:        thread_t        thread,
                   1036:        kern_return_t   retval)
                   1037: {
                   1038:        thread->top_act->mact.pcb->iss.eax = retval;
                   1039: }
                   1040: 
                   1041: /*
                   1042:  * Initialize the machine-dependent state for a new thread.
                   1043:  */
                   1044: kern_return_t
                   1045: thread_machine_create(thread_t thread, thread_act_t thr_act, void (*start_pos)(void))
                   1046: {
                   1047:         MachineThrAct_t mact = &thr_act->mact;
                   1048: 
                   1049: #if    MACH_ASSERT
                   1050:        if (watchacts & WA_PCB)
                   1051:                printf("thread_machine_create(thr=%x,thr_act=%x,st=%x)\n",
                   1052:                        thread, thr_act, start_pos);
                   1053: #endif /* MACH_ASSERT */
                   1054: 
                   1055:         assert(thread != NULL);
                   1056:         assert(thr_act != NULL);
                   1057: 
                   1058:         /*
                   1059:          *      Allocate a kernel stack per shuttle
                   1060:          */
                   1061:         thread->kernel_stack = (int)stack_alloc(thread,start_pos);
                   1062:         assert(thread->kernel_stack != 0);
                   1063: 
                   1064:         /*
                   1065:          *      Point top of kernel stack to user`s registers.
                   1066:          */
                   1067:         STACK_IEL(thread->kernel_stack)->saved_state = &mact->pcb->iss;
                   1068: 
                   1069:        /*
                   1070:         * Utah code fiddles with pcb here - (we don't need to)
                   1071:         */
                   1072:        return(KERN_SUCCESS);
                   1073: }
                   1074: 
                   1075: /*
                   1076:  * Machine-dependent cleanup prior to destroying a thread
                   1077:  */
                   1078: void
                   1079: thread_machine_destroy( thread_t thread )
                   1080: {
                   1081:         spl_t s;
                   1082: 
                   1083:         assert(thread->kernel_stack != 0);
                   1084: 
                   1085:         s = splsched();
                   1086:         stack_free(thread);
                   1087:         splx(s);
                   1088: }
                   1089: 
                   1090: /*
                   1091:  * This is used to set the current thr_act/thread
                   1092:  * when starting up a new processor
                   1093:  */
                   1094: void
                   1095: thread_machine_set_current( thread_t thread )
                   1096: {
                   1097:        register int    my_cpu;
                   1098: 
                   1099:        mp_disable_preemption();
                   1100:        my_cpu = cpu_number();
                   1101: 
                   1102:         cpu_data[my_cpu].active_thread = thread;
                   1103:        active_kloaded[my_cpu] =
                   1104:                thread->top_act->kernel_loaded ? thread->top_act : THR_ACT_NULL;
                   1105: 
                   1106:        mp_enable_preemption();
                   1107: }
                   1108: 
                   1109: 
                   1110: /*
                   1111:  * Pool of kernel activations.
                   1112:  */
                   1113: 
                   1114: void act_machine_init()
                   1115: {
                   1116:        int i;
                   1117:        thread_act_t thr_act;
                   1118: 
                   1119: #if    MACH_ASSERT
                   1120:        if (watchacts & WA_PCB)
                   1121:                printf("act_machine_init()\n");
                   1122: #endif /* MACH_ASSERT */
                   1123: 
                   1124:        /* Good to verify this once */
                   1125:        assert( THREAD_MACHINE_STATE_MAX <= THREAD_STATE_MAX );
                   1126: 
                   1127:        /*
                   1128:         * If we start using kernel activations,
                   1129:         * would normally create kernel_thread_pool here,
                   1130:         * populating it from the act_zone
                   1131:         */
                   1132: }
                   1133: 
                   1134: kern_return_t
                   1135: act_machine_create(task_t task, thread_act_t thr_act)
                   1136: {
                   1137:        MachineThrAct_t mact = &thr_act->mact;
                   1138:        pcb_t pcb;
                   1139: 
                   1140: #if    MACH_ASSERT
                   1141:        if (watchacts & WA_PCB)
                   1142:                printf("act_machine_create(task=%x,thr_act=%x) pcb=%x\n",
                   1143:                        task,thr_act, &mact->xxx_pcb);
                   1144: #endif /* MACH_ASSERT */
                   1145: 
                   1146:        /*
                   1147:         * Clear & Init the pcb  (sets up user-mode s regs)
                   1148:         */
                   1149:        pcb_init(thr_act);
                   1150: 
                   1151:        return KERN_SUCCESS;
                   1152: }
                   1153: 
                   1154: void
                   1155: act_machine_destroy(thread_act_t thr_act)
                   1156: {
                   1157: 
                   1158: #if    MACH_ASSERT
                   1159:        if (watchacts & WA_PCB)
                   1160:                printf("act_machine_destroy(0x%x)\n", thr_act);
                   1161: #endif /* MACH_ASSERT */
                   1162: 
                   1163:        pcb_terminate(thr_act);
                   1164: }
                   1165: 
                   1166: void
                   1167: act_machine_return(int code)
                   1168: {
                   1169:        thread_act_t    thr_act = current_act();
                   1170:        thread_act_t    cur_act;
                   1171:        thread_t        cur_thread = current_thread();
                   1172:        vm_offset_t     pcb_stack;
                   1173:        unsigned int    uesp, ueip;
                   1174:        struct ipc_port *iplock;
                   1175: 
                   1176: #if    MACH_ASSERT
                   1177:        /*
                   1178:        * We don't go through the locking dance here needed to
                   1179:        * acquire thr_act->thread safely.
                   1180:        */
                   1181: 
                   1182:        if (watchacts & WA_EXIT)
                   1183:                printf("act_machine_return(0x%x) cur_act=%x(%d) thr=%x(%d)\n",
                   1184:                        code, thr_act, thr_act->ref_count,
                   1185:                        thr_act->thread, thr_act->thread
                   1186:                                        ? thr_act->thread->ref_count : 0);
                   1187: #endif /* MACH_ASSERT */
                   1188: 
                   1189:        /*
                   1190:         * This code is called with nothing locked.
                   1191:         * It also returns with nothing locked, if it returns.
                   1192:         *
                   1193:         * This routine terminates the current thread activation.
                   1194:         * If this is the only activation associated with its
                   1195:         * thread shuttle, then the entire thread (shuttle plus
                   1196:         * activation) is terminated.
                   1197:         */
                   1198:        assert( code == KERN_TERMINATED );
                   1199:        assert( thr_act );
                   1200: 
                   1201: #ifdef CALLOUT_RPC_MODEL
                   1202: 
                   1203:        /*
                   1204:         * JMM - RPC is not going to be done with a callout/direct-
                   1205:         * stack manipulation mechanism.  Instead we will return/
                   1206:         * unwind normally as if from a continuation.
                   1207:         */
                   1208:        act_lock_thread(thr_act);
                   1209:        iplock = thr_act->pool_port;    /* remember for unlock call */
                   1210: 
                   1211:        if (thr_act->thread->top_act != thr_act) {
                   1212:                /*
                   1213:                 * this is not the top activation;
                   1214:                 * if possible, we should clone the shuttle so that
                   1215:                 * both the root RPC-chain and the soon-to-be-orphaned
                   1216:                 * RPC-chain have shuttles
                   1217:                 *
                   1218:                 * JMM - Cloning shuttles isn't the right approach.  We
                   1219:                 * need to alert the higher up activations to return our
                   1220:                 * shuttle (because scheduling attributes may TRUELY be
                   1221:                 * unique and not cloneable.
                   1222:                 */
                   1223:                act_unlock_thread(thr_act);
                   1224:                panic("act_machine_return: ORPHAN CASE NOT YET IMPLEMENTED");
                   1225:        }
                   1226: 
                   1227:        if (thr_act->lower != THR_ACT_NULL) {
                   1228:                /* send it an appropriate return code */
                   1229:                thr_act->lower->alerts |= SERVER_TERMINATED;
                   1230:                install_special_handler(thr_act->lower);
                   1231: 
                   1232:                /* Return to previous act with error code */
                   1233:                act_locked_act_reference(thr_act);      /* keep it around */
                   1234:                act_switch_swapcheck(cur_thread, (ipc_port_t)0);
                   1235:                (void) switch_act(THR_ACT_NULL);
                   1236:                /* assert(thr_act->ref_count == 0); */          /* XXX */
                   1237:                cur_act = cur_thread->top_act;
                   1238:                MACH_RPC_RET(cur_act) = KERN_RPC_SERVER_TERMINATED;         
                   1239:             
                   1240:                machine_kernel_stack_init(cur_thread, 
                   1241:                                          (void (*)(void)) mach_rpc_return_error);
                   1242:                /*
                   1243:                 * The following unlocks must be done separately since fields 
                   1244:                 * used by `act_unlock_thread()' have been cleared, meaning
                   1245:                 * that it would not release all of the appropriate locks.
                   1246:                 */
                   1247:                rpc_unlock(cur_thread);
                   1248:                if (iplock) ip_unlock(iplock);  /* must be done separately */
                   1249:                act_unlock(thr_act);
                   1250:                act_deallocate(thr_act);                /* free it */
                   1251:                Load_context(cur_thread);
                   1252:                /*NOTREACHED*/
                   1253: 
                   1254:                panic("act_machine_return: TALKING ZOMBIE! (2)");
                   1255:        }
                   1256:        act_unlock_thread(thr_act);
                   1257: 
                   1258: #endif /* CALLOUT_RPC_MODEL */
                   1259: 
                   1260:        /* This is the only activation attached to the shuttle... */
                   1261:        /* terminate the entire thread (shuttle plus activation) */
                   1262: 
                   1263:        assert(thr_act->thread->top_act == thr_act);
                   1264:        thread_terminate_self();
                   1265: 
                   1266:        /*NOTREACHED*/
                   1267: 
                   1268:        panic("act_machine_return: TALKING ZOMBIE! (1)");
                   1269: }
                   1270: 
                   1271: 
                   1272: /*
                   1273:  * Perform machine-dependent per-thread initializations
                   1274:  */
                   1275: void
                   1276: thread_machine_init(void)
                   1277: {
                   1278:        pcb_module_init();
                   1279: }
                   1280: 
                   1281: /*
                   1282:  * Some routines for debugging activation code
                   1283:  */
                   1284: static void    dump_handlers(thread_act_t);
                   1285: void   dump_regs(thread_act_t);
                   1286: 
                   1287: static void
                   1288: dump_handlers(thread_act_t thr_act)
                   1289: {
                   1290:     ReturnHandler *rhp = thr_act->handlers;
                   1291:     int        counter = 0;
                   1292: 
                   1293:     printf("\t");
                   1294:     while (rhp) {
                   1295:        if (rhp == &thr_act->special_handler){
                   1296:            if (rhp->next)
                   1297:                printf("[NON-Zero next ptr(%x)]", rhp->next);
                   1298:            printf("special_handler()->");
                   1299:            break;
                   1300:        }
                   1301:        printf("hdlr_%d(%x)->",counter,rhp->handler);
                   1302:        rhp = rhp->next;
                   1303:        if (++counter > 32) {
                   1304:                printf("Aborting: HUGE handler chain\n");
                   1305:                break;
                   1306:        }
                   1307:     }
                   1308:     printf("HLDR_NULL\n");
                   1309: }
                   1310: 
                   1311: void
                   1312: dump_regs(thread_act_t thr_act)
                   1313: {
                   1314:        if (thr_act->mact.pcb) {
                   1315:                register struct i386_saved_state *ssp = USER_REGS(thr_act);
                   1316:                /* Print out user register state */
                   1317:                printf("\tRegs:\tedi=%x esi=%x ebp=%x ebx=%x edx=%x\n",
                   1318:                    ssp->edi, ssp->esi, ssp->ebp, ssp->ebx, ssp->edx);
                   1319:                printf("\t\tecx=%x eax=%x eip=%x efl=%x uesp=%x\n",
                   1320:                    ssp->ecx, ssp->eax, ssp->eip, ssp->efl, ssp->uesp);
                   1321:                printf("\t\tcs=%x ss=%x\n", ssp->cs, ssp->ss);
                   1322:        }
                   1323: }
                   1324: 
                   1325: int
                   1326: dump_act(thread_act_t thr_act)
                   1327: {
                   1328:        if (!thr_act)
                   1329:                return(0);
                   1330: 
                   1331:        printf("thr_act(0x%x)(%d): thread=%x(%d) task=%x(%d)\n",
                   1332:               thr_act, thr_act->ref_count,
                   1333:               thr_act->thread, thr_act->thread ? thr_act->thread->ref_count:0,
                   1334:               thr_act->task,   thr_act->task   ? thr_act->task->ref_count : 0);
                   1335: 
                   1336:        if (thr_act->pool_port) {
                   1337:            thread_pool_t actpp = &thr_act->pool_port->ip_thread_pool;
                   1338:            printf("\tpool(acts_p=%x, waiting=%d) pool_next %x\n",
                   1339:                actpp->thr_acts, actpp->waiting, thr_act->thread_pool_next);
                   1340:        }else
                   1341:            printf("\tno thread_pool\n");
                   1342: 
                   1343:        printf("\talerts=%x mask=%x susp=%d user_stop=%d active=%x ast=%x\n",
                   1344:                       thr_act->alerts, thr_act->alert_mask,
                   1345:                       thr_act->suspend_count, thr_act->user_stop_count,
                   1346:                       thr_act->active, thr_act->ast);
                   1347:        printf("\thi=%x lo=%x\n", thr_act->higher, thr_act->lower);
                   1348:        printf("\tpcb=%x, ustk=%x\n",
                   1349:                       thr_act->mact.pcb, thr_act->user_stack);
                   1350: 
                   1351:        if (thr_act->thread && thr_act->thread->kernel_stack) {
                   1352:            vm_offset_t stack = thr_act->thread->kernel_stack;
                   1353: 
                   1354:            printf("\tk_stk %x  eip %x ebx %x esp %x iss %x\n",
                   1355:                stack, STACK_IKS(stack)->k_eip, STACK_IKS(stack)->k_ebx,
                   1356:                STACK_IKS(stack)->k_esp, STACK_IEL(stack)->saved_state);
                   1357:        }
                   1358: 
                   1359:        dump_handlers(thr_act);
                   1360:        dump_regs(thr_act);
                   1361:        return((int)thr_act);
                   1362: }
                   1363: unsigned int
                   1364: get_useraddr()
                   1365: {
                   1366:   
                   1367:         thread_act_t thr_act = current_act();
                   1368:  
                   1369:        if (thr_act->mact.pcb) 
                   1370:                return(thr_act->mact.pcb->iss.eip);
                   1371:        else 
                   1372:                return(0);
                   1373: 
                   1374: }
                   1375: 
                   1376: void
                   1377: thread_swapin_mach_alloc(thread_t thread)
                   1378: {
                   1379: 
                   1380:   /* 386 does not have saveareas */
                   1381: 
                   1382: }
                   1383: /*
                   1384:  * detach and return a kernel stack from a thread
                   1385:  */
                   1386: 
                   1387: vm_offset_t
                   1388: stack_detach(thread_t thread)
                   1389: {
                   1390:   vm_offset_t stack;
                   1391: 
                   1392: #ifdef KDEBUG
                   1393:                KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_DETACH),
                   1394:                        thread, thread->priority,
                   1395:                        thread->sched_pri, 0,
                   1396:                        0);
                   1397: #endif
                   1398: 
                   1399:   stack = thread->kernel_stack;
                   1400:   thread->kernel_stack = 0;
                   1401:   return(stack);
                   1402: }
                   1403: 
                   1404: /*
                   1405:  * attach a kernel stack to a thread and initialize it
                   1406:  */
                   1407: 
                   1408: void
                   1409: stack_attach(struct thread_shuttle *thread,
                   1410:             vm_offset_t stack,
                   1411:             void (*continuation)(void))
                   1412: {
                   1413:   struct i386_kernel_state *statep;
                   1414:   thread_act_t thr_act;
                   1415: 
                   1416: #ifdef KDEBUG
                   1417:                KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_ATTACH),
                   1418:                        thread, thread->priority,
                   1419:                        thread->sched_pri, continuation, 
                   1420:                        0);
                   1421: #endif
                   1422: 
                   1423:   assert(stack);
                   1424:   statep = STACK_IKS(stack);
                   1425:   thread->kernel_stack = stack;
                   1426: 
                   1427:   statep->k_eip = (unsigned long) Thread_continue;
                   1428:   statep->k_ebx = (unsigned long) continuation;
                   1429:   statep->k_esp = (unsigned long) STACK_IEL(stack);
                   1430: 
                   1431:   STACK_IEL(stack)->saved_state = &thr_act->mact.pcb->iss;
                   1432: 
                   1433:   return;
                   1434: }
                   1435: 
                   1436: /*
                   1437:  * move a stack from old to new thread
                   1438:  */
                   1439: 
                   1440: void
                   1441: stack_handoff(thread_t old,
                   1442:              thread_t new)
                   1443: {
                   1444: 
                   1445:   vm_offset_t stack;
                   1446:   pmap_t new_pmap;
                   1447: 
                   1448: #ifdef KDEBUG
                   1449:                KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_HANDOFF),
                   1450:                        thread, thread->priority,
                   1451:                        thread->sched_pri, continuation, 
                   1452:                        0);
                   1453: #endif
                   1454: 
                   1455:   assert(new->top_act);
                   1456:   assert(old->top_act);
                   1457: 
                   1458:   stack = stack_detach(old);
                   1459:   stack_attach(new, stack, 0);
                   1460: 
                   1461:   new_pmap = new->top_act->task->map->pmap;
                   1462:   if (old->top_act->task->map->pmap != new_pmap)
                   1463:        PMAP_ACTIVATE_MAP(new->top_act->task->map, cpu_number());
                   1464: 
                   1465:   thread_machine_set_current(new);
                   1466: 
                   1467:   active_stacks[cpu_number()] = new->kernel_stack;
                   1468: 
                   1469:   return;
                   1470: }

unix.superglobalmegacorp.com

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