Exemplo n.º 1
0
/*
 * Set the thread state from a regset passed in via ptrace
 */
static int genregs_set(struct task_struct *target,
		       const struct user_regset *regset,
		       unsigned int pos, unsigned int count,
		       const void *kbuf, const void __user * ubuf)
{
	struct pt_regs *regs = task_pt_regs(target);
	int ret;

	/* ignore r0 */
	ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4);
	/* r1 - r31 */
	if (!ret)
		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
					 regs->gpr+1, 4, 4*32);
	/* PC */
	if (!ret)
		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				 &regs->pc, 4*32, 4*33);
	/*
	 * Skip SR and padding... userspace isn't allowed to changes bits in
	 * the Supervision register
	 */
	if (!ret)
		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
						4*33, -1);

	return ret;
}
static int fpregs32_set(struct task_struct *target,
			const struct user_regset *regset,
			unsigned int pos, unsigned int count,
			const void *kbuf, const void __user *ubuf)
{
	unsigned long *fpregs = target->thread.float_regs;
	int ret;

#if 0
	if (target == current)
		save_and_clear_fpu();
#endif
	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				 fpregs,
				 0, 32 * sizeof(u32));
	if (!ret)
		user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
					  32 * sizeof(u32),
					  33 * sizeof(u32));
	if (!ret && count > 0) {
		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
					 &target->thread.fsr,
					 33 * sizeof(u32),
					 34 * sizeof(u32));
	}

	if (!ret)
		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
						34 * sizeof(u32), -1);
	return ret;
}
static int hw_break_set(struct task_struct *target,
			const struct user_regset *regset,
			unsigned int pos, unsigned int count,
			const void *kbuf, const void __user *ubuf)
{
	unsigned int note_type = regset->core_note_type;
	int ret, idx = 0, offset, limit;
	u32 ctrl;
	u64 addr;

	/* Resource info and pad */
	offset = offsetof(struct user_hwdebug_state, dbg_regs);
	ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
	if (ret)
		return ret;

	/* (address, ctrl) registers */
	limit = regset->n * regset->size;
	while (count && offset < limit) {
		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr,
					 offset, offset + PTRACE_HBP_ADDR_SZ);
		if (ret)
			return ret;
		ret = ptrace_hbp_set_addr(note_type, target, idx, addr);
		if (ret)
			return ret;
		offset += PTRACE_HBP_ADDR_SZ;

		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl,
					 offset, offset + PTRACE_HBP_CTRL_SZ);
		if (ret)
			return ret;
		ret = ptrace_hbp_set_ctrl(note_type, target, idx, ctrl);
		if (ret)
			return ret;
		offset += PTRACE_HBP_CTRL_SZ;

		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
						offset,
						offset + PTRACE_HBP_PAD_SZ);
		if (ret)
			return ret;
		offset += PTRACE_HBP_PAD_SZ;
		idx++;
	}

	return 0;
}
Exemplo n.º 4
0
/*
 * update the contents of the MN10300 userspace general registers
 */
static int genregs_set(struct task_struct *target,
		       const struct user_regset *regset,
		       unsigned int pos, unsigned int count,
		       const void *kbuf, const void __user *ubuf)
{
	struct pt_regs *regs = task_pt_regs(target);
	unsigned long tmp;
	int ret;

	/* we need to skip regs->next */
	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				 regs, 0, PT_ORIG_D0 * sizeof(long));
	if (ret < 0)
		return ret;

	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				 &regs->orig_d0, PT_ORIG_D0 * sizeof(long),
				 PT_EPSW * sizeof(long));
	if (ret < 0)
		return ret;

	/* we need to mask off changes to EPSW */
	tmp = regs->epsw;
	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				 &tmp, PT_EPSW * sizeof(long),
				 PT_PC * sizeof(long));
	tmp &= EPSW_FLAG_V | EPSW_FLAG_C | EPSW_FLAG_N | EPSW_FLAG_Z;
	tmp |= regs->epsw & ~(EPSW_FLAG_V | EPSW_FLAG_C | EPSW_FLAG_N |
			      EPSW_FLAG_Z);
	regs->epsw = tmp;

	if (ret < 0)
		return ret;

	/* and finally load the PC */
	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				 &regs->pc, PT_PC * sizeof(long),
				 NR_PTREGS * sizeof(long));

	if (ret < 0)
		return ret;

	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
					 NR_PTREGS * sizeof(long), -1);
}
Exemplo n.º 5
0
/*
 * For vfp_set() a read-modify-write is done on the VFP registers,
 * in order to avoid writing back a half-modified set of registers on
 * failure.
 */
