Annotation of XNU/osfmk/i386/bsd_i386.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: #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.