Annotation of XNU/osfmk/i386/bsd_i386.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: #ifdef MACH_BSD
                     23: #include <cpus.h>
                     24: #include <mach_rt.h>
                     25: #include <mach_debug.h>
                     26: #include <mach_ldebug.h>
                     27: 
                     28: #include <mach/kern_return.h>
                     29: #include <mach/thread_status.h>
                     30: #include <mach/vm_param.h>
                     31: #include <mach/rpc.h>
                     32: 
                     33: #include <kern/counters.h>
                     34: #include <kern/cpu_data.h>
                     35: #include <kern/mach_param.h>
                     36: #include <kern/task.h>
                     37: #include <kern/thread.h>
                     38: #include <kern/thread_swap.h>
                     39: #include <kern/sched_prim.h>
                     40: #include <kern/misc_protos.h>
                     41: #include <kern/assert.h>
                     42: #include <kern/spl.h>
                     43: #include <ipc/ipc_port.h>
                     44: #include <vm/vm_kern.h>
                     45: #include <vm/pmap.h>
                     46: 
                     47: #include <i386/thread.h>
                     48: #include <i386/eflags.h>
                     49: #include <i386/proc_reg.h>
                     50: #include <i386/seg.h>
                     51: #include <i386/tss.h>
                     52: #include <i386/user_ldt.h>
                     53: #include <i386/fpu.h>
                     54: #include <i386/iopb_entries.h>
                     55: #include <i386/machdep_call.h>
                     56: 
                     57: #define       USRSTACK        0xc0000000
                     58: 
                     59: kern_return_t
                     60: thread_userstack(
                     61:     thread_t,
                     62:     int,
                     63:     thread_state_t,
                     64:     unsigned int,
                     65:     vm_offset_t *
                     66: );
                     67: 
                     68: kern_return_t
                     69: thread_entrypoint(
                     70:     thread_t,
                     71:     int,
                     72:     thread_state_t,
                     73:     unsigned int,
                     74:     vm_offset_t *
                     75: ); 
                     76: 
                     77: struct i386_saved_state *
                     78: get_user_regs(
                     79:         thread_act_t);
                     80: 
                     81: void
                     82: act_thread_dup(
                     83:     thread_act_t,
                     84:     thread_act_t
                     85: );
                     86: 
                     87: unsigned int get_msr_exportmask(void);
                     88: 
                     89: unsigned int get_msr_nbits(void);
                     90: 
                     91: unsigned int get_msr_rbits(void);
                     92: 
                     93: /*
                     94:  * thread_userstack:
                     95:  *
                     96:  * Return the user stack pointer from the machine
                     97:  * dependent thread state info.
                     98:  */
                     99: kern_return_t
                    100: thread_userstack(
                    101:     thread_t            thread,
                    102:     int                 flavor,
                    103:     thread_state_t      tstate,
                    104:     unsigned int        count,
                    105:     vm_offset_t         *user_stack
                    106: )
                    107: {
                    108:         struct i386_saved_state *state;
                    109:        i386_thread_state_t *state25;
                    110:        vm_offset_t     uesp;
                    111: 
                    112:         /*
                    113:          * Set a default.
                    114:          */
                    115:         if (*user_stack == 0)
                    116:                 *user_stack = USRSTACK;
                    117: 
                    118:         switch (flavor) {
                    119:        case i386_THREAD_STATE: /* FIXME */
                    120:                 state25 = (i386_thread_state_t *) tstate;
                    121:                 *user_stack = state25->esp ? state25->esp : USRSTACK;
                    122:                break;
                    123: 
                    124:         case i386_NEW_THREAD_STATE:
                    125:                 if (count < i386_NEW_THREAD_STATE_COUNT)
                    126:                         return (KERN_INVALID_ARGUMENT);
                    127:                else {
                    128:                        state = (struct i386_saved_state *) tstate;
                    129:                        uesp = state->uesp;
                    130:                }
                    131: 
                    132:                 /*
                    133:                  * If a valid user stack is specified, use it.
                    134:                  */
                    135:                 *user_stack = uesp ? uesp : USRSTACK;
                    136:                 break;
                    137:         default :
                    138:                 return (KERN_INVALID_ARGUMENT);
                    139:         }
                    140:                 
                    141:         return (KERN_SUCCESS);
                    142: }    
                    143: 
                    144: kern_return_t
                    145: thread_entrypoint(
                    146:     thread_t            thread,
                    147:     int                 flavor,
                    148:     thread_state_t      tstate,
                    149:     unsigned int        count,
                    150:     vm_offset_t         *entry_point
                    151: )
                    152: { 
                    153:     struct i386_saved_state    *state;
                    154:     i386_thread_state_t *state25;
                    155: 
                    156:     /*
                    157:      * Set a default.
                    158:      */
                    159:     if (*entry_point == 0)
                    160:        *entry_point = VM_MIN_ADDRESS;
                    161:                
                    162:     switch (flavor) {
                    163:     case i386_THREAD_STATE:
                    164:        state25 = (i386_thread_state_t *) tstate;
                    165:        *entry_point = state25->eip ? state25->eip: VM_MIN_ADDRESS;
                    166:        break;
                    167: 
                    168:     case i386_NEW_THREAD_STATE:
                    169:        if (count < i386_THREAD_STATE_COUNT)
                    170:            return (KERN_INVALID_ARGUMENT);
                    171:        else {
                    172:                state = (struct i386_saved_state *) tstate;
                    173: 
                    174:                /*
                    175:                * If a valid entry point is specified, use it.
                    176:                */
                    177:                *entry_point = state->eip ? state->eip: VM_MIN_ADDRESS;
                    178:        }
                    179:        break;
                    180:     }
                    181: 
                    182:     return (KERN_SUCCESS);
                    183: }   
                    184: 
                    185: struct i386_saved_state *
                    186: get_user_regs(thread_act_t th)
                    187: {
                    188:        if (th->mact.pcb)
                    189:                return(USER_REGS(th));
                    190:        else {
                    191:                printf("[get_user_regs: thread does not have pcb]");
                    192:                return NULL;
                    193:        }
                    194: }
                    195: 
                    196: /*
                    197:  * Duplicate parent state in child
                    198:  * for U**X fork.
                    199:  */
                    200: void
                    201: act_thread_dup(
                    202:     thread_act_t               parent,
                    203:     thread_act_t               child
                    204: )
                    205: {
                    206:        struct i386_saved_state *parent_state, *child_state;
                    207:        struct i386_machine_state       *ims;
                    208:        struct i386_float_state         floatregs;
                    209: 
                    210: #ifdef XXX
                    211:        /* Save the FPU state */
                    212:        if ((pcb_t)(per_proc_info[cpu_number()].fpu_pcb) == parent->mact.pcb) {
                    213:                fp_state_save(parent);
                    214:        }
                    215: #endif
                    216: 
                    217:        if (child->mact.pcb == NULL 
                    218:        || parent->mact.pcb == NULL)  {
                    219:                panic("[thread_dup, child (%x) or parent (%x) is NULL!]",
                    220:                        child->mact.pcb, parent->mact.pcb);
                    221:                return;
                    222:        }
                    223: 
                    224:        /* Copy over the i386_saved_state registers */
                    225:        child->mact.pcb->iss = parent->mact.pcb->iss;
                    226: 
                    227:        /* Check to see if parent is using floating point
                    228:         * and if so, copy the registers to the child
                    229:         * FIXME - make sure this works.
                    230:         */
                    231: 
                    232:        if (parent->mact.pcb->ims.ifps)  {
                    233:                if (fpu_get_state(parent, &floatregs) == KERN_SUCCESS)
                    234:                        fpu_set_state(child, &floatregs);
                    235:        }
                    236:        
                    237:        /* FIXME - should a user specified LDT, TSS and V86 info
                    238:         * be duplicated as well?? - probably not.
                    239:         */
                    240: }
                    241: 
                    242: /* 
                    243:  * FIXME - thread_set_child
                    244:  */
                    245: 
                    246: void thread_set_child(thread_act_t child, int pid);
                    247: void
                    248: thread_set_child(thread_act_t child, int pid)
                    249: {
                    250:        child->mact.pcb->iss.eax = pid;
                    251:        child->mact.pcb->iss.edx = 1;
                    252:        child->mact.pcb->iss.efl &= ~EFL_CF;
                    253: }
                    254: 
                    255: 
                    256: 
                    257: /*
                    258:  * Move pages from one kernel virtual address to another.
                    259:  * Both addresses are assumed to reside in the Sysmap,
                    260:  * and size must be a multiple of the page size.
                    261:  */
                    262: void
                    263: pagemove(
                    264:        register caddr_t from,
                    265:        register caddr_t to,
                    266:        int size)
                    267: {
                    268:        pmap_movepage((unsigned long)from, (unsigned long)to, (vm_size_t)size);
                    269: }
                    270: 
                    271: /*
                    272:  * System Call handling code
                    273:  */
                    274: 
                    275: #define        ERESTART        -1              /* restart syscall */
                    276: #define        EJUSTRETURN     -2              /* don't modify regs, just return */
                    277: 
                    278: struct sysent {                /* system call table */
                    279:        unsigned short          sy_narg;                /* number of args */
                    280:        unsigned short          sy_parallel;    /* can execute in parallel */
                    281:        unsigned long           (*sy_call)(void *, void *, int *);      /* implementing function */
                    282: };
                    283: 
                    284: extern struct sysent sysent[];
                    285: 
                    286: void  *get_bsdtask_info(
                    287:        task_t);
                    288: 
                    289: int set_bsduthreadargs (thread_act_t, struct i386_saved_state *, void *);
                    290: 
                    291: void * get_bsduthreadarg(thread_act_t);
                    292: 
                    293: void unix_syscall(struct i386_saved_state *);
                    294: 
                    295: void
                    296: unix_syscall_return(int error)
                    297: {
                    298:   panic("unix_syscall_return not implemented yet!!");
                    299: }
                    300: 
                    301: 
                    302: void
                    303: unix_syscall(struct i386_saved_state *regs)
                    304: {
                    305:     thread_act_t               thread;
                    306:     void       *p, *vt; 
                    307:     unsigned short     code;
                    308:     struct sysent              *callp;
                    309:        int     nargs, error, rval[2];
                    310:     vm_offset_t                params;
                    311:     extern int nsysent;
                    312: 
                    313:     thread = current_act();
                    314:     p = get_bsdtask_info(current_task());
                    315: 
                    316:     //printf("[scall : eax %x]",  regs->eax);
                    317:     code = regs->eax;
                    318:     params = (vm_offset_t) ((caddr_t)regs->uesp + sizeof (int));
                    319:     callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
                    320:     if (callp == sysent) {
                    321:        code = fuword(params);
                    322:        params += sizeof (int);
                    323:        callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
                    324:     }
                    325:     
                    326:     vt = get_bsduthreadarg(thread);
                    327: 
                    328:     if ((nargs = (callp->sy_narg * sizeof (int))) &&
                    329:            (error = copyin((char *) params, (char *)vt , nargs)) != 0) {
                    330:        regs->eax = error;
                    331:        regs->efl |= EFL_CF;
                    332:        thread_exception_return();
                    333:        /* NOTREACHED */
                    334:     }
                    335:     
                    336:     rval[0] = 0;
                    337:     rval[1] = regs->edx;
                    338: 
                    339:     set_bsduthreadargs(thread, regs, NULL);
                    340: 
                    341:     if (callp->sy_narg > 8)
                    342:        panic("unix_syscall max arg count exceeded (%d)", callp->sy_narg);
                    343: 
                    344: 
                    345:     error = (*(callp->sy_call))(p, (void *) vt, rval);
                    346:        
                    347:        if (error == ERESTART) {
                    348:                regs->eip -= 7;
                    349:        }
                    350:        else if (error != EJUSTRETURN) {
                    351:                if (error) {
                    352:                    regs->eax = error;
                    353:                    regs->efl |= EFL_CF;        /* carry bit */
                    354:                } else { /* (not error) */
                    355:                    regs->eax = rval[0];
                    356:                    regs->edx = rval[1];
                    357:                    regs->efl &= ~EFL_CF;
                    358:                } 
                    359:        }
                    360: 
                    361:     thread_exception_return();
                    362:     /* NOTREACHED */
                    363: }
                    364: 
                    365: 
                    366: void
                    367: machdep_syscall( struct i386_saved_state *regs)
                    368: {
                    369:     int                                trapno, nargs;
                    370:     machdep_call_t             *entry;
                    371:     thread_t                   thread;
                    372:     
                    373:     trapno = regs->eax;
                    374:     if (trapno < 0 || trapno >= machdep_call_count) {
                    375:        regs->eax = (unsigned int)kern_invalid();
                    376: 
                    377:        thread_exception_return();
                    378:        /* NOTREACHED */
                    379:     }
                    380:     
                    381:     entry = &machdep_call_table[trapno];
                    382:     nargs = entry->nargs;
                    383: 
                    384:     if (nargs > 0) {
                    385:        int                     args[nargs];
                    386: 
                    387:        if (copyin((char *) regs->uesp + sizeof (int),
                    388:                    (char *) args,
                    389:                    nargs * sizeof (int))) {
                    390: 
                    391:            regs->eax = KERN_INVALID_ADDRESS;
                    392: 
                    393:            thread_exception_return();
                    394:            /* NOTREACHED */
                    395:        }
                    396: 
                    397:        asm volatile("
                    398:            1:
                    399:            mov (%2),%%eax;
                    400:            pushl %%eax;
                    401:            sub $4,%2;
                    402:            dec %1;
                    403:            jne 1b;
                    404:            mov %3,%%eax;
                    405:            call *%%eax;
                    406:            mov %%eax,%0"
                    407:            
                    408:            : "=r" (regs->eax)
                    409:            : "r" (nargs),
                    410:                "r" (&args[nargs - 1]),
                    411:                "g" (entry->routine)
                    412:            : "ax", "cx", "dx", "sp");
                    413:     }
                    414:     else
                    415:        regs->eax = (unsigned int)(*entry->routine)();
                    416: 
                    417:     (void) thread_set_funneled(FALSE);
                    418: 
                    419:     thread_exception_return();
                    420:     /* NOTREACHED */
                    421: }
                    422: 
                    423: 
                    424: kern_return_t
                    425: thread_set_cthread_self(int self)
                    426: {
                    427:    current_act()->mact.pcb->cthread_self = (unsigned int)self;
                    428:    
                    429:    return (KERN_SUCCESS);
                    430: }
                    431: 
                    432: kern_return_t
                    433: thread_get_cthread_self(void)
                    434: {
                    435:     return ((kern_return_t)current_act()->mact.pcb->cthread_self);
                    436: }
                    437: 
                    438: void
                    439: mach25_syscall(struct i386_saved_state *regs)
                    440: {
                    441:        printf("*** Atttempt to execute a Mach 2.5 system call at EIP=%x EAX=%x(%d)\n",
                    442:                        regs->eip, regs->eax, -regs->eax);
                    443:        panic("FIXME!");
                    444: }
                    445: 
                    446: #endif /* MACH_BSD */
                    447: 
                    448: #undef current_thread
                    449: thread_act_t
                    450: current_thread(void)
                    451: {
                    452:   return(current_thread_fast());
                    453: }

unix.superglobalmegacorp.com

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