Commit 87d80533 authored by Al Viro's avatar Al Viro
Browse files

sparc32: get rid of odd callers of copy_regset_to_user()



the life is much simpler if copy_regset_to_user() (and ->get())
gets called only with pos == 0; sparc32 PTRACE_GETREGS and
PTRACE_GETFPREGS are among the few things that use it to fetch
pieces of regset _not_ starting at the beginning.  It's actually
easier to define a separate regset that would provide what
we need, rather than trying to cobble that from the one
PTRACE_GETREGSET uses.

Extra ->get() instances do not amount to much code and once
we get the conversion of ->get() to new API (dependent upon the
lack of weird callers of ->get()) they'll shrink a lot, along
with the rest of ->get() instances...

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 030754c9
Loading
Loading
Loading
Loading
+82 −35
Original line number Diff line number Diff line
@@ -99,15 +99,13 @@ static int genregs32_get(struct task_struct *target,
	if (ret || !count)
		return ret;

	if (pos < 32 * sizeof(u32)) {
	if (regwindow32_get(target, regs, uregs))
		return -EFAULT;
	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
				  uregs,
				  16 * sizeof(u32), 32 * sizeof(u32));
		if (ret || !count)
	if (ret)
		return ret;
	}

	uregs[0] = regs->psr;
	uregs[1] = regs->pc;
@@ -288,6 +286,73 @@ static const struct user_regset sparc32_regsets[] = {
	},
};

static int getregs_get(struct task_struct *target,
			 const struct user_regset *regset,
			 unsigned int pos, unsigned int count,
			 void *kbuf, void __user *ubuf)
{
	const struct pt_regs *regs = target->thread.kregs;
	u32 v[4];
	int ret;

	if (target == current)
		flush_user_windows();

	v[0] = regs->psr;
	v[1] = regs->pc;
	v[2] = regs->npc;
	v[3] = regs->y;
	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
				  v,
				  0 * sizeof(u32), 4 * sizeof(u32));
	if (ret)
		return ret;

	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
				  regs->u_regs + 1,
				  4 * sizeof(u32), 19 * sizeof(u32));
}

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

#if 0
	if (target == current)
		save_and_clear_fpu();
#endif

	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
				  fpregs,
				  0, 32 * sizeof(u32));
	if (ret)
		return ret;
	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
				  &target->thread.fsr,
				  32 * sizeof(u32), 33 * sizeof(u32));
	if (ret)
		return ret;
	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
				  33 * sizeof(u32), 68 * sizeof(u32));
}

static const struct user_regset ptrace32_regsets[] = {
	[REGSET_GENERAL] = {
		.n = 19, .size = sizeof(u32), .get = getregs_get,
	},
	[REGSET_FP] = {
		.n = 68, .size = sizeof(u32), .get = getfpregs_get,
	},
};

static const struct user_regset_view ptrace32_view = {
	.regsets = ptrace32_regsets, .n = ARRAY_SIZE(ptrace32_regsets)
};

static const struct user_regset_view user_sparc32_view = {
	.name = "sparc", .e_machine = EM_SPARC,
	.regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
@@ -327,15 +392,10 @@ long arch_ptrace(struct task_struct *child, long request,

	switch(request) {
	case PTRACE_GETREGS: {
		ret = copy_regset_to_user(child, view, REGSET_GENERAL,
					  32 * sizeof(u32),
					  4 * sizeof(u32),
					  &pregs->psr);
		if (!ret)
			copy_regset_to_user(child, view, REGSET_GENERAL,
					    1 * sizeof(u32),
					    15 * sizeof(u32),
					    &pregs->u_regs[0]);
		ret = copy_regset_to_user(child, &ptrace32_view,
					  REGSET_GENERAL, 0,
					  19 * sizeof(u32),
					  pregs);
		break;
	}

@@ -353,23 +413,10 @@ long arch_ptrace(struct task_struct *child, long request,
	}

	case PTRACE_GETFPREGS: {
		ret = copy_regset_to_user(child, view, REGSET_FP,
					  0 * sizeof(u32),
					  32 * sizeof(u32),
					  &fps->regs[0]);
		if (!ret)
			ret = copy_regset_to_user(child, view, REGSET_FP,
						  33 * sizeof(u32),
						  1 * sizeof(u32),
						  &fps->fsr);

		if (!ret) {
			if (__put_user(0, &fps->fpqd) ||
			    __put_user(0, &fps->flags) ||
			    __put_user(0, &fps->extra) ||
			    clear_user(fps->fpq, sizeof(fps->fpq)))
				ret = -EFAULT;
		}
		ret = copy_regset_to_user(child, &ptrace32_view,
					  REGSET_FP, 0,
					  68 * sizeof(u32),
					  fps);
		break;
	}