|
@@ -119,6 +119,97 @@ int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
|
|
|
return -EIO;
|
|
|
}
|
|
|
|
|
|
+static int gpr_get(struct task_struct *target, const struct user_regset *regset,
|
|
|
+ unsigned int pos, unsigned int count,
|
|
|
+ void *kbuf, void __user *ubuf)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (target->thread.regs == NULL)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ CHECK_FULL_REGS(target->thread.regs);
|
|
|
+
|
|
|
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
|
|
+ target->thread.regs,
|
|
|
+ 0, offsetof(struct pt_regs, msr));
|
|
|
+ if (!ret) {
|
|
|
+ unsigned long msr = get_user_msr(target);
|
|
|
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &msr,
|
|
|
+ offsetof(struct pt_regs, msr),
|
|
|
+ offsetof(struct pt_regs, msr) +
|
|
|
+ sizeof(msr));
|
|
|
+ }
|
|
|
+
|
|
|
+ BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
|
|
|
+ offsetof(struct pt_regs, msr) + sizeof(long));
|
|
|
+
|
|
|
+ if (!ret)
|
|
|
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
|
|
+ &target->thread.regs->orig_gpr3,
|
|
|
+ offsetof(struct pt_regs, orig_gpr3),
|
|
|
+ sizeof(struct pt_regs));
|
|
|
+ if (!ret)
|
|
|
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
|
|
|
+ sizeof(struct pt_regs), -1);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int gpr_set(struct task_struct *target, const struct user_regset *regset,
|
|
|
+ unsigned int pos, unsigned int count,
|
|
|
+ const void *kbuf, const void __user *ubuf)
|
|
|
+{
|
|
|
+ unsigned long reg;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (target->thread.regs == NULL)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ CHECK_FULL_REGS(target->thread.regs);
|
|
|
+
|
|
|
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
|
|
+ target->thread.regs,
|
|
|
+ 0, PT_MSR * sizeof(reg));
|
|
|
+
|
|
|
+ if (!ret && count > 0) {
|
|
|
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®,
|
|
|
+ PT_MSR * sizeof(reg),
|
|
|
+ (PT_MSR + 1) * sizeof(reg));
|
|
|
+ if (!ret)
|
|
|
+ ret = set_user_msr(target, reg);
|
|
|
+ }
|
|
|
+
|
|
|
+ BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
|
|
|
+ offsetof(struct pt_regs, msr) + sizeof(long));
|
|
|
+
|
|
|
+ if (!ret)
|
|
|
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
|
|
+ &target->thread.regs->orig_gpr3,
|
|
|
+ PT_ORIG_R3 * sizeof(reg),
|
|
|
+ (PT_MAX_PUT_REG + 1) * sizeof(reg));
|
|
|
+
|
|
|
+ if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret)
|
|
|
+ ret = user_regset_copyin_ignore(
|
|
|
+ &pos, &count, &kbuf, &ubuf,
|
|
|
+ (PT_MAX_PUT_REG + 1) * sizeof(reg),
|
|
|
+ PT_TRAP * sizeof(reg));
|
|
|
+
|
|
|
+ if (!ret && count > 0) {
|
|
|
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®,
|
|
|
+ PT_TRAP * sizeof(reg),
|
|
|
+ (PT_TRAP + 1) * sizeof(reg));
|
|
|
+ if (!ret)
|
|
|
+ ret = set_user_trap(target, reg);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ret)
|
|
|
+ ret = user_regset_copyin_ignore(
|
|
|
+ &pos, &count, &kbuf, &ubuf,
|
|
|
+ (PT_TRAP + 1) * sizeof(reg), -1);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
|
|
|
static int fpr_get(struct task_struct *target, const struct user_regset *regset,
|
|
|
unsigned int pos, unsigned int count,
|