|
@@ -41,6 +41,7 @@
|
|
#include <asm/mipsmtregs.h>
|
|
#include <asm/mipsmtregs.h>
|
|
#include <asm/pgtable.h>
|
|
#include <asm/pgtable.h>
|
|
#include <asm/page.h>
|
|
#include <asm/page.h>
|
|
|
|
+#include <asm/processor.h>
|
|
#include <asm/syscall.h>
|
|
#include <asm/syscall.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/uaccess.h>
|
|
#include <asm/bootinfo.h>
|
|
#include <asm/bootinfo.h>
|
|
@@ -589,9 +590,179 @@ static int fpr_set(struct task_struct *target,
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Copy the DSP context to the supplied 32-bit NT_MIPS_DSP buffer.
|
|
|
|
+ */
|
|
|
|
+static int dsp32_get(struct task_struct *target,
|
|
|
|
+ const struct user_regset *regset,
|
|
|
|
+ unsigned int pos, unsigned int count,
|
|
|
|
+ void *kbuf, void __user *ubuf)
|
|
|
|
+{
|
|
|
|
+ unsigned int start, num_regs, i;
|
|
|
|
+ u32 dspregs[NUM_DSP_REGS + 1];
|
|
|
|
+
|
|
|
|
+ BUG_ON(count % sizeof(u32));
|
|
|
|
+
|
|
|
|
+ if (!cpu_has_dsp)
|
|
|
|
+ return -EIO;
|
|
|
|
+
|
|
|
|
+ start = pos / sizeof(u32);
|
|
|
|
+ num_regs = count / sizeof(u32);
|
|
|
|
+
|
|
|
|
+ if (start + num_regs > NUM_DSP_REGS + 1)
|
|
|
|
+ return -EIO;
|
|
|
|
+
|
|
|
|
+ for (i = start; i < num_regs; i++)
|
|
|
|
+ switch (i) {
|
|
|
|
+ case 0 ... NUM_DSP_REGS - 1:
|
|
|
|
+ dspregs[i] = target->thread.dsp.dspr[i];
|
|
|
|
+ break;
|
|
|
|
+ case NUM_DSP_REGS:
|
|
|
|
+ dspregs[i] = target->thread.dsp.dspcontrol;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, dspregs, 0,
|
|
|
|
+ sizeof(dspregs));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Copy the supplied 32-bit NT_MIPS_DSP buffer to the DSP context.
|
|
|
|
+ */
|
|
|
|
+static int dsp32_set(struct task_struct *target,
|
|
|
|
+ const struct user_regset *regset,
|
|
|
|
+ unsigned int pos, unsigned int count,
|
|
|
|
+ const void *kbuf, const void __user *ubuf)
|
|
|
|
+{
|
|
|
|
+ unsigned int start, num_regs, i;
|
|
|
|
+ u32 dspregs[NUM_DSP_REGS + 1];
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ BUG_ON(count % sizeof(u32));
|
|
|
|
+
|
|
|
|
+ if (!cpu_has_dsp)
|
|
|
|
+ return -EIO;
|
|
|
|
+
|
|
|
|
+ start = pos / sizeof(u32);
|
|
|
|
+ num_regs = count / sizeof(u32);
|
|
|
|
+
|
|
|
|
+ if (start + num_regs > NUM_DSP_REGS + 1)
|
|
|
|
+ return -EIO;
|
|
|
|
+
|
|
|
|
+ err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, dspregs, 0,
|
|
|
|
+ sizeof(dspregs));
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+
|
|
|
|
+ for (i = start; i < num_regs; i++)
|
|
|
|
+ switch (i) {
|
|
|
|
+ case 0 ... NUM_DSP_REGS - 1:
|
|
|
|
+ target->thread.dsp.dspr[i] = (s32)dspregs[i];
|
|
|
|
+ break;
|
|
|
|
+ case NUM_DSP_REGS:
|
|
|
|
+ target->thread.dsp.dspcontrol = (s32)dspregs[i];
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_64BIT
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Copy the DSP context to the supplied 64-bit NT_MIPS_DSP buffer.
|
|
|
|
+ */
|
|
|
|
+static int dsp64_get(struct task_struct *target,
|
|
|
|
+ const struct user_regset *regset,
|
|
|
|
+ unsigned int pos, unsigned int count,
|
|
|
|
+ void *kbuf, void __user *ubuf)
|
|
|
|
+{
|
|
|
|
+ unsigned int start, num_regs, i;
|
|
|
|
+ u64 dspregs[NUM_DSP_REGS + 1];
|
|
|
|
+
|
|
|
|
+ BUG_ON(count % sizeof(u64));
|
|
|
|
+
|
|
|
|
+ if (!cpu_has_dsp)
|
|
|
|
+ return -EIO;
|
|
|
|
+
|
|
|
|
+ start = pos / sizeof(u64);
|
|
|
|
+ num_regs = count / sizeof(u64);
|
|
|
|
+
|
|
|
|
+ if (start + num_regs > NUM_DSP_REGS + 1)
|
|
|
|
+ return -EIO;
|
|
|
|
+
|
|
|
|
+ for (i = start; i < num_regs; i++)
|
|
|
|
+ switch (i) {
|
|
|
|
+ case 0 ... NUM_DSP_REGS - 1:
|
|
|
|
+ dspregs[i] = target->thread.dsp.dspr[i];
|
|
|
|
+ break;
|
|
|
|
+ case NUM_DSP_REGS:
|
|
|
|
+ dspregs[i] = target->thread.dsp.dspcontrol;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, dspregs, 0,
|
|
|
|
+ sizeof(dspregs));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Copy the supplied 64-bit NT_MIPS_DSP buffer to the DSP context.
|
|
|
|
+ */
|
|
|
|
+static int dsp64_set(struct task_struct *target,
|
|
|
|
+ const struct user_regset *regset,
|
|
|
|
+ unsigned int pos, unsigned int count,
|
|
|
|
+ const void *kbuf, const void __user *ubuf)
|
|
|
|
+{
|
|
|
|
+ unsigned int start, num_regs, i;
|
|
|
|
+ u64 dspregs[NUM_DSP_REGS + 1];
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ BUG_ON(count % sizeof(u64));
|
|
|
|
+
|
|
|
|
+ if (!cpu_has_dsp)
|
|
|
|
+ return -EIO;
|
|
|
|
+
|
|
|
|
+ start = pos / sizeof(u64);
|
|
|
|
+ num_regs = count / sizeof(u64);
|
|
|
|
+
|
|
|
|
+ if (start + num_regs > NUM_DSP_REGS + 1)
|
|
|
|
+ return -EIO;
|
|
|
|
+
|
|
|
|
+ err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, dspregs, 0,
|
|
|
|
+ sizeof(dspregs));
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+
|
|
|
|
+ for (i = start; i < num_regs; i++)
|
|
|
|
+ switch (i) {
|
|
|
|
+ case 0 ... NUM_DSP_REGS - 1:
|
|
|
|
+ target->thread.dsp.dspr[i] = dspregs[i];
|
|
|
|
+ break;
|
|
|
|
+ case NUM_DSP_REGS:
|
|
|
|
+ target->thread.dsp.dspcontrol = dspregs[i];
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#endif /* CONFIG_64BIT */
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Determine whether the DSP context is present.
|
|
|
|
+ */
|
|
|
|
+static int dsp_active(struct task_struct *target,
|
|
|
|
+ const struct user_regset *regset)
|
|
|
|
+{
|
|
|
|
+ return cpu_has_dsp ? NUM_DSP_REGS + 1 : -ENODEV;
|
|
|
|
+}
|
|
|
|
+
|
|
enum mips_regset {
|
|
enum mips_regset {
|
|
REGSET_GPR,
|
|
REGSET_GPR,
|
|
REGSET_FPR,
|
|
REGSET_FPR,
|
|
|
|
+ REGSET_DSP,
|
|
};
|
|
};
|
|
|
|
|
|
struct pt_regs_offset {
|
|
struct pt_regs_offset {
|
|
@@ -697,6 +868,15 @@ static const struct user_regset mips_regsets[] = {
|
|
.get = fpr_get,
|
|
.get = fpr_get,
|
|
.set = fpr_set,
|
|
.set = fpr_set,
|
|
},
|
|
},
|
|
|
|
+ [REGSET_DSP] = {
|
|
|
|
+ .core_note_type = NT_MIPS_DSP,
|
|
|
|
+ .n = NUM_DSP_REGS + 1,
|
|
|
|
+ .size = sizeof(u32),
|
|
|
|
+ .align = sizeof(u32),
|
|
|
|
+ .get = dsp32_get,
|
|
|
|
+ .set = dsp32_set,
|
|
|
|
+ .active = dsp_active,
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
static const struct user_regset_view user_mips_view = {
|
|
static const struct user_regset_view user_mips_view = {
|
|
@@ -728,6 +908,15 @@ static const struct user_regset mips64_regsets[] = {
|
|
.get = fpr_get,
|
|
.get = fpr_get,
|
|
.set = fpr_set,
|
|
.set = fpr_set,
|
|
},
|
|
},
|
|
|
|
+ [REGSET_DSP] = {
|
|
|
|
+ .core_note_type = NT_MIPS_DSP,
|
|
|
|
+ .n = NUM_DSP_REGS + 1,
|
|
|
|
+ .size = sizeof(u64),
|
|
|
|
+ .align = sizeof(u64),
|
|
|
|
+ .get = dsp64_get,
|
|
|
|
+ .set = dsp64_set,
|
|
|
|
+ .active = dsp_active,
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
static const struct user_regset_view user_mips64_view = {
|
|
static const struct user_regset_view user_mips64_view = {
|