Annotation of XNU/osfmk/ppc/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:  * Copyright (c) 1990,1991,1992 The University of Utah and
                     27:  * the Center for Software Science (CSS).  All rights reserved.
                     28:  *
                     29:  * Permission to use, copy, modify and distribute this software is hereby
                     30:  * granted provided that (1) source code retains these copyright, permission,
                     31:  * and disclaimer notices, and (2) redistributions including binaries
                     32:  * reproduce the notices in supporting documentation, and (3) all advertising
                     33:  * materials mentioning features or use of this software display the following
                     34:  * acknowledgement: ``This product includes software developed by the Center
                     35:  * for Software Science at the University of Utah.''
                     36:  *
                     37:  * THE UNIVERSITY OF UTAH AND CSS ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
                     38:  * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSS DISCLAIM ANY LIABILITY OF
                     39:  * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     40:  *
                     41:  * CSS requests users of this software to return to [email protected] any
                     42:  * improvements that they make and grant CSS redistribution rights.
                     43:  *
                     44:  *     Utah $Hdr: pcb.c 1.23 92/06/27$
                     45:  */
                     46: 
                     47: #include <cpus.h>
                     48: #include <debug.h>
                     49: 
                     50: #include <types.h>
                     51: #include <kern/task.h>
                     52: #include <kern/thread.h>
                     53: #include <kern/thread_act.h>
                     54: #include <kern/thread_swap.h>
                     55: #include <mach/thread_status.h>
                     56: #include <vm/vm_kern.h>
                     57: #include <kern/mach_param.h>
                     58: 
                     59: #include <kern/misc_protos.h>
                     60: #include <ppc/misc_protos.h>
                     61: #include <ppc/fpu_protos.h>
                     62: #include <ppc/exception.h>
                     63: #include <ppc/proc_reg.h>
                     64: #include <kern/spl.h>
                     65: #include <ppc/pmap.h>
                     66: #include <ppc/trap.h>
                     67: #include <ppc/mappings.h>
                     68: #include <ppc/savearea.h>
                     69: #include <ppc/Firmware.h>
                     70: #include <ppc/asm.h>
                     71: #include <ppc/thread_act.h>
                     72: 
                     73: #include <sys/kdebug.h>
                     74: 
                     75: extern int             real_ncpus;                                             /* Number of actual CPUs */
                     76: extern struct  Saveanchor saveanchor;                  /* Aliged savearea anchor */
                     77: 
                     78: /*
                     79:  * These constants are dumb. They should not be in asm.h!
                     80:  */
                     81: 
                     82: #define KF_SIZE                (FM_SIZE+ARG_SIZE+FM_REDZONE)
                     83: 
                     84: #if DEBUG
                     85: int   fpu_trap_count = 0;
                     86: int   fpu_switch_count = 0;
                     87: int   vec_trap_count = 0;
                     88: int   vec_switch_count = 0;
                     89: #endif
                     90: 
                     91: extern struct thread_shuttle   *Switch_context(
                     92:                                        struct thread_shuttle   *old,
                     93:                                        void                    (*cont)(void),
                     94:                                        struct thread_shuttle   *new);
                     95: 
                     96: 
                     97: #if    MACH_LDEBUG || MACH_KDB
                     98: void           log_thread_action (char *, long, long, long);
                     99: #endif
                    100: 
                    101: 
                    102: /*
                    103:  * consider_machine_collect: try to collect machine-dependent pages
                    104:  */
                    105: void
                    106: consider_machine_collect()
                    107: {
                    108:     /*
                    109:      * none currently available
                    110:      */
                    111:        return;
                    112: }
                    113: 
                    114: /*
                    115:  * stack_attach: Attach a kernel stack to a thread.
                    116:  */
                    117: void
                    118: machine_kernel_stack_init(
                    119:        struct thread_shuttle *thread,
                    120:        void            (*continuation)(void))
                    121: {
                    122:     vm_offset_t        stack;
                    123:     unsigned int                       *kss;
                    124:        struct savearea                 *sv;
                    125: 
                    126:     assert(thread->top_act->mact.pcb);
                    127:     assert(thread->kernel_stack);
                    128:     stack = thread->kernel_stack;
                    129: 
                    130: #if    MACH_ASSERT
                    131:     if (watchacts & WA_PCB)
                    132:                printf("machine_kernel_stack_init(thr=%x,stk=%x,cont=%x)\n", thread,stack,continuation);
                    133: #endif /* MACH_ASSERT */
                    134:        
                    135:        kss = (unsigned int *)STACK_IKS(stack);
                    136:        sv=(savearea *)(thread->top_act->mact.pcb);                     /* This for the sake of C */
                    137: 
                    138:     sv->save_lr = (unsigned int) continuation;                 /* Set up the execution address */
                    139:     sv->save_srr0 = (unsigned int) continuation;               /* Here too */
                    140:        sv->save_srr1 = MSR_SUPERVISOR_INT_ON;                          /* Set the normal running MSR */
                    141:     sv->save_r1 = (vm_offset_t) ((int)kss - KF_SIZE);  /* Point to the top frame on the stack */
                    142: 
                    143:     *((int *)sv->save_r1) = 0;                                                 /* Zero the frame backpointer */
                    144:        thread->top_act->mact.ksp = 0;                                          /* Show that the kernel stack is in use already */
                    145: 
                    146: }
                    147: 
                    148: /*
                    149:  * switch_context: Switch from one thread to another, needed for
                    150:  *                switching of space
                    151:  * 
                    152:  */
                    153: struct thread_shuttle*
                    154: switch_context(
                    155:        struct thread_shuttle *old,
                    156:        void (*continuation)(void),
                    157:        struct thread_shuttle *new)
                    158: {
                    159:        register thread_act_t old_act = old->top_act, new_act = new->top_act;
                    160:        register struct thread_shuttle* retval;
                    161:        pmap_t  new_pmap;
                    162: #if    MACH_LDEBUG || MACH_KDB
                    163:        log_thread_action("switch", 
                    164:                          (long)old, 
                    165:                          (long)new, 
                    166:                          (long)__builtin_return_address(0));
                    167: #endif
                    168:        assert(old_act->kernel_loaded ||
                    169:               active_stacks[cpu_number()] == old_act->thread->kernel_stack);
                    170:        assert (get_preemption_level() == 1);
                    171:        check_simple_locks();
                    172: 
                    173:        /* Our context might wake up on another processor, so we must
                    174:         * not keep hot state in our FPU, it must go back to the pcb
                    175:         * so that it can be found by the other if needed
                    176:         */
                    177:        if(real_ncpus > 1) {    /* This is potentially slow, so only do when actually SMP */
                    178:                fpu_save();                     /* Save floating point if used */
                    179:                vec_save();                     /* Save vector if used */
                    180:        }
                    181: 
                    182: #if DEBUG
                    183:        if (watchacts & WA_PCB) {
                    184:                printf("switch_context(0x%08x, 0x%x, 0x%08x)\n",
                    185:                       old,continuation,new);
                    186:        }
                    187: #endif /* DEBUG */
                    188: 
                    189:        /*
                    190:         * We do not have to worry about the PMAP module, so switch.
                    191:         *
                    192:         * We must not use top_act->map since this may not be the actual
                    193:         * task map, but the map being used for a klcopyin/out.
                    194:         */
                    195: 
                    196:        new_pmap = new_act->task->map->pmap;
                    197:        if (old_act->task->map->pmap != new_pmap) {
                    198:                pmap_switch(new_pmap);
                    199:        }
                    200: 
                    201:        /* Sanity check - is the stack pointer inside the stack that
                    202:         * we're about to switch to? Is the execution address within
                    203:         * the kernel's VM space??
                    204:         */
                    205: #if 0
                    206:        printf("************* stack=%08X; R1=%08X; LR=%08X; old=%08X; cont=%08X; new=%08X\n",
                    207:                new->kernel_stack, new_act->mact.pcb->ss.r1,
                    208:                new_act->mact.pcb->ss.lr, old, continuation, new);      /* (TEST/DEBUG) */
                    209:        assert((new->kernel_stack < new_act->mact.pcb->ss.r1) &&
                    210:               ((unsigned int)STACK_IKS(new->kernel_stack) >
                    211:                new_act->mact.pcb->ss.r1));
                    212:        assert(new_act->mact.pcb->ss.lr < VM_MAX_KERNEL_ADDRESS);
                    213: #endif
                    214: 
                    215: 
                    216:        KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED) | DBG_FUNC_NONE,
                    217:                     (int)old, (int)new, old->sched_pri, new->sched_pri, 0);
                    218: 
                    219: 
                    220:        retval = Switch_context(old, continuation, new);
                    221:        assert(retval != (struct thread_shuttle*)NULL);
                    222: 
                    223:        /* We've returned from having switched context, so we should be
                    224:         * back in the original context.
                    225:         */
                    226: 
                    227:        return retval;
                    228: }
                    229: 
                    230: /*
                    231:  * Alter the thread's state so that a following thread_exception_return
                    232:  * will make the thread return 'retval' from a syscall.
                    233:  */
                    234: void
                    235: thread_set_syscall_return(
                    236:        struct thread_shuttle *thread,
                    237:        kern_return_t   retval)
                    238: {
                    239:        struct ppc_saved_state *ssp = &thread->top_act->mact.pcb->ss;
                    240: 
                    241: #if    MACH_ASSERT
                    242:        if (watchacts & WA_PCB)
                    243:                printf("thread_set_syscall_return(thr=%x,retval=%d)\n", thread,retval);
                    244: #endif /* MACH_ASSERT */
                    245: 
                    246:         ssp->r3 = retval;
                    247: }
                    248: 
                    249: /*
                    250:  * Initialize the machine-dependent state for a new thread.
                    251:  */
                    252: kern_return_t
                    253: thread_machine_create(
                    254:                      struct thread_shuttle *thread,
                    255:                      thread_act_t thr_act,
                    256:                      void (*start_pos)(void))
                    257: {
                    258: 
                    259:        savearea                *sv;                                                                    /* Pointer to newly allocated savearea */
                    260:        unsigned int    *CIsTooLimited, i;
                    261: 
                    262: 
                    263: #if    MACH_ASSERT
                    264:     if (watchacts & WA_PCB)
                    265:        printf("thread_machine_create(thr=%x,thr_act=%x,st=%x)\n", thread, thr_act, start_pos);
                    266: #endif /* MACH_ASSERT */
                    267: 
                    268:        hw_atomic_add(&saveanchor.saveneed, 4);                                 /* Account for the number of saveareas we think we "need"
                    269:                                                                                                                           for this activation */
                    270:        assert(thr_act->mact.pcb == (pcb_t)0);                                  /* Make sure there was no previous savearea */
                    271:        
                    272:        sv = save_alloc();                                                                              /* Go get us a savearea */
                    273:                
                    274:        bzero((char *) sv, sizeof(struct pcb));                                 /* Clear out the whole shebang */
                    275:        
                    276:        sv->save_act = thr_act;                                                                 /* Set who owns it */
                    277:        /* XXX: TO BE REMOVED WA for AltiVec compiler bug */
                    278:        sv->save_vrsave = 0xffffffff;
                    279:        thr_act->mact.pcb = (pcb_t)sv;                                                  /* Point to the save area */
                    280: 
                    281:     thread->kernel_stack = (int)stack_alloc(thread,start_pos);                         /* Allocate our kernel stack */
                    282:     assert(thread->kernel_stack);                                                      /* Make sure we got it */
                    283: 
                    284: #if    MACH_ASSERT
                    285:        if (watchacts & WA_PCB)
                    286:                printf("pcb_init(%x) pcb=%x\n", thr_act, sv);
                    287: #endif /* MACH_ASSERT */
                    288:        /*
                    289:         * User threads will pull their context from the pcb when first
                    290:         * returning to user mode, so fill in all the necessary values.
                    291:         * Kernel threads are initialized from the save state structure 
                    292:         * at the base of the kernel stack (see stack_attach()).
                    293:         */
                    294: 
                    295:        sv->save_srr1 = MSR_EXPORT_MASK_SET;                                    /* Set the default user MSR */
                    296:        
                    297:        CIsTooLimited = (unsigned int *)(&sv->save_sr0);                        /* Make a pointer 'cause C can't cast on the left */
                    298:        for(i=0; i<16; i++) {                                                                   /* Initialize all SRs */
                    299:                CIsTooLimited[i] = SEG_REG_PROT | (i << 20) | thr_act->task->map->pmap->space;  /* Set the SR value */
                    300:        }
                    301:        sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | thr_act->task->map->pmap->space;      /* Default the copyin */
                    302: 
                    303:     return(KERN_SUCCESS);
                    304: }
                    305: 
                    306: /*
                    307:  * Machine-dependent cleanup prior to destroying a thread
                    308:  */
                    309: void
                    310: thread_machine_destroy( thread_t thread )
                    311: {
                    312:        spl_t s;
                    313: 
                    314:        assert(thread->kernel_stack);
                    315:        s = splsched();
                    316:        stack_free(thread);
                    317:        splx(s);
                    318: }
                    319: 
                    320: /*
                    321:  * flush out any lazily evaluated HW state in the
                    322:  * owning thread's context, before termination.
                    323:  */
                    324: void
                    325: thread_machine_flush( thread_act_t cur_act )
                    326: {
                    327: }
                    328: 
                    329: /*
                    330:  * Number of times we needed to swap an activation back in before
                    331:  * switching to it.
                    332:  */
                    333: int switch_act_swapins = 0;
                    334: 
                    335: /*
                    336:  * machine_switch_act
                    337:  *
                    338:  * Machine-dependent details of activation switching.  Called with
                    339:  * RPC locks held and preemption disabled.
                    340:  */
                    341: void
                    342: machine_switch_act( 
                    343:        thread_t        thread,
                    344:        thread_act_t    old,
                    345:        thread_act_t    new,
                    346:        int                             cpu)
                    347: {
                    348:        pmap_t          new_pmap;
                    349: 
                    350:        /* Our context might wake up on another processor, so we must
                    351:         * not keep hot state in our FPU, it must go back to the pcb
                    352:         * so that it can be found by the other if needed
                    353:         */
                    354:        if(real_ncpus > 1) {    /* This is potentially slow, so only do when actually SMP */
                    355:                fpu_save();                     /* Save floating point if used */
                    356:                vec_save();                     /* Save vector if used */
                    357:        }
                    358: 
                    359:        active_stacks[cpu] = thread->kernel_stack;
                    360: 
                    361:        ast_context(new, cpu);
                    362: 
                    363:        /* Activations might have different pmaps 
                    364:         * (process->kernel->server, for example).
                    365:         * Change space if needed
                    366:         */
                    367:        new_pmap = new->task->map->pmap;
                    368:        if (old->task->map->pmap != new_pmap) {
                    369:                pmap_switch(new_pmap);
                    370:        }
                    371: }
                    372: 
                    373: void
                    374: pcb_user_to_kernel(thread_act_t act)
                    375: {
                    376: 
                    377:        return;                                                                                                 /* Not needed, I hope... */
                    378: }
                    379: 
                    380: 
                    381: /*
                    382:  * act_machine_sv_free
                    383:  * release saveareas associated with an act. if flag is true, release
                    384:  * user level savearea(s) too, else don't
                    385:  *
                    386:  * this code cannot block so we call the proper save area free routine
                    387:  */
                    388: void
                    389: act_machine_sv_free(thread_act_t act)
                    390: {
                    391:        register pcb_t pcb,userpcb,npcb;
                    392:        register savearea *svp;
                    393:        register int i;
                    394: 
                    395: /*
                    396:  *     This next bit insures that any live facility context for this thread is discarded on every processor
                    397:  *     that may have it.  We go through all per-processor blocks and zero the facility owner if
                    398:  *     it is the thread being destroyed. This needs to be done via a compare-and-swap because
                    399:  *     some other processor could change the owner while we are clearing it. It turns out that 
                    400:  *     this is the only place where we need the interlock, normal use of the owner field is cpu-local
                    401:  *     and doesn't need the interlock. Because we are called during termintation, and a thread
                    402:  *     terminates itself, the context on other processors has been saved (because we save it as
                    403:  *     part of the context switch), even if it is still considered live. Since the dead thread is 
                    404:  *     not running elsewhere, and the context is saved, any other processor looking at the owner
                    405:  *     field will not attempt to save context again, meaning that it doesn't matter if the owner
                    406:  *     changes out from under it.
                    407:  */
                    408:  
                    409:        /* 
                    410:         * free VMX and FPU saveareas.  do not free user save areas.
                    411:      * user VMX and FPU saveareas, if any, i'm told are last in
                    412:      * the chain so we just stop if we find them
                    413:         * we identify user VMX and FPU saveareas when we find a pcb
                    414:         * with a save level of 0.  we identify user regular save
                    415:         * areas when we find one with MSR_PR set
                    416:         */
                    417: 
                    418:        pcb = act->mact.VMX_pcb;                                                                /* Get the top vector savearea */
                    419:        while(pcb) {                                                                                    /* Any VMX saved state? */
                    420:                svp = (savearea *)pcb;                                                          /* save lots of casting later */
                    421:                if (svp->save_level_vec == 0) break;   /* done when hit user if any */
                    422:                pcb = (pcb_t)svp->save_prev_vector;                             /* Get one underneath our's */          
                    423:                svp->save_flags &= ~SAVvmxvalid;                                                /* Clear the VMX flag */
                    424:                if(!(svp->save_flags & SAVinuse)) {                                     /* Anyone left with this one? */                        
                    425: 
                    426:                                save_ret(svp);                          /* release it */
                    427:                }
                    428:        }
                    429:        act->mact.VMX_pcb = pcb;
                    430:        if (act->mact.VMX_lvl != 0) {
                    431:          for(i=0; i < real_ncpus; i++) {                                                       /* Cycle through processors */
                    432:                (void)hw_compare_and_store((unsigned int)act, 0, &per_proc_info[i].VMX_thread); /* Clear if ours */
                    433:          }
                    434:        }
                    435: 
                    436:        pcb = act->mact.FPU_pcb;                                                                /* Get the top floating point savearea */
                    437:        while(pcb) {                                                                                    /* Any floating point saved state? */
                    438:                svp = (savearea *)pcb;
                    439:                if (svp->save_level_fp == 0) break;     /* done when hit user if any */
                    440:                pcb = (pcb_t)svp->save_prev_float;                                      /* Get one underneath our's */          
                    441:                svp->save_flags &= ~SAVfpuvalid;                                                /* Clear the floating point flag */
                    442:                if(!(svp->save_flags & SAVinuse)) {                                     /* Anyone left with this one? */                        
                    443:                                save_ret(svp);                                                  /* Nope, release it */
                    444:                }
                    445:        }
                    446:        act->mact.FPU_pcb = pcb;
                    447:        if (act->mact.FPU_lvl != 0) {
                    448:          for(i=0; i < real_ncpus; i++) {                                                       /* Cycle through processors */
                    449:                (void)hw_compare_and_store((unsigned int)act, 0, &per_proc_info[i].FPU_thread); /* Clear if ours */
                    450:          }
                    451:        }
                    452: 
                    453:        /*
                    454:         * free all regular saveareas except a user savearea, if any
                    455:         */
                    456: 
                    457:        pcb = act->mact.pcb;
                    458:        userpcb = (pcb_t)0;
                    459:        while(pcb) {
                    460:          svp = (savearea *)pcb;
                    461:          if ((svp->save_srr1 & MASK(MSR_PR))) {
                    462:                assert(userpcb == (pcb_t)0);
                    463:                userpcb = pcb;
                    464:                svp = (savearea *)userpcb;
                    465:                npcb = (pcb_t)svp->save_prev;
                    466:                svp->save_prev = (struct savearea *)0;
                    467:          } else {
                    468:                svp->save_flags = 0;
                    469:                npcb = (pcb_t)svp->save_prev;
                    470:                save_ret(svp);
                    471:          }
                    472:          pcb = npcb;
                    473:        }
                    474:        act->mact.pcb = userpcb;
                    475: 
                    476: }
                    477: 
                    478: /*
                    479:  * act_machine_destroy: Shutdown any state associated with a thread pcb.
                    480:  */
                    481: void
                    482: act_machine_destroy(thread_act_t act)
                    483: {
                    484:        register pcb_t  pcb, opcb;
                    485:        int i;
                    486: 
                    487: #if    MACH_ASSERT
                    488:        if (watchacts & WA_PCB)
                    489:                printf("act_machine_destroy(0x%x)\n", act);
                    490: #endif /* MACH_ASSERT */
                    491:        
                    492:        if(act->mact.bbDescAddr) {                                                              /* Check if the Blue box assist is active */
                    493:                (void) vm_map_unwire(act->map,                                          /* Unwire the descriptor in user's address space */
                    494:                        (vm_offset_t)act->mact.bbUserDA,
                    495:                        (vm_offset_t)act->mact.bbUserDA + PAGE_SIZE,
                    496:                        FALSE);
                    497:                
                    498:                kmem_free(kernel_map, (vm_offset_t)act->mact.bbDescAddr, PAGE_SIZE);    /* Release the page */
                    499:                
                    500:                act->mact.bbDescAddr = 0;                                                       /* Clear kernel pointer to it */
                    501:                act->mact.bbUserDA = 0;                                                         /* Clear user pointer to it */
                    502:                act->mact.bbTableStart = 0;                                                     /* Clear start of table address */
                    503:        
                    504:        }
                    505: 
                    506: /*
                    507:  *     This next bit insures that any live facility context for this thread is discarded on every processor
                    508:  *     that may have it.  We go through all per-processor blocks and zero the facility owner if
                    509:  *     it is the thread being destroyed. This needs to be done via a compare-and-swap because
                    510:  *     some other processor could change the owner while we are clearing it. It turns out that 
                    511:  *     this is the only place where we need the interlock, normal use of the owner field is cpu-local
                    512:  *     and doesn't need the interlock. Because we are called during termintation, and a thread
                    513:  *     terminates itself, the context on other processors has been saved (because we save it as
                    514:  *     part of the context switch), even if it is still considered live. Since the dead thread is 
                    515:  *     not running elsewhere, and the context is saved, any other processor looking at the owner
                    516:  *     field will not attempt to save context again, meaning that it doesn't matter if the owner
                    517:  *     changes out from under it.
                    518:  */
                    519:  
                    520:        for(i=0; i < real_ncpus; i++) {                                                 /* Cycle through processors */
                    521:                (void)hw_compare_and_store((unsigned int)act, 0, &per_proc_info[i].FPU_thread); /* Clear if ours */
                    522:                (void)hw_compare_and_store((unsigned int)act, 0, &per_proc_info[i].VMX_thread); /* Clear if ours */
                    523:        }
                    524:        
                    525:        pcb = act->mact.VMX_pcb;                                                                /* Get the top vector savearea */
                    526:        while(pcb) {                                                                                    /* Any VMX saved state? */
                    527:                opcb = pcb;                                                                                     /* Save current savearea address */
                    528:                pcb = (pcb_t)(((savearea *)pcb)->save_prev_vector);     /* Get one underneath our's */          
                    529:                ((savearea *)opcb)->save_flags &= ~SAVvmxvalid;         /* Clear the VMX flag */
                    530:                
                    531:                if(!(((savearea *)opcb)->save_flags & SAVinuse)) {      /* Anyone left with this one? */                        
                    532:                        save_release((savearea *)opcb);                                 /* Nope, release it */
                    533:                }
                    534:        }
                    535:        act->mact.VMX_pcb = (pcb_t)0;                                                   /* Clear pointer */     
                    536: 
                    537:        pcb = act->mact.FPU_pcb;                                                                /* Get the top floating point savearea */
                    538:        while(pcb) {                                                                                    /* Any floating point saved state? */
                    539:                opcb = pcb;                                                                                     /* Save current savearea address */
                    540:                pcb = (pcb_t)(((savearea *)pcb)->save_prev_float);      /* Get one underneath our's */          
                    541:                ((savearea *)opcb)->save_flags &= ~SAVfpuvalid;         /* Clear the floating point flag */
                    542:                
                    543:                if(!(((savearea *)opcb)->save_flags & SAVinuse)) {      /* Anyone left with this one? */                        
                    544:                        save_release((savearea *)opcb);                                 /* Nope, release it */
                    545:                }
                    546:        }
                    547:        act->mact.FPU_pcb = (pcb_t)0;                                                   /* Clear pointer */     
                    548: 
                    549:        pcb = act->mact.pcb;                                                                    /* Get the top normal savearea */
                    550:        act->mact.pcb = (pcb_t)0;                                                               /* Clear pointer */     
                    551:        
                    552:        while(pcb) {                                                                                    /* Any normal saved state left? */
                    553:                opcb = pcb;                                                                                     /* Keep track of what we're working on */
                    554:                pcb = (pcb_t)(((savearea *)pcb)->save_prev);            /* Get one underneath our's */
                    555:                
                    556:                ((savearea *)opcb)->save_flags = 0;                                     /* Clear all flags since we release this in any case */
                    557:                save_release((savearea *)opcb);                                         /* Release this one */
                    558:        }
                    559: 
                    560:        hw_atomic_sub(&saveanchor.saveneed, 4);                                 /* Unaccount for the number of saveareas we think we "need"
                    561:                                                                                                                           for this activation */
                    562: }
                    563: 
                    564: kern_return_t
                    565: act_machine_create(task_t task, thread_act_t thr_act)
                    566: {
                    567:        /*
                    568:         * Clear & Init the pcb  (sets up user-mode s regs)
                    569:         * We don't use this anymore.
                    570:         */
                    571: 
                    572:        register pcb_t pcb;
                    573:        register int i;
                    574:        unsigned int *CIsTooLimited;
                    575:        pmap_t pmap;
                    576:        
                    577:        return KERN_SUCCESS;
                    578: }
                    579: 
                    580: void act_machine_init()
                    581: {
                    582: #if    MACH_ASSERT
                    583:     if (watchacts & WA_PCB)
                    584:        printf("act_machine_init()\n");
                    585: #endif /* MACH_ASSERT */
                    586: 
                    587:     /* Good to verify these once */
                    588:     assert( THREAD_MACHINE_STATE_MAX <= THREAD_STATE_MAX );
                    589: 
                    590:     assert( THREAD_STATE_MAX >= PPC_THREAD_STATE_COUNT );
                    591:     assert( THREAD_STATE_MAX >= PPC_EXCEPTION_STATE_COUNT );
                    592:     assert( THREAD_STATE_MAX >= PPC_FLOAT_STATE_COUNT );
                    593:     assert( THREAD_STATE_MAX >= sizeof(struct ppc_saved_state)/sizeof(int));
                    594: 
                    595:     /*
                    596:      * If we start using kernel activations,
                    597:      * would normally create kernel_thread_pool here,
                    598:      * populating it from the act_zone
                    599:      */
                    600: }
                    601: 
                    602: void
                    603: act_machine_return(int code)
                    604: {
                    605:     thread_act_t thr_act = current_act();
                    606:     thread_act_t       cur_act;
                    607:     thread_t   cur_thread = current_thread();
                    608:     struct ipc_port    *iplock;
                    609: 
                    610: #if    MACH_ASSERT
                    611:     if (watchacts & WA_EXIT)
                    612:        printf("act_machine_return(0x%x) cur_act=%x(%d) thr=%x(%d)\n",
                    613:               code, thr_act, thr_act->ref_count,
                    614:               thr_act->thread, thr_act->thread
                    615:               ? thr_act->thread->ref_count : 0);
                    616: #endif /* MACH_ASSERT */
                    617: 
                    618: 
                    619:        /*
                    620:         * This code is called with nothing locked.
                    621:         * It also returns with nothing locked, if it returns.
                    622:         *
                    623:         * This routine terminates the current thread activation.
                    624:         * If this is the only activation associated with its
                    625:         * thread shuttle, then the entire thread (shuttle plus
                    626:         * activation) is terminated.
                    627:         */
                    628:        assert( code == KERN_TERMINATED );
                    629:        assert( thr_act );
                    630: 
                    631:        act_lock_thread(thr_act);
                    632: 
                    633: #ifdef CALLOUT_RPC_MODEL
                    634:        /*
                    635:         * JMM - This needs to get cleaned up to work under the much simpler
                    636:         * return (instead of callout model).
                    637:         */
                    638:        if (thr_act->thread->top_act != thr_act) {
                    639:                /*
                    640:                 * this is not the top activation;
                    641:                 * if possible, we should clone the shuttle so that
                    642:                 * both the root RPC-chain and the soon-to-be-orphaned
                    643:                 * RPC-chain have shuttles
                    644:                 *
                    645:                 * JMM - Cloning is a horrible idea!  Instead we should alert
                    646:                 * the pieces upstream to return the shuttle.  We will use
                    647:                 * alerts for this.
                    648:                 */
                    649:                act_unlock_thread(thr_act);
                    650:                panic("act_machine_return: ORPHAN CASE NOT YET IMPLEMENTED");
                    651:        }
                    652: 
                    653:        if (thr_act->lower != THR_ACT_NULL) {
                    654:                /* terminate the entire thread (shuttle plus activation) */
                    655:                /* terminate only this activation, send an appropriate   */
                    656:                /* return code back to the activation that invoked us.   */
                    657:                iplock = thr_act->pool_port;    /* remember for unlock call */
                    658:                thr_act->lower->alerts |= SERVER_TERMINATED;
                    659:                install_special_handler(thr_act->lower);
                    660:                
                    661:                /* Return to previous act with error code */
                    662: 
                    663:                act_locked_act_reference(thr_act);      /* keep it around */
                    664:                act_switch_swapcheck(cur_thread, (ipc_port_t)0);
                    665: 
                    666:                (void) switch_act(THR_ACT_NULL);
                    667:                /* assert(thr_act->ref_count == 0); */          /* XXX */
                    668:                cur_act = cur_thread->top_act;
                    669:                MACH_RPC_RET(cur_act) = KERN_RPC_SERVER_TERMINATED;         
                    670:                machine_kernel_stack_init(cur_thread, 
                    671:                                  (void (*)(void)) mach_rpc_return_error);
                    672:                /*
                    673:                 * The following unlocks must be done separately since fields 
                    674:                 * used by `act_unlock_thread()' have been cleared, meaning
                    675:                 * that it would not release all of the appropriate locks.
                    676:                 */
                    677:                rpc_unlock(cur_thread);
                    678:                if (iplock) ip_unlock(iplock);  /* must be done separately */
                    679:                act_unlock(thr_act);
                    680:                act_deallocate(thr_act);                /* free it */
                    681:                Load_context(cur_thread);
                    682:                /*NOTREACHED*/
                    683:                
                    684:                panic("act_machine_return: TALKING ZOMBIE! (2)");
                    685:        }
                    686: 
                    687: #endif /* CALLOUT_RPC_MODEL */
                    688: 
                    689:        /* This is the only activation attached to the shuttle... */
                    690: 
                    691:        assert(thr_act->thread->top_act == thr_act);
                    692:        act_unlock_thread(thr_act);
                    693:        thread_terminate_self();
                    694: 
                    695:        /*NOTREACHED*/
                    696:        panic("act_machine_return: TALKING ZOMBIE! (1)");
                    697: }
                    698: 
                    699: void
                    700: thread_machine_set_current(struct thread_shuttle *thread)
                    701: {
                    702:     register int       my_cpu = cpu_number();
                    703: 
                    704:     cpu_data[my_cpu].active_thread = thread;
                    705:        
                    706:     active_kloaded[my_cpu] = thread->top_act->kernel_loaded ? thread->top_act : THR_ACT_NULL;
                    707: }
                    708: 
                    709: void
                    710: thread_machine_init(void)
                    711: {
                    712: #ifdef MACHINE_STACK
                    713: #if KERNEL_STACK_SIZE > PPC_PGBYTES
                    714:        panic("KERNEL_STACK_SIZE can't be greater than PPC_PGBYTES\n");
                    715: #endif
                    716: #endif
                    717: }
                    718: 
                    719: #if MACH_ASSERT
                    720: void
                    721: dump_pcb(pcb_t pcb)
                    722: {
                    723:        printf("pcb @ %8.8x:\n", pcb);
                    724: #if DEBUG
                    725:        regDump(&pcb->ss);
                    726: #endif /* DEBUG */
                    727: }
                    728: 
                    729: void
                    730: dump_thread(thread_t th)
                    731: {
                    732:        printf(" thread @ 0x%x:\n", th);
                    733: }
                    734: 
                    735: int
                    736:     dump_act(thread_act_t thr_act)
                    737: {
                    738:     if (!thr_act)
                    739:        return(0);
                    740: 
                    741:     printf("thr_act(0x%x)(%d): thread=%x(%d) task=%x(%d)\n",
                    742:           thr_act, thr_act->ref_count,
                    743:           thr_act->thread, thr_act->thread ? thr_act->thread->ref_count:0,
                    744:           thr_act->task,   thr_act->task   ? thr_act->task->ref_count : 0);
                    745: 
                    746:     printf("\talerts=%x mask=%x susp=%x active=%x hi=%x lo=%x\n",
                    747:           thr_act->alerts, thr_act->alert_mask,
                    748:           thr_act->suspend_count, thr_act->active,
                    749:           thr_act->higher, thr_act->lower);
                    750: 
                    751:     return((int)thr_act);
                    752: }
                    753: 
                    754: #endif
                    755: 
                    756: unsigned int 
                    757: get_useraddr()
                    758: {
                    759: 
                    760:        thread_act_t thr_act = current_act();
                    761: 
                    762:        return(thr_act->mact.pcb->ss.srr0);
                    763: }
                    764: 
                    765: /*
                    766:  * detach and return a kernel stack from a thread
                    767:  */
                    768: 
                    769: vm_offset_t
                    770: stack_detach(thread_t thread)
                    771: {
                    772:   vm_offset_t stack;
                    773: 
                    774: #ifdef KDEBUG
                    775:                KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_DETACH),
                    776:                        thread, thread->priority,
                    777:                        thread->sched_pri, 0,
                    778:                        0);
                    779: #endif
                    780:   stack = thread->kernel_stack;
                    781:   thread->kernel_stack = 0;
                    782:   return(stack);
                    783: }
                    784: 
                    785: /*
                    786:  * attach a kernel stack to a thread and initialize it
                    787:  *
                    788:  * attaches a stack to a thread. if there is no save
                    789:  * area we allocate one.  the top save area is then
                    790:  * loaded with the pc (continuation address), the initial
                    791:  * stack pointer, and a std kernel MSR. if the top
                    792:  * save area is the user save area bad things will 
                    793:  * happen
                    794:  *
                    795:  */
                    796: 
                    797: void
                    798: stack_attach(struct thread_shuttle *thread,
                    799:             vm_offset_t stack,
                    800:             void (*continuation)(void))
                    801: {
                    802:   thread_act_t thr_act;
                    803:   unsigned int *kss;
                    804:   struct savearea *sv;
                    805: 
                    806: #ifdef KDEBUG
                    807:         KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_ATTACH),
                    808:             thread, thread->priority,
                    809:             thread->sched_pri, continuation,
                    810:             0);
                    811: #endif
                    812: 
                    813:   assert(stack);
                    814:   kss = (unsigned int *)STACK_IKS(stack);
                    815:   thread->kernel_stack = stack;
                    816: 
                    817:   /* during initialization we sometimes do not have an
                    818:      activation. in that case do not do anything */
                    819:   if ((thr_act = thread->top_act) != 0) {
                    820:     sv = save_get();  /* cannot block */
                    821:     //    bzero((char *) sv, sizeof(struct pcb));
                    822:     sv->save_act = thr_act;
                    823:        sv->save_prev = (struct savearea *)thr_act->mact.pcb;
                    824:     thr_act->mact.pcb = (pcb_t)sv;
                    825: 
                    826:     sv->save_srr0 = (unsigned int) continuation;
                    827:     /* sv->save_r3 = ARG ? */
                    828:     sv->save_r1 = (vm_offset_t)((int)kss - KF_SIZE);
                    829:        sv->save_srr1 = MSR_SUPERVISOR_INT_ON;
                    830:     *((int *)sv->save_r1) = 0;
                    831:     thr_act->mact.ksp = 0;                           
                    832:   }
                    833: 
                    834:   return;
                    835: }
                    836: 
                    837: /*
                    838:  * move a stack from old to new thread
                    839:  */
                    840: 
                    841: void
                    842: stack_handoff(thread_t old,
                    843:              thread_t new)
                    844: {
                    845: 
                    846:   vm_offset_t stack;
                    847:   pmap_t new_pmap;
                    848: 
                    849:   assert(new->top_act);
                    850:   assert(old->top_act);
                    851: 
                    852:   stack = stack_detach(old);
                    853:   new->kernel_stack = stack;
                    854: 
                    855: #if NCPUS > 1
                    856:   if (real_ncpus > 1) {
                    857:        fpu_save();
                    858:        vec_save();
                    859:   }
                    860: #endif
                    861: 
                    862:   KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_HANDOFF) | DBG_FUNC_NONE,
                    863:                     (int)old, (int)new, old->sched_pri, new->sched_pri, 0);
                    864: 
                    865:   new_pmap = new->top_act->task->map->pmap;
                    866:   if (old->top_act->task->map->pmap != new_pmap) {
                    867:     pmap_switch(new_pmap);
                    868:   }
                    869: 
                    870:   thread_machine_set_current(new);
                    871:   active_stacks[cpu_number()] = new->kernel_stack;
                    872:   per_proc_info[cpu_number()].Uassist = new->top_act->mact.cthread_self;
                    873:   return;
                    874: }
                    875: 
                    876: /*
                    877:  * clean and initialize the current kernel stack and go to
                    878:  * the given continuation routine
                    879:  */
                    880: 
                    881: void
                    882: call_continuation(void (*continuation)(void) )
                    883: {
                    884: 
                    885:   unsigned int *kss;
                    886:   vm_offset_t tsp;
                    887: 
                    888:   assert(current_thread()->kernel_stack);
                    889:   kss = (unsigned int *)STACK_IKS(current_thread()->kernel_stack);
                    890:   assert(continuation);
                    891: 
                    892:   tsp = (vm_offset_t)((int)kss - KF_SIZE);
                    893:   assert(tsp);
                    894:   *((int *)tsp) = 0;
                    895: 
                    896:   Call_continuation(continuation, tsp);
                    897:   
                    898:   return;
                    899: }
                    900: 
                    901: void
                    902: thread_swapin_mach_alloc(thread_t thread)
                    903: {
                    904:     struct savearea *sv;
                    905: 
                    906:        assert(thread->top_act->mact.pcb == 0);
                    907: 
                    908:     sv = save_alloc();
                    909:        assert(sv);
                    910:        //    bzero((char *) sv, sizeof(struct pcb));
                    911:     sv->save_act = thread->top_act;
                    912:     thread->top_act->mact.pcb = (pcb_t)sv;
                    913: 
                    914: }

unix.superglobalmegacorp.com

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