|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.