|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* HISTORY ! 26: ! 27: 1997/05/16 Rene Vega -- cleanup sync/isync usage. ! 28: */ ! 29: ! 30: #import <machdep/ppc/exception.h> ! 31: #import <mach/mach_types.h> ! 32: #import <kern/mach_param.h> ! 33: #import <kern/thread.h> ! 34: #import <kern/kernel_stack.h> ! 35: #import <machdep/ppc/thread.h> ! 36: #import <bsd/ppc/psl.h> ! 37: #import <sys/time.h> ! 38: #import <bsd/ppc/vmparam.h> ! 39: #import <kernserv/ppc/spl.h> ! 40: #import <sys/param.h> ! 41: #import <sys/proc.h> ! 42: #import <kern/parallel.h> ! 43: #include <machdep/ppc/proc_reg.h> ! 44: #include <ppc/trap.h> ! 45: #ifdef KDEBUG ! 46: #include <kern/kdebug.h> ! 47: #include <mach_counters.h> ! 48: #include <kern/counters.h> ! 49: #import <machdep/ppc/frame.h> ! 50: #endif ! 51: #import <machdep/ppc/asm.h> ! 52: #import <assym.h> ! 53: ! 54: pcb_t active_pcbs[NCPUS]; /* PCB belonging to the active thread */ ! 55: ! 56: #if DEBUG ! 57: int fpu_trap_count = 0; ! 58: int fpu_switch_count = 0; ! 59: #endif ! 60: ! 61: extern struct per_proc_info per_proc_info[]; ! 62: ! 63: #define current_pcb() active_pcbs[cpu_number()] ! 64: ! 65: zone_t pcb_zone; ! 66: ! 67: /* ! 68: * Initialize pcb allocation zone. ! 69: */ ! 70: void ! 71: pcb_module_init(void) ! 72: { ! 73: int i; ! 74: pcb_zone = zinit( ! 75: sizeof (struct pcb), ! 76: THREAD_MAX * sizeof (struct pcb), ! 77: THREAD_CHUNK * sizeof (struct pcb), ! 78: FALSE, "pcb"); ! 79: ! 80: for (i=0; i < NCPUS; i++) { ! 81: active_pcbs[i] = 0; ! 82: } ! 83: } ! 84: ! 85: /* ! 86: * Allocated and initialize a pcb for a new thread. ! 87: */ ! 88: void pcb_init(thread_t thread) ! 89: { ! 90: struct pcb *pcb = (void *)zalloc(pcb_zone); ! 91: pmap_t pmap = thread->task->map->pmap; ! 92: ! 93: ! 94: thread->pcb = pcb; ! 95: ! 96: /* all fields default to zero */ ! 97: bzero((caddr_t)pcb, sizeof (struct pcb)); ! 98: ! 99: /* ! 100: * User threads will pull their context from the pcb when first ! 101: * returning to user mode, so fill in all the necessary values. ! 102: * Kernel threads are initialized from the save state structure ! 103: * at the base of the kernel stack (see stack_attach()). ! 104: */ ! 105: ! 106: pcb->ss.srr1 = MSR_EXPORT_MASK_SET; ! 107: ! 108: pcb->sr0 = SEG_REG_PROT | (pmap->space<<4); ! 109: pcb->ss.sr_copyin = SEG_REG_PROT | SR_COPYIN + (pmap->space<<4); ! 110: } ! 111: ! 112: /* ! 113: * Release machine dependent resources on ! 114: * thread termination. ! 115: */ ! 116: pcb_terminate( ! 117: thread_t thread ! 118: ) ! 119: { ! 120: struct pcb *pcb = thread->pcb; ! 121: ! 122: ! 123: if (per_proc_info[cpu_number()].fpu_pcb == pcb) ! 124: { ! 125: per_proc_info[cpu_number()].fpu_pcb = (pcb_t)0; ! 126: } ! 127: ! 128: thread->pcb = 0; ! 129: zfree(pcb_zone, pcb); ! 130: } ! 131: ! 132: #define KF_SIZE (FM_SIZE+ARG_SIZE+FM_REDZONE) ! 133: ! 134: /* ! 135: * stack_attach: Attach a kernel stack to a thread. ! 136: */ ! 137: void stack_attach(thread, stack, continuation) ! 138: register thread_t thread; ! 139: vm_offset_t stack; ! 140: void (*continuation)(); ! 141: { ! 142: struct ppc_kernel_state *kss; ! 143: struct pcb *pcb = thread->pcb; ! 144: ! 145: #ifdef KDEBUG ! 146: if (continuation) { ! 147: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_ATTACH), ! 148: thread, thread->priority, ! 149: thread->sched_pri, continuation, ! 150: 0); ! 151: } ! 152: #endif ! 153: thread->kernel_stack = stack; ! 154: kss = STACK_IKS(stack); ! 155: ! 156: /* ! 157: * Build a kernel state area + arg frame on the stack for the initial ! 158: * switch into the thread. We also store a zero into the kernel ! 159: * stack pointer so the trap code knows there is already a frame ! 160: * on the kernel stack. ! 161: */ ! 162: ! 163: kss->lr = (unsigned int) continuation; ! 164: kss->r1 = (vm_offset_t) ((int)kss - KF_SIZE); ! 165: ! 166: *((int*)kss->r1) = 0; /* Zero the frame backpointer */ ! 167: ! 168: pcb->ksp = 0; ! 169: } ! 170: ! 171: vm_offset_t ! 172: stack_detach( ! 173: thread_t thread ! 174: ) ! 175: { ! 176: vm_offset_t stack; ! 177: ! 178: stack = thread->kernel_stack; ! 179: thread->kernel_stack = 0; ! 180: ! 181: return (stack); ! 182: } ! 183: ! 184: /* ! 185: * stack_handoff: Move the current threads kernel stack to the new thread. ! 186: */ ! 187: void ! 188: stack_handoff( ! 189: thread_t old, ! 190: thread_t new ! 191: ) ! 192: { ! 193: vm_offset_t stack = stack_detach(old); ! 194: ! 195: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_HANDOFF), ! 196: old, new, ! 197: old->priority, old->sched_pri, ! 198: new->sched_pri); ! 199: ! 200: stack_attach(new, stack, 0); ! 201: ! 202: /* ! 203: * Change software state. ! 204: */ ! 205: if (new->task != old->task) { ! 206: int mycpu = cpu_number(); ! 207: ! 208: PMAP_DEACTIVATE(vm_map_pmap(old->task->map), old, mycpu); ! 209: PMAP_ACTIVATE(vm_map_pmap(new->task->map), new, mycpu); ! 210: pmap_switch(new->task->map->pmap); ! 211: } ! 212: ! 213: // current_thread() = new; // can't use this because it may be inlined! ! 214: cpu_data[cpu_number()].active_thread = new; ! 215: current_pcb() = new->pcb; ! 216: cpu_data[cpu_number()].flags = new->pcb->flags; ! 217: ! 218: #if NCPUS > 1 ! 219: /* There is no free lunch! ! 220: * save the floating point state for the old thread ! 221: * if the fpu has been used since the last context switch ! 222: */ ! 223: fp_state_save(old); ! 224: ! 225: #endif /* NCPUS > 1 */ ! 226: ! 227: new->pcb->ksp = 0; ! 228: ! 229: } ! 230: ! 231: void ! 232: call_continuation( ! 233: void (*continuation)(void) ! 234: ) ! 235: { ! 236: struct ppc_kernel_state *kss; ! 237: extern Call_continuation(); ! 238: int tkss; ! 239: ! 240: ! 241: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_CALL_CONT), ! 242: current_thread(), current_thread()->priority, ! 243: current_thread()->sched_pri, continuation, ! 244: 0); ! 245: ! 246: kss = STACK_IKS(current_thread()->kernel_stack); ! 247: ! 248: *((int*)((int)kss - KF_SIZE)) = 0; /* Zero the frame backpointer */ ! 249: tkss = (int)kss - KF_SIZE; ! 250: ! 251: Call_continuation(continuation, tkss); ! 252: } ! 253: ! 254: ! 255: /* ! 256: * switch_context: Switch from one thread to another. ! 257: */ ! 258: thread_t ! 259: switch_context( ! 260: thread_t old, ! 261: void (*continuation)(void), ! 262: thread_t new ! 263: ) ! 264: { ! 265: thread_t ret_thread; ! 266: extern thread_t Switch_context(); ! 267: #ifdef KDEBUG ! 268: struct linkage_area *frame_ptr; ! 269: uint i; ! 270: uint lr[4]; ! 271: #endif ! 272: ! 273: if (new->task != old->task) { ! 274: int mycpu = cpu_number(); ! 275: ! 276: PMAP_DEACTIVATE(vm_map_pmap(old->task->map), old, mycpu); ! 277: PMAP_ACTIVATE(vm_map_pmap(new->task->map), new, mycpu); ! 278: ! 279: pmap_switch(new->task->map->pmap); ! 280: } ! 281: ! 282: // current_thread() = new; // can't use this because it may be inlined! ! 283: cpu_data[cpu_number()].active_thread = new; ! 284: //current_stack() = new->kernel_stack; // assembly does this ! 285: current_pcb()= new->pcb; ! 286: cpu_data[cpu_number()].flags = new->pcb->flags; ! 287: ! 288: #if NCPUS > 1 ! 289: /* There is no free lunch! ! 290: * Save the floating point state for the old thread ! 291: * if the fpu has been used since the last context switch. ! 292: * Otherwise we need to broadcast an interrupt to the ! 293: * old fpu to get the state. ! 294: */ ! 295: fp_state_save(old); ! 296: ! 297: #else ! 298: //disable_fpu(); ! 299: #endif ! 300: ! 301: #ifdef KDEBUG ! 302: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED) | DBG_FUNC_END, ! 303: old, new, ! 304: old->priority, old->sched_pri, ! 305: new->sched_pri); ! 306: ! 307: frame_ptr = STACK_IKS(new->kernel_stack)->r1; ! 308: lr[0] = lr[1] = lr[2] = lr[3] = 0; ! 309: lr[0] = STACK_IKS(new->kernel_stack)->lr; ! 310: for (i=1;i<4;i++) { ! 311: if (frame_ptr == NULL) break; ! 312: lr[i] = frame_ptr->saved_lr; ! 313: frame_ptr = frame_ptr->saved_sp; ! 314: } ! 315: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED) | DBG_FUNC_START, ! 316: new, lr[0], lr[1], lr[2], lr[3]); ! 317: ! 318: lr[0] = lr[1] = lr[2] = lr[3] = 0; ! 319: for (i=0;i<4;i++) { ! 320: if (frame_ptr == NULL) break; ! 321: lr[i] = frame_ptr->saved_lr; ! 322: frame_ptr = frame_ptr->saved_sp; ! 323: } ! 324: if (lr[0]) { ! 325: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED), ! 326: 0, lr[0], lr[1], lr[2], lr[3]); ! 327: }; ! 328: #endif ! 329: ret_thread = Switch_context(old, continuation, new); ! 330: ! 331: return(ret_thread); ! 332: } ! 333: ! 334: void ! 335: start_initial_context( ! 336: thread_t thread ! 337: ) ! 338: { ! 339: struct pcb *pcb = thread->pcb; ! 340: ! 341: /* ! 342: * Change software state. ! 343: */ ! 344: ! 345: PMAP_ACTIVATE(vm_map_pmap(thread->task->map), thread, 0); ! 346: ! 347: // current_thread() = thread; // can't use this because it may be inlined! ! 348: cpu_data[cpu_number()].active_thread = thread; ! 349: current_stack() = thread->kernel_stack; ! 350: current_pcb() = thread->pcb; ! 351: cpu_data[cpu_number()].flags = thread->pcb->flags; ! 352: ! 353: /* ! 354: * Change hardware state ! 355: */ ! 356: load_context(thread); ! 357: /*NOTREACHED*/ ! 358: } ! 359: ! 360: /* ! 361: * Duplicate parent state in child ! 362: * for U**X fork. ! 363: */ ! 364: thread_dup( ! 365: thread_t parent, ! 366: thread_t child ! 367: ) ! 368: { ! 369: struct ppc_saved_state *parent_state, *child_state; ! 370: struct ppc_float_state *parent_float_state, *child_float_state; ! 371: struct ppc_exception_state *parent_exception_state, ! 372: *child_exception_state; ! 373: ! 374: /* Save the FPU state */ ! 375: if (per_proc_info[cpu_number()].fpu_pcb == parent->pcb) { ! 376: fp_state_save(parent); ! 377: } ! 378: ! 379: parent_state = &parent->pcb->ss; ! 380: child_state = &child->pcb->ss; ! 381: ! 382: /* rely on compiler structure assignment */ ! 383: *child_state = *parent_state; ! 384: ! 385: parent_float_state = &parent->pcb->fs; ! 386: child_float_state = &child->pcb->fs; ! 387: ! 388: /* rely on compiler structure assignment */ ! 389: *child_float_state = *parent_float_state; ! 390: #if 0 ! 391: parent_exception_state = &parent->pcb->es; ! 392: child_exception_state = &child->pcb->es; ! 393: ! 394: /* rely on compiler structure assignment */ ! 395: *child_exception_state = *parent_exception_state; ! 396: #endif ! 397: child_state->r3 = child->task->proc->p_pid; ! 398: child_state->r4 = 1; ! 399: ! 400: child_state->sr_copyin = child->pcb->sr0 + SR_COPYIN; ! 401: } ! 402: ! 403: /* ! 404: * Set thread integer state ! 405: */ ! 406: kern_return_t ! 407: set_thread_state( ! 408: thread_t thread, ! 409: thread_state_t tstate, ! 410: unsigned int count ! 411: ) ! 412: { ! 413: struct ppc_saved_state *saved_state; ! 414: struct ppc_thread_state *state; ! 415: ! 416: if (count < PPC_THREAD_STATE_COUNT) ! 417: return (KERN_INVALID_ARGUMENT); ! 418: ! 419: if (thread->task->kernel_privilege) { ! 420: /* ! 421: * State for kernel threads ! 422: * can only be set before thread ! 423: * is first started. ! 424: * ! 425: * XXX This hack is due to the ! 426: * fact that the &^%$#@! kernel loader ! 427: * uses the thread_set_state() call to ! 428: * start a thread in kernel mode. ! 429: */ ! 430: if (thread->swap_func != thread_bootstrap_return) ! 431: return (KERN_INVALID_ARGUMENT); ! 432: } ! 433: ! 434: state = (struct ppc_thread_state *)tstate; ! 435: saved_state = &thread->pcb->ss; ! 436: ! 437: /* ! 438: * structure assignment - depends on ! 439: * ppc_thread_state being a prefix of ppc_saved_state ! ! 440: */ ! 441: ! 442: *((struct ppc_thread_state *)saved_state) = *state; ! 443: ! 444: saved_state->sr_copyin = thread->pcb->sr0 + SR_COPYIN; ! 445: ! 446: saved_state->srr1 |= MSR_EXPORT_MASK_SET; ! 447: ! 448: if (thread->task->kernel_privilege) { ! 449: saved_state->srr1 &= ~ MASK(MSR_PR); ! 450: thread_start(thread, state->srr0); ! 451: } ! 452: ! 453: return (KERN_SUCCESS); ! 454: } ! 455: ! 456: /* ! 457: * Set thread floating point state ! 458: */ ! 459: kern_return_t ! 460: set_thread_fpstate( ! 461: thread_t thread, ! 462: thread_state_t tstate, ! 463: unsigned int count ! 464: ) ! 465: { ! 466: struct ppc_float_state *state; ! 467: ! 468: if (count < PPC_FLOAT_STATE_COUNT) ! 469: return (KERN_INVALID_ARGUMENT); ! 470: ! 471: fpu_save(); ! 472: fpu_disable(); ! 473: ! 474: state = (struct ppc_float_state *)tstate; ! 475: ! 476: /* structure assignment */ ! 477: thread->pcb->fs = *state; ! 478: ! 479: return (KERN_SUCCESS); ! 480: } ! 481: ! 482: /* ! 483: * Set thread exception point state ! 484: */ ! 485: kern_return_t ! 486: set_thread_exstate( ! 487: thread_t thread, ! 488: thread_state_t tstate, ! 489: unsigned int count ! 490: ) ! 491: { ! 492: struct ppc_exception_state *state; ! 493: ! 494: if (count < PPC_EXCEPTION_STATE_COUNT) ! 495: return (KERN_INVALID_ARGUMENT); ! 496: ! 497: state = (struct ppc_exception_state *)tstate; ! 498: ! 499: /* structure assignment */ ! 500: thread->pcb->es = *state; ! 501: ! 502: return (KERN_SUCCESS); ! 503: } ! 504: ! 505: /* ! 506: * Set externally visible thread ! 507: * state. ! 508: */ ! 509: kern_return_t ! 510: thread_setstatus( ! 511: thread_t thread, ! 512: int flavor, ! 513: thread_state_t tstate, ! 514: unsigned int count ! 515: ) ! 516: { ! 517: switch (flavor) { ! 518: ! 519: case PPC_THREAD_STATE: ! 520: return (set_thread_state(thread, tstate, count)); ! 521: ! 522: case PPC_FLOAT_STATE: ! 523: return (set_thread_fpstate(thread, tstate, count)); ! 524: ! 525: case PPC_EXCEPTION_STATE: ! 526: return (set_thread_exstate(thread, tstate, count)); ! 527: ! 528: default: ! 529: return (KERN_INVALID_ARGUMENT); ! 530: } ! 531: } ! 532: ! 533: /* ! 534: * Get thread state flavor list ! 535: */ ! 536: kern_return_t ! 537: get_thread_state_flavor_list( ! 538: thread_state_t tstate, ! 539: unsigned int *count ! 540: ) ! 541: { ! 542: struct thread_state_flavor *state; ! 543: ! 544: if (*count < PPC_THREAD_STATE_FLAVOR_LIST_COUNT) ! 545: return (KERN_INVALID_ARGUMENT); ! 546: ! 547: state = (struct thread_state_flavor *)tstate; ! 548: ! 549: state->flavor = PPC_THREAD_STATE; ! 550: state->count = PPC_THREAD_STATE_COUNT; ! 551: ! 552: (++state)->flavor = PPC_FLOAT_STATE; ! 553: state->count = PPC_FLOAT_STATE_COUNT; ! 554: ! 555: (++state)->flavor = PPC_EXCEPTION_STATE; ! 556: state->count = PPC_EXCEPTION_STATE_COUNT; ! 557: ! 558: *count = PPC_THREAD_STATE_FLAVOR_LIST_COUNT; ! 559: ! 560: return (KERN_SUCCESS); ! 561: } ! 562: ! 563: /* ! 564: * Get thread integer state ! 565: */ ! 566: kern_return_t ! 567: get_thread_state( ! 568: thread_t thread, ! 569: thread_state_t tstate, ! 570: unsigned int *count ! 571: ) ! 572: { ! 573: struct ppc_thread_state *saved_state; ! 574: struct ppc_thread_state *state; ! 575: ! 576: if (*count < PPC_THREAD_STATE_COUNT) ! 577: return (KERN_INVALID_ARGUMENT); ! 578: ! 579: state = (struct ppc_thread_state *)tstate; ! 580: saved_state = (struct ppc_thread_state *) &thread->pcb->ss; ! 581: ! 582: /* ! 583: * structure assignment - depends on ! 584: * ppc_thread_state being a prefix of ppc_saved_state ! ! 585: */ ! 586: *state = *((struct ppc_thread_state *)saved_state); ! 587: ! 588: *count = PPC_THREAD_STATE_COUNT; ! 589: ! 590: return (KERN_SUCCESS); ! 591: } ! 592: ! 593: /* ! 594: * Get thread floating point state ! 595: */ ! 596: kern_return_t ! 597: get_thread_fpstate( ! 598: thread_t thread, ! 599: thread_state_t tstate, ! 600: unsigned int *count ! 601: ) ! 602: { ! 603: struct ppc_float_state *state; ! 604: ! 605: if (*count < PPC_FLOAT_STATE_COUNT) ! 606: return (KERN_INVALID_ARGUMENT); ! 607: ! 608: fpu_save(); ! 609: fpu_disable(); ! 610: ! 611: state = (struct ppc_float_state *)tstate; ! 612: ! 613: /* structure assignment */ ! 614: *state = thread->pcb->fs; ! 615: ! 616: *count = PPC_FLOAT_STATE_COUNT; ! 617: ! 618: return (KERN_SUCCESS); ! 619: } ! 620: ! 621: /* ! 622: * Get thread exception point state ! 623: */ ! 624: kern_return_t ! 625: get_thread_exstate( ! 626: thread_t thread, ! 627: thread_state_t tstate, ! 628: unsigned int *count ! 629: ) ! 630: { ! 631: struct ppc_exception_state *state; ! 632: ! 633: if (*count < PPC_EXCEPTION_STATE_COUNT) ! 634: return (KERN_INVALID_ARGUMENT); ! 635: ! 636: state = (struct ppc_exception_state *)tstate; ! 637: ! 638: /* structure assignment */ ! 639: *state = thread->pcb->es; ! 640: ! 641: *count = PPC_EXCEPTION_STATE_COUNT; ! 642: ! 643: return (KERN_SUCCESS); ! 644: } ! 645: ! 646: /* ! 647: * Return externally visible ! 648: * thread status. ! 649: */ ! 650: kern_return_t ! 651: thread_getstatus( ! 652: thread_t thread, ! 653: int flavor, ! 654: thread_state_t tstate, ! 655: unsigned int *count ! 656: ) ! 657: { ! 658: switch (flavor) { ! 659: ! 660: case THREAD_STATE_FLAVOR_LIST: ! 661: return (get_thread_state_flavor_list(tstate, count)); ! 662: ! 663: case PPC_THREAD_STATE: ! 664: return (get_thread_state(thread, tstate, count)); ! 665: ! 666: case PPC_FLOAT_STATE: ! 667: return (get_thread_fpstate(thread, tstate, count)); ! 668: ! 669: case PPC_EXCEPTION_STATE: ! 670: return (get_thread_exstate(thread, tstate, count)); ! 671: ! 672: default: ! 673: return (KERN_INVALID_ARGUMENT); ! 674: } ! 675: } ! 676: ! 677: /* ! 678: * thread_userstack: ! 679: * ! 680: * Return the user stack pointer from the machine ! 681: * dependent thread state info. ! 682: */ ! 683: kern_return_t ! 684: thread_userstack( ! 685: thread_t thread, ! 686: int flavor, ! 687: thread_state_t tstate, ! 688: unsigned int count, ! 689: vm_offset_t *user_stack ! 690: ) ! 691: { ! 692: struct ppc_thread_state *state; ! 693: ! 694: /* ! 695: * Set a default. ! 696: */ ! 697: if (*user_stack == 0) ! 698: *user_stack = USRSTACK; ! 699: ! 700: switch (flavor) { ! 701: case PPC_THREAD_STATE: ! 702: if (count < PPC_THREAD_STATE_COUNT) ! 703: return (KERN_INVALID_ARGUMENT); ! 704: ! 705: state = (struct ppc_thread_state *) tstate; ! 706: ! 707: /* ! 708: * If a valid user stack is specified, use it. ! 709: */ ! 710: *user_stack = state->r1 ? state->r1: USRSTACK; ! 711: break; ! 712: default : ! 713: return (KERN_INVALID_ARGUMENT); ! 714: } ! 715: ! 716: return (KERN_SUCCESS); ! 717: } ! 718: ! 719: kern_return_t ! 720: thread_entrypoint( ! 721: thread_t thread, ! 722: int flavor, ! 723: thread_state_t tstate, ! 724: unsigned int count, ! 725: vm_offset_t *entry_point ! 726: ) ! 727: { ! 728: struct ppc_thread_state *state; ! 729: ! 730: /* ! 731: * Set a default. ! 732: */ ! 733: if (*entry_point == 0) ! 734: *entry_point = VM_MIN_ADDRESS; ! 735: ! 736: switch (flavor) { ! 737: ! 738: case PPC_THREAD_STATE: ! 739: if (count < PPC_THREAD_STATE_COUNT) ! 740: return (KERN_INVALID_ARGUMENT); ! 741: ! 742: state = (struct ppc_thread_state *) tstate; ! 743: ! 744: /* ! 745: * If a valid entry point is specified, use it. ! 746: */ ! 747: *entry_point = state->srr0 ? state->srr0: VM_MIN_ADDRESS; ! 748: break; ! 749: default: ! 750: return (KERN_INVALID_ARGUMENT); ! 751: } ! 752: ! 753: return (KERN_SUCCESS); ! 754: } ! 755: ! 756: ! 757: void __volatile__ ! 758: thread_syscall_return( ! 759: kern_return_t retval) ! 760: { ! 761: thread_t thread = current_thread(); ! 762: struct ppc_saved_state *ssp = &thread->pcb->ss; ! 763: ! 764: ssp->r3 = retval; ! 765: ! 766: thread_exception_return(); ! 767: /* NOTREACHED */ ! 768: } ! 769: ! 770: void ! 771: thread_set_syscall_return( ! 772: thread_t thread, ! 773: kern_return_t retval) ! 774: { ! 775: struct ppc_saved_state *ssp = &thread->pcb->ss; ! 776: ! 777: ssp->r3 = retval; ! 778: } ! 779: ! 780: void ! 781: pmap_switch(pmap_t map) ! 782: { ! 783: unsigned int i; ! 784: ! 785: if (map->space == PPC_SID_KERNEL) ! 786: return; ! 787: ! 788: /* sr value has Ks=1, Ku=1, and vsid composed of space+seg num */ ! 789: i = SEG_REG_PROT | (map->space << 4); ! 790: ! 791: isync(); /* context sync before */ ! 792: /* mtsr(0x0, i + 0x0); SR0 is part of the kernel address space */ ! 793: /* mtsr(0x1, i + 0x1); SR1 is part of the kernel address space */ ! 794: /* mtsr(0x2, i + 0x2); SR2 is part of the kernel address space */ ! 795: /* mtsr(0x3, i + 0x3); SR3 is part of the kernel address space */ ! 796: mtsr(0x4, i + 0x4); ! 797: mtsr(0x5, i + 0x5); ! 798: mtsr(0x6, i + 0x6); ! 799: mtsr(0x7, i + 0x7); ! 800: mtsr(0x8, i + 0x8); ! 801: mtsr(0x9, i + 0x9); ! 802: mtsr(0xa, i + 0xa); ! 803: mtsr(0xb, i + 0xb); ! 804: mtsr(0xc, i + 0xc); ! 805: mtsr(0xd, i + 0xd); ! 806: mtsr(0xe, i + 0xe); ! 807: mtsr(0xf, i + 0xf); ! 808: isync(); /* context sync after */ ! 809: } ! 810: ! 811: /* ! 812: * task_map_io_ports() is required by the driverkit routines. ! 813: */ ! 814: kern_return_t ! 815: task_map_io_ports( ! 816: task_t task, ! 817: unsigned int port, ! 818: unsigned int length, ! 819: boolean_t unmap ! 820: ) ! 821: { ! 822: return (KERN_SUCCESS); ! 823: } ! 824: ! 825: ! 826: #if MACH_ASSERT ! 827: void ! 828: dump_pcb(pcb_t pcb) ! 829: { ! 830: printf("pcb @ %8.8x:\n", pcb); ! 831: printf("ksp = 0x%08x\n\n",pcb->ksp); ! 832: #if DEBUG ! 833: regDump(&pcb->ss); ! 834: #endif /* DEBUG */ ! 835: } ! 836: ! 837: void ! 838: dump_thread(thread_t th) ! 839: { ! 840: printf(" thread @ 0x%x:\n", th); ! 841: } ! 842: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.