X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/0b4e3aa066abc0728aacb4bbeb86f53f9737156e..a3d08fcd5120d2aa8303b6349ca8b14e3f284af3:/osfmk/i386/bsd_i386.c diff --git a/osfmk/i386/bsd_i386.c b/osfmk/i386/bsd_i386.c index d7caa5a15..bdd39922a 100644 --- a/osfmk/i386/bsd_i386.c +++ b/osfmk/i386/bsd_i386.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -40,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -54,7 +54,9 @@ #include #include -#define USRSTACK 0xc0000000 +#include +#include +struct proc; kern_return_t thread_userstack( @@ -79,18 +81,15 @@ struct i386_saved_state * get_user_regs( thread_act_t); -void -act_thread_dup( - thread_act_t, - thread_act_t -); - unsigned int get_msr_exportmask(void); unsigned int get_msr_nbits(void); unsigned int get_msr_rbits(void); +kern_return_t +thread_compose_cthread_desc(unsigned int addr, pcb_t pcb); + /* * thread_userstack: * @@ -111,22 +110,18 @@ thread_userstack( i386_thread_state_t *state25; vm_offset_t uesp; - /* - * Set a default. - */ - if (*user_stack == 0) - *user_stack = USRSTACK; - if (customstack) *customstack = 0; + switch (flavor) { case i386_THREAD_STATE: /* FIXME */ state25 = (i386_thread_state_t *) tstate; - *user_stack = state25->esp ? state25->esp : USRSTACK; - if (customstack && state25->esp) - *customstack = 1; - else - *customstack = 0; + if (state25->esp) + *user_stack = state25->esp; + if (customstack && state25->esp) + *customstack = 1; + else + *customstack = 0; break; case i386_NEW_THREAD_STATE: @@ -137,14 +132,13 @@ thread_userstack( uesp = state->uesp; } - /* - * If a valid user stack is specified, use it. - */ - *user_stack = uesp ? uesp : USRSTACK; - if (customstack && uesp) - *customstack = 1; - else - *customstack = 0; + /* If a valid user stack is specified, use it. */ + if (uesp) + *user_stack = uesp; + if (customstack && uesp) + *customstack = 1; + else + *customstack = 0; break; default : return (KERN_INVALID_ARGUMENT); @@ -209,8 +203,8 @@ get_user_regs(thread_act_t th) * Duplicate parent state in child * for U**X fork. */ -void -act_thread_dup( +kern_return_t +machine_thread_dup( thread_act_t parent, thread_act_t child ) @@ -226,12 +220,8 @@ act_thread_dup( } #endif - if (child->mact.pcb == NULL - || parent->mact.pcb == NULL) { - panic("[thread_dup, child (%x) or parent (%x) is NULL!]", - child->mact.pcb, parent->mact.pcb); - return; - } + if (child->mact.pcb == NULL || parent->mact.pcb == NULL) + return (KERN_FAILURE); /* Copy over the i386_saved_state registers */ child->mact.pcb->iss = parent->mact.pcb->iss; @@ -249,6 +239,8 @@ act_thread_dup( /* FIXME - should a user specified LDT, TSS and V86 info * be duplicated as well?? - probably not. */ + + return (KERN_SUCCESS); } /* @@ -302,6 +294,7 @@ struct sysent { /* system call table */ unsigned long (*sy_call)(void *, void *, int *); /* implementing function */ }; +#define NO_FUNNEL 0 #define KERNEL_FUNNEL 1 #define NETWORK_FUNNEL 2 @@ -310,26 +303,39 @@ extern funnel_t * network_flock; extern struct sysent sysent[]; - int set_bsduthreadargs (thread_act_t, struct i386_saved_state *, void *); void * get_bsduthreadarg(thread_act_t); void unix_syscall(struct i386_saved_state *); -/* USED ONLY FROM VFORK/EXIT */ void unix_syscall_return(int error) { thread_act_t thread; volatile int *rval; struct i386_saved_state *regs; + struct proc *p; + struct proc *current_proc(); + unsigned short code; + vm_offset_t params; + struct sysent *callp; + extern int nsysent; thread = current_act(); rval = (int *)get_bsduthreadrval(thread); + p = current_proc(); regs = USER_REGS(thread); + /* reconstruct code for tracing before blasting eax */ + code = regs->eax; + params = (vm_offset_t) ((caddr_t)regs->uesp + sizeof (int)); + callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; + if (callp == sysent) { + code = fuword(params); + } + if (error == ERESTART) { regs->eip -= 7; } @@ -344,7 +350,13 @@ unix_syscall_return(int error) } } - (void) thread_funnel_set(current_thread()->funnel_lock, FALSE); + ktrsysret(p, code, error, rval[0], callp->sy_funnel); + + KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_END, + error, rval[0], rval[1], 0, 0); + + if (callp->sy_funnel != NO_FUNNEL) + (void) thread_funnel_set(current_thread()->funnel_lock, FALSE); thread_exception_return(); /* NOTREACHED */ @@ -355,14 +367,16 @@ void unix_syscall(struct i386_saved_state *regs) { thread_act_t thread; - void *p, *vt; + void *vt; unsigned short code; struct sysent *callp; int nargs, error; volatile int *rval; - int funnel_type; + int funnel_type; vm_offset_t params; extern int nsysent; + struct proc *p; + struct proc *current_proc(); thread = current_act(); p = current_proc(); @@ -391,19 +405,26 @@ unix_syscall(struct i386_saved_state *regs) rval[0] = 0; rval[1] = regs->edx; - if(callp->sy_funnel == NETWORK_FUNNEL) { - (void) thread_funnel_set(network_flock, TRUE); - } - else { - (void) thread_funnel_set(kernel_flock, TRUE); - } + funnel_type = callp->sy_funnel; + if(funnel_type == KERNEL_FUNNEL) + (void) thread_funnel_set(kernel_flock, TRUE); + else if (funnel_type == NETWORK_FUNNEL) + (void) thread_funnel_set(network_flock, TRUE); + set_bsduthreadargs(thread, regs, NULL); if (callp->sy_narg > 8) panic("unix_syscall max arg count exceeded (%d)", callp->sy_narg); + ktrsyscall(p, code, callp->sy_narg, vt, funnel_type); + + { + int *ip = (int *)vt; + KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_START, + *ip, *(ip+1), *(ip+2), *(ip+3), 0); + } - error = (*(callp->sy_call))(p, (void *) vt, rval); + error = (*(callp->sy_call))(p, (void *) vt, (int *) &rval[0]); #if 0 /* May be needed with vfork changes */ @@ -423,7 +444,13 @@ unix_syscall(struct i386_saved_state *regs) } } - (void) thread_funnel_set(current_thread()->funnel_lock, FALSE); + ktrsysret(p, code, error, rval[0], funnel_type); + + KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_EXCP_SC, code) | DBG_FUNC_END, + error, rval[0], rval[1], 0, 0); + + if(funnel_type != NO_FUNNEL) + (void) thread_funnel_set(current_thread()->funnel_lock, FALSE); thread_exception_return(); /* NOTREACHED */ @@ -436,6 +463,8 @@ machdep_syscall( struct i386_saved_state *regs) int trapno, nargs; machdep_call_t *entry; thread_t thread; + struct proc *p; + struct proc *current_proc(); trapno = regs->eax; if (trapno < 0 || trapno >= machdep_call_count) { @@ -461,33 +490,55 @@ machdep_syscall( struct i386_saved_state *regs) /* NOTREACHED */ } - asm volatile(" - 1: - mov (%2),%%eax; - pushl %%eax; - sub $4,%2; - dec %1; - jne 1b; - mov %3,%%eax; - call *%%eax; - mov %%eax,%0" - - : "=r" (regs->eax) - : "r" (nargs), - "r" (&args[nargs - 1]), - "g" (entry->routine) - : "ax", "cx", "dx", "sp"); + switch (nargs) { + case 1: + regs->eax = (*entry->routine)(args[0]); + break; + case 2: + regs->eax = (*entry->routine)(args[0],args[1]); + break; + case 3: + regs->eax = (*entry->routine)(args[0],args[1],args[2]); + break; + case 4: + regs->eax = (*entry->routine)(args[0],args[1],args[2],args[3]); + break; + default: + panic("machdep_syscall(): too many args"); + } } else - regs->eax = (unsigned int)(*entry->routine)(); + regs->eax = (*entry->routine)(); - (void) thread_funnel_set(current_thread()->funnel_lock, FALSE); + if (current_thread()->funnel_lock) + (void) thread_funnel_set(current_thread()->funnel_lock, FALSE); thread_exception_return(); /* NOTREACHED */ } +kern_return_t +thread_compose_cthread_desc(unsigned int addr, pcb_t pcb) +{ + struct real_descriptor desc; + extern struct fake_descriptor *mp_ldt[]; + struct real_descriptor *ldtp; + int mycpu = cpu_number(); + + ldtp = (struct real_descriptor *)mp_ldt[mycpu]; + desc.limit_low = 1; + desc.limit_high = 0; + desc.base_low = addr & 0xffff; + desc.base_med = (addr >> 16) & 0xff; + desc.base_high = (addr >> 24) & 0xff; + desc.access = ACC_P|ACC_PL_U|ACC_DATA_W; + desc.granularity = SZ_32|SZ_G; + pcb->cthread_desc = desc; + ldtp[sel_idx(USER_CTHREAD)] = desc; + return(KERN_SUCCESS); +} + kern_return_t thread_set_cthread_self(int self) { @@ -502,6 +553,16 @@ thread_get_cthread_self(void) return ((kern_return_t)current_act()->mact.pcb->cthread_self); } +kern_return_t +thread_fast_set_cthread_self(int self) +{ + pcb_t pcb; + pcb = (pcb_t)current_act()->mact.pcb; + thread_compose_cthread_desc((unsigned int)self, pcb); + pcb->cthread_self = (unsigned int)self; /* preserve old func too */ + return (USER_CTHREAD); +} + void mach25_syscall(struct i386_saved_state *regs) { @@ -509,12 +570,52 @@ mach25_syscall(struct i386_saved_state *regs) regs->eip, regs->eax, -regs->eax); panic("FIXME!"); } - #endif /* MACH_BSD */ -#undef current_thread -thread_act_t -current_thread(void) + +/* This routine is called from assembly before each and every mach trap. + */ + +extern unsigned int mach_call_start(unsigned int, unsigned int *); + +__private_extern__ +unsigned int +mach_call_start(unsigned int call_number, unsigned int *args) { - return(current_thread_fast()); + int i, argc; + unsigned int kdarg[3]; + +/* Always prepare to trace mach system calls */ + + kdarg[0]=0; + kdarg[1]=0; + kdarg[2]=0; + + argc = mach_trap_table[call_number>>4].mach_trap_arg_count; + + if (argc > 3) + argc = 3; + + for (i=0; i < argc; i++) + kdarg[i] = (int)*(args + i); + + KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC, (call_number>>4)) | DBG_FUNC_START, + kdarg[0], kdarg[1], kdarg[2], 0, 0); + + return call_number; /* pass this back thru */ } + +/* This routine is called from assembly after each mach system call + */ + +extern unsigned int mach_call_end(unsigned int, unsigned int); + +__private_extern__ +unsigned int +mach_call_end(unsigned int call_number, unsigned int retval) +{ + KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC,(call_number>>4)) | DBG_FUNC_END, + retval, 0, 0, 0, 0); + return retval; /* pass this back thru */ +} +