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

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
...@@ -759,10 +759,57 @@ static int dsp_active(struct task_struct *target, ...@@ -759,10 +759,57 @@ static int dsp_active(struct task_struct *target,
return cpu_has_dsp ? NUM_DSP_REGS + 1 : -ENODEV; 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 { enum mips_regset {
REGSET_GPR, REGSET_GPR,
REGSET_FPR, REGSET_FPR,
REGSET_DSP, REGSET_DSP,
REGSET_FP_MODE,
}; };
struct pt_regs_offset { struct pt_regs_offset {
...@@ -877,6 +924,14 @@ static const struct user_regset mips_regsets[] = { ...@@ -877,6 +924,14 @@ static const struct user_regset mips_regsets[] = {
.set = dsp32_set, .set = dsp32_set,
.active = dsp_active, .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 = { static const struct user_regset_view user_mips_view = {
...@@ -917,6 +972,14 @@ static const struct user_regset mips64_regsets[] = { ...@@ -917,6 +972,14 @@ static const struct user_regset mips64_regsets[] = {
.set = dsp64_set, .set = dsp64_set,
.active = dsp_active, .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 = { static const struct user_regset_view user_mips64_view = {
......
...@@ -423,6 +423,7 @@ typedef struct elf64_shdr { ...@@ -423,6 +423,7 @@ typedef struct elf64_shdr {
#define NT_ARC_V2 0x600 /* ARCv2 accumulator/extra registers */ #define NT_ARC_V2 0x600 /* ARCv2 accumulator/extra registers */
#define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note */ #define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note */
#define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */ #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 */ /* Note header in a PT_NOTE section */
typedef struct elf32_note { typedef struct elf32_note {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment