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: Maciej W. Rozycki <macro@mips.com>
Signed-off-by: Paul 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
This commit is contained in:
Maciej W. Rozycki 2018-05-15 23:40:18 +01:00 committed by Paul Burton
parent 44109c6017
commit 1ae22a0e35
No known key found for this signature in database
GPG Key ID: 3EA79FACB57500DD
2 changed files with 64 additions and 0 deletions

View File

@ -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 = {

View File

@ -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 {