Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 6c79759e authored by Paul Burton's avatar Paul Burton
Browse files

MIPS: ptrace: Remove FP support when CONFIG_MIPS_FP_SUPPORT=n



When CONFIG_MIPS_FP_SUPPORT=n we don't support floating point, so remove
the related ptrace support. Besides removing code which should not be
needed, this prepares us for the removal of FPU state in struct
task_struct which this code requires.

Signed-off-by: default avatarPaul Burton <paul.burton@mips.com>
Patchwork: https://patchwork.linux-mips.org/patch/21008/
Cc: linux-mips@linux-mips.org
parent 85164fd8
Loading
Loading
Loading
Loading
+159 −141
Original line number Diff line number Diff line
@@ -61,21 +61,6 @@ void ptrace_disable(struct task_struct *child)
	clear_tsk_thread_flag(child, TIF_LOAD_WATCH);
}

/*
 * Poke at FCSR according to its mask.  Set the Cause bits even
 * if a corresponding Enable bit is set.  This will be noticed at
 * the time the thread is switched to and SIGFPE thrown accordingly.
 */
static void ptrace_setfcr31(struct task_struct *child, u32 value)
{
	u32 fcr31;
	u32 mask;

	fcr31 = child->thread.fpu.fcr31;
	mask = boot_cpu_data.fpu_msk31;
	child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
}

/*
 * Read a general register set.	 We always use the 64-bit format, even
 * for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
@@ -132,55 +117,6 @@ int ptrace_setregs(struct task_struct *child, struct user_pt_regs __user *data)
	return 0;
}

int ptrace_getfpregs(struct task_struct *child, __u32 __user *data)
{
	int i;

	if (!access_ok(VERIFY_WRITE, data, 33 * 8))
		return -EIO;

	if (tsk_used_math(child)) {
		union fpureg *fregs = get_fpu_regs(child);
		for (i = 0; i < 32; i++)
			__put_user(get_fpr64(&fregs[i], 0),
				   i + (__u64 __user *)data);
	} else {
		for (i = 0; i < 32; i++)
			__put_user((__u64) -1, i + (__u64 __user *) data);
	}

	__put_user(child->thread.fpu.fcr31, data + 64);
	__put_user(boot_cpu_data.fpu_id, data + 65);

	return 0;
}

int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
{
	union fpureg *fregs;
	u64 fpr_val;
	u32 value;
	int i;

	if (!access_ok(VERIFY_READ, data, 33 * 8))
		return -EIO;

	init_fp_ctx(child);
	fregs = get_fpu_regs(child);

	for (i = 0; i < 32; i++) {
		__get_user(fpr_val, i + (__u64 __user *)data);
		set_fpr64(&fregs[i], 0, fpr_val);
	}

	__get_user(value, data + 64);
	ptrace_setfcr31(child, value);

	/* FIR may not be written.  */

	return 0;
}

int ptrace_get_watch_regs(struct task_struct *child,
			  struct pt_watch_regs __user *addr)
{
@@ -401,6 +337,73 @@ static int gpr64_set(struct task_struct *target,

#endif /* CONFIG_64BIT */


#ifdef CONFIG_MIPS_FP_SUPPORT

/*
 * Poke at FCSR according to its mask.  Set the Cause bits even
 * if a corresponding Enable bit is set.  This will be noticed at
 * the time the thread is switched to and SIGFPE thrown accordingly.
 */
static void ptrace_setfcr31(struct task_struct *child, u32 value)
{
	u32 fcr31;
	u32 mask;

	fcr31 = child->thread.fpu.fcr31;
	mask = boot_cpu_data.fpu_msk31;
	child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
}

int ptrace_getfpregs(struct task_struct *child, __u32 __user *data)
{
	int i;

	if (!access_ok(VERIFY_WRITE, data, 33 * 8))
		return -EIO;

	if (tsk_used_math(child)) {
		union fpureg *fregs = get_fpu_regs(child);
		for (i = 0; i < 32; i++)
			__put_user(get_fpr64(&fregs[i], 0),
				   i + (__u64 __user *)data);
	} else {
		for (i = 0; i < 32; i++)
			__put_user((__u64) -1, i + (__u64 __user *) data);
	}

	__put_user(child->thread.fpu.fcr31, data + 64);
	__put_user(boot_cpu_data.fpu_id, data + 65);

	return 0;
}

int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
{
	union fpureg *fregs;
	u64 fpr_val;
	u32 value;
	int i;

	if (!access_ok(VERIFY_READ, data, 33 * 8))
		return -EIO;

	init_fp_ctx(child);
	fregs = get_fpu_regs(child);

	for (i = 0; i < 32; i++) {
		__get_user(fpr_val, i + (__u64 __user *)data);
		set_fpr64(&fregs[i], 0, fpr_val);
	}

	__get_user(value, data + 64);
	ptrace_setfcr31(child, value);

	/* FIR may not be written.  */

	return 0;
}

/*
 * Copy the floating-point context to the supplied NT_PRFPREG buffer,
 * !CONFIG_CPU_HAS_MSA variant.  FP context's general register slots
@@ -571,6 +574,54 @@ static int fpr_set(struct task_struct *target,
	return err;
}

/* Copy the FP mode setting to the supplied NT_MIPS_FP_MODE buffer.  */
static int fp_mode_get(struct task_struct *target,
		       const struct user_regset *regset,
		       unsigned int pos, unsigned int count,
		       void *kbuf, void __user *ubuf)
{
	int fp_mode;

	fp_mode = mips_get_process_fp_mode(target);
	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &fp_mode, 0,
				   sizeof(fp_mode));
}

/*
 * Copy the supplied NT_MIPS_FP_MODE buffer to the FP mode setting.
 *
 * We optimize for the case where `count % sizeof(int) == 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
 * mode writes.
 */
static int fp_mode_set(struct task_struct *target,
		       const struct user_regset *regset,
		       unsigned int pos, unsigned int count,
		       const void *kbuf, const void __user *ubuf)
{
	int fp_mode;
	int err;

	BUG_ON(count % sizeof(int));

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

	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fp_mode, 0,
				 sizeof(fp_mode));
	if (err)
		return err;

	if (count > 0)
		err = mips_set_process_fp_mode(target, fp_mode);

	return err;
}

#endif /* CONFIG_MIPS_FP_SUPPORT */

#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)

/*
@@ -740,57 +791,13 @@ static int dsp_active(struct task_struct *target,
	return cpu_has_dsp ? NUM_DSP_REGS + 1 : -ENODEV;
}

/* Copy the FP mode setting to the supplied NT_MIPS_FP_MODE buffer.  */
static int fp_mode_get(struct task_struct *target,
		       const struct user_regset *regset,
		       unsigned int pos, unsigned int count,
		       void *kbuf, void __user *ubuf)
{
	int fp_mode;

	fp_mode = mips_get_process_fp_mode(target);
	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &fp_mode, 0,
				   sizeof(fp_mode));
}

/*
 * Copy the supplied NT_MIPS_FP_MODE buffer to the FP mode setting.
 *
 * We optimize for the case where `count % sizeof(int) == 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
 * mode writes.
 */
static int fp_mode_set(struct task_struct *target,
		       const struct user_regset *regset,
		       unsigned int pos, unsigned int count,
		       const void *kbuf, const void __user *ubuf)
{
	int fp_mode;
	int err;

	BUG_ON(count % sizeof(int));

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

	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fp_mode, 0,
				 sizeof(fp_mode));
	if (err)
		return err;

	if (count > 0)
		err = mips_set_process_fp_mode(target, fp_mode);

	return err;
}

enum mips_regset {
	REGSET_GPR,
	REGSET_FPR,
	REGSET_DSP,
#ifdef CONFIG_MIPS_FP_SUPPORT
	REGSET_FPR,
	REGSET_FP_MODE,
#endif
};

struct pt_regs_offset {
@@ -888,14 +895,6 @@ static const struct user_regset mips_regsets[] = {
		.get		= gpr32_get,
		.set		= gpr32_set,
	},
	[REGSET_FPR] = {
		.core_note_type	= NT_PRFPREG,
		.n		= ELF_NFPREG,
		.size		= sizeof(elf_fpreg_t),
		.align		= sizeof(elf_fpreg_t),
		.get		= fpr_get,
		.set		= fpr_set,
	},
	[REGSET_DSP] = {
		.core_note_type	= NT_MIPS_DSP,
		.n		= NUM_DSP_REGS + 1,
@@ -905,6 +904,15 @@ static const struct user_regset mips_regsets[] = {
		.set		= dsp32_set,
		.active		= dsp_active,
	},
#ifdef CONFIG_MIPS_FP_SUPPORT
	[REGSET_FPR] = {
		.core_note_type	= NT_PRFPREG,
		.n		= ELF_NFPREG,
		.size		= sizeof(elf_fpreg_t),
		.align		= sizeof(elf_fpreg_t),
		.get		= fpr_get,
		.set		= fpr_set,
	},
	[REGSET_FP_MODE] = {
		.core_note_type	= NT_MIPS_FP_MODE,
		.n		= 1,
@@ -913,6 +921,7 @@ static const struct user_regset mips_regsets[] = {
		.get		= fp_mode_get,
		.set		= fp_mode_set,
	},
#endif
};

static const struct user_regset_view user_mips_view = {
@@ -936,14 +945,6 @@ static const struct user_regset mips64_regsets[] = {
		.get		= gpr64_get,
		.set		= gpr64_set,
	},
	[REGSET_FPR] = {
		.core_note_type	= NT_PRFPREG,
		.n		= ELF_NFPREG,
		.size		= sizeof(elf_fpreg_t),
		.align		= sizeof(elf_fpreg_t),
		.get		= fpr_get,
		.set		= fpr_set,
	},
	[REGSET_DSP] = {
		.core_note_type	= NT_MIPS_DSP,
		.n		= NUM_DSP_REGS + 1,
@@ -953,6 +954,7 @@ static const struct user_regset mips64_regsets[] = {
		.set		= dsp64_set,
		.active		= dsp_active,
	},
#ifdef CONFIG_MIPS_FP_SUPPORT
	[REGSET_FP_MODE] = {
		.core_note_type	= NT_MIPS_FP_MODE,
		.n		= 1,
@@ -961,6 +963,15 @@ static const struct user_regset mips64_regsets[] = {
		.get		= fp_mode_get,
		.set		= fp_mode_set,
	},
	[REGSET_FPR] = {
		.core_note_type	= NT_PRFPREG,
		.n		= ELF_NFPREG,
		.size		= sizeof(elf_fpreg_t),
		.align		= sizeof(elf_fpreg_t),
		.get		= fpr_get,
		.set		= fpr_set,
	},
#endif
};

static const struct user_regset_view user_mips64_view = {
@@ -1021,7 +1032,6 @@ long arch_ptrace(struct task_struct *child, long request,
	/* Read the word at location addr in the USER area. */
	case PTRACE_PEEKUSR: {
		struct pt_regs *regs;
		union fpureg *fregs;
		unsigned long tmp = 0;

		regs = task_pt_regs(child);
@@ -1031,7 +1041,10 @@ long arch_ptrace(struct task_struct *child, long request,
		case 0 ... 31:
			tmp = regs->regs[addr];
			break;
		case FPR_BASE ... FPR_BASE + 31:
#ifdef CONFIG_MIPS_FP_SUPPORT
		case FPR_BASE ... FPR_BASE + 31: {
			union fpureg *fregs;

			if (!tsk_used_math(child)) {
				/* FP not yet used */
				tmp = -1;
@@ -1053,6 +1066,15 @@ long arch_ptrace(struct task_struct *child, long request,
#endif
			tmp = get_fpr64(&fregs[addr - FPR_BASE], 0);
			break;
		}
		case FPC_CSR:
			tmp = child->thread.fpu.fcr31;
			break;
		case FPC_EIR:
			/* implementation / version register */
			tmp = boot_cpu_data.fpu_id;
			break;
#endif
		case PC:
			tmp = regs->cp0_epc;
			break;
@@ -1073,13 +1095,6 @@ long arch_ptrace(struct task_struct *child, long request,
			tmp = regs->acx;
			break;
#endif
		case FPC_CSR:
			tmp = child->thread.fpu.fcr31;
			break;
		case FPC_EIR:
			/* implementation / version register */
			tmp = boot_cpu_data.fpu_id;
			break;
		case DSP_BASE ... DSP_BASE + 5: {
			dspreg_t *dregs;

@@ -1130,6 +1145,7 @@ long arch_ptrace(struct task_struct *child, long request,
				 mips_syscall_is_indirect(child, regs))
				mips_syscall_update_nr(child, regs);
			break;
#ifdef CONFIG_MIPS_FP_SUPPORT
		case FPR_BASE ... FPR_BASE + 31: {
			union fpureg *fregs = get_fpu_regs(child);

@@ -1149,6 +1165,11 @@ long arch_ptrace(struct task_struct *child, long request,
			set_fpr64(&fregs[addr - FPR_BASE], 0, data);
			break;
		}
		case FPC_CSR:
			init_fp_ctx(child);
			ptrace_setfcr31(child, data);
			break;
#endif
		case PC:
			regs->cp0_epc = data;
			break;
@@ -1163,10 +1184,6 @@ long arch_ptrace(struct task_struct *child, long request,
			regs->acx = data;
			break;
#endif
		case FPC_CSR:
			init_fp_ctx(child);
			ptrace_setfcr31(child, data);
			break;
		case DSP_BASE ... DSP_BASE + 5: {
			dspreg_t *dregs;

@@ -1202,6 +1219,7 @@ long arch_ptrace(struct task_struct *child, long request,
		ret = ptrace_setregs(child, datavp);
		break;

#ifdef CONFIG_MIPS_FP_SUPPORT
	case PTRACE_GETFPREGS:
		ret = ptrace_getfpregs(child, datavp);
		break;
@@ -1209,7 +1227,7 @@ long arch_ptrace(struct task_struct *child, long request,
	case PTRACE_SETFPREGS:
		ret = ptrace_setfpregs(child, datavp);
		break;

#endif
	case PTRACE_GET_THREAD_AREA:
		ret = put_user(task_thread_info(child)->tp_value, datalp);
		break;
+20 −13
Original line number Diff line number Diff line
@@ -82,7 +82,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
	/* Read the word at location addr in the USER area. */
	case PTRACE_PEEKUSR: {
		struct pt_regs *regs;
		union fpureg *fregs;
		unsigned int tmp;

		regs = task_pt_regs(child);
@@ -92,7 +91,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
		case 0 ... 31:
			tmp = regs->regs[addr];
			break;
		case FPR_BASE ... FPR_BASE + 31:
#ifdef CONFIG_MIPS_FP_SUPPORT
		case FPR_BASE ... FPR_BASE + 31: {
			union fpureg *fregs;

			if (!tsk_used_math(child)) {
				/* FP not yet used */
				tmp = -1;
@@ -111,6 +113,15 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
			}
			tmp = get_fpr64(&fregs[addr - FPR_BASE], 0);
			break;
		}
		case FPC_CSR:
			tmp = child->thread.fpu.fcr31;
			break;
		case FPC_EIR:
			/* implementation / version register */
			tmp = boot_cpu_data.fpu_id;
			break;
#endif /* CONFIG_MIPS_FP_SUPPORT */
		case PC:
			tmp = regs->cp0_epc;
			break;
@@ -126,13 +137,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
		case MMLO:
			tmp = regs->lo;
			break;
		case FPC_CSR:
			tmp = child->thread.fpu.fcr31;
			break;
		case FPC_EIR:
			/* implementation / version register */
			tmp = boot_cpu_data.fpu_id;
			break;
		case DSP_BASE ... DSP_BASE + 5: {
			dspreg_t *dregs;

@@ -203,6 +207,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
				 mips_syscall_is_indirect(child, regs))
				mips_syscall_update_nr(child, regs);
			break;
#ifdef CONFIG_MIPS_FP_SUPPORT
		case FPR_BASE ... FPR_BASE + 31: {
			union fpureg *fregs = get_fpu_regs(child);

@@ -225,6 +230,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
			set_fpr64(&fregs[addr - FPR_BASE], 0, data);
			break;
		}
		case FPC_CSR:
			child->thread.fpu.fcr31 = data;
			break;
#endif /* CONFIG_MIPS_FP_SUPPORT */
		case PC:
			regs->cp0_epc = data;
			break;
@@ -234,9 +243,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
		case MMLO:
			regs->lo = data;
			break;
		case FPC_CSR:
			child->thread.fpu.fcr31 = data;
			break;
		case DSP_BASE ... DSP_BASE + 5: {
			dspreg_t *dregs;

@@ -274,6 +280,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
				(struct user_pt_regs __user *) (__u64) data);
		break;

#ifdef CONFIG_MIPS_FP_SUPPORT
	case PTRACE_GETFPREGS:
		ret = ptrace_getfpregs(child, (__u32 __user *) (__u64) data);
		break;
@@ -281,7 +288,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
	case PTRACE_SETFPREGS:
		ret = ptrace_setfpregs(child, (__u32 __user *) (__u64) data);
		break;

#endif
	case PTRACE_GET_THREAD_AREA:
		ret = put_user(task_thread_info(child)->tp_value,
				(unsigned int __user *) (unsigned long) data);