Annotation of kernel/machdep/ppc/pcb.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*     HISTORY
                     26: 
                     27:        1997/05/16      Rene Vega -- cleanup sync/isync usage.
                     28: */
                     29: 
                     30: #import <machdep/ppc/exception.h>
                     31: #import <mach/mach_types.h>
                     32: #import <kern/mach_param.h>
                     33: #import <kern/thread.h>
                     34: #import <kern/kernel_stack.h>
                     35: #import <machdep/ppc/thread.h>
                     36: #import <bsd/ppc/psl.h>
                     37: #import <sys/time.h>
                     38: #import <bsd/ppc/vmparam.h>
                     39: #import <kernserv/ppc/spl.h>
                     40: #import <sys/param.h>
                     41: #import <sys/proc.h>
                     42: #import <kern/parallel.h>
                     43: #include <machdep/ppc/proc_reg.h>
                     44: #include <ppc/trap.h>
                     45: #ifdef KDEBUG
                     46: #include <kern/kdebug.h>
                     47: #include <mach_counters.h>
                     48: #include <kern/counters.h>
                     49: #import <machdep/ppc/frame.h>
                     50: #endif
                     51: #import <machdep/ppc/asm.h>
                     52: #import <assym.h>
                     53: 
                     54: pcb_t active_pcbs[NCPUS];      /* PCB belonging to the active thread */
                     55: 
                     56: #if DEBUG
                     57: int    fpu_trap_count = 0;
                     58: int    fpu_switch_count = 0;
                     59: #endif
                     60: 
                     61: extern struct per_proc_info per_proc_info[];
                     62: 
                     63: #define current_pcb() active_pcbs[cpu_number()]
                     64: 
                     65: zone_t          pcb_zone;
                     66: 
                     67: /*
                     68:  * Initialize pcb allocation zone.
                     69:  */
                     70: void
                     71: pcb_module_init(void)
                     72: {
                     73:        int i;
                     74:     pcb_zone = zinit(
                     75:                     sizeof (struct pcb),
                     76:                     THREAD_MAX * sizeof (struct pcb),
                     77:                     THREAD_CHUNK * sizeof (struct pcb),
                     78:                     FALSE, "pcb");
                     79: 
                     80:        for (i=0; i < NCPUS; i++) {
                     81:                active_pcbs[i] = 0;
                     82:        }
                     83: }
                     84: 
                     85: /*
                     86:  * Allocated and initialize a pcb for a new thread.
                     87:  */
                     88: void pcb_init(thread_t  thread)
                     89: {
                     90:         struct pcb      *pcb = (void *)zalloc(pcb_zone);
                     91:        pmap_t pmap = thread->task->map->pmap;
                     92: 
                     93: 
                     94:         thread->pcb = pcb;
                     95: 
                     96:        /* all fields default to zero */
                     97:         bzero((caddr_t)pcb, sizeof (struct pcb));
                     98: 
                     99:        /*
                    100:         * User threads will pull their context from the pcb when first
                    101:         * returning to user mode, so fill in all the necessary values.
                    102:         * Kernel threads are initialized from the save state structure 
                    103:         * at the base of the kernel stack (see stack_attach()).
                    104:         */
                    105: 
                    106:        pcb->ss.srr1 = MSR_EXPORT_MASK_SET;
                    107: 
                    108:        pcb->sr0     = SEG_REG_PROT | (pmap->space<<4);
                    109:        pcb->ss.sr_copyin    = SEG_REG_PROT | SR_COPYIN + (pmap->space<<4);
                    110: }
                    111: 
                    112: /*
                    113:  * Release machine dependent resources on
                    114:  * thread termination.
                    115:  */
                    116: pcb_terminate(
                    117:     thread_t    thread
                    118: )
                    119: {
                    120:        struct pcb      *pcb = thread->pcb;
                    121: 
                    122: 
                    123:        if (per_proc_info[cpu_number()].fpu_pcb == pcb)
                    124:        {
                    125:                per_proc_info[cpu_number()].fpu_pcb = (pcb_t)0;
                    126:        }
                    127: 
                    128:         thread->pcb = 0;
                    129:         zfree(pcb_zone, pcb);
                    130: }
                    131: 
                    132: #define KF_SIZE                (FM_SIZE+ARG_SIZE+FM_REDZONE)
                    133: 
                    134: /*
                    135:  * stack_attach: Attach a kernel stack to a thread.
                    136:  */
                    137: void stack_attach(thread, stack, continuation)
                    138:         register thread_t       thread;
                    139:         vm_offset_t             stack;
                    140:         void                    (*continuation)();
                    141: {
                    142:        struct ppc_kernel_state *kss;
                    143:         struct pcb      *pcb = thread->pcb;
                    144: 
                    145: #ifdef KDEBUG
                    146:        if (continuation) {
                    147:                KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_ATTACH),
                    148:                        thread, thread->priority,
                    149:                        thread->sched_pri, continuation, 
                    150:                        0);
                    151:        }
                    152: #endif
                    153:        thread->kernel_stack = stack;
                    154:        kss = STACK_IKS(stack);
                    155: 
                    156:        /*
                    157:         * Build a kernel state area + arg frame on the stack for the initial
                    158:         * switch into the thread. We also store a zero into the kernel
                    159:         * stack pointer so the trap code knows there is already a frame
                    160:         * on the kernel stack.
                    161:         */
                    162: 
                    163:        kss->lr = (unsigned int) continuation;
                    164:        kss->r1 = (vm_offset_t) ((int)kss - KF_SIZE);
                    165: 
                    166:        *((int*)kss->r1) = 0;       /* Zero the frame backpointer */
                    167: 
                    168:         pcb->ksp = 0;
                    169: }
                    170: 
                    171: vm_offset_t
                    172: stack_detach(
                    173:     thread_t            thread
                    174: )
                    175: {
                    176:     vm_offset_t         stack;
                    177: 
                    178:     stack = thread->kernel_stack;
                    179:     thread->kernel_stack = 0;
                    180: 
                    181:     return (stack);
                    182: }
                    183: 
                    184: /*
                    185:  * stack_handoff: Move the current threads kernel stack to the new thread.
                    186:  */
                    187: void
                    188: stack_handoff(
                    189:     thread_t           old,
                    190:     thread_t           new
                    191: )
                    192: {
                    193:     vm_offset_t                stack = stack_detach(old);
                    194: 
                    195:    KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_HANDOFF),
                    196:        old, new, 
                    197:        old->priority, old->sched_pri, 
                    198:        new->sched_pri);
                    199: 
                    200:     stack_attach(new, stack, 0);
                    201: 
                    202:     /*
                    203:      * Change software state.
                    204:      */
                    205:     if (new->task != old->task) {
                    206:        int             mycpu = cpu_number();
                    207: 
                    208:        PMAP_DEACTIVATE(vm_map_pmap(old->task->map), old, mycpu);
                    209:        PMAP_ACTIVATE(vm_map_pmap(new->task->map), new, mycpu);
                    210:        pmap_switch(new->task->map->pmap);
                    211:     }
                    212: 
                    213:     // current_thread() = new; // can't use this because it may be inlined!
                    214:     cpu_data[cpu_number()].active_thread = new;
                    215:     current_pcb() = new->pcb;
                    216:     cpu_data[cpu_number()].flags = new->pcb->flags;
                    217: 
                    218: #if NCPUS > 1
                    219:        /* There is no free lunch!
                    220:         * save the floating point state for the old thread
                    221:         * if the fpu has been used since the last context switch
                    222:         */
                    223:        fp_state_save(old);
                    224:        
                    225: #endif /* NCPUS > 1 */
                    226: 
                    227:        new->pcb->ksp = 0;
                    228: 
                    229: }
                    230: 
                    231: void
                    232: call_continuation(
                    233:     void            (*continuation)(void)
                    234: )
                    235: {
                    236:        struct ppc_kernel_state *kss;
                    237:     extern Call_continuation();
                    238:        int tkss;
                    239: 
                    240: 
                    241:        KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_CALL_CONT),
                    242:                        current_thread(), current_thread()->priority, 
                    243:                        current_thread()->sched_pri, continuation, 
                    244:                        0);
                    245: 
                    246:        kss = STACK_IKS(current_thread()->kernel_stack);
                    247: 
                    248:        *((int*)((int)kss - KF_SIZE)) = 0;       /* Zero the frame backpointer */
                    249:        tkss = (int)kss - KF_SIZE;
                    250: 
                    251:     Call_continuation(continuation, tkss);
                    252: }
                    253: 
                    254: 
                    255: /*
                    256:  * switch_context: Switch from one thread to another.
                    257:  */
                    258: thread_t
                    259: switch_context(
                    260:     thread_t           old,
                    261:     void               (*continuation)(void),
                    262:     thread_t           new
                    263: )
                    264: {
                    265:     thread_t ret_thread;
                    266:     extern thread_t Switch_context();
                    267: #ifdef KDEBUG
                    268:     struct linkage_area *frame_ptr;
                    269:     uint i;
                    270:     uint lr[4];
                    271: #endif
                    272: 
                    273:     if (new->task != old->task) {
                    274:        int             mycpu = cpu_number();
                    275: 
                    276:        PMAP_DEACTIVATE(vm_map_pmap(old->task->map), old, mycpu);
                    277:        PMAP_ACTIVATE(vm_map_pmap(new->task->map), new, mycpu);
                    278: 
                    279:        pmap_switch(new->task->map->pmap);
                    280:     }
                    281:        
                    282:     // current_thread() = new; // can't use this because it may be inlined!
                    283:     cpu_data[cpu_number()].active_thread = new;
                    284:     //current_stack() = new->kernel_stack; // assembly does this
                    285:     current_pcb()= new->pcb;
                    286:     cpu_data[cpu_number()].flags = new->pcb->flags;
                    287: 
                    288: #if NCPUS > 1
                    289:        /* There is no free lunch!
                    290:         * Save the floating point state for the old thread
                    291:         * if the fpu has been used since the last context switch.
                    292:         * Otherwise we need to broadcast an interrupt to the
                    293:         * old fpu to get the state.
                    294:         */
                    295:        fp_state_save(old);
                    296: 
                    297: #else
                    298:        //disable_fpu();
                    299: #endif 
                    300: 
                    301: #ifdef KDEBUG
                    302:        KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED) | DBG_FUNC_END,
                    303:                        old, new, 
                    304:                        old->priority, old->sched_pri, 
                    305:                        new->sched_pri);
                    306: 
                    307:        frame_ptr = STACK_IKS(new->kernel_stack)->r1;
                    308:        lr[0] = lr[1] = lr[2] = lr[3] = 0;
                    309:        lr[0] = STACK_IKS(new->kernel_stack)->lr;
                    310:        for (i=1;i<4;i++) {
                    311:          if (frame_ptr == NULL) break;
                    312:          lr[i] = frame_ptr->saved_lr;
                    313:          frame_ptr = frame_ptr->saved_sp;
                    314:        }
                    315:        KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED) | DBG_FUNC_START,
                    316:                        new, lr[0], lr[1], lr[2], lr[3]); 
                    317: 
                    318:        lr[0] = lr[1] = lr[2] = lr[3] = 0;
                    319:        for (i=0;i<4;i++) {
                    320:          if (frame_ptr == NULL) break;
                    321:          lr[i] = frame_ptr->saved_lr;
                    322:          frame_ptr = frame_ptr->saved_sp;
                    323:        }
                    324:        if (lr[0]) {
                    325:                KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED),
                    326:                        0, lr[0], lr[1], lr[2], lr[3]);
                    327:        };
                    328: #endif
                    329:        ret_thread = Switch_context(old, continuation, new);
                    330: 
                    331:        return(ret_thread);
                    332: }
                    333: 
                    334: void
                    335: start_initial_context(
                    336:     thread_t            thread
                    337: )
                    338: {
                    339:     struct pcb          *pcb = thread->pcb;
                    340: 
                    341:     /*
                    342:      * Change software state.
                    343:      */
                    344: 
                    345:    PMAP_ACTIVATE(vm_map_pmap(thread->task->map), thread, 0);
                    346: 
                    347: // current_thread() = thread; // can't use this because it may be inlined!
                    348:    cpu_data[cpu_number()].active_thread = thread;
                    349:    current_stack() = thread->kernel_stack;
                    350:    current_pcb() = thread->pcb;
                    351:    cpu_data[cpu_number()].flags = thread->pcb->flags;
                    352: 
                    353:     /*
                    354:      * Change hardware state
                    355:      */
                    356:     load_context(thread);
                    357:     /*NOTREACHED*/
                    358: }
                    359: 
                    360: /*
                    361:  * Duplicate parent state in child
                    362:  * for U**X fork.
                    363:  */
                    364: thread_dup(
                    365:     thread_t           parent,
                    366:     thread_t           child
                    367: )
                    368: {
                    369:        struct ppc_saved_state  *parent_state, *child_state;
                    370:        struct ppc_float_state  *parent_float_state, *child_float_state;
                    371:        struct ppc_exception_state      *parent_exception_state,
                    372:                                        *child_exception_state;
                    373: 
                    374:        /* Save the FPU state */
                    375:        if (per_proc_info[cpu_number()].fpu_pcb == parent->pcb) {
                    376:                fp_state_save(parent);
                    377:        }
                    378: 
                    379:        parent_state = &parent->pcb->ss;
                    380:        child_state = &child->pcb->ss;
                    381: 
                    382:        /* rely on compiler structure assignment */
                    383:        *child_state = *parent_state;
                    384: 
                    385:        parent_float_state = &parent->pcb->fs;
                    386:        child_float_state = &child->pcb->fs;
                    387: 
                    388:        /* rely on compiler structure assignment */
                    389:        *child_float_state = *parent_float_state;
                    390: #if 0
                    391:        parent_exception_state = &parent->pcb->es;
                    392:        child_exception_state = &child->pcb->es;
                    393: 
                    394:        /* rely on compiler structure assignment */
                    395:        *child_exception_state = *parent_exception_state;
                    396: #endif
                    397:        child_state->r3 = child->task->proc->p_pid;
                    398:        child_state->r4 = 1;
                    399: 
                    400:        child_state->sr_copyin = child->pcb->sr0 + SR_COPYIN;
                    401: }
                    402: 
                    403: /*
                    404:  * Set thread integer state
                    405:  */
                    406: kern_return_t
                    407: set_thread_state(
                    408:     thread_t                   thread,
                    409:     thread_state_t             tstate,
                    410:     unsigned int               count
                    411: )
                    412: {
                    413:        struct ppc_saved_state  *saved_state;
                    414:        struct ppc_thread_state *state;
                    415:     
                    416:        if (count < PPC_THREAD_STATE_COUNT)
                    417:                return (KERN_INVALID_ARGUMENT);
                    418:        
                    419:        if (thread->task->kernel_privilege) {
                    420:                /*
                    421:                * State for kernel threads
                    422:                * can only be set before thread
                    423:                * is first started.
                    424:                *
                    425:                * XXX This hack is due to the
                    426:                * fact that the &^%$#@! kernel loader
                    427:                * uses the thread_set_state() call to
                    428:                * start a thread in kernel mode.
                    429:                */
                    430:                if (thread->swap_func != thread_bootstrap_return)
                    431:                        return (KERN_INVALID_ARGUMENT);
                    432:        }
                    433: 
                    434:        state = (struct ppc_thread_state *)tstate;
                    435:        saved_state = &thread->pcb->ss;
                    436: 
                    437:        /*
                    438:        * structure assignment - depends on 
                    439:        * ppc_thread_state being a prefix of ppc_saved_state !
                    440:        */
                    441: 
                    442:        *((struct ppc_thread_state *)saved_state) = *state;
                    443: 
                    444:        saved_state->sr_copyin = thread->pcb->sr0 + SR_COPYIN;
                    445: 
                    446:        saved_state->srr1 |= MSR_EXPORT_MASK_SET;
                    447: 
                    448:        if (thread->task->kernel_privilege) {
                    449:                saved_state->srr1 &= ~ MASK(MSR_PR);
                    450:                thread_start(thread, state->srr0);
                    451:        }
                    452: 
                    453:        return (KERN_SUCCESS);
                    454: }
                    455: 
                    456: /*
                    457:  * Set thread floating point state
                    458:  */
                    459: kern_return_t
                    460: set_thread_fpstate(
                    461:     thread_t                   thread,
                    462:     thread_state_t             tstate,
                    463:     unsigned int               count
                    464: )
                    465: {
                    466:        struct ppc_float_state  *state;
                    467:     
                    468:        if (count < PPC_FLOAT_STATE_COUNT)
                    469:                return (KERN_INVALID_ARGUMENT);
                    470: 
                    471:        fpu_save();
                    472:        fpu_disable();
                    473: 
                    474:        state = (struct ppc_float_state *)tstate;
                    475: 
                    476:        /* structure assignment */
                    477:        thread->pcb->fs = *state;
                    478:     
                    479:        return (KERN_SUCCESS);
                    480: }
                    481: 
                    482: /*
                    483:  * Set thread exception point state
                    484:  */
                    485: kern_return_t
                    486: set_thread_exstate(
                    487:     thread_t                   thread,
                    488:     thread_state_t             tstate,
                    489:     unsigned int               count
                    490: )
                    491: {
                    492:        struct ppc_exception_state      *state;
                    493:     
                    494:        if (count < PPC_EXCEPTION_STATE_COUNT)
                    495:                return (KERN_INVALID_ARGUMENT);
                    496: 
                    497:        state = (struct ppc_exception_state *)tstate;
                    498: 
                    499:        /* structure assignment */
                    500:        thread->pcb->es = *state;
                    501:     
                    502:        return (KERN_SUCCESS);
                    503: }
                    504: 
                    505: /*
                    506:  * Set externally visible thread
                    507:  * state.
                    508:  */
                    509: kern_return_t
                    510: thread_setstatus(
                    511:     thread_t                   thread,
                    512:     int                                flavor,
                    513:     thread_state_t             tstate,
                    514:     unsigned int               count
                    515: )
                    516: {
                    517:     switch (flavor) {
                    518: 
                    519:     case PPC_THREAD_STATE:
                    520:        return (set_thread_state(thread, tstate, count));
                    521:     
                    522:     case PPC_FLOAT_STATE:
                    523:        return (set_thread_fpstate(thread, tstate, count));
                    524: 
                    525:     case PPC_EXCEPTION_STATE:
                    526:        return (set_thread_exstate(thread, tstate, count));
                    527: 
                    528:     default:
                    529:        return (KERN_INVALID_ARGUMENT);
                    530:     }
                    531: }
                    532: 
                    533: /*
                    534:  * Get thread state flavor list
                    535:  */
                    536: kern_return_t
                    537: get_thread_state_flavor_list(
                    538:     thread_state_t             tstate,
                    539:     unsigned int               *count
                    540: )
                    541: {
                    542:        struct thread_state_flavor *state;
                    543: 
                    544:        if (*count < PPC_THREAD_STATE_FLAVOR_LIST_COUNT)
                    545:                return (KERN_INVALID_ARGUMENT);
                    546:        
                    547:        state = (struct thread_state_flavor *)tstate;
                    548: 
                    549:        state->flavor = PPC_THREAD_STATE;
                    550:        state->count = PPC_THREAD_STATE_COUNT;
                    551:     
                    552:        (++state)->flavor = PPC_FLOAT_STATE;
                    553:        state->count = PPC_FLOAT_STATE_COUNT;
                    554:     
                    555:        (++state)->flavor = PPC_EXCEPTION_STATE;
                    556:        state->count = PPC_EXCEPTION_STATE_COUNT;
                    557:     
                    558:        *count = PPC_THREAD_STATE_FLAVOR_LIST_COUNT;
                    559:     
                    560:        return (KERN_SUCCESS);
                    561: }
                    562: 
                    563: /*
                    564:  * Get thread integer state
                    565:  */
                    566: kern_return_t
                    567: get_thread_state(
                    568:     thread_t                   thread,
                    569:     thread_state_t             tstate,
                    570:     unsigned int               *count
                    571: )
                    572: {
                    573:        struct ppc_thread_state *saved_state;
                    574:        struct ppc_thread_state *state;
                    575:     
                    576:        if (*count < PPC_THREAD_STATE_COUNT)
                    577:                return (KERN_INVALID_ARGUMENT);
                    578:        
                    579:        state = (struct ppc_thread_state *)tstate;
                    580:        saved_state = (struct ppc_thread_state *) &thread->pcb->ss;
                    581: 
                    582:        /*
                    583:         * structure assignment - depends on 
                    584:         * ppc_thread_state being a prefix of ppc_saved_state !
                    585:         */
                    586:        *state = *((struct ppc_thread_state *)saved_state);
                    587: 
                    588:        *count = PPC_THREAD_STATE_COUNT;
                    589:     
                    590:        return (KERN_SUCCESS);
                    591: }
                    592: 
                    593: /*
                    594:  * Get thread floating point state
                    595:  */
                    596: kern_return_t
                    597: get_thread_fpstate(
                    598:     thread_t                   thread,
                    599:     thread_state_t             tstate,
                    600:     unsigned int               *count
                    601: )
                    602: {
                    603:        struct ppc_float_state  *state;
                    604:     
                    605:        if (*count < PPC_FLOAT_STATE_COUNT)
                    606:                return (KERN_INVALID_ARGUMENT);
                    607: 
                    608:        fpu_save();
                    609:        fpu_disable();
                    610: 
                    611:        state = (struct ppc_float_state *)tstate;
                    612: 
                    613:        /* structure assignment */
                    614:        *state = thread->pcb->fs;
                    615: 
                    616:        *count = PPC_FLOAT_STATE_COUNT;
                    617:     
                    618:        return (KERN_SUCCESS);
                    619: }
                    620: 
                    621: /*
                    622:  * Get thread exception point state
                    623:  */
                    624: kern_return_t
                    625: get_thread_exstate(
                    626:     thread_t                   thread,
                    627:     thread_state_t             tstate,
                    628:     unsigned int               *count
                    629: )
                    630: {
                    631:        struct ppc_exception_state      *state;
                    632:     
                    633:        if (*count < PPC_EXCEPTION_STATE_COUNT)
                    634:                return (KERN_INVALID_ARGUMENT);
                    635: 
                    636:        state = (struct ppc_exception_state *)tstate;
                    637: 
                    638:        /* structure assignment */
                    639:        *state = thread->pcb->es;
                    640: 
                    641:        *count = PPC_EXCEPTION_STATE_COUNT;
                    642:     
                    643:        return (KERN_SUCCESS);
                    644: }
                    645: 
                    646: /*
                    647:  * Return externally visible
                    648:  * thread status.
                    649:  */
                    650: kern_return_t
                    651: thread_getstatus(
                    652:     thread_t                   thread,
                    653:     int                                flavor,
                    654:     thread_state_t             tstate,
                    655:     unsigned int               *count
                    656: )
                    657: {
                    658:     switch (flavor) {
                    659: 
                    660:        case THREAD_STATE_FLAVOR_LIST:
                    661:                return (get_thread_state_flavor_list(tstate, count));
                    662: 
                    663:        case PPC_THREAD_STATE:
                    664:                return (get_thread_state(thread, tstate, count));
                    665:        
                    666:        case PPC_FLOAT_STATE:
                    667:                return (get_thread_fpstate(thread, tstate, count));
                    668:        
                    669:        case PPC_EXCEPTION_STATE:
                    670:                return (get_thread_exstate(thread, tstate, count));
                    671:        
                    672:        default:
                    673:                return (KERN_INVALID_ARGUMENT);
                    674:     }
                    675: }
                    676: 
                    677: /*
                    678:  * thread_userstack:
                    679:  *
                    680:  * Return the user stack pointer from the machine 
                    681:  * dependent thread state info.
                    682:  */
                    683: kern_return_t
                    684: thread_userstack(
                    685:     thread_t           thread,
                    686:     int                        flavor,
                    687:     thread_state_t     tstate,
                    688:     unsigned int       count,
                    689:     vm_offset_t                *user_stack
                    690: )
                    691: {
                    692:        struct ppc_thread_state *state;
                    693: 
                    694:        /*
                    695:         * Set a default.
                    696:         */
                    697:        if (*user_stack == 0)
                    698:                *user_stack = USRSTACK;
                    699:                
                    700:        switch (flavor) {
                    701:        case PPC_THREAD_STATE:
                    702:                if (count < PPC_THREAD_STATE_COUNT)
                    703:                        return (KERN_INVALID_ARGUMENT);
                    704: 
                    705:                state = (struct ppc_thread_state *) tstate;
                    706: 
                    707:                /*
                    708:                 * If a valid user stack is specified, use it.
                    709:                 */
                    710:                *user_stack = state->r1 ? state->r1: USRSTACK;
                    711:                break;
                    712:        default :
                    713:                return (KERN_INVALID_ARGUMENT);
                    714:        }
                    715: 
                    716:        return (KERN_SUCCESS);
                    717: }
                    718: 
                    719: kern_return_t
                    720: thread_entrypoint(
                    721:     thread_t           thread,
                    722:     int                        flavor,
                    723:     thread_state_t     tstate,
                    724:     unsigned int       count,
                    725:     vm_offset_t                *entry_point
                    726: )
                    727: {
                    728:     struct ppc_thread_state    *state;
                    729: 
                    730:     /*
                    731:      * Set a default.
                    732:      */
                    733:     if (*entry_point == 0)
                    734:        *entry_point = VM_MIN_ADDRESS;
                    735:                
                    736:     switch (flavor) {
                    737: 
                    738:     case PPC_THREAD_STATE:
                    739:        if (count < PPC_THREAD_STATE_COUNT)
                    740:            return (KERN_INVALID_ARGUMENT);
                    741: 
                    742:        state = (struct ppc_thread_state *) tstate;
                    743: 
                    744:        /*
                    745:         * If a valid entry point is specified, use it.
                    746:         */
                    747:        *entry_point = state->srr0 ? state->srr0: VM_MIN_ADDRESS;
                    748:        break;
                    749:     default:
                    750:        return (KERN_INVALID_ARGUMENT);
                    751:     }
                    752: 
                    753:     return (KERN_SUCCESS);
                    754: }
                    755: 
                    756: 
                    757: void __volatile__
                    758: thread_syscall_return(
                    759:        kern_return_t   retval)
                    760: {
                    761:        thread_t        thread = current_thread();
                    762:        struct ppc_saved_state *ssp = &thread->pcb->ss;
                    763: 
                    764:        ssp->r3 = retval;
                    765: 
                    766:        thread_exception_return();
                    767:        /* NOTREACHED */
                    768: }
                    769: 
                    770: void
                    771: thread_set_syscall_return(
                    772:        thread_t        thread,
                    773:        kern_return_t   retval)
                    774: {
                    775:        struct ppc_saved_state *ssp = &thread->pcb->ss;
                    776: 
                    777:        ssp->r3 = retval;
                    778: }
                    779: 
                    780: void
                    781: pmap_switch(pmap_t map)
                    782: {
                    783:        unsigned int i;
                    784: 
                    785:        if (map->space == PPC_SID_KERNEL)
                    786:                return;
                    787: 
                    788:        /* sr value has Ks=1, Ku=1, and vsid composed of space+seg num */
                    789:        i = SEG_REG_PROT | (map->space << 4);
                    790: 
                    791:        isync();                /* context sync before */
                    792: /*     mtsr(0x0, i + 0x0); SR0 is part of the kernel address space */
                    793: /*     mtsr(0x1, i + 0x1); SR1 is part of the kernel address space */
                    794: /*     mtsr(0x2, i + 0x2); SR2 is part of the kernel address space */
                    795: /*     mtsr(0x3, i + 0x3); SR3 is part of the kernel address space */
                    796:        mtsr(0x4, i + 0x4);
                    797:        mtsr(0x5, i + 0x5);
                    798:        mtsr(0x6, i + 0x6);
                    799:        mtsr(0x7, i + 0x7);
                    800:        mtsr(0x8, i + 0x8);
                    801:        mtsr(0x9, i + 0x9);
                    802:        mtsr(0xa, i + 0xa);
                    803:        mtsr(0xb, i + 0xb);
                    804:        mtsr(0xc, i + 0xc);
                    805:        mtsr(0xd, i + 0xd);
                    806:        mtsr(0xe, i + 0xe);
                    807:        mtsr(0xf, i + 0xf);
                    808:        isync();                /* context sync after */
                    809: }
                    810: 
                    811: /*
                    812:  * task_map_io_ports() is required by the driverkit routines.
                    813:  */
                    814: kern_return_t
                    815: task_map_io_ports(
                    816:     task_t             task,
                    817:     unsigned int       port,
                    818:     unsigned int       length,
                    819:     boolean_t          unmap
                    820: )
                    821: {
                    822:        return (KERN_SUCCESS);
                    823: }
                    824: 
                    825: 
                    826: #if MACH_ASSERT
                    827: void
                    828: dump_pcb(pcb_t pcb)
                    829: {
                    830:        printf("pcb @ %8.8x:\n", pcb);
                    831:        printf("ksp       = 0x%08x\n\n",pcb->ksp);
                    832: #if DEBUG
                    833:        regDump(&pcb->ss);
                    834: #endif /* DEBUG */
                    835: }
                    836: 
                    837: void
                    838: dump_thread(thread_t th)
                    839: {
                    840:        printf(" thread @ 0x%x:\n", th);
                    841: }
                    842: #endif

unix.superglobalmegacorp.com

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