Annotation of XNU/osfmk/i386/pcb.c, revision 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.