Exemple #1
0
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;
	}
}
Exemple #2
0
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 */
}
Exemple #3
0
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 */
}
Exemple #4
0
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;
    }
}
Exemple #5
0
/*
 * 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;
    }
}
Exemple #6
0
/* 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
}
Exemple #7
0
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;
    }
}
Exemple #8
0
/*
 * 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;
    }
}
Exemple #9
0
	 *	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);