static int vfp_set(struct task_struct *target,
			  const struct user_regset *regset,
			  unsigned int pos, unsigned int count,
			  const void *kbuf, const void __user *ubuf)
{
	int ret;
	struct thread_info *thread = task_thread_info(target);
/*	struct vfp_hard_struct new_vfp = thread->vfpstate.hard; */
	struct vfp_hard_struct new_vfp;
	const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);
	const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);

	vfp_sync_hwstate(thread);
	new_vfp = thread->vfpstate.hard;
	
	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				  &new_vfp.fpregs,
				  user_fpregs_offset,
				  user_fpregs_offset + sizeof(new_vfp.fpregs));
	if (ret)
		return ret;

	ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
				user_fpregs_offset + sizeof(new_vfp.fpregs),
				user_fpscr_offset);
	if (ret)
		return ret;

	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				 &new_vfp.fpscr,
				 user_fpscr_offset,
				 user_fpscr_offset + sizeof(new_vfp.fpscr));
	if (ret)
		return ret;

/*	vfp_sync_hwstate(thread); */
/*	thread->vfpstate.hard = new_vfp; */
	vfp_flush_hwstate(thread);
	thread->vfpstate.hard = new_vfp;

	return 0;
}
Exemplo n.º 6
0
/*
 * update the contents of the MN10300 userspace FPU registers
 */
static int fpuregs_set(struct task_struct *target,
		       const struct user_regset *regset,
		       unsigned int pos, unsigned int count,
		       const void *kbuf, const void __user *ubuf)
{
	struct fpu_state_struct fpu_state = target->thread.fpu_state;
	int ret;

	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				 &fpu_state, 0, sizeof(fpu_state));
	if (ret < 0)
		return ret;

	fpu_kill_state(target);
	target->thread.fpu_state = fpu_state;
	set_using_fpu(target);

	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
					 sizeof(fpu_state), -1);
}
Exemplo n.º 7
0
/*
 * Copy the supplied NT_PRFPREG buffer to the floating-point context.
 * Choose the appropriate helper for general registers, and then copy
 * the FCSR register separately.  Ignore the incoming FIR register
 * contents though, as the register is read-only.
 *
 * We optimize for the case where `count % sizeof(elf_fpreg_t) == 0',
 * which is supposed to have been guaranteed by the kernel before
 * calling us, e.g. in `ptrace_regset'.  We enforce that requirement,
 * so that we can safely avoid preinitializing temporaries for
 * partial register writes.
 */
static int fpr_set(struct task_struct *target,
		   const struct user_regset *regset,
		   unsigned int pos, unsigned int count,
		   const void *kbuf, const void __user *ubuf)
{
	const int fcr31_pos = NUM_FPU_REGS * sizeof(elf_fpreg_t);
	const int fir_pos = fcr31_pos + sizeof(u32);
	u32 fcr31;
	int err;

	BUG_ON(count % sizeof(elf_fpreg_t));

	if (pos + count > sizeof(elf_fpregset_t))
		return -EIO;

	init_fp_ctx(target);

	if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
		err = fpr_set_fpa(target, &pos, &count, &kbuf, &ubuf);
	else
		err = fpr_set_msa(target, &pos, &count, &kbuf, &ubuf);
	if (err)
		return err;

	if (count > 0) {
		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
					 &fcr31,
					 fcr31_pos, fcr31_pos + sizeof(u32));
		if (err)
			return err;

		ptrace_setfcr31(target, fcr31);
	}

	if (count > 0)
		err = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
						fir_pos,
						fir_pos + sizeof(u32));

	return err;
}
Exemplo n.º 8
0
/*
 * update the contents of the Blackfin userspace general registers
 */
static int genregs_set(struct task_struct *target,
		       const struct user_regset *regset,
		       unsigned int pos, unsigned int count,
		       const void *kbuf, const void __user *ubuf)
{
	struct pt_regs *regs = task_pt_regs(target);
	int ret;

	/* Don't let people set SYSCFG (it's at the end of pt_regs) */
	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				 regs, 0, PT_SYSCFG);
	if (ret < 0)
		return ret;

	/* This sucks ... */
	target->thread.usp = regs->usp;
	/* regs->retx = regs->pc; */

	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
					PT_SYSCFG, -1);
}
Exemplo n.º 9
0
static int genregs_set(struct task_struct *target,
		       const struct user_regset *regset,
		       unsigned int pos, unsigned int count,
		       const void *kbuf, const void __user *ubuf)
{
	struct pt_regs *regs = task_pt_regs(target);
	int ret;

	
	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				 regs, 0, PT_SYSCFG);
	if (ret < 0)
		return ret;

	
	target->thread.usp = regs->usp;
	

	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
					PT_SYSCFG, -1);
}
Exemplo n.º 10
0
static int fpr_set(struct task_struct *target,
		   const struct user_regset *regset,
		   unsigned int pos, unsigned int count,
		   const void *kbuf, const void __user *ubuf)
{
	unsigned i;
	int err;
	u64 fpr_val;
	u32 fcr31;

	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
					 &target->thread.fpu.fpr,
					 0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
		if (err)
			return err;
	} else {
		for (i = 0; i < NUM_FPU_REGS; i++) {
			err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
						 &fpr_val,
						 i * sizeof(elf_fpreg_t),
						 (i + 1) * sizeof(elf_fpreg_t));
			if (err)
				return err;
			set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
		}
	}

	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fcr31,
			    NUM_FPU_REGS * sizeof(elf_fpreg_t),
			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
	if (err)
		return err;

	target->thread.fpu.fcr31 = fcr31 & ~FPU_CSR_ALL_X;

	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32),
			    sizeof(elf_fpregset_t));
}
static int genregs32_set(struct task_struct *target,
			 const struct user_regset *regset,
			 unsigned int pos, unsigned int count,
			 const void *kbuf, const void __user *ubuf)
{
	struct pt_regs *regs = target->thread.kregs;
	unsigned long __user *reg_window;
	const unsigned long *k = kbuf;
	const unsigned long __user *u = ubuf;
	unsigned long reg;

	if (target == current)
		flush_user_windows();

	pos /= sizeof(reg);
	count /= sizeof(reg);

	if (kbuf) {
		for (; count > 0 && pos < 16; count--)
			regs->u_regs[pos++] = *k++;

		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
		reg_window -= 16;
		for (; count > 0 && pos < 32; count--) {
			if (put_user(*k++, &reg_window[pos++]))
				return -EFAULT;
		}
	} else {
		for (; count > 0 && pos < 16; count--) {
			if (get_user(reg, u++))
				return -EFAULT;
			regs->u_regs[pos++] = reg;
		}

		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
		reg_window -= 16;
		for (; count > 0 && pos < 32; count--) {
			if (get_user(reg, u++) ||
			    put_user(reg, &reg_window[pos++]))
				return -EFAULT;
		}
	}
	while (count > 0) {
		unsigned long psr;

		if (kbuf)
			reg = *k++;
		else if (get_user(reg, u++))
			return -EFAULT;

		switch (pos) {
		case 32: /* PSR */
			psr = regs->psr;
			psr &= ~(PSR_ICC | PSR_SYSCALL);
			psr |= (reg & (PSR_ICC | PSR_SYSCALL));
			regs->psr = psr;
			break;
		case 33: /* PC */
			regs->pc = reg;
			break;
		case 34: /* NPC */
			regs->npc = reg;
			break;
		case 35: /* Y */
			regs->y = reg;
			break;
		case 36: /* WIM */
		case 37: /* TBR */
			break;
		default:
			goto finish;
		}

		pos++;
		count--;
	}
finish:
	pos *= sizeof(reg);
	count *= sizeof(reg);

	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
					 38 * sizeof(reg), -1);
}