struct i386_saved_state * get_user_regs(thread_act_t th) { if (th->mact.pcb) return(USER_REGS(th)); else { printf("[get_user_regs: thread does not have pcb]"); return NULL; } }
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; } else if (error != EJUSTRETURN) { if (error) { regs->eax = error; regs->efl |= EFL_CF; /* carry bit */ } else { /* (not error) */ regs->eax = rval[0]; regs->edx = rval[1]; regs->efl &= ~EFL_CF; } } 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 */ }
void unix_syscall(struct i386_saved_state *regs) { thread_act_t thread; void *vt; unsigned short code; struct sysent *callp; int nargs, error; volatile int *rval; int funnel_type; vm_offset_t params; extern int nsysent; struct proc *p; struct proc *current_proc(); thread = current_act(); p = current_proc(); rval = (int *)get_bsduthreadrval(thread); //printf("[scall : eax %x]", regs->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); params += sizeof (int); callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; } vt = get_bsduthreadarg(thread); if ((nargs = (callp->sy_narg * sizeof (int))) && (error = copyin((char *) params, (char *)vt , nargs)) != 0) { regs->eax = error; regs->efl |= EFL_CF; thread_exception_return(); /* NOTREACHED */ } rval[0] = 0; rval[1] = regs->edx; 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, (int *) &rval[0]); #if 0 /* May be needed with vfork changes */ regs = USER_REGS(thread); #endif if (error == ERESTART) { regs->eip -= 7; } else if (error != EJUSTRETURN) { if (error) { regs->eax = error; regs->efl |= EFL_CF; /* carry bit */ } else { /* (not error) */ regs->eax = rval[0]; regs->edx = rval[1]; regs->efl &= ~EFL_CF; } } 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 */ }
kern_return_t act_machine_get_state( thread_act_t thr_act, thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t *count) { #if MACH_ASSERT if (watchacts & WA_STATE) printf("act_%x act_m_get_state(thr_act=%x,flav=%x,st=%x,cnt@%x=%x)\n", current_act(), thr_act, flavor, tstate, count, (count ? *count : 0)); #endif /* MACH_ASSERT */ switch (flavor) { case THREAD_STATE_FLAVOR_LIST: if (*count < 3) return (KERN_INVALID_ARGUMENT); tstate[0] = HP700_THREAD_STATE; tstate[1] = HP700_FLOAT_STATE; tstate[2] = THREAD_SYSCALL_STATE; *count = 3; return KERN_SUCCESS; case THREAD_SYSCALL_STATE: { register struct thread_syscall_state *state; register struct hp700_saved_state *saved_state = USER_REGS(thr_act); if (*count < HP700_SYSCALL_STATE_COUNT) return KERN_INVALID_ARGUMENT; state = (struct thread_syscall_state *) tstate; state->r1 = saved_state->r1; state->rp = saved_state->rp; state->r3 = saved_state->r3; state->t1 = saved_state->t1; state->arg3 = saved_state->arg3; state->arg2 = saved_state->arg2; state->arg1 = saved_state->arg1; state->arg0 = saved_state->arg0; state->dp = saved_state->dp; state->ret0 = saved_state->ret0; state->ret1 = saved_state->ret1; state->sp = saved_state->sp; state->iioq_head = saved_state->iioq_head; state->iioq_tail = saved_state->iioq_tail; *count = HP700_SYSCALL_STATE_COUNT; return KERN_SUCCESS; } case HP700_THREAD_STATE: { register struct hp700_thread_state *state; register struct hp700_saved_state *saved_state = USER_REGS(thr_act); if (*count < HP700_THREAD_STATE_COUNT) return KERN_INVALID_ARGUMENT; state = (struct hp700_thread_state *) tstate; state->flags = saved_state->flags; state->r1 = saved_state->r1; state->rp = saved_state->rp; state->r3 = saved_state->r3; state->r4 = saved_state->r4; state->r5 = saved_state->r5; state->r6 = saved_state->r6; state->r7 = saved_state->r7; state->r8 = saved_state->r8; state->r9 = saved_state->r9; state->r10 = saved_state->r10; state->r11 = saved_state->r11; state->r12 = saved_state->r12; state->r13 = saved_state->r13; state->r14 = saved_state->r14; state->r15 = saved_state->r15; state->r16 = saved_state->r16; state->r17 = saved_state->r17; state->r18 = saved_state->r18; state->t4 = saved_state->t4; state->t3 = saved_state->t3; state->t2 = saved_state->t2; state->t1 = saved_state->t1; state->arg3 = saved_state->arg3; state->arg2 = saved_state->arg2; state->arg1 = saved_state->arg1; state->arg0 = saved_state->arg0; state->dp = saved_state->dp; state->ret0 = saved_state->ret0; state->ret1 = saved_state->ret1; state->sp = saved_state->sp; state->r31 = saved_state->r31; state->sr0 = saved_state->sr0; state->sr1 = saved_state->sr1; state->sr2 = saved_state->sr2; state->sr3 = saved_state->sr3; state->sr4 = saved_state->sr4; state->sr5 = saved_state->sr5; state->sr6 = saved_state->sr6; state->rctr = saved_state->rctr; state->pidr1 = saved_state->pidr1; state->pidr2 = saved_state->pidr2; state->ccr = saved_state->ccr; state->sar = saved_state->sar; state->pidr3 = saved_state->pidr3; state->pidr4 = saved_state->pidr4; state->iioq_head = saved_state->iioq_head; state->iioq_tail = saved_state->iioq_tail; state->iisq_head = saved_state->iisq_head; state->iisq_tail = saved_state->iisq_tail; state->fpu = saved_state->fpu; /* * Only export the meaningful bits of the psw */ state->ipsw = saved_state->ipsw & (PSW_R | PSW_X | PSW_T | PSW_N | PSW_B | PSW_V | PSW_CB); *count = HP700_THREAD_STATE_COUNT; return KERN_SUCCESS; } case HP700_FLOAT_STATE: { register struct hp700_float_state *state; register struct hp700_float_state *saved_state = USER_FREGS(thr_act); if (*count < HP700_FLOAT_STATE_COUNT) return KERN_INVALID_ARGUMENT; state = (struct hp700_float_state *) tstate; if (fpu_pcb == thr_act->mact.pcb) fpu_flush(); if(thr_act->mact.pcb->ss.fpu) { assert(thr_act->mact.pcb->ss.fpu == 1); bcopy((char *)saved_state, (char *)state, sizeof(struct hp700_float_state)); } else bzero((char*)state, sizeof(struct hp700_float_state)); *count = HP700_FLOAT_STATE_COUNT; return KERN_SUCCESS; } default: return KERN_INVALID_ARGUMENT; } }
/* * thread_setstatus: * * Set the status of the specified thread. */ kern_return_t act_machine_set_state( thread_act_t thr_act, thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t count) { int kernel_act = thr_act->kernel_loading || thr_act->kernel_loaded; #if MACH_ASSERT if (watchacts & WA_STATE) printf("act_%x act_m_set_state(thr_act=%x,flav=%x,st=%x,cnt=%x)\n", current_act(), thr_act, flavor, tstate, count); #endif /* MACH_ASSERT */ switch (flavor) { case THREAD_SYSCALL_STATE: { register struct thread_syscall_state *state; register struct hp700_saved_state *saved_state = USER_REGS(thr_act); state = (struct thread_syscall_state *)tstate; saved_state->r1 = state->r1; saved_state->rp = state->rp; saved_state->r3 = state->r3; saved_state->t1 = state->t1; saved_state->arg3 = state->arg3; saved_state->arg2 = state->arg2; saved_state->arg1 = state->arg1; saved_state->arg0 = state->arg0; saved_state->dp = state->dp; saved_state->ret0 = state->ret0; saved_state->ret1 = state->ret1; saved_state->sp = state->sp; if(kernel_act) { saved_state->iioq_head = state->iioq_head; saved_state->iioq_tail = state->iioq_tail; } else { saved_state->iioq_head = state->iioq_head | PC_PRIV_USER; saved_state->iioq_tail = state->iioq_tail | PC_PRIV_USER; } return KERN_SUCCESS; } case HP700_THREAD_STATE: { register struct hp700_thread_state *state; register struct hp700_saved_state *saved_state = USER_REGS(thr_act); state = (struct hp700_thread_state *)tstate; if(state->flags & (SS_INSYSCALL|SS_INTRAP)) saved_state->flags = state->flags; saved_state->r1 = state->r1; saved_state->rp = state->rp; saved_state->r3 = state->r3; saved_state->r4 = state->r4; saved_state->r5 = state->r5; saved_state->r6 = state->r6; saved_state->r7 = state->r7; saved_state->r8 = state->r8; saved_state->r9 = state->r9; saved_state->r10 = state->r10; saved_state->r11 = state->r11; saved_state->r12 = state->r12; saved_state->r13 = state->r13; saved_state->r14 = state->r14; saved_state->r15 = state->r15; saved_state->r16 = state->r16; saved_state->r17 = state->r17; saved_state->r18 = state->r18; saved_state->t4 = state->t4; saved_state->t3 = state->t3; saved_state->t2 = state->t2; saved_state->t1 = state->t1; saved_state->arg3 = state->arg3; saved_state->arg2 = state->arg2; saved_state->arg1 = state->arg1; saved_state->arg0 = state->arg0; saved_state->dp = state->dp; saved_state->ret0 = state->ret0; saved_state->ret1 = state->ret1; saved_state->sp = state->sp; saved_state->r31 = state->r31; saved_state->sar = state->sar; if(kernel_act) { saved_state->iioq_head = state->iioq_head; saved_state->iioq_tail = state->iioq_tail; } else { saved_state->iioq_head = state->iioq_head | PC_PRIV_USER; saved_state->iioq_tail = state->iioq_tail | PC_PRIV_USER; } saved_state->iisq_head = state->iisq_head; saved_state->iisq_tail = state->iisq_tail; saved_state->sr0 = state->sr0; saved_state->sr1 = state->sr1; saved_state->sr2 = state->sr2; saved_state->sr3 = state->sr3; saved_state->fpu = state->fpu; /* * Make sure only PSW_T, PSW_X, PSW_N, PSW_B, PSW_V and PSW_CB * bits are set by users. */ saved_state->ipsw = state->ipsw & (PSW_R | PSW_T | PSW_X | PSW_N | PSW_B | PSW_V | PSW_CB); /* * Always make sure that PSW_C, PSW_Q, PSW_P, PSW_D are set. The PSW_I * bit is set according to eiem at context switch. */ saved_state->ipsw |= PSW_C | PSW_Q | PSW_P | PSW_D | PSW_I; /* * if single step, set the count to 0 so that 1 instruction * is excecuted before trapping. */ if(saved_state->ipsw & PSW_R) saved_state->rctr = 0; return KERN_SUCCESS; } case HP700_FLOAT_STATE: { register struct hp700_float_state *state; register struct hp700_float_state *saved_state = USER_FREGS(thr_act); state = (struct hp700_float_state *) tstate; if (fpu_pcb == thr_act->mact.pcb) fpu_pcb = 0; /* must restore coprocessor */ bcopy((char *)state, (char *)saved_state, sizeof(struct hp700_float_state)); thr_act->mact.pcb->ss.fpu = 1; return KERN_SUCCESS; } default: return KERN_INVALID_ARGUMENT; } }
/* Instruction pointers operate differently on mc88110 */ void m88110_syscall(register_t code, struct trapframe *tf) { int i, nsys, nap; struct sysent *callp; struct proc *p; int error; register_t args[11], rval[2], *ap; u_quad_t sticks; #ifdef DIAGNOSTIC extern struct pcb *curpcb; #endif uvmexp.syscalls++; p = curproc; callp = p->p_emul->e_sysent; nsys = p->p_emul->e_nsysent; #ifdef DIAGNOSTIC if (USERMODE(tf->tf_epsr) == 0) panic("syscall"); if (curpcb != &p->p_addr->u_pcb) panic("syscall curpcb/ppcb"); if (tf != (struct trapframe *)&curpcb->user_state) panic("syscall trapframe"); #endif sticks = p->p_sticks; p->p_md.md_tf = tf; /* * For 88k, all the arguments are passed in the registers (r2-r12) * For syscall (and __syscall), r2 (and r3) has the actual code. * __syscall takes a quad syscall number, so that other * arguments are at their natural alignments. */ ap = &tf->tf_r[2]; nap = 11; /* r2-r12 */ switch (code) { case SYS_syscall: code = *ap++; nap--; break; case SYS___syscall: if (callp != sysent) break; code = ap[_QUAD_LOWWORD]; ap += 2; nap -= 2; break; } /* Callp currently points to syscall, which returns ENOSYS. */ if (code < 0 || code >= nsys) callp += p->p_emul->e_nosys; else { callp += code; i = callp->sy_argsize / sizeof(register_t); if (i > nap) panic("syscall nargs"); /* * just copy them; syscall stub made sure all the * args are moved from user stack to registers. */ bcopy((caddr_t)ap, (caddr_t)args, i * sizeof(register_t)); } #ifdef SYSCALL_DEBUG scdebug_call(p, code, args); #endif #ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) ktrsyscall(p, code, callp->sy_argsize, args); #endif rval[0] = 0; rval[1] = tf->tf_r[3]; #if NSYSTRACE > 0 if (ISSET(p->p_flag, P_SYSTRACE)) error = systrace_redirect(code, p, args, rval); else #endif error = (*callp->sy_call)(p, args, rval); /* * system call will look like: * ld r10, r31, 32; r10,r11,r12 might be garbage. * ld r11, r31, 36 * ld r12, r31, 40 * or r13, r0, <code> * tb0 0, r0, <128> <- exip * br err <- enip * jmp r1 * err: or.u r3, r0, hi16(errno) * st r2, r3, lo16(errno) * subu r2, r0, 1 * jmp r1 * * So, when we take syscall trap, exip/enip will be as * shown above. * Given this, * 1. If the system call returned 0, need to jmp r1. * exip += 8 * 2. If the system call returned an errno > 0, increment * exip += 4 and plug the value in r2. This will have us * executing "br err" on return to user space. * 3. If the system call code returned ERESTART, * we need to rexecute the trap instruction. leave exip as is. * 4. If the system call returned EJUSTRETURN, just return. * exip += 4 */ switch (error) { case 0: /* * If fork succeeded and we are the child, our stack * has moved and the pointer tf is no longer valid, * and p is wrong. Compute the new trapframe pointer. * (The trap frame invariably resides at the * tippity-top of the u. area.) */ p = curproc; tf = (struct trapframe *)USER_REGS(p); tf->tf_r[2] = rval[0]; tf->tf_r[3] = rval[1]; tf->tf_epsr &= ~PSR_C; /* skip two instructions */ if (tf->tf_exip & 1) tf->tf_exip = tf->tf_enip + 4; else tf->tf_exip += 4 + 4; break; case ERESTART: /* * Reexecute the trap. * exip is already at the trap instruction, so * there is nothing to do. */ tf->tf_epsr &= ~PSR_C; break; case EJUSTRETURN: tf->tf_epsr &= ~PSR_C; /* skip one instruction */ if (tf->tf_exip & 1) tf->tf_exip = tf->tf_enip; else tf->tf_exip += 4; break; default: if (p->p_emul->e_errno) error = p->p_emul->e_errno[error]; tf->tf_r[2] = error; tf->tf_epsr |= PSR_C; /* fail */ /* skip one instruction */ if (tf->tf_exip & 1) tf->tf_exip = tf->tf_enip; else tf->tf_exip += 4; break; } #ifdef SYSCALL_DEBUG scdebug_ret(p, code, error, rval); #endif userret(p, tf, sticks); #ifdef KTRACE if (KTRPOINT(p, KTR_SYSRET)) ktrsysret(p, code, error, rval[0]); #endif }
kern_return_t act_machine_get_state( thread_act_t thr_act, thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t *count) { #if MACH_ASSERT if (watchacts & WA_STATE) printf("act_%x act_machine_get_state(thr_act=%x,flav=%x,st=%x,cnt@%x=%x)\n", current_act(), thr_act, flavor, tstate, count, (count ? *count : 0)); #endif /* MACH_ASSERT */ switch (flavor) { case THREAD_STATE_FLAVOR_LIST: if (*count < 3) return (KERN_INVALID_ARGUMENT); tstate[0] = PPC_THREAD_STATE; tstate[1] = PPC_FLOAT_STATE; tstate[2] = PPC_EXCEPTION_STATE; *count = 3; return KERN_SUCCESS; case PPC_THREAD_STATE: { register struct ppc_thread_state *state; register struct ppc_saved_state *saved_state = USER_REGS(thr_act); if (*count < PPC_THREAD_STATE_COUNT) return KERN_INVALID_ARGUMENT; state = (struct ppc_thread_state *) tstate; state->r0 = saved_state->r0; state->r1 = saved_state->r1; state->r2 = saved_state->r2; state->r3 = saved_state->r3; state->r4 = saved_state->r4; state->r5 = saved_state->r5; state->r6 = saved_state->r6; state->r7 = saved_state->r7; state->r8 = saved_state->r8; state->r9 = saved_state->r9; state->r10 = saved_state->r10; state->r11 = saved_state->r11; state->r12 = saved_state->r12; state->r13 = saved_state->r13; state->r14 = saved_state->r14; state->r15 = saved_state->r15; state->r16 = saved_state->r16; state->r17 = saved_state->r17; state->r18 = saved_state->r18; state->r19 = saved_state->r19; state->r20 = saved_state->r20; state->r21 = saved_state->r21; state->r22 = saved_state->r22; state->r23 = saved_state->r23; state->r24 = saved_state->r24; state->r25 = saved_state->r25; state->r26 = saved_state->r26; state->r27 = saved_state->r27; state->r28 = saved_state->r28; state->r29 = saved_state->r29; state->r30 = saved_state->r30; state->r31 = saved_state->r31; state->cr = saved_state->cr; state->xer = saved_state->xer; state->lr = saved_state->lr; state->ctr = saved_state->ctr; state->srr0 = saved_state->srr0; /* * Only export the meaningful bits of the msr */ state->srr1 = MSR_REMOVE_SYSCALL_MARK(saved_state->srr1); state->mq = saved_state->mq; /* MQ register (601 only) */ *count = PPC_THREAD_STATE_COUNT; return KERN_SUCCESS; } case PPC_EXCEPTION_STATE: { register struct ppc_exception_state *state; register struct ppc_exception_state *pcb_state = &thr_act->mact.pcb->es; if (*count < PPC_EXCEPTION_STATE_COUNT) return KERN_INVALID_ARGUMENT; state = (struct ppc_exception_state *) tstate; bcopy((char *)pcb_state, (char *)state, sizeof(*state)); *count = PPC_EXCEPTION_STATE_COUNT; return KERN_SUCCESS; } case PPC_FLOAT_STATE: { register struct ppc_float_state *state; register struct ppc_float_state *float_state = &thr_act->mact.pcb->fs; if (*count < PPC_FLOAT_STATE_COUNT) return KERN_INVALID_ARGUMENT; fpu_save(); state = (struct ppc_float_state *) tstate; bcopy((char *)float_state, (char *)state, sizeof(*state)); *count = PPC_FLOAT_STATE_COUNT; return KERN_SUCCESS; } default: return KERN_INVALID_ARGUMENT; } }
/* * thread_setstatus: * * Set the status of the specified thread. */ kern_return_t act_machine_set_state( thread_act_t thr_act, thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t count) { int kernel_act = thr_act->kernel_loading || thr_act->kernel_loaded; #if MACH_ASSERT if (watchacts & WA_STATE) printf("act_%x act_machine_set_state(thr_act=%x,flav=%x,st=%x,cnt=%x)\n", current_act(), thr_act, flavor, tstate, count); #endif /* MACH_ASSERT */ switch (flavor) { case PPC_THREAD_STATE: { register struct ppc_thread_state *state; register struct ppc_saved_state *saved_state = USER_REGS(thr_act); state = (struct ppc_thread_state *)tstate; saved_state->r0 = state->r0; saved_state->r1 = state->r1; saved_state->r2 = state->r2; saved_state->r3 = state->r3; saved_state->r4 = state->r4; saved_state->r5 = state->r5; saved_state->r6 = state->r6; saved_state->r7 = state->r7; saved_state->r8 = state->r8; saved_state->r9 = state->r9; saved_state->r10 = state->r10; saved_state->r11 = state->r11; saved_state->r12 = state->r12; saved_state->r13 = state->r13; saved_state->r14 = state->r14; saved_state->r15 = state->r15; saved_state->r16 = state->r16; saved_state->r17 = state->r17; saved_state->r18 = state->r18; saved_state->r19 = state->r19; saved_state->r20 = state->r20; saved_state->r21 = state->r21; saved_state->r22 = state->r22; saved_state->r23 = state->r23; saved_state->r24 = state->r24; saved_state->r25 = state->r25; saved_state->r26 = state->r26; saved_state->r27 = state->r27; saved_state->r28 = state->r28; saved_state->r29 = state->r29; saved_state->r30 = state->r30; saved_state->r31 = state->r31; saved_state->cr = state->cr; saved_state->xer = state->xer; saved_state->lr = state->lr; saved_state->ctr = state->ctr; saved_state->srr0 = state->srr0; /* * Make sure that the MSR contains only user-importable info */ saved_state->srr1 = MSR_PREPARE_FOR_IMPORT(saved_state->srr1, state->srr1); /* User activations must not run privileged */ if ((!kernel_act) && ((saved_state->srr1 & MASK(MSR_PR)) == 0)) { printf("WARNING - system privilage bit shouldn't be set " "in user task - MSR=0x%08x\n",saved_state->srr1); saved_state->srr1 |= MASK(MSR_PR); } saved_state->mq = state->mq; /* MQ register (601 only) */ return KERN_SUCCESS; } case PPC_EXCEPTION_STATE: { register struct ppc_exception_state *state; register struct ppc_exception_state *pcb_state = &thr_act->mact.pcb->es; state = (struct ppc_exception_state *) tstate; /* Store the state whole, no security problems */ bcopy((char *)state, (char *)pcb_state, sizeof(*state)); return KERN_SUCCESS; } case PPC_FLOAT_STATE: { register struct ppc_float_state *state; register struct ppc_float_state *float_state = &thr_act->mact.pcb->fs; state = (struct ppc_float_state *) tstate; bcopy((char *)state, (char *)float_state, sizeof(*state)); if ((pcb_t)(per_proc_info[cpu_number()].fpu_pcb) == thr_act->mact.pcb) per_proc_info[cpu_number()].fpu_pcb = 0; /* must restore fpu */ /* TODO NMGS - do we need to set fpscr to prevent latent traps? */ return KERN_SUCCESS; } default: return KERN_INVALID_ARGUMENT; } }
* We want to run continuation, giving it as an argument * the return value from Load_context/Switch_context. * Thread_continue takes care of the mismatch between * the argument-passing/return-value conventions. * This function will not return normally, * so we don`t have to worry about a return address. */ STACK_IKS(stack)->k_eip = (long) Thread_continue; STACK_IKS(stack)->k_ebx = (long) continuation; STACK_IKS(stack)->k_esp = (long) STACK_IEL(stack); STACK_IKS(stack)->k_ebp = (long) 0; /* * Point top of kernel stack to user`s registers. */ STACK_IEL(stack)->saved_state = USER_REGS(thread); } /* * stack_detach: * * Detaches a kernel stack from a thread, returning the old stack. */ vm_offset_t stack_detach(thread_t thread) { vm_offset_t stack; counter(if (--c_stacks_current < c_stacks_min) c_stacks_min = c_stacks_current);