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

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>
1.1.1.2 ! root       45: #if    KDEBUG
1.1       root       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: 
1.1.1.2 ! root      145: #if KDEBUG
1.1       root      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: 
1.1.1.2 ! root      195: #if KDEBUG
1.1       root      196:    KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_HANDOFF),
                    197:        old, new, 
                    198:        old->priority, old->sched_pri, 
                    199:        new->sched_pri);
1.1.1.2 ! root      200: #endif
1.1       root      201: 
                    202:     stack_attach(new, stack, 0);
                    203: 
                    204:     /*
                    205:      * Change software state.
                    206:      */
                    207:     if (new->task != old->task) {
                    208:        int             mycpu = cpu_number();
                    209: 
                    210:        PMAP_DEACTIVATE(vm_map_pmap(old->task->map), old, mycpu);
                    211:        PMAP_ACTIVATE(vm_map_pmap(new->task->map), new, mycpu);
                    212:        pmap_switch(new->task->map->pmap);
                    213:     }
                    214: 
                    215:     // current_thread() = new; // can't use this because it may be inlined!
                    216:     cpu_data[cpu_number()].active_thread = new;
                    217:     current_pcb() = new->pcb;
                    218:     cpu_data[cpu_number()].flags = new->pcb->flags;
                    219: 
                    220: #if NCPUS > 1
                    221:        /* There is no free lunch!
                    222:         * save the floating point state for the old thread
                    223:         * if the fpu has been used since the last context switch
                    224:         */
                    225:        fp_state_save(old);
                    226:        
                    227: #endif /* NCPUS > 1 */
                    228: 
                    229:        new->pcb->ksp = 0;
                    230: 
                    231: }
                    232: 
                    233: void
                    234: call_continuation(
                    235:     void            (*continuation)(void)
                    236: )
                    237: {
                    238:        struct ppc_kernel_state *kss;
                    239:     extern Call_continuation();
                    240:        int tkss;
                    241: 
                    242: 
1.1.1.2 ! root      243: #if KDEBUG
1.1       root      244:        KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_CALL_CONT),
                    245:                        current_thread(), current_thread()->priority, 
                    246:                        current_thread()->sched_pri, continuation, 
                    247:                        0);
1.1.1.2 ! root      248: #endif
1.1       root      249: 
                    250:        kss = STACK_IKS(current_thread()->kernel_stack);
                    251: 
                    252:        *((int*)((int)kss - KF_SIZE)) = 0;       /* Zero the frame backpointer */
                    253:        tkss = (int)kss - KF_SIZE;
                    254: 
                    255:     Call_continuation(continuation, tkss);
                    256: }
                    257: 
                    258: 
                    259: /*
                    260:  * switch_context: Switch from one thread to another.
                    261:  */
                    262: thread_t
                    263: switch_context(
                    264:     thread_t           old,
                    265:     void               (*continuation)(void),
                    266:     thread_t           new
                    267: )
                    268: {
                    269:     thread_t ret_thread;
                    270:     extern thread_t Switch_context();
1.1.1.2 ! root      271: #if KDEBUG
1.1       root      272:     struct linkage_area *frame_ptr;
                    273:     uint i;
                    274:     uint lr[4];
                    275: #endif
                    276: 
                    277:     if (new->task != old->task) {
                    278:        int             mycpu = cpu_number();
                    279: 
                    280:        PMAP_DEACTIVATE(vm_map_pmap(old->task->map), old, mycpu);
                    281:        PMAP_ACTIVATE(vm_map_pmap(new->task->map), new, mycpu);
                    282: 
                    283:        pmap_switch(new->task->map->pmap);
                    284:     }
                    285:        
                    286:     // current_thread() = new; // can't use this because it may be inlined!
                    287:     cpu_data[cpu_number()].active_thread = new;
                    288:     //current_stack() = new->kernel_stack; // assembly does this
                    289:     current_pcb()= new->pcb;
                    290:     cpu_data[cpu_number()].flags = new->pcb->flags;
                    291: 
                    292: #if NCPUS > 1
                    293:        /* There is no free lunch!
                    294:         * Save the floating point state for the old thread
                    295:         * if the fpu has been used since the last context switch.
                    296:         * Otherwise we need to broadcast an interrupt to the
                    297:         * old fpu to get the state.
                    298:         */
                    299:        fp_state_save(old);
                    300: 
                    301: #else
                    302:        //disable_fpu();
                    303: #endif 
                    304: 
1.1.1.2 ! root      305: #if KDEBUG
1.1       root      306:        KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED) | DBG_FUNC_END,
                    307:                        old, new, 
                    308:                        old->priority, old->sched_pri, 
                    309:                        new->sched_pri);
                    310: 
                    311:        frame_ptr = STACK_IKS(new->kernel_stack)->r1;
                    312:        lr[0] = lr[1] = lr[2] = lr[3] = 0;
                    313:        lr[0] = STACK_IKS(new->kernel_stack)->lr;
                    314:        for (i=1;i<4;i++) {
                    315:          if (frame_ptr == NULL) break;
                    316:          lr[i] = frame_ptr->saved_lr;
                    317:          frame_ptr = frame_ptr->saved_sp;
                    318:        }
                    319:        KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED) | DBG_FUNC_START,
                    320:                        new, lr[0], lr[1], lr[2], lr[3]); 
                    321: 
                    322:        lr[0] = lr[1] = lr[2] = lr[3] = 0;
                    323:        for (i=0;i<4;i++) {
                    324:          if (frame_ptr == NULL) break;
                    325:          lr[i] = frame_ptr->saved_lr;
                    326:          frame_ptr = frame_ptr->saved_sp;
                    327:        }
                    328:        if (lr[0]) {
                    329:                KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED),
                    330:                        0, lr[0], lr[1], lr[2], lr[3]);
                    331:        };
                    332: #endif
                    333:        ret_thread = Switch_context(old, continuation, new);
                    334: 
                    335:        return(ret_thread);
                    336: }
                    337: 
                    338: void
                    339: start_initial_context(
                    340:     thread_t            thread
                    341: )
                    342: {
                    343:     struct pcb          *pcb = thread->pcb;
                    344: 
                    345:     /*
                    346:      * Change software state.
                    347:      */
                    348: 
                    349:    PMAP_ACTIVATE(vm_map_pmap(thread->task->map), thread, 0);
                    350: 
                    351: // current_thread() = thread; // can't use this because it may be inlined!
                    352:    cpu_data[cpu_number()].active_thread = thread;
                    353:    current_stack() = thread->kernel_stack;
                    354:    current_pcb() = thread->pcb;
                    355:    cpu_data[cpu_number()].flags = thread->pcb->flags;
                    356: 
                    357:     /*
                    358:      * Change hardware state
                    359:      */
                    360:     load_context(thread);
                    361:     /*NOTREACHED*/
                    362: }
                    363: 
                    364: /*
                    365:  * Duplicate parent state in child
                    366:  * for U**X fork.
                    367:  */
                    368: thread_dup(
                    369:     thread_t           parent,
                    370:     thread_t           child
                    371: )
                    372: {
                    373:        struct ppc_saved_state  *parent_state, *child_state;
                    374:        struct ppc_float_state  *parent_float_state, *child_float_state;
                    375:        struct ppc_exception_state      *parent_exception_state,
                    376:                                        *child_exception_state;
                    377: 
                    378:        /* Save the FPU state */
                    379:        if (per_proc_info[cpu_number()].fpu_pcb == parent->pcb) {
                    380:                fp_state_save(parent);
                    381:        }
                    382: 
                    383:        parent_state = &parent->pcb->ss;
                    384:        child_state = &child->pcb->ss;
                    385: 
                    386:        /* rely on compiler structure assignment */
                    387:        *child_state = *parent_state;
                    388: 
                    389:        parent_float_state = &parent->pcb->fs;
                    390:        child_float_state = &child->pcb->fs;
                    391: 
                    392:        /* rely on compiler structure assignment */
                    393:        *child_float_state = *parent_float_state;
                    394: #if 0
                    395:        parent_exception_state = &parent->pcb->es;
                    396:        child_exception_state = &child->pcb->es;
                    397: 
                    398:        /* rely on compiler structure assignment */
                    399:        *child_exception_state = *parent_exception_state;
                    400: #endif
                    401:        child_state->r3 = child->task->proc->p_pid;
                    402:        child_state->r4 = 1;
                    403: 
                    404:        child_state->sr_copyin = child->pcb->sr0 + SR_COPYIN;
                    405: }
                    406: 
                    407: /*
                    408:  * Set thread integer state
                    409:  */
                    410: kern_return_t
                    411: set_thread_state(
                    412:     thread_t                   thread,
                    413:     thread_state_t             tstate,
                    414:     unsigned int               count
                    415: )
                    416: {
                    417:        struct ppc_saved_state  *saved_state;
                    418:        struct ppc_thread_state *state;
                    419:     
                    420:        if (count < PPC_THREAD_STATE_COUNT)
                    421:                return (KERN_INVALID_ARGUMENT);
                    422:        
                    423:        if (thread->task->kernel_privilege) {
                    424:                /*
                    425:                * State for kernel threads
                    426:                * can only be set before thread
                    427:                * is first started.
                    428:                *
                    429:                * XXX This hack is due to the
                    430:                * fact that the &^%$#@! kernel loader
                    431:                * uses the thread_set_state() call to
                    432:                * start a thread in kernel mode.
                    433:                */
                    434:                if (thread->swap_func != thread_bootstrap_return)
                    435:                        return (KERN_INVALID_ARGUMENT);
                    436:        }
                    437: 
                    438:        state = (struct ppc_thread_state *)tstate;
                    439:        saved_state = &thread->pcb->ss;
                    440: 
                    441:        /*
                    442:        * structure assignment - depends on 
                    443:        * ppc_thread_state being a prefix of ppc_saved_state !
                    444:        */
                    445: 
                    446:        *((struct ppc_thread_state *)saved_state) = *state;
                    447: 
                    448:        saved_state->sr_copyin = thread->pcb->sr0 + SR_COPYIN;
                    449: 
                    450:        saved_state->srr1 |= MSR_EXPORT_MASK_SET;
                    451: 
                    452:        if (thread->task->kernel_privilege) {
                    453:                saved_state->srr1 &= ~ MASK(MSR_PR);
                    454:                thread_start(thread, state->srr0);
                    455:        }
                    456: 
                    457:        return (KERN_SUCCESS);
                    458: }
                    459: 
                    460: /*
                    461:  * Set thread floating point state
                    462:  */
                    463: kern_return_t
                    464: set_thread_fpstate(
                    465:     thread_t                   thread,
                    466:     thread_state_t             tstate,
                    467:     unsigned int               count
                    468: )
                    469: {
                    470:        struct ppc_float_state  *state;
                    471:     
                    472:        if (count < PPC_FLOAT_STATE_COUNT)
                    473:                return (KERN_INVALID_ARGUMENT);
                    474: 
                    475:        fpu_save();
                    476:        fpu_disable();
                    477: 
                    478:        state = (struct ppc_float_state *)tstate;
                    479: 
                    480:        /* structure assignment */
                    481:        thread->pcb->fs = *state;
                    482:     
                    483:        return (KERN_SUCCESS);
                    484: }
                    485: 
                    486: /*
                    487:  * Set thread exception point state
                    488:  */
                    489: kern_return_t
                    490: set_thread_exstate(
                    491:     thread_t                   thread,
                    492:     thread_state_t             tstate,
                    493:     unsigned int               count
                    494: )
                    495: {
                    496:        struct ppc_exception_state      *state;
                    497:     
                    498:        if (count < PPC_EXCEPTION_STATE_COUNT)
                    499:                return (KERN_INVALID_ARGUMENT);
                    500: 
                    501:        state = (struct ppc_exception_state *)tstate;
                    502: 
                    503:        /* structure assignment */
                    504:        thread->pcb->es = *state;
                    505:     
                    506:        return (KERN_SUCCESS);
                    507: }
                    508: 
                    509: /*
                    510:  * Set externally visible thread
                    511:  * state.
                    512:  */
                    513: kern_return_t
                    514: thread_setstatus(
                    515:     thread_t                   thread,
                    516:     int                                flavor,
                    517:     thread_state_t             tstate,
                    518:     unsigned int               count
                    519: )
                    520: {
                    521:     switch (flavor) {
                    522: 
                    523:     case PPC_THREAD_STATE:
                    524:        return (set_thread_state(thread, tstate, count));
                    525:     
                    526:     case PPC_FLOAT_STATE:
                    527:        return (set_thread_fpstate(thread, tstate, count));
                    528: 
                    529:     case PPC_EXCEPTION_STATE:
                    530:        return (set_thread_exstate(thread, tstate, count));
                    531: 
                    532:     default:
                    533:        return (KERN_INVALID_ARGUMENT);
                    534:     }
                    535: }
                    536: 
                    537: /*
                    538:  * Get thread state flavor list
                    539:  */
                    540: kern_return_t
                    541: get_thread_state_flavor_list(
                    542:     thread_state_t             tstate,
                    543:     unsigned int               *count
                    544: )
                    545: {
                    546:        struct thread_state_flavor *state;
                    547: 
                    548:        if (*count < PPC_THREAD_STATE_FLAVOR_LIST_COUNT)
                    549:                return (KERN_INVALID_ARGUMENT);
                    550:        
                    551:        state = (struct thread_state_flavor *)tstate;
                    552: 
                    553:        state->flavor = PPC_THREAD_STATE;
                    554:        state->count = PPC_THREAD_STATE_COUNT;
                    555:     
                    556:        (++state)->flavor = PPC_FLOAT_STATE;
                    557:        state->count = PPC_FLOAT_STATE_COUNT;
                    558:     
                    559:        (++state)->flavor = PPC_EXCEPTION_STATE;
                    560:        state->count = PPC_EXCEPTION_STATE_COUNT;
                    561:     
                    562:        *count = PPC_THREAD_STATE_FLAVOR_LIST_COUNT;
                    563:     
                    564:        return (KERN_SUCCESS);
                    565: }
                    566: 
                    567: /*
                    568:  * Get thread integer state
                    569:  */
                    570: kern_return_t
                    571: get_thread_state(
                    572:     thread_t                   thread,
                    573:     thread_state_t             tstate,
                    574:     unsigned int               *count
                    575: )
                    576: {
                    577:        struct ppc_thread_state *saved_state;
                    578:        struct ppc_thread_state *state;
                    579:     
                    580:        if (*count < PPC_THREAD_STATE_COUNT)
                    581:                return (KERN_INVALID_ARGUMENT);
                    582:        
                    583:        state = (struct ppc_thread_state *)tstate;
                    584:        saved_state = (struct ppc_thread_state *) &thread->pcb->ss;
                    585: 
                    586:        /*
                    587:         * structure assignment - depends on 
                    588:         * ppc_thread_state being a prefix of ppc_saved_state !
                    589:         */
                    590:        *state = *((struct ppc_thread_state *)saved_state);
                    591: 
                    592:        *count = PPC_THREAD_STATE_COUNT;
                    593:     
                    594:        return (KERN_SUCCESS);
                    595: }
                    596: 
                    597: /*
                    598:  * Get thread floating point state
                    599:  */
                    600: kern_return_t
                    601: get_thread_fpstate(
                    602:     thread_t                   thread,
                    603:     thread_state_t             tstate,
                    604:     unsigned int               *count
                    605: )
                    606: {
                    607:        struct ppc_float_state  *state;
                    608:     
                    609:        if (*count < PPC_FLOAT_STATE_COUNT)
                    610:                return (KERN_INVALID_ARGUMENT);
                    611: 
                    612:        fpu_save();
                    613:        fpu_disable();
                    614: 
                    615:        state = (struct ppc_float_state *)tstate;
                    616: 
                    617:        /* structure assignment */
                    618:        *state = thread->pcb->fs;
                    619: 
                    620:        *count = PPC_FLOAT_STATE_COUNT;
                    621:     
                    622:        return (KERN_SUCCESS);
                    623: }
                    624: 
                    625: /*
                    626:  * Get thread exception point state
                    627:  */
                    628: kern_return_t
                    629: get_thread_exstate(
                    630:     thread_t                   thread,
                    631:     thread_state_t             tstate,
                    632:     unsigned int               *count
                    633: )
                    634: {
                    635:        struct ppc_exception_state      *state;
                    636:     
                    637:        if (*count < PPC_EXCEPTION_STATE_COUNT)
                    638:                return (KERN_INVALID_ARGUMENT);
                    639: 
                    640:        state = (struct ppc_exception_state *)tstate;
                    641: 
                    642:        /* structure assignment */
                    643:        *state = thread->pcb->es;
                    644: 
                    645:        *count = PPC_EXCEPTION_STATE_COUNT;
                    646:     
                    647:        return (KERN_SUCCESS);
                    648: }
                    649: 
                    650: /*
                    651:  * Return externally visible
                    652:  * thread status.
                    653:  */
                    654: kern_return_t
                    655: thread_getstatus(
                    656:     thread_t                   thread,
                    657:     int                                flavor,
                    658:     thread_state_t             tstate,
                    659:     unsigned int               *count
                    660: )
                    661: {
                    662:     switch (flavor) {
                    663: 
                    664:        case THREAD_STATE_FLAVOR_LIST:
                    665:                return (get_thread_state_flavor_list(tstate, count));
                    666: 
                    667:        case PPC_THREAD_STATE:
                    668:                return (get_thread_state(thread, tstate, count));
                    669:        
                    670:        case PPC_FLOAT_STATE:
                    671:                return (get_thread_fpstate(thread, tstate, count));
                    672:        
                    673:        case PPC_EXCEPTION_STATE:
                    674:                return (get_thread_exstate(thread, tstate, count));
                    675:        
                    676:        default:
                    677:                return (KERN_INVALID_ARGUMENT);
                    678:     }
                    679: }
                    680: 
                    681: /*
                    682:  * thread_userstack:
                    683:  *
                    684:  * Return the user stack pointer from the machine 
                    685:  * dependent thread state info.
                    686:  */
                    687: kern_return_t
                    688: thread_userstack(
                    689:     thread_t           thread,
                    690:     int                        flavor,
                    691:     thread_state_t     tstate,
                    692:     unsigned int       count,
                    693:     vm_offset_t                *user_stack
                    694: )
                    695: {
                    696:        struct ppc_thread_state *state;
                    697: 
                    698:        /*
                    699:         * Set a default.
                    700:         */
                    701:        if (*user_stack == 0)
                    702:                *user_stack = USRSTACK;
                    703:                
                    704:        switch (flavor) {
                    705:        case PPC_THREAD_STATE:
                    706:                if (count < PPC_THREAD_STATE_COUNT)
                    707:                        return (KERN_INVALID_ARGUMENT);
                    708: 
                    709:                state = (struct ppc_thread_state *) tstate;
                    710: 
                    711:                /*
                    712:                 * If a valid user stack is specified, use it.
                    713:                 */
                    714:                *user_stack = state->r1 ? state->r1: USRSTACK;
                    715:                break;
                    716:        default :
                    717:                return (KERN_INVALID_ARGUMENT);
                    718:        }
                    719: 
                    720:        return (KERN_SUCCESS);
                    721: }
                    722: 
                    723: kern_return_t
                    724: thread_entrypoint(
                    725:     thread_t           thread,
                    726:     int                        flavor,
                    727:     thread_state_t     tstate,
                    728:     unsigned int       count,
                    729:     vm_offset_t                *entry_point
                    730: )
                    731: {
                    732:     struct ppc_thread_state    *state;
                    733: 
                    734:     /*
                    735:      * Set a default.
                    736:      */
                    737:     if (*entry_point == 0)
                    738:        *entry_point = VM_MIN_ADDRESS;
                    739:                
                    740:     switch (flavor) {
                    741: 
                    742:     case PPC_THREAD_STATE:
                    743:        if (count < PPC_THREAD_STATE_COUNT)
                    744:            return (KERN_INVALID_ARGUMENT);
                    745: 
                    746:        state = (struct ppc_thread_state *) tstate;
                    747: 
                    748:        /*
                    749:         * If a valid entry point is specified, use it.
                    750:         */
                    751:        *entry_point = state->srr0 ? state->srr0: VM_MIN_ADDRESS;
                    752:        break;
                    753:     default:
                    754:        return (KERN_INVALID_ARGUMENT);
                    755:     }
                    756: 
                    757:     return (KERN_SUCCESS);
                    758: }
                    759: 
                    760: 
                    761: void __volatile__
                    762: thread_syscall_return(
                    763:        kern_return_t   retval)
                    764: {
                    765:        thread_t        thread = current_thread();
                    766:        struct ppc_saved_state *ssp = &thread->pcb->ss;
                    767: 
                    768:        ssp->r3 = retval;
                    769: 
                    770:        thread_exception_return();
                    771:        /* NOTREACHED */
                    772: }
                    773: 
                    774: void
                    775: thread_set_syscall_return(
                    776:        thread_t        thread,
                    777:        kern_return_t   retval)
                    778: {
                    779:        struct ppc_saved_state *ssp = &thread->pcb->ss;
                    780: 
                    781:        ssp->r3 = retval;
                    782: }
                    783: 
                    784: void
                    785: pmap_switch(pmap_t map)
                    786: {
                    787:        unsigned int i;
                    788: 
                    789:        if (map->space == PPC_SID_KERNEL)
                    790:                return;
                    791: 
                    792:        /* sr value has Ks=1, Ku=1, and vsid composed of space+seg num */
                    793:        i = SEG_REG_PROT | (map->space << 4);
                    794: 
                    795:        isync();                /* context sync before */
                    796: /*     mtsr(0x0, i + 0x0); SR0 is part of the kernel address space */
                    797: /*     mtsr(0x1, i + 0x1); SR1 is part of the kernel address space */
                    798: /*     mtsr(0x2, i + 0x2); SR2 is part of the kernel address space */
                    799: /*     mtsr(0x3, i + 0x3); SR3 is part of the kernel address space */
                    800:        mtsr(0x4, i + 0x4);
                    801:        mtsr(0x5, i + 0x5);
                    802:        mtsr(0x6, i + 0x6);
                    803:        mtsr(0x7, i + 0x7);
                    804:        mtsr(0x8, i + 0x8);
                    805:        mtsr(0x9, i + 0x9);
                    806:        mtsr(0xa, i + 0xa);
                    807:        mtsr(0xb, i + 0xb);
                    808:        mtsr(0xc, i + 0xc);
                    809:        mtsr(0xd, i + 0xd);
                    810:        mtsr(0xe, i + 0xe);
                    811:        mtsr(0xf, i + 0xf);
                    812:        isync();                /* context sync after */
                    813: }
                    814: 
                    815: /*
                    816:  * task_map_io_ports() is required by the driverkit routines.
                    817:  */
                    818: kern_return_t
                    819: task_map_io_ports(
                    820:     task_t             task,
                    821:     unsigned int       port,
                    822:     unsigned int       length,
                    823:     boolean_t          unmap
                    824: )
                    825: {
                    826:        return (KERN_SUCCESS);
                    827: }
                    828: 
                    829: 
                    830: #if MACH_ASSERT
                    831: void
                    832: dump_pcb(pcb_t pcb)
                    833: {
                    834:        printf("pcb @ %8.8x:\n", pcb);
                    835:        printf("ksp       = 0x%08x\n\n",pcb->ksp);
                    836: #if DEBUG
                    837:        regDump(&pcb->ss);
                    838: #endif /* DEBUG */
                    839: }
                    840: 
                    841: void
                    842: dump_thread(thread_t th)
                    843: {
                    844:        printf(" thread @ 0x%x:\n", th);
                    845: }
                    846: #endif

unix.superglobalmegacorp.com

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