Commit 4d90eb97 authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman
Browse files

powerpc/ptrace: Create ptrace_get_fpr() and ptrace_put_fpr()



On the same model as ptrace_get_reg() and ptrace_put_reg(),
create ptrace_get_fpr() and ptrace_put_fpr() to get/set
the floating points registers.

We move the boundary checkings in them.

Signed-off-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/24a1baedea7f7ae7b6bf27be98bab6d01b5ca2c1.1597770847.git.christophe.leroy@csgroup.eu
parent e009fa43
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
CFLAGS_ptrace-view.o		+= -DUTS_MACHINE='"$(UTS_MACHINE)"'

obj-y				+= ptrace.o ptrace-view.o
obj-y				+= ptrace-fpu.o
obj-$(CONFIG_COMPAT)		+= ptrace32.o
obj-$(CONFIG_VSX)		+= ptrace-vsx.o
ifneq ($(CONFIG_VSX),y)
+4 −0
Original line number Diff line number Diff line
@@ -164,6 +164,10 @@ int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data);

extern const struct user_regset_view user_ppc_native_view;

/* ptrace-fpu */
int ptrace_get_fpr(struct task_struct *child, int index, unsigned long *data);
int ptrace_put_fpr(struct task_struct *child, int index, unsigned long data);

/* ptrace-(no)adv */
void ppc_gethwdinfo(struct ppc_debug_info *dbginfo);
int ptrace_get_debugreg(struct task_struct *child, unsigned long addr,
+40 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-or-later

#include <linux/regset.h>

#include <asm/switch_to.h>

#include "ptrace-decl.h"

int ptrace_get_fpr(struct task_struct *child, int index, unsigned long *data)
{
	unsigned int fpidx = index - PT_FPR0;

	if (index > PT_FPSCR)
		return -EIO;

	flush_fp_to_thread(child);
	if (fpidx < (PT_FPSCR - PT_FPR0))
		memcpy(data, &child->thread.TS_FPR(fpidx), sizeof(long));
	else
		*data = child->thread.fp_state.fpscr;

	return 0;
}

int ptrace_put_fpr(struct task_struct *child, int index, unsigned long data)
{
	unsigned int fpidx = index - PT_FPR0;

	if (index > PT_FPSCR)
		return -EIO;

	flush_fp_to_thread(child);
	if (fpidx < (PT_FPSCR - PT_FPR0))
		memcpy(&child->thread.TS_FPR(fpidx), &data, sizeof(long));
	else
		child->thread.fp_state.fpscr = data;

	return 0;
}
+11 −29
Original line number Diff line number Diff line
@@ -56,25 +56,17 @@ long arch_ptrace(struct task_struct *child, long request,
		ret = -EIO;
		/* convert to index and check */
		index = addr / sizeof(long);
		if ((addr & (sizeof(long) - 1)) || (index > PT_FPSCR)
		    || (child->thread.regs == NULL))
		if ((addr & (sizeof(long) - 1)) || !child->thread.regs)
			break;

		CHECK_FULL_REGS(child->thread.regs);
		if (index < PT_FPR0) {
		if (index < PT_FPR0)
			ret = ptrace_get_reg(child, (int) index, &tmp);
		else
			ret = ptrace_get_fpr(child, index, &tmp);

		if (ret)
			break;
		} else {
			unsigned int fpidx = index - PT_FPR0;

			flush_fp_to_thread(child);
			if (fpidx < (PT_FPSCR - PT_FPR0))
				memcpy(&tmp, &child->thread.TS_FPR(fpidx),
				       sizeof(long));
			else
				tmp = child->thread.fp_state.fpscr;
		}
		ret = put_user(tmp, datalp);
		break;
	}
@@ -86,24 +78,14 @@ long arch_ptrace(struct task_struct *child, long request,
		ret = -EIO;
		/* convert to index and check */
		index = addr / sizeof(long);
		if ((addr & (sizeof(long) - 1)) || (index > PT_FPSCR)
		    || (child->thread.regs == NULL))
		if ((addr & (sizeof(long) - 1)) || !child->thread.regs)
			break;

		CHECK_FULL_REGS(child->thread.regs);
		if (index < PT_FPR0) {
		if (index < PT_FPR0)
			ret = ptrace_put_reg(child, index, data);
		} else {
			unsigned int fpidx = index - PT_FPR0;

			flush_fp_to_thread(child);
			if (fpidx < (PT_FPSCR - PT_FPR0))
				memcpy(&child->thread.TS_FPR(fpidx), &data,
				       sizeof(long));
		else
				child->thread.fp_state.fpscr = data;
			ret = 0;
		}
			ret = ptrace_put_fpr(child, index, data);
		break;
	}