|
|
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: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: ! 51: #include <cpus.h> ! 52: #include <mach_rt.h> ! 53: #include <mach_debug.h> ! 54: #include <mach_ldebug.h> ! 55: ! 56: #include <mach/kern_return.h> ! 57: #include <mach/thread_status.h> ! 58: #include <mach/vm_param.h> ! 59: #include <mach/rpc.h> ! 60: ! 61: #include <kern/counters.h> ! 62: #include <kern/mach_param.h> ! 63: #include <kern/task.h> ! 64: #include <kern/thread.h> ! 65: #include <kern/thread_act.h> ! 66: #include <kern/thread_swap.h> ! 67: #include <kern/sched_prim.h> ! 68: #include <kern/misc_protos.h> ! 69: #include <kern/assert.h> ! 70: #include <kern/spl.h> ! 71: #include <ipc/ipc_port.h> ! 72: #include <vm/vm_kern.h> ! 73: #include <vm/pmap.h> ! 74: ! 75: #include <i386/thread.h> ! 76: #include <i386/eflags.h> ! 77: #include <i386/proc_reg.h> ! 78: #include <i386/seg.h> ! 79: #include <i386/tss.h> ! 80: #include <i386/user_ldt.h> ! 81: #include <i386/fpu.h> ! 82: #include <i386/iopb_entries.h> ! 83: ! 84: /* ! 85: * Maps state flavor to number of words in the state: ! 86: */ ! 87: unsigned int state_count[] = { ! 88: /* FLAVOR_LIST */ 0, ! 89: i386_NEW_THREAD_STATE_COUNT, ! 90: i386_FLOAT_STATE_COUNT, ! 91: i386_ISA_PORT_MAP_STATE_COUNT, ! 92: i386_V86_ASSIST_STATE_COUNT, ! 93: i386_REGS_SEGS_STATE_COUNT, ! 94: i386_THREAD_SYSCALL_STATE_COUNT, ! 95: /* THREAD_STATE_NONE */ 0, ! 96: i386_SAVED_STATE_COUNT, ! 97: }; ! 98: ! 99: /* Forward */ ! 100: ! 101: void act_machine_throughcall(thread_act_t thr_act); ! 102: extern thread_t Switch_context( ! 103: thread_t old, ! 104: void (*cont)(void), ! 105: thread_t new); ! 106: extern void Thread_continue(void); ! 107: extern void Load_context( ! 108: thread_t thread); ! 109: ! 110: /* ! 111: * consider_machine_collect: ! 112: * ! 113: * Try to collect machine-dependent pages ! 114: */ ! 115: void ! 116: consider_machine_collect() ! 117: { ! 118: } ! 119: ! 120: /* ! 121: * machine_kernel_stack_init: ! 122: * ! 123: * Initialize a kernel stack which has already been ! 124: * attached to its thread_activation. ! 125: */ ! 126: ! 127: void ! 128: machine_kernel_stack_init( ! 129: thread_t thread, ! 130: void (*continuation)(void)) ! 131: { ! 132: thread_act_t thr_act = thread->top_act; ! 133: vm_offset_t stack; ! 134: ! 135: assert(thr_act); ! 136: stack = thread->kernel_stack; ! 137: assert(stack); ! 138: ! 139: #if MACH_ASSERT ! 140: if (watchacts & WA_PCB) { ! 141: printf("machine_kernel_stack_init(thr=%x,stk=%x,cont=%x)\n", ! 142: thread,stack,continuation); ! 143: printf("\tstack_iks=%x, stack_iel=%x\n", ! 144: STACK_IKS(stack), STACK_IEL(stack)); ! 145: } ! 146: #endif /* MACH_ASSERT */ ! 147: ! 148: /* ! 149: * We want to run continuation, giving it as an argument ! 150: * the return value from Load_context/Switch_context. ! 151: * Thread_continue takes care of the mismatch between ! 152: * the argument-passing/return-value conventions. ! 153: * This function will not return normally, ! 154: * so we don`t have to worry about a return address. ! 155: */ ! 156: STACK_IKS(stack)->k_eip = (int) Thread_continue; ! 157: STACK_IKS(stack)->k_ebx = (int) continuation; ! 158: STACK_IKS(stack)->k_esp = (int) STACK_IEL(stack); ! 159: ! 160: /* ! 161: * Point top of kernel stack to user`s registers. ! 162: */ ! 163: STACK_IEL(stack)->saved_state = &thr_act->mact.pcb->iss; ! 164: } ! 165: ! 166: ! 167: #if NCPUS > 1 ! 168: #define curr_gdt(mycpu) (mp_gdt[mycpu]) ! 169: #define curr_ktss(mycpu) (mp_ktss[mycpu]) ! 170: #else ! 171: #define curr_gdt(mycpu) (gdt) ! 172: #define curr_ktss(mycpu) (&ktss) ! 173: #endif ! 174: ! 175: #define gdt_desc_p(mycpu,sel) \ ! 176: ((struct real_descriptor *)&curr_gdt(mycpu)[sel_idx(sel)]) ! 177: ! 178: void ! 179: act_machine_switch_pcb( thread_act_t new_act ) ! 180: { ! 181: pcb_t pcb = new_act->mact.pcb; ! 182: int mycpu; ! 183: { ! 184: register iopb_tss_t tss = pcb->ims.io_tss; ! 185: vm_offset_t pcb_stack_top; ! 186: ! 187: assert(new_act->thread != NULL); ! 188: assert(new_act->thread->kernel_stack != 0); ! 189: STACK_IEL(new_act->thread->kernel_stack)->saved_state = ! 190: &new_act->mact.pcb->iss; ! 191: ! 192: /* ! 193: * Save a pointer to the top of the "kernel" stack - ! 194: * actually the place in the PCB where a trap into ! 195: * kernel mode will push the registers. ! 196: * The location depends on V8086 mode. If we are ! 197: * not in V8086 mode, then a trap into the kernel ! 198: * won`t save the v86 segments, so we leave room. ! 199: */ ! 200: ! 201: pcb_stack_top = (pcb->iss.efl & EFL_VM) ! 202: ? (int) (&pcb->iss + 1) ! 203: : (int) (&pcb->iss.v86_segs); ! 204: ! 205: mp_disable_preemption(); ! 206: mycpu = cpu_number(); ! 207: ! 208: if (tss == 0) { ! 209: /* ! 210: * No per-thread IO permissions. ! 211: * Use standard kernel TSS. ! 212: */ ! 213: if (!(gdt_desc_p(mycpu,KERNEL_TSS)->access & ACC_TSS_BUSY)) ! 214: set_tr(KERNEL_TSS); ! 215: curr_ktss(mycpu)->esp0 = pcb_stack_top; ! 216: } ! 217: else { ! 218: /* ! 219: * Set the IO permissions. Use this thread`s TSS. ! 220: */ ! 221: *gdt_desc_p(mycpu,USER_TSS) ! 222: = *(struct real_descriptor *)tss->iopb_desc; ! 223: tss->tss.esp0 = pcb_stack_top; ! 224: set_tr(USER_TSS); ! 225: gdt_desc_p(mycpu,KERNEL_TSS)->access &= ~ ACC_TSS_BUSY; ! 226: } ! 227: } ! 228: ! 229: { ! 230: register user_ldt_t ldt = pcb->ims.ldt; ! 231: /* ! 232: * Set the thread`s LDT. ! 233: */ ! 234: if (ldt == 0) { ! 235: /* ! 236: * Use system LDT. ! 237: */ ! 238: set_ldt(KERNEL_LDT); ! 239: } ! 240: else { ! 241: /* ! 242: * Thread has its own LDT. ! 243: */ ! 244: *gdt_desc_p(mycpu,USER_LDT) = ldt->desc; ! 245: set_ldt(USER_LDT); ! 246: } ! 247: } ! 248: mp_enable_preemption(); ! 249: /* ! 250: * Load the floating-point context, if necessary. ! 251: */ ! 252: fpu_load_context(pcb); ! 253: ! 254: } ! 255: ! 256: /* ! 257: * flush out any lazily evaluated HW state in the ! 258: * owning thread's context, before termination. ! 259: */ ! 260: void ! 261: thread_machine_flush( thread_act_t cur_act ) ! 262: { ! 263: fpflush(cur_act); ! 264: } ! 265: ! 266: /* ! 267: * Switch to the first thread on a CPU. ! 268: */ ! 269: void ! 270: load_context( ! 271: thread_t new) ! 272: { ! 273: act_machine_switch_pcb(new->top_act); ! 274: Load_context(new); ! 275: } ! 276: ! 277: /* ! 278: * Number of times we needed to swap an activation back in before ! 279: * switching to it. ! 280: */ ! 281: int switch_act_swapins = 0; ! 282: ! 283: /* ! 284: * machine_switch_act ! 285: * ! 286: * Machine-dependent details of activation switching. Called with ! 287: * RPC locks held and preemption disabled. ! 288: */ ! 289: void ! 290: machine_switch_act( ! 291: thread_t thread, ! 292: thread_act_t old, ! 293: thread_act_t new, ! 294: int cpu) ! 295: { ! 296: /* ! 297: * Switch the vm, ast and pcb context. ! 298: * Save FP registers if in use and set TS (task switch) bit. ! 299: */ ! 300: fpu_save_context(thread); ! 301: ! 302: active_stacks[cpu] = thread->kernel_stack; ! 303: ast_context(new, cpu); ! 304: ! 305: PMAP_SWITCH_CONTEXT(old, new, cpu); ! 306: act_machine_switch_pcb(new); ! 307: } ! 308: ! 309: /* ! 310: * Switch to a new thread. ! 311: * Save the old thread`s kernel state or continuation, ! 312: * and return it. ! 313: */ ! 314: thread_t ! 315: switch_context( ! 316: thread_t old, ! 317: void (*continuation)(void), ! 318: thread_t new) ! 319: { ! 320: register thread_act_t old_act = old->top_act, ! 321: new_act = new->top_act; ! 322: ! 323: #if MACH_RT ! 324: assert(old_act->kernel_loaded || ! 325: active_stacks[cpu_number()] == old_act->thread->kernel_stack); ! 326: assert (get_preemption_level() == 1); ! 327: #endif ! 328: check_simple_locks(); ! 329: ! 330: /* ! 331: * Save FP registers if in use. ! 332: */ ! 333: fpu_save_context(old); ! 334: ! 335: #if MACH_ASSERT ! 336: if (watchacts & WA_SWITCH) ! 337: printf("\tswitch_context(old=%x con=%x new=%x)\n", ! 338: old, continuation, new); ! 339: #endif /* MACH_ASSERT */ ! 340: ! 341: /* ! 342: * Switch address maps if need be, even if not switching tasks. ! 343: * (A server activation may be "borrowing" a client map.) ! 344: */ ! 345: { ! 346: int mycpu = cpu_number(); ! 347: ! 348: PMAP_SWITCH_CONTEXT(old_act, new_act, mycpu) ! 349: } ! 350: ! 351: /* ! 352: * Load the rest of the user state for the new thread ! 353: */ ! 354: act_machine_switch_pcb(new_act); ! 355: return(Switch_context(old, continuation, new)); ! 356: } ! 357: ! 358: void ! 359: pcb_module_init(void) ! 360: { ! 361: fpu_module_init(); ! 362: iopb_init(); ! 363: } ! 364: ! 365: void ! 366: pcb_init( register thread_act_t thr_act ) ! 367: { ! 368: register pcb_t pcb; ! 369: ! 370: assert(thr_act->mact.pcb == (pcb_t)0); ! 371: pcb = thr_act->mact.pcb = &thr_act->mact.xxx_pcb; ! 372: ! 373: #if MACH_ASSERT ! 374: if (watchacts & WA_PCB) ! 375: printf("pcb_init(%x) pcb=%x\n", thr_act, pcb); ! 376: #endif /* MACH_ASSERT */ ! 377: ! 378: /* ! 379: * We can't let random values leak out to the user. ! 380: * (however, act_create() zeroed the entire thr_act, mact, pcb) ! 381: * bzero((char *) pcb, sizeof *pcb); ! 382: */ ! 383: simple_lock_init(&pcb->lock, ETAP_MISC_PCB); ! 384: ! 385: /* ! 386: * Guarantee that the bootstrapped thread will be in user ! 387: * mode. ! 388: */ ! 389: pcb->iss.cs = USER_CS; ! 390: pcb->iss.ss = USER_DS; ! 391: pcb->iss.ds = USER_DS; ! 392: pcb->iss.es = USER_DS; ! 393: pcb->iss.fs = USER_DS; ! 394: pcb->iss.gs = USER_DS; ! 395: pcb->iss.efl = EFL_USER_SET; ! 396: } ! 397: ! 398: /* ! 399: * Adjust saved register state for thread belonging to task ! 400: * created with kernel_task_create(). ! 401: */ ! 402: void ! 403: pcb_user_to_kernel( ! 404: thread_act_t thr_act) ! 405: { ! 406: register pcb_t pcb = thr_act->mact.pcb; ! 407: ! 408: pcb->iss.cs = KERNEL_CS; ! 409: pcb->iss.ss = KERNEL_DS; ! 410: pcb->iss.ds = KERNEL_DS; ! 411: pcb->iss.es = KERNEL_DS; ! 412: pcb->iss.fs = KERNEL_DS; ! 413: pcb->iss.gs = CPU_DATA; ! 414: } ! 415: ! 416: void ! 417: pcb_terminate( ! 418: register thread_act_t thr_act) ! 419: { ! 420: register pcb_t pcb = thr_act->mact.pcb; ! 421: ! 422: assert(pcb); ! 423: ! 424: if (pcb->ims.io_tss != 0) ! 425: iopb_destroy(pcb->ims.io_tss); ! 426: if (pcb->ims.ifps != 0) ! 427: fp_free(pcb->ims.ifps); ! 428: if (pcb->ims.ldt != 0) ! 429: user_ldt_free(pcb->ims.ldt); ! 430: thr_act->mact.pcb = (pcb_t)0; ! 431: } ! 432: ! 433: /* ! 434: * pcb_collect: ! 435: * ! 436: * Attempt to free excess pcb memory. ! 437: */ ! 438: ! 439: void ! 440: pcb_collect( ! 441: register thread_act_t thr_act) ! 442: { ! 443: /* accomplishes very little */ ! 444: } ! 445: ! 446: /* ! 447: * act_machine_sv_free ! 448: * release saveareas associated with an act. if flag is true, release ! 449: * user level savearea(s) too, else don't ! 450: */ ! 451: void ! 452: act_machine_sv_free(thread_act_t act, int flag) ! 453: { ! 454: ! 455: } ! 456: ! 457: /* ! 458: * act_machine_set_state: ! 459: * ! 460: * Set the status of the specified thread. Called with "appropriate" ! 461: * thread-related locks held (see act_lock_thread()), so ! 462: * thr_act->thread is guaranteed not to change. ! 463: */ ! 464: ! 465: kern_return_t ! 466: act_machine_set_state( ! 467: thread_act_t thr_act, ! 468: thread_flavor_t flavor, ! 469: thread_state_t tstate, ! 470: mach_msg_type_number_t count) ! 471: { ! 472: int kernel_act = thr_act->kernel_loading || ! 473: thr_act->kernel_loaded; ! 474: ! 475: #if MACH_ASSERT ! 476: if (watchacts & WA_STATE) ! 477: printf("act_%x act_m_set_state(thr_act=%x,flav=%x,st=%x,cnt=%x)\n", ! 478: current_act(), thr_act, flavor, tstate, count); ! 479: #endif /* MACH_ASSERT */ ! 480: ! 481: switch (flavor) { ! 482: case THREAD_SYSCALL_STATE: ! 483: { ! 484: register struct thread_syscall_state *state; ! 485: register struct i386_saved_state *saved_state = USER_REGS(thr_act); ! 486: ! 487: state = (struct thread_syscall_state *) tstate; ! 488: saved_state->eax = state->eax; ! 489: saved_state->edx = state->edx; ! 490: if (kernel_act) ! 491: saved_state->efl = state->efl; ! 492: else ! 493: saved_state->efl = (state->efl & ~EFL_USER_CLEAR) | EFL_USER_SET; ! 494: saved_state->eip = state->eip; ! 495: saved_state->uesp = state->esp; ! 496: break; ! 497: } ! 498: ! 499: case i386_SAVED_STATE: ! 500: { ! 501: register struct i386_saved_state *state; ! 502: register struct i386_saved_state *saved_state; ! 503: ! 504: if (count < i386_SAVED_STATE_COUNT) { ! 505: return(KERN_INVALID_ARGUMENT); ! 506: } ! 507: ! 508: state = (struct i386_saved_state *) tstate; ! 509: ! 510: saved_state = USER_REGS(thr_act); ! 511: ! 512: /* ! 513: * General registers ! 514: */ ! 515: saved_state->edi = state->edi; ! 516: saved_state->esi = state->esi; ! 517: saved_state->ebp = state->ebp; ! 518: saved_state->uesp = state->uesp; ! 519: saved_state->ebx = state->ebx; ! 520: saved_state->edx = state->edx; ! 521: saved_state->ecx = state->ecx; ! 522: saved_state->eax = state->eax; ! 523: saved_state->eip = state->eip; ! 524: if (kernel_act) ! 525: saved_state->efl = state->efl; ! 526: else ! 527: saved_state->efl = (state->efl & ~EFL_USER_CLEAR) ! 528: | EFL_USER_SET; ! 529: ! 530: /* ! 531: * Segment registers. Set differently in V8086 mode. ! 532: */ ! 533: if (state->efl & EFL_VM) { ! 534: /* ! 535: * Set V8086 mode segment registers. ! 536: */ ! 537: saved_state->cs = state->cs & 0xffff; ! 538: saved_state->ss = state->ss & 0xffff; ! 539: saved_state->v86_segs.v86_ds = state->ds & 0xffff; ! 540: saved_state->v86_segs.v86_es = state->es & 0xffff; ! 541: saved_state->v86_segs.v86_fs = state->fs & 0xffff; ! 542: saved_state->v86_segs.v86_gs = state->gs & 0xffff; ! 543: ! 544: /* ! 545: * Zero protected mode segment registers. ! 546: */ ! 547: saved_state->ds = 0; ! 548: saved_state->es = 0; ! 549: saved_state->fs = 0; ! 550: saved_state->gs = 0; ! 551: ! 552: if (thr_act->mact.pcb->ims.v86s.int_table) { ! 553: /* ! 554: * Hardware assist on. ! 555: */ ! 556: thr_act->mact.pcb->ims.v86s.flags = ! 557: state->efl & (EFL_TF | EFL_IF); ! 558: } ! 559: } ! 560: else if (!kernel_act) { ! 561: /* ! 562: * 386 mode. Set segment registers for flat ! 563: * 32-bit address space. ! 564: */ ! 565: saved_state->cs = USER_CS; ! 566: saved_state->ss = USER_DS; ! 567: saved_state->ds = USER_DS; ! 568: saved_state->es = USER_DS; ! 569: saved_state->fs = USER_DS; ! 570: saved_state->gs = USER_DS; ! 571: } ! 572: else { ! 573: /* ! 574: * User setting segment registers. ! 575: * Code and stack selectors have already been ! 576: * checked. Others will be reset by 'iret' ! 577: * if they are not valid. ! 578: */ ! 579: saved_state->cs = state->cs; ! 580: saved_state->ss = state->ss; ! 581: saved_state->ds = state->ds; ! 582: saved_state->es = state->es; ! 583: saved_state->fs = state->fs; ! 584: saved_state->gs = state->gs; ! 585: } ! 586: break; ! 587: } ! 588: ! 589: case i386_NEW_THREAD_STATE: ! 590: case i386_REGS_SEGS_STATE: ! 591: { ! 592: register struct i386_new_thread_state *state; ! 593: register struct i386_saved_state *saved_state; ! 594: ! 595: if (count < i386_NEW_THREAD_STATE_COUNT) { ! 596: return(KERN_INVALID_ARGUMENT); ! 597: } ! 598: ! 599: if (flavor == i386_REGS_SEGS_STATE) { ! 600: /* ! 601: * Code and stack selectors must not be null, ! 602: * and must have user protection levels. ! 603: * Only the low 16 bits are valid. ! 604: */ ! 605: state->cs &= 0xffff; ! 606: state->ss &= 0xffff; ! 607: state->ds &= 0xffff; ! 608: state->es &= 0xffff; ! 609: state->fs &= 0xffff; ! 610: state->gs &= 0xffff; ! 611: ! 612: if (!kernel_act && ! 613: (state->cs == 0 || (state->cs & SEL_PL) != SEL_PL_U ! 614: || state->ss == 0 || (state->ss & SEL_PL) != SEL_PL_U)) ! 615: return KERN_INVALID_ARGUMENT; ! 616: } ! 617: ! 618: state = (struct i386_new_thread_state *) tstate; ! 619: ! 620: saved_state = USER_REGS(thr_act); ! 621: ! 622: /* ! 623: * General registers ! 624: */ ! 625: saved_state->edi = state->edi; ! 626: saved_state->esi = state->esi; ! 627: saved_state->ebp = state->ebp; ! 628: saved_state->uesp = state->uesp; ! 629: saved_state->ebx = state->ebx; ! 630: saved_state->edx = state->edx; ! 631: saved_state->ecx = state->ecx; ! 632: saved_state->eax = state->eax; ! 633: saved_state->eip = state->eip; ! 634: if (kernel_act) ! 635: saved_state->efl = state->efl; ! 636: else ! 637: saved_state->efl = (state->efl & ~EFL_USER_CLEAR) ! 638: | EFL_USER_SET; ! 639: ! 640: /* ! 641: * Segment registers. Set differently in V8086 mode. ! 642: */ ! 643: if (state->efl & EFL_VM) { ! 644: /* ! 645: * Set V8086 mode segment registers. ! 646: */ ! 647: saved_state->cs = state->cs & 0xffff; ! 648: saved_state->ss = state->ss & 0xffff; ! 649: saved_state->v86_segs.v86_ds = state->ds & 0xffff; ! 650: saved_state->v86_segs.v86_es = state->es & 0xffff; ! 651: saved_state->v86_segs.v86_fs = state->fs & 0xffff; ! 652: saved_state->v86_segs.v86_gs = state->gs & 0xffff; ! 653: ! 654: /* ! 655: * Zero protected mode segment registers. ! 656: */ ! 657: saved_state->ds = 0; ! 658: saved_state->es = 0; ! 659: saved_state->fs = 0; ! 660: saved_state->gs = 0; ! 661: ! 662: if (thr_act->mact.pcb->ims.v86s.int_table) { ! 663: /* ! 664: * Hardware assist on. ! 665: */ ! 666: thr_act->mact.pcb->ims.v86s.flags = ! 667: state->efl & (EFL_TF | EFL_IF); ! 668: } ! 669: } ! 670: else if (flavor == i386_NEW_THREAD_STATE && !kernel_act) { ! 671: /* ! 672: * 386 mode. Set segment registers for flat ! 673: * 32-bit address space. ! 674: */ ! 675: saved_state->cs = USER_CS; ! 676: saved_state->ss = USER_DS; ! 677: saved_state->ds = USER_DS; ! 678: saved_state->es = USER_DS; ! 679: saved_state->fs = USER_DS; ! 680: saved_state->gs = USER_DS; ! 681: } ! 682: else { ! 683: /* ! 684: * User setting segment registers. ! 685: * Code and stack selectors have already been ! 686: * checked. Others will be reset by 'iret' ! 687: * if they are not valid. ! 688: */ ! 689: saved_state->cs = state->cs; ! 690: saved_state->ss = state->ss; ! 691: saved_state->ds = state->ds; ! 692: saved_state->es = state->es; ! 693: saved_state->fs = state->fs; ! 694: saved_state->gs = state->gs; ! 695: } ! 696: break; ! 697: } ! 698: ! 699: case i386_FLOAT_STATE: { ! 700: ! 701: if (count < i386_FLOAT_STATE_COUNT) ! 702: return(KERN_INVALID_ARGUMENT); ! 703: ! 704: return fpu_set_state(thr_act,(struct i386_float_state*)tstate); ! 705: } ! 706: ! 707: /* ! 708: * Temporary - replace by i386_io_map ! 709: */ ! 710: case i386_ISA_PORT_MAP_STATE: { ! 711: register struct i386_isa_port_map_state *state; ! 712: register iopb_tss_t tss; ! 713: ! 714: if (count < i386_ISA_PORT_MAP_STATE_COUNT) ! 715: return(KERN_INVALID_ARGUMENT); ! 716: ! 717: break; ! 718: } ! 719: ! 720: case i386_V86_ASSIST_STATE: ! 721: { ! 722: register struct i386_v86_assist_state *state; ! 723: vm_offset_t int_table; ! 724: int int_count; ! 725: ! 726: if (count < i386_V86_ASSIST_STATE_COUNT) ! 727: return KERN_INVALID_ARGUMENT; ! 728: ! 729: state = (struct i386_v86_assist_state *) tstate; ! 730: int_table = state->int_table; ! 731: int_count = state->int_count; ! 732: ! 733: if (int_table >= VM_MAX_ADDRESS || ! 734: int_table + ! 735: int_count * sizeof(struct v86_interrupt_table) ! 736: > VM_MAX_ADDRESS) ! 737: return KERN_INVALID_ARGUMENT; ! 738: ! 739: thr_act->mact.pcb->ims.v86s.int_table = int_table; ! 740: thr_act->mact.pcb->ims.v86s.int_count = int_count; ! 741: ! 742: thr_act->mact.pcb->ims.v86s.flags = ! 743: USER_REGS(thr_act)->efl & (EFL_TF | EFL_IF); ! 744: break; ! 745: } ! 746: ! 747: case i386_THREAD_STATE: { ! 748: struct i386_saved_state *saved_state; ! 749: i386_thread_state_t *state25; ! 750: ! 751: saved_state = USER_REGS(thr_act); ! 752: state25 = (i386_thread_state_t *)tstate; ! 753: ! 754: saved_state->eax = state25->eax; ! 755: saved_state->ebx = state25->ebx; ! 756: saved_state->ecx = state25->ecx; ! 757: saved_state->edx = state25->edx; ! 758: saved_state->edi = state25->edi; ! 759: saved_state->esi = state25->esi; ! 760: saved_state->ebp = state25->ebp; ! 761: saved_state->uesp = state25->esp; ! 762: saved_state->efl = (state25->eflags & ~EFL_USER_CLEAR) ! 763: | EFL_USER_SET; ! 764: saved_state->eip = state25->eip; ! 765: saved_state->cs = USER_CS; /* FIXME? */ ! 766: saved_state->ss = USER_DS; ! 767: saved_state->ds = USER_DS; ! 768: saved_state->es = USER_DS; ! 769: saved_state->fs = USER_DS; ! 770: saved_state->gs = USER_DS; ! 771: } ! 772: break; ! 773: ! 774: default: ! 775: return(KERN_INVALID_ARGUMENT); ! 776: } ! 777: ! 778: return(KERN_SUCCESS); ! 779: } ! 780: ! 781: /* ! 782: * thread_getstatus: ! 783: * ! 784: * Get the status of the specified thread. ! 785: */ ! 786: ! 787: ! 788: kern_return_t ! 789: act_machine_get_state( ! 790: thread_act_t thr_act, ! 791: thread_flavor_t flavor, ! 792: thread_state_t tstate, ! 793: mach_msg_type_number_t *count) ! 794: { ! 795: #if MACH_ASSERT ! 796: if (watchacts & WA_STATE) ! 797: printf("act_%x act_m_get_state(thr_act=%x,flav=%x,st=%x,cnt@%x=%x)\n", ! 798: current_act(), thr_act, flavor, tstate, ! 799: count, (count ? *count : 0)); ! 800: #endif /* MACH_ASSERT */ ! 801: ! 802: switch (flavor) { ! 803: ! 804: case i386_SAVED_STATE: ! 805: { ! 806: register struct i386_saved_state *state; ! 807: register struct i386_saved_state *saved_state; ! 808: ! 809: if (*count < i386_SAVED_STATE_COUNT) ! 810: return(KERN_INVALID_ARGUMENT); ! 811: ! 812: state = (struct i386_saved_state *) tstate; ! 813: saved_state = USER_REGS(thr_act); ! 814: ! 815: /* ! 816: * First, copy everything: ! 817: */ ! 818: *state = *saved_state; ! 819: ! 820: if (saved_state->efl & EFL_VM) { ! 821: /* ! 822: * V8086 mode. ! 823: */ ! 824: state->ds = saved_state->v86_segs.v86_ds & 0xffff; ! 825: state->es = saved_state->v86_segs.v86_es & 0xffff; ! 826: state->fs = saved_state->v86_segs.v86_fs & 0xffff; ! 827: state->gs = saved_state->v86_segs.v86_gs & 0xffff; ! 828: ! 829: if (thr_act->mact.pcb->ims.v86s.int_table) { ! 830: /* ! 831: * Hardware assist on ! 832: */ ! 833: if ((thr_act->mact.pcb->ims.v86s.flags & ! 834: (EFL_IF|V86_IF_PENDING)) == 0) ! 835: state->efl &= ~EFL_IF; ! 836: } ! 837: } ! 838: else { ! 839: /* ! 840: * 386 mode. ! 841: */ ! 842: state->ds = saved_state->ds & 0xffff; ! 843: state->es = saved_state->es & 0xffff; ! 844: state->fs = saved_state->fs & 0xffff; ! 845: state->gs = saved_state->gs & 0xffff; ! 846: } ! 847: *count = i386_SAVED_STATE_COUNT; ! 848: break; ! 849: } ! 850: ! 851: case i386_NEW_THREAD_STATE: ! 852: case i386_REGS_SEGS_STATE: ! 853: { ! 854: register struct i386_new_thread_state *state; ! 855: register struct i386_saved_state *saved_state; ! 856: ! 857: if (*count < i386_NEW_THREAD_STATE_COUNT) ! 858: return(KERN_INVALID_ARGUMENT); ! 859: ! 860: state = (struct i386_new_thread_state *) tstate; ! 861: saved_state = USER_REGS(thr_act); ! 862: ! 863: /* ! 864: * General registers. ! 865: */ ! 866: state->edi = saved_state->edi; ! 867: state->esi = saved_state->esi; ! 868: state->ebp = saved_state->ebp; ! 869: state->ebx = saved_state->ebx; ! 870: state->edx = saved_state->edx; ! 871: state->ecx = saved_state->ecx; ! 872: state->eax = saved_state->eax; ! 873: state->eip = saved_state->eip; ! 874: state->efl = saved_state->efl; ! 875: state->uesp = saved_state->uesp; ! 876: ! 877: state->cs = saved_state->cs; ! 878: state->ss = saved_state->ss; ! 879: if (saved_state->efl & EFL_VM) { ! 880: /* ! 881: * V8086 mode. ! 882: */ ! 883: state->ds = saved_state->v86_segs.v86_ds & 0xffff; ! 884: state->es = saved_state->v86_segs.v86_es & 0xffff; ! 885: state->fs = saved_state->v86_segs.v86_fs & 0xffff; ! 886: state->gs = saved_state->v86_segs.v86_gs & 0xffff; ! 887: ! 888: if (thr_act->mact.pcb->ims.v86s.int_table) { ! 889: /* ! 890: * Hardware assist on ! 891: */ ! 892: if ((thr_act->mact.pcb->ims.v86s.flags & ! 893: (EFL_IF|V86_IF_PENDING)) == 0) ! 894: state->efl &= ~EFL_IF; ! 895: } ! 896: } ! 897: else { ! 898: /* ! 899: * 386 mode. ! 900: */ ! 901: state->ds = saved_state->ds & 0xffff; ! 902: state->es = saved_state->es & 0xffff; ! 903: state->fs = saved_state->fs & 0xffff; ! 904: state->gs = saved_state->gs & 0xffff; ! 905: } ! 906: *count = i386_NEW_THREAD_STATE_COUNT; ! 907: break; ! 908: } ! 909: ! 910: case THREAD_SYSCALL_STATE: ! 911: { ! 912: register struct thread_syscall_state *state; ! 913: register struct i386_saved_state *saved_state = USER_REGS(thr_act); ! 914: ! 915: state = (struct thread_syscall_state *) tstate; ! 916: state->eax = saved_state->eax; ! 917: state->edx = saved_state->edx; ! 918: state->efl = saved_state->efl; ! 919: state->eip = saved_state->eip; ! 920: state->esp = saved_state->uesp; ! 921: *count = i386_THREAD_SYSCALL_STATE_COUNT; ! 922: break; ! 923: } ! 924: ! 925: case THREAD_STATE_FLAVOR_LIST: ! 926: if (*count < 5) ! 927: return (KERN_INVALID_ARGUMENT); ! 928: tstate[0] = i386_NEW_THREAD_STATE; ! 929: tstate[1] = i386_FLOAT_STATE; ! 930: tstate[2] = i386_ISA_PORT_MAP_STATE; ! 931: tstate[3] = i386_V86_ASSIST_STATE; ! 932: tstate[4] = THREAD_SYSCALL_STATE; ! 933: *count = 5; ! 934: break; ! 935: ! 936: case i386_FLOAT_STATE: { ! 937: ! 938: if (*count < i386_FLOAT_STATE_COUNT) ! 939: return(KERN_INVALID_ARGUMENT); ! 940: ! 941: *count = i386_FLOAT_STATE_COUNT; ! 942: return fpu_get_state(thr_act,(struct i386_float_state *)tstate); ! 943: } ! 944: ! 945: /* ! 946: * Temporary - replace by i386_io_map ! 947: */ ! 948: case i386_ISA_PORT_MAP_STATE: { ! 949: register struct i386_isa_port_map_state *state; ! 950: register iopb_tss_t tss; ! 951: ! 952: if (*count < i386_ISA_PORT_MAP_STATE_COUNT) ! 953: return(KERN_INVALID_ARGUMENT); ! 954: ! 955: state = (struct i386_isa_port_map_state *) tstate; ! 956: tss = thr_act->mact.pcb->ims.io_tss; ! 957: ! 958: if (tss == 0) { ! 959: int i; ! 960: ! 961: /* ! 962: * The thread has no ktss, so no IO permissions. ! 963: */ ! 964: ! 965: for (i = 0; i < sizeof state->pm; i++) ! 966: state->pm[i] = 0xff; ! 967: } else { ! 968: /* ! 969: * The thread has its own ktss. ! 970: */ ! 971: ! 972: bcopy((char *) tss->bitmap, ! 973: (char *) state->pm, ! 974: sizeof state->pm); ! 975: } ! 976: ! 977: *count = i386_ISA_PORT_MAP_STATE_COUNT; ! 978: break; ! 979: } ! 980: ! 981: case i386_V86_ASSIST_STATE: ! 982: { ! 983: register struct i386_v86_assist_state *state; ! 984: ! 985: if (*count < i386_V86_ASSIST_STATE_COUNT) ! 986: return KERN_INVALID_ARGUMENT; ! 987: ! 988: state = (struct i386_v86_assist_state *) tstate; ! 989: state->int_table = thr_act->mact.pcb->ims.v86s.int_table; ! 990: state->int_count = thr_act->mact.pcb->ims.v86s.int_count; ! 991: ! 992: *count = i386_V86_ASSIST_STATE_COUNT; ! 993: break; ! 994: } ! 995: ! 996: case i386_THREAD_STATE: { ! 997: struct i386_saved_state *saved_state; ! 998: i386_thread_state_t *state; ! 999: ! 1000: saved_state = USER_REGS(thr_act); ! 1001: state = (i386_thread_state_t *)tstate; ! 1002: ! 1003: state->eax = saved_state->eax; ! 1004: state->ebx = saved_state->ebx; ! 1005: state->ecx = saved_state->ecx; ! 1006: state->edx = saved_state->edx; ! 1007: state->edi = saved_state->edi; ! 1008: state->esi = saved_state->esi; ! 1009: state->ebp = saved_state->ebp; ! 1010: state->esp = saved_state->uesp; ! 1011: state->eflags = saved_state->efl; ! 1012: state->eip = saved_state->eip; ! 1013: state->cs = saved_state->cs; ! 1014: state->ss = saved_state->ss; ! 1015: state->ds = saved_state->ds; ! 1016: state->es = saved_state->es; ! 1017: state->fs = saved_state->fs; ! 1018: state->gs = saved_state->gs; ! 1019: break; ! 1020: } ! 1021: ! 1022: default: ! 1023: return(KERN_INVALID_ARGUMENT); ! 1024: } ! 1025: ! 1026: return(KERN_SUCCESS); ! 1027: } ! 1028: ! 1029: /* ! 1030: * Alter the thread`s state so that a following thread_exception_return ! 1031: * will make the thread return 'retval' from a syscall. ! 1032: */ ! 1033: void ! 1034: thread_set_syscall_return( ! 1035: thread_t thread, ! 1036: kern_return_t retval) ! 1037: { ! 1038: thread->top_act->mact.pcb->iss.eax = retval; ! 1039: } ! 1040: ! 1041: /* ! 1042: * Initialize the machine-dependent state for a new thread. ! 1043: */ ! 1044: kern_return_t ! 1045: thread_machine_create(thread_t thread, thread_act_t thr_act, void (*start_pos)(void)) ! 1046: { ! 1047: MachineThrAct_t mact = &thr_act->mact; ! 1048: ! 1049: #if MACH_ASSERT ! 1050: if (watchacts & WA_PCB) ! 1051: printf("thread_machine_create(thr=%x,thr_act=%x,st=%x)\n", ! 1052: thread, thr_act, start_pos); ! 1053: #endif /* MACH_ASSERT */ ! 1054: ! 1055: assert(thread != NULL); ! 1056: assert(thr_act != NULL); ! 1057: ! 1058: /* ! 1059: * Allocate a kernel stack per shuttle ! 1060: */ ! 1061: thread->kernel_stack = (int)stack_alloc(thread,start_pos); ! 1062: assert(thread->kernel_stack != 0); ! 1063: ! 1064: /* ! 1065: * Point top of kernel stack to user`s registers. ! 1066: */ ! 1067: STACK_IEL(thread->kernel_stack)->saved_state = &mact->pcb->iss; ! 1068: ! 1069: /* ! 1070: * Utah code fiddles with pcb here - (we don't need to) ! 1071: */ ! 1072: return(KERN_SUCCESS); ! 1073: } ! 1074: ! 1075: /* ! 1076: * Machine-dependent cleanup prior to destroying a thread ! 1077: */ ! 1078: void ! 1079: thread_machine_destroy( thread_t thread ) ! 1080: { ! 1081: spl_t s; ! 1082: ! 1083: assert(thread->kernel_stack != 0); ! 1084: ! 1085: s = splsched(); ! 1086: stack_free(thread); ! 1087: splx(s); ! 1088: } ! 1089: ! 1090: /* ! 1091: * This is used to set the current thr_act/thread ! 1092: * when starting up a new processor ! 1093: */ ! 1094: void ! 1095: thread_machine_set_current( thread_t thread ) ! 1096: { ! 1097: register int my_cpu; ! 1098: ! 1099: mp_disable_preemption(); ! 1100: my_cpu = cpu_number(); ! 1101: ! 1102: cpu_data[my_cpu].active_thread = thread; ! 1103: active_kloaded[my_cpu] = ! 1104: thread->top_act->kernel_loaded ? thread->top_act : THR_ACT_NULL; ! 1105: ! 1106: mp_enable_preemption(); ! 1107: } ! 1108: ! 1109: ! 1110: /* ! 1111: * Pool of kernel activations. ! 1112: */ ! 1113: ! 1114: void act_machine_init() ! 1115: { ! 1116: int i; ! 1117: thread_act_t thr_act; ! 1118: ! 1119: #if MACH_ASSERT ! 1120: if (watchacts & WA_PCB) ! 1121: printf("act_machine_init()\n"); ! 1122: #endif /* MACH_ASSERT */ ! 1123: ! 1124: /* Good to verify this once */ ! 1125: assert( THREAD_MACHINE_STATE_MAX <= THREAD_STATE_MAX ); ! 1126: ! 1127: /* ! 1128: * If we start using kernel activations, ! 1129: * would normally create kernel_thread_pool here, ! 1130: * populating it from the act_zone ! 1131: */ ! 1132: } ! 1133: ! 1134: kern_return_t ! 1135: act_machine_create(task_t task, thread_act_t thr_act) ! 1136: { ! 1137: MachineThrAct_t mact = &thr_act->mact; ! 1138: pcb_t pcb; ! 1139: ! 1140: #if MACH_ASSERT ! 1141: if (watchacts & WA_PCB) ! 1142: printf("act_machine_create(task=%x,thr_act=%x) pcb=%x\n", ! 1143: task,thr_act, &mact->xxx_pcb); ! 1144: #endif /* MACH_ASSERT */ ! 1145: ! 1146: /* ! 1147: * Clear & Init the pcb (sets up user-mode s regs) ! 1148: */ ! 1149: pcb_init(thr_act); ! 1150: ! 1151: return KERN_SUCCESS; ! 1152: } ! 1153: ! 1154: void ! 1155: act_machine_destroy(thread_act_t thr_act) ! 1156: { ! 1157: ! 1158: #if MACH_ASSERT ! 1159: if (watchacts & WA_PCB) ! 1160: printf("act_machine_destroy(0x%x)\n", thr_act); ! 1161: #endif /* MACH_ASSERT */ ! 1162: ! 1163: pcb_terminate(thr_act); ! 1164: } ! 1165: ! 1166: void ! 1167: act_machine_return(int code) ! 1168: { ! 1169: thread_act_t thr_act = current_act(); ! 1170: thread_act_t cur_act; ! 1171: thread_t cur_thread = current_thread(); ! 1172: vm_offset_t pcb_stack; ! 1173: unsigned int uesp, ueip; ! 1174: struct ipc_port *iplock; ! 1175: ! 1176: #if MACH_ASSERT ! 1177: /* ! 1178: * We don't go through the locking dance here needed to ! 1179: * acquire thr_act->thread safely. ! 1180: */ ! 1181: ! 1182: if (watchacts & WA_EXIT) ! 1183: printf("act_machine_return(0x%x) cur_act=%x(%d) thr=%x(%d)\n", ! 1184: code, thr_act, thr_act->ref_count, ! 1185: thr_act->thread, thr_act->thread ! 1186: ? thr_act->thread->ref_count : 0); ! 1187: #endif /* MACH_ASSERT */ ! 1188: ! 1189: /* ! 1190: * This code is called with nothing locked. ! 1191: * It also returns with nothing locked, if it returns. ! 1192: * ! 1193: * This routine terminates the current thread activation. ! 1194: * If this is the only activation associated with its ! 1195: * thread shuttle, then the entire thread (shuttle plus ! 1196: * activation) is terminated. ! 1197: */ ! 1198: assert( code == KERN_TERMINATED ); ! 1199: assert( thr_act ); ! 1200: ! 1201: #ifdef CALLOUT_RPC_MODEL ! 1202: ! 1203: /* ! 1204: * JMM - RPC is not going to be done with a callout/direct- ! 1205: * stack manipulation mechanism. Instead we will return/ ! 1206: * unwind normally as if from a continuation. ! 1207: */ ! 1208: act_lock_thread(thr_act); ! 1209: iplock = thr_act->pool_port; /* remember for unlock call */ ! 1210: ! 1211: if (thr_act->thread->top_act != thr_act) { ! 1212: /* ! 1213: * this is not the top activation; ! 1214: * if possible, we should clone the shuttle so that ! 1215: * both the root RPC-chain and the soon-to-be-orphaned ! 1216: * RPC-chain have shuttles ! 1217: * ! 1218: * JMM - Cloning shuttles isn't the right approach. We ! 1219: * need to alert the higher up activations to return our ! 1220: * shuttle (because scheduling attributes may TRUELY be ! 1221: * unique and not cloneable. ! 1222: */ ! 1223: act_unlock_thread(thr_act); ! 1224: panic("act_machine_return: ORPHAN CASE NOT YET IMPLEMENTED"); ! 1225: } ! 1226: ! 1227: if (thr_act->lower != THR_ACT_NULL) { ! 1228: /* send it an appropriate return code */ ! 1229: thr_act->lower->alerts |= SERVER_TERMINATED; ! 1230: install_special_handler(thr_act->lower); ! 1231: ! 1232: /* Return to previous act with error code */ ! 1233: act_locked_act_reference(thr_act); /* keep it around */ ! 1234: act_switch_swapcheck(cur_thread, (ipc_port_t)0); ! 1235: (void) switch_act(THR_ACT_NULL); ! 1236: /* assert(thr_act->ref_count == 0); */ /* XXX */ ! 1237: cur_act = cur_thread->top_act; ! 1238: MACH_RPC_RET(cur_act) = KERN_RPC_SERVER_TERMINATED; ! 1239: ! 1240: machine_kernel_stack_init(cur_thread, ! 1241: (void (*)(void)) mach_rpc_return_error); ! 1242: /* ! 1243: * The following unlocks must be done separately since fields ! 1244: * used by `act_unlock_thread()' have been cleared, meaning ! 1245: * that it would not release all of the appropriate locks. ! 1246: */ ! 1247: rpc_unlock(cur_thread); ! 1248: if (iplock) ip_unlock(iplock); /* must be done separately */ ! 1249: act_unlock(thr_act); ! 1250: act_deallocate(thr_act); /* free it */ ! 1251: Load_context(cur_thread); ! 1252: /*NOTREACHED*/ ! 1253: ! 1254: panic("act_machine_return: TALKING ZOMBIE! (2)"); ! 1255: } ! 1256: act_unlock_thread(thr_act); ! 1257: ! 1258: #endif /* CALLOUT_RPC_MODEL */ ! 1259: ! 1260: /* This is the only activation attached to the shuttle... */ ! 1261: /* terminate the entire thread (shuttle plus activation) */ ! 1262: ! 1263: assert(thr_act->thread->top_act == thr_act); ! 1264: thread_terminate_self(); ! 1265: ! 1266: /*NOTREACHED*/ ! 1267: ! 1268: panic("act_machine_return: TALKING ZOMBIE! (1)"); ! 1269: } ! 1270: ! 1271: ! 1272: /* ! 1273: * Perform machine-dependent per-thread initializations ! 1274: */ ! 1275: void ! 1276: thread_machine_init(void) ! 1277: { ! 1278: pcb_module_init(); ! 1279: } ! 1280: ! 1281: /* ! 1282: * Some routines for debugging activation code ! 1283: */ ! 1284: static void dump_handlers(thread_act_t); ! 1285: void dump_regs(thread_act_t); ! 1286: ! 1287: static void ! 1288: dump_handlers(thread_act_t thr_act) ! 1289: { ! 1290: ReturnHandler *rhp = thr_act->handlers; ! 1291: int counter = 0; ! 1292: ! 1293: printf("\t"); ! 1294: while (rhp) { ! 1295: if (rhp == &thr_act->special_handler){ ! 1296: if (rhp->next) ! 1297: printf("[NON-Zero next ptr(%x)]", rhp->next); ! 1298: printf("special_handler()->"); ! 1299: break; ! 1300: } ! 1301: printf("hdlr_%d(%x)->",counter,rhp->handler); ! 1302: rhp = rhp->next; ! 1303: if (++counter > 32) { ! 1304: printf("Aborting: HUGE handler chain\n"); ! 1305: break; ! 1306: } ! 1307: } ! 1308: printf("HLDR_NULL\n"); ! 1309: } ! 1310: ! 1311: void ! 1312: dump_regs(thread_act_t thr_act) ! 1313: { ! 1314: if (thr_act->mact.pcb) { ! 1315: register struct i386_saved_state *ssp = USER_REGS(thr_act); ! 1316: /* Print out user register state */ ! 1317: printf("\tRegs:\tedi=%x esi=%x ebp=%x ebx=%x edx=%x\n", ! 1318: ssp->edi, ssp->esi, ssp->ebp, ssp->ebx, ssp->edx); ! 1319: printf("\t\tecx=%x eax=%x eip=%x efl=%x uesp=%x\n", ! 1320: ssp->ecx, ssp->eax, ssp->eip, ssp->efl, ssp->uesp); ! 1321: printf("\t\tcs=%x ss=%x\n", ssp->cs, ssp->ss); ! 1322: } ! 1323: } ! 1324: ! 1325: int ! 1326: dump_act(thread_act_t thr_act) ! 1327: { ! 1328: if (!thr_act) ! 1329: return(0); ! 1330: ! 1331: printf("thr_act(0x%x)(%d): thread=%x(%d) task=%x(%d)\n", ! 1332: thr_act, thr_act->ref_count, ! 1333: thr_act->thread, thr_act->thread ? thr_act->thread->ref_count:0, ! 1334: thr_act->task, thr_act->task ? thr_act->task->ref_count : 0); ! 1335: ! 1336: if (thr_act->pool_port) { ! 1337: thread_pool_t actpp = &thr_act->pool_port->ip_thread_pool; ! 1338: printf("\tpool(acts_p=%x, waiting=%d) pool_next %x\n", ! 1339: actpp->thr_acts, actpp->waiting, thr_act->thread_pool_next); ! 1340: }else ! 1341: printf("\tno thread_pool\n"); ! 1342: ! 1343: printf("\talerts=%x mask=%x susp=%d user_stop=%d active=%x ast=%x\n", ! 1344: thr_act->alerts, thr_act->alert_mask, ! 1345: thr_act->suspend_count, thr_act->user_stop_count, ! 1346: thr_act->active, thr_act->ast); ! 1347: printf("\thi=%x lo=%x\n", thr_act->higher, thr_act->lower); ! 1348: printf("\tpcb=%x, ustk=%x\n", ! 1349: thr_act->mact.pcb, thr_act->user_stack); ! 1350: ! 1351: if (thr_act->thread && thr_act->thread->kernel_stack) { ! 1352: vm_offset_t stack = thr_act->thread->kernel_stack; ! 1353: ! 1354: printf("\tk_stk %x eip %x ebx %x esp %x iss %x\n", ! 1355: stack, STACK_IKS(stack)->k_eip, STACK_IKS(stack)->k_ebx, ! 1356: STACK_IKS(stack)->k_esp, STACK_IEL(stack)->saved_state); ! 1357: } ! 1358: ! 1359: dump_handlers(thr_act); ! 1360: dump_regs(thr_act); ! 1361: return((int)thr_act); ! 1362: } ! 1363: unsigned int ! 1364: get_useraddr() ! 1365: { ! 1366: ! 1367: thread_act_t thr_act = current_act(); ! 1368: ! 1369: if (thr_act->mact.pcb) ! 1370: return(thr_act->mact.pcb->iss.eip); ! 1371: else ! 1372: return(0); ! 1373: ! 1374: } ! 1375: ! 1376: void ! 1377: thread_swapin_mach_alloc(thread_t thread) ! 1378: { ! 1379: ! 1380: /* 386 does not have saveareas */ ! 1381: ! 1382: } ! 1383: /* ! 1384: * detach and return a kernel stack from a thread ! 1385: */ ! 1386: ! 1387: vm_offset_t ! 1388: stack_detach(thread_t thread) ! 1389: { ! 1390: vm_offset_t stack; ! 1391: ! 1392: #ifdef KDEBUG ! 1393: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_DETACH), ! 1394: thread, thread->priority, ! 1395: thread->sched_pri, 0, ! 1396: 0); ! 1397: #endif ! 1398: ! 1399: stack = thread->kernel_stack; ! 1400: thread->kernel_stack = 0; ! 1401: return(stack); ! 1402: } ! 1403: ! 1404: /* ! 1405: * attach a kernel stack to a thread and initialize it ! 1406: */ ! 1407: ! 1408: void ! 1409: stack_attach(struct thread_shuttle *thread, ! 1410: vm_offset_t stack, ! 1411: void (*continuation)(void)) ! 1412: { ! 1413: struct i386_kernel_state *statep; ! 1414: thread_act_t thr_act; ! 1415: ! 1416: #ifdef KDEBUG ! 1417: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_ATTACH), ! 1418: thread, thread->priority, ! 1419: thread->sched_pri, continuation, ! 1420: 0); ! 1421: #endif ! 1422: ! 1423: assert(stack); ! 1424: statep = STACK_IKS(stack); ! 1425: thread->kernel_stack = stack; ! 1426: ! 1427: statep->k_eip = (unsigned long) Thread_continue; ! 1428: statep->k_ebx = (unsigned long) continuation; ! 1429: statep->k_esp = (unsigned long) STACK_IEL(stack); ! 1430: ! 1431: STACK_IEL(stack)->saved_state = &thr_act->mact.pcb->iss; ! 1432: ! 1433: return; ! 1434: } ! 1435: ! 1436: /* ! 1437: * move a stack from old to new thread ! 1438: */ ! 1439: ! 1440: void ! 1441: stack_handoff(thread_t old, ! 1442: thread_t new) ! 1443: { ! 1444: ! 1445: vm_offset_t stack; ! 1446: pmap_t new_pmap; ! 1447: ! 1448: #ifdef KDEBUG ! 1449: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_HANDOFF), ! 1450: thread, thread->priority, ! 1451: thread->sched_pri, continuation, ! 1452: 0); ! 1453: #endif ! 1454: ! 1455: assert(new->top_act); ! 1456: assert(old->top_act); ! 1457: ! 1458: stack = stack_detach(old); ! 1459: stack_attach(new, stack, 0); ! 1460: ! 1461: new_pmap = new->top_act->task->map->pmap; ! 1462: if (old->top_act->task->map->pmap != new_pmap) ! 1463: PMAP_ACTIVATE_MAP(new->top_act->task->map, cpu_number()); ! 1464: ! 1465: thread_machine_set_current(new); ! 1466: ! 1467: active_stacks[cpu_number()] = new->kernel_stack; ! 1468: ! 1469: return; ! 1470: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.