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

Unverified Commit 1ae22a0e authored by Maciej W. Rozycki's avatar Maciej W. Rozycki Committed by Paul Burton
Browse files

MIPS: Add FP_MODE regset support



Define an NT_MIPS_FP_MODE core file note and implement a corresponding
regset holding the state handled by PR_SET_FP_MODE and PR_GET_FP_MODE
prctl(2) requests.  This lets debug software correctly interpret the
contents of floating-point general registers both in live debugging and
in core files, and also switch floating-point modes of a live process.

[paul.burton@mips.com:
  - Changed NT_MIPS_FP_MODE to 0x801 to match first nibble of
    NT_MIPS_DSP, which was also changed to avoid a conflict.]

Signed-off-by: default avatarMaciej W. Rozycki <macro@mips.com>
Signed-off-by: default avatarPaul Burton <paul.burton@mips.com>
Patchwork: https://patchwork.linux-mips.org/patch/19331/
Cc: James Hogan <jhogan@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
parent 44109c60
Loading
Loading
Loading
Loading
+63 −0
Original line number Diff line number Diff line
@@ -759,10 +759,57 @@ 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,
	REGSET_FP_MODE,
};

struct pt_regs_offset {
@@ -877,6 +924,14 @@ static const struct user_regset mips_regsets[] = {
		.set		= dsp32_set,
		.active		= dsp_active,
	},
	[REGSET_FP_MODE] = {
		.core_note_type	= NT_MIPS_FP_MODE,
		.n		= 1,
		.size		= sizeof(int),
		.align		= sizeof(int),
		.get		= fp_mode_get,
		.set		= fp_mode_set,
	},
};

static const struct user_regset_view user_mips_view = {
@@ -917,6 +972,14 @@ static const struct user_regset mips64_regsets[] = {
		.set		= dsp64_set,
		.active		= dsp_active,
	},
	[REGSET_FP_MODE] = {
		.core_note_type	= NT_MIPS_FP_MODE,
		.n		= 1,
		.size		= sizeof(int),
		.align		= sizeof(int),
		.get		= fp_mode_get,
		.set		= fp_mode_set,
	},
};

static const struct user_regset_view user_mips64_view = {
+1 −0
Original line number Diff line number Diff line
@@ -423,6 +423,7 @@ typedef struct elf64_shdr {
#define NT_ARC_V2	0x600		/* ARCv2 accumulator/extra registers */
#define NT_VMCOREDD	0x700		/* Vmcore Device Dump Note */
#define NT_MIPS_DSP	0x800		/* MIPS DSP ASE registers */
#define NT_MIPS_FP_MODE	0x801		/* MIPS floating-point mode */

/* Note header in a PT_NOTE section */
typedef struct elf32_note {