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:
parent
44109c6017
commit
1ae22a0e35
|
@ -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 = {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue