From: Al Viro <viro@xxxxxxxxxxxxxxxxxx> Note: compat variant of REGSET_TM_CGPR is almost certainly wrong; it claims to be 48*64bit, but just as compat REGSET_GPR it stores 44*32bit of (truncated) registers + 4 32bit zeros... followed by 48 more 32bit zeroes. Might be too late to change - it's a userland ABI, after all ;-/ Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx> --- arch/powerpc/kernel/ptrace/ptrace-altivec.c | 37 ++---- arch/powerpc/kernel/ptrace/ptrace-decl.h | 44 +++---- arch/powerpc/kernel/ptrace/ptrace-novsx.c | 5 +- arch/powerpc/kernel/ptrace/ptrace-spe.c | 16 +-- arch/powerpc/kernel/ptrace/ptrace-tm.c | 152 +++++++---------------- arch/powerpc/kernel/ptrace/ptrace-view.c | 185 ++++++++++------------------ arch/powerpc/kernel/ptrace/ptrace-vsx.c | 13 +- 7 files changed, 148 insertions(+), 304 deletions(-) diff --git a/arch/powerpc/kernel/ptrace/ptrace-altivec.c b/arch/powerpc/kernel/ptrace/ptrace-altivec.c index dd8b75dfbd06..0d9bc4bd4972 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-altivec.c +++ b/arch/powerpc/kernel/ptrace/ptrace-altivec.c @@ -41,38 +41,25 @@ int vr_active(struct task_struct *target, const struct user_regset *regset) * }; */ int vr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { - int ret; + union { + elf_vrreg_t reg; + u32 word; + } vrsave; flush_altivec_to_thread(target); BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) != offsetof(struct thread_vr_state, vr[32])); - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.vr_state, 0, - 33 * sizeof(vector128)); - if (!ret) { - /* - * Copy out only the low-order word of vrsave. - */ - int start, end; - union { - elf_vrreg_t reg; - u32 word; - } vrsave; - memset(&vrsave, 0, sizeof(vrsave)); - - vrsave.word = target->thread.vrsave; - - start = 33 * sizeof(vector128); - end = start + sizeof(vrsave); - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave, - start, end); - } - - return ret; + membuf_write(&to, &target->thread.vr_state, 33 * sizeof(vector128)); + /* + * Copy out only the low-order word of vrsave. + */ + memset(&vrsave, 0, sizeof(vrsave)); + vrsave.word = target->thread.vrsave; + return membuf_write(&to, &vrsave, sizeof(vrsave)); } /* diff --git a/arch/powerpc/kernel/ptrace/ptrace-decl.h b/arch/powerpc/kernel/ptrace/ptrace-decl.h index 3c8a81999292..67447a6197eb 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-decl.h +++ b/arch/powerpc/kernel/ptrace/ptrace-decl.h @@ -63,8 +63,7 @@ enum powerpc_regset { /* ptrace-(no)vsx */ -int fpr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +user_regset_get2_fn fpr_get; int fpr_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf); @@ -72,8 +71,7 @@ int fpr_set(struct task_struct *target, const struct user_regset *regset, /* ptrace-vsx */ int vsr_active(struct task_struct *target, const struct user_regset *regset); -int vsr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +user_regset_get2_fn vsr_get; int vsr_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf); @@ -81,8 +79,7 @@ int vsr_set(struct task_struct *target, const struct user_regset *regset, /* ptrace-altivec */ int vr_active(struct task_struct *target, const struct user_regset *regset); -int vr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +user_regset_get2_fn vr_get; int vr_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf); @@ -90,8 +87,7 @@ int vr_set(struct task_struct *target, const struct user_regset *regset, /* ptrace-spe */ int evr_active(struct task_struct *target, const struct user_regset *regset); -int evr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +user_regset_get2_fn evr_get; int evr_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf); @@ -100,9 +96,8 @@ int evr_set(struct task_struct *target, const struct user_regset *regset, int gpr32_get_common(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf, - unsigned long *regs); + struct membuf to, + unsigned long *regs); int gpr32_set_common(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, @@ -118,55 +113,46 @@ static inline void flush_tmregs_to_thread(struct task_struct *tsk) { } #endif int tm_cgpr_active(struct task_struct *target, const struct user_regset *regset); -int tm_cgpr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +user_regset_get2_fn tm_cgpr_get; int tm_cgpr_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf); int tm_cfpr_active(struct task_struct *target, const struct user_regset *regset); -int tm_cfpr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +user_regset_get2_fn tm_cfpr_get; int tm_cfpr_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf); int tm_cvmx_active(struct task_struct *target, const struct user_regset *regset); -int tm_cvmx_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +user_regset_get2_fn tm_cvmx_get; int tm_cvmx_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf); int tm_cvsx_active(struct task_struct *target, const struct user_regset *regset); -int tm_cvsx_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +user_regset_get2_fn tm_cvsx_get; int tm_cvsx_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf); int tm_spr_active(struct task_struct *target, const struct user_regset *regset); -int tm_spr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +user_regset_get2_fn tm_spr_get; int tm_spr_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf); int tm_tar_active(struct task_struct *target, const struct user_regset *regset); -int tm_tar_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +user_regset_get2_fn tm_tar_get; int tm_tar_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf); int tm_ppr_active(struct task_struct *target, const struct user_regset *regset); -int tm_ppr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +user_regset_get2_fn tm_ppr_get; int tm_ppr_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf); int tm_dscr_active(struct task_struct *target, const struct user_regset *regset); -int tm_dscr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +user_regset_get2_fn tm_dscr_get; int tm_dscr_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf); -int tm_cgpr32_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); +user_regset_get2_fn tm_cgpr32_get; int tm_cgpr32_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf); diff --git a/arch/powerpc/kernel/ptrace/ptrace-novsx.c b/arch/powerpc/kernel/ptrace/ptrace-novsx.c index b2dc4e92d11a..b3b36835658a 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-novsx.c +++ b/arch/powerpc/kernel/ptrace/ptrace-novsx.c @@ -19,15 +19,14 @@ * }; */ int fpr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) != offsetof(struct thread_fp_state, fpr[32])); flush_fp_to_thread(target); - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.fp_state, 0, -1); + return membuf_write(&to, &target->thread.fp_state, 33 * sizeof(u64)); } /* diff --git a/arch/powerpc/kernel/ptrace/ptrace-spe.c b/arch/powerpc/kernel/ptrace/ptrace-spe.c index 68b86b4a4be4..47034d069045 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-spe.c +++ b/arch/powerpc/kernel/ptrace/ptrace-spe.c @@ -23,25 +23,17 @@ int evr_active(struct task_struct *target, const struct user_regset *regset) } int evr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { - int ret; - flush_spe_to_thread(target); - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.evr, - 0, sizeof(target->thread.evr)); + membuf_write(&to, &target->thread.evr, sizeof(target->thread.evr)); BUILD_BUG_ON(offsetof(struct thread_struct, acc) + sizeof(u64) != offsetof(struct thread_struct, spefscr)); - if (!ret) - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.acc, - sizeof(target->thread.evr), -1); - - return ret; + return membuf_write(&to, &target->thread.acc, + sizeof(u64) + sizeof(u32)); } int evr_set(struct task_struct *target, const struct user_regset *regset, diff --git a/arch/powerpc/kernel/ptrace/ptrace-tm.c b/arch/powerpc/kernel/ptrace/ptrace-tm.c index 32d62c606681..54f2d076206f 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-tm.c +++ b/arch/powerpc/kernel/ptrace/ptrace-tm.c @@ -70,10 +70,7 @@ int tm_cgpr_active(struct task_struct *target, const struct user_regset *regset) * tm_cgpr_get - get CGPR registers * @target: The target task. * @regset: The user regset structure. - * @pos: The buffer position. - * @count: Number of bytes to copy. - * @kbuf: Kernel buffer to copy from. - * @ubuf: User buffer to copy into. + * @to: Destination of copy. * * This function gets transaction checkpointed GPR registers. * @@ -87,10 +84,8 @@ int tm_cgpr_active(struct task_struct *target, const struct user_regset *regset) * }; */ int tm_cgpr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { - int ret; - if (!cpu_has_feature(CPU_FTR_TM)) return -ENODEV; @@ -101,31 +96,18 @@ int tm_cgpr_get(struct task_struct *target, const struct user_regset *regset, flush_fp_to_thread(target); flush_altivec_to_thread(target); - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.ckpt_regs, - 0, offsetof(struct pt_regs, msr)); - if (!ret) { - unsigned long msr = get_user_ckpt_msr(target); - - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &msr, - offsetof(struct pt_regs, msr), - offsetof(struct pt_regs, msr) + - sizeof(msr)); - } + membuf_write(&to, &target->thread.ckpt_regs, + offsetof(struct pt_regs, msr)); + membuf_store(&to, get_user_ckpt_msr(target)); 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.ckpt_regs.orig_gpr3, - offsetof(struct pt_regs, orig_gpr3), - sizeof(struct user_pt_regs)); - if (!ret) - ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, - sizeof(struct user_pt_regs), -1); - - return ret; + membuf_write(&to, &target->thread.ckpt_regs.orig_gpr3, + sizeof(struct user_pt_regs) - + offsetof(struct pt_regs, orig_gpr3)); + return membuf_zero(&to, ELF_NGREG * sizeof(unsigned long) - + sizeof(struct user_pt_regs)); } /* @@ -229,10 +211,7 @@ int tm_cfpr_active(struct task_struct *target, const struct user_regset *regset) * tm_cfpr_get - get CFPR registers * @target: The target task. * @regset: The user regset structure. - * @pos: The buffer position. - * @count: Number of bytes to copy. - * @kbuf: Kernel buffer to copy from. - * @ubuf: User buffer to copy into. + * @to: Destination of copy. * * This function gets in transaction checkpointed FPR registers. * @@ -247,7 +226,7 @@ int tm_cfpr_active(struct task_struct *target, const struct user_regset *regset) *}; */ int tm_cfpr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { u64 buf[33]; int i; @@ -266,7 +245,7 @@ int tm_cfpr_get(struct task_struct *target, const struct user_regset *regset, for (i = 0; i < 32 ; i++) buf[i] = target->thread.TS_CKFPR(i); buf[32] = target->thread.ckfp_state.fpscr; - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1); + return membuf_write(&to, buf, sizeof(buf)); } /** @@ -344,10 +323,7 @@ int tm_cvmx_active(struct task_struct *target, const struct user_regset *regset) * tm_cvmx_get - get CMVX registers * @target: The target task. * @regset: The user regset structure. - * @pos: The buffer position. - * @count: Number of bytes to copy. - * @kbuf: Kernel buffer to copy from. - * @ubuf: User buffer to copy into. + * @to: Destination of copy. * * This function gets in transaction checkpointed VMX registers. * @@ -363,10 +339,12 @@ int tm_cvmx_active(struct task_struct *target, const struct user_regset *regset) *}; */ int tm_cvmx_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { - int ret; - + union { + elf_vrreg_t reg; + u32 word; + } vrsave; BUILD_BUG_ON(TVSO(vscr) != TVSO(vr[32])); if (!cpu_has_feature(CPU_FTR_TM)) @@ -380,23 +358,13 @@ int tm_cvmx_get(struct task_struct *target, const struct user_regset *regset, flush_fp_to_thread(target); flush_altivec_to_thread(target); - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.ckvr_state, - 0, 33 * sizeof(vector128)); - if (!ret) { - /* - * Copy out only the low-order word of vrsave. - */ - union { - elf_vrreg_t reg; - u32 word; - } vrsave; - memset(&vrsave, 0, sizeof(vrsave)); - vrsave.word = target->thread.ckvrsave; - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave, - 33 * sizeof(vector128), -1); - } - - return ret; + membuf_write(&to, &target->thread.ckvr_state, 33 * sizeof(vector128)); + /* + * Copy out only the low-order word of vrsave. + */ + memset(&vrsave, 0, sizeof(vrsave)); + vrsave.word = target->thread.ckvrsave; + return membuf_write(&to, &vrsave, sizeof(vrsave)); } /** @@ -484,10 +452,7 @@ int tm_cvsx_active(struct task_struct *target, const struct user_regset *regset) * tm_cvsx_get - get CVSX registers * @target: The target task. * @regset: The user regset structure. - * @pos: The buffer position. - * @count: Number of bytes to copy. - * @kbuf: Kernel buffer to copy from. - * @ubuf: User buffer to copy into. + * @to: Destination of copy. * * This function gets in transaction checkpointed VSX registers. * @@ -501,10 +466,10 @@ int tm_cvsx_active(struct task_struct *target, const struct user_regset *regset) *}; */ int tm_cvsx_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { u64 buf[32]; - int ret, i; + int i; if (!cpu_has_feature(CPU_FTR_TM)) return -ENODEV; @@ -520,10 +485,7 @@ int tm_cvsx_get(struct task_struct *target, const struct user_regset *regset, for (i = 0; i < 32 ; i++) buf[i] = target->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET]; - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - buf, 0, 32 * sizeof(double)); - - return ret; + return membuf_write(&to, buf, 32 * sizeof(double)); } /** @@ -597,10 +559,7 @@ int tm_spr_active(struct task_struct *target, const struct user_regset *regset) * tm_spr_get - get the TM related SPR registers * @target: The target task. * @regset: The user regset structure. - * @pos: The buffer position. - * @count: Number of bytes to copy. - * @kbuf: Kernel buffer to copy from. - * @ubuf: User buffer to copy into. + * @to: Destination of copy. * * This function gets transactional memory related SPR registers. * The userspace interface buffer layout is as follows. @@ -612,10 +571,8 @@ int tm_spr_active(struct task_struct *target, const struct user_regset *regset) * }; */ int tm_spr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { - int ret; - /* Build tests */ BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr)); BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar)); @@ -630,21 +587,11 @@ int tm_spr_get(struct task_struct *target, const struct user_regset *regset, flush_altivec_to_thread(target); /* TFHAR register */ - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.tm_tfhar, 0, sizeof(u64)); - + membuf_write(&to, &target->thread.tm_tfhar, sizeof(u64)); /* TEXASR register */ - if (!ret) - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.tm_texasr, sizeof(u64), - 2 * sizeof(u64)); - + membuf_write(&to, &target->thread.tm_texasr, sizeof(u64)); /* TFIAR register */ - if (!ret) - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.tm_tfiar, - 2 * sizeof(u64), 3 * sizeof(u64)); - return ret; + return membuf_write(&to, &target->thread.tm_tfiar, sizeof(u64)); } /** @@ -714,19 +661,15 @@ int tm_tar_active(struct task_struct *target, const struct user_regset *regset) } int tm_tar_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { - int ret; - if (!cpu_has_feature(CPU_FTR_TM)) return -ENODEV; if (!MSR_TM_ACTIVE(target->thread.regs->msr)) return -ENODATA; - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.tm_tar, 0, sizeof(u64)); - return ret; + return membuf_write(&to, &target->thread.tm_tar, sizeof(u64)); } int tm_tar_set(struct task_struct *target, const struct user_regset *regset, @@ -759,19 +702,15 @@ int tm_ppr_active(struct task_struct *target, const struct user_regset *regset) int tm_ppr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { - int ret; - if (!cpu_has_feature(CPU_FTR_TM)) return -ENODEV; if (!MSR_TM_ACTIVE(target->thread.regs->msr)) return -ENODATA; - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.tm_ppr, 0, sizeof(u64)); - return ret; + return membuf_write(&to, &target->thread.tm_ppr, sizeof(u64)); } int tm_ppr_set(struct task_struct *target, const struct user_regset *regset, @@ -803,19 +742,15 @@ int tm_dscr_active(struct task_struct *target, const struct user_regset *regset) } int tm_dscr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { - int ret; - if (!cpu_has_feature(CPU_FTR_TM)) return -ENODEV; if (!MSR_TM_ACTIVE(target->thread.regs->msr)) return -ENODATA; - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.tm_dscr, 0, sizeof(u64)); - return ret; + return membuf_write(&to, &target->thread.tm_dscr, sizeof(u64)); } int tm_dscr_set(struct task_struct *target, const struct user_regset *regset, @@ -836,10 +771,11 @@ int tm_dscr_set(struct task_struct *target, const struct user_regset *regset, } int tm_cgpr32_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { - return gpr32_get_common(target, regset, pos, count, kbuf, ubuf, + gpr32_get_common(target, regset, to, &target->thread.ckpt_regs.gpr[0]); + return membuf_zero(&to, ELF_NGREG * sizeof(u32)); } int tm_cgpr32_set(struct task_struct *target, const struct user_regset *regset, diff --git a/arch/powerpc/kernel/ptrace/ptrace-view.c b/arch/powerpc/kernel/ptrace/ptrace-view.c index caeb5822a8f4..9dbd786a1e08 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-view.c +++ b/arch/powerpc/kernel/ptrace/ptrace-view.c @@ -215,9 +215,9 @@ int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data) } static int gpr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { - int i, ret; + int i; if (target->thread.regs == NULL) return -EIO; @@ -228,30 +228,17 @@ static int gpr_get(struct task_struct *target, const struct user_regset *regset, target->thread.regs->gpr[i] = NV_REG_POISON; } - 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)); - } + membuf_write(&to, target->thread.regs, offsetof(struct pt_regs, msr)); + membuf_store(&to, get_user_msr(target)); 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 user_pt_regs)); - if (!ret) - ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, - sizeof(struct user_pt_regs), -1); - - return ret; + membuf_write(&to, &target->thread.regs->orig_gpr3, + sizeof(struct user_pt_regs) - + offsetof(struct pt_regs, orig_gpr3)); + return membuf_zero(&to, ELF_NGREG * sizeof(unsigned long) - + sizeof(struct user_pt_regs)); } static int gpr_set(struct task_struct *target, const struct user_regset *regset, @@ -309,10 +296,9 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset, #ifdef CONFIG_PPC64 static int ppr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.regs->ppr, 0, sizeof(u64)); + return membuf_write(&to, &target->thread.regs->ppr, sizeof(u64)); } static int ppr_set(struct task_struct *target, const struct user_regset *regset, @@ -324,10 +310,9 @@ static int ppr_set(struct task_struct *target, const struct user_regset *regset, } static int dscr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.dscr, 0, sizeof(u64)); + return membuf_write(&to, &target->thread.dscr, sizeof(u64)); } static int dscr_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, @@ -339,10 +324,9 @@ static int dscr_set(struct task_struct *target, const struct user_regset *regset #endif #ifdef CONFIG_PPC_BOOK3S_64 static int tar_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.tar, 0, sizeof(u64)); + return membuf_write(&to, &target->thread.tar, sizeof(u64)); } static int tar_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, @@ -364,7 +348,7 @@ static int ebb_active(struct task_struct *target, const struct user_regset *regs } static int ebb_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { /* Build tests */ BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr)); @@ -376,8 +360,7 @@ static int ebb_get(struct task_struct *target, const struct user_regset *regset, if (!target->thread.used_ebb) return -ENODATA; - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.ebbrr, - 0, 3 * sizeof(unsigned long)); + return membuf_write(&to, &target->thread.ebbrr, 3 * sizeof(unsigned long)); } static int ebb_set(struct task_struct *target, const struct user_regset *regset, @@ -420,7 +403,7 @@ static int pmu_active(struct task_struct *target, const struct user_regset *regs } static int pmu_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { /* Build tests */ BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar)); @@ -431,8 +414,7 @@ static int pmu_get(struct task_struct *target, const struct user_regset *regset, if (!cpu_has_feature(CPU_FTR_ARCH_207S)) return -ENODEV; - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.siar, - 0, 5 * sizeof(unsigned long)); + return membuf_write(&to, &target->thread.siar, 5 * sizeof(unsigned long)); } static int pmu_set(struct task_struct *target, const struct user_regset *regset, @@ -486,7 +468,7 @@ static int pkey_active(struct task_struct *target, const struct user_regset *reg } static int pkey_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { BUILD_BUG_ON(TSO(amr) + sizeof(unsigned long) != TSO(iamr)); BUILD_BUG_ON(TSO(iamr) + sizeof(unsigned long) != TSO(uamor)); @@ -494,8 +476,7 @@ static int pkey_get(struct task_struct *target, const struct user_regset *regset if (!arch_pkeys_enabled()) return -ENODEV; - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.amr, - 0, ELF_NPKEY * sizeof(unsigned long)); + return membuf_write(&to, &target->thread.amr, ELF_NPKEY * sizeof(unsigned long)); } static int pkey_set(struct task_struct *target, const struct user_regset *regset, @@ -529,110 +510,110 @@ static const struct user_regset native_regsets[] = { [REGSET_GPR] = { .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, .size = sizeof(long), .align = sizeof(long), - .get = gpr_get, .set = gpr_set + .get2 = gpr_get, .set = gpr_set }, [REGSET_FPR] = { .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, .size = sizeof(double), .align = sizeof(double), - .get = fpr_get, .set = fpr_set + .get2 = fpr_get, .set = fpr_set }, #ifdef CONFIG_ALTIVEC [REGSET_VMX] = { .core_note_type = NT_PPC_VMX, .n = 34, .size = sizeof(vector128), .align = sizeof(vector128), - .active = vr_active, .get = vr_get, .set = vr_set + .active = vr_active, .get2 = vr_get, .set = vr_set }, #endif #ifdef CONFIG_VSX [REGSET_VSX] = { .core_note_type = NT_PPC_VSX, .n = 32, .size = sizeof(double), .align = sizeof(double), - .active = vsr_active, .get = vsr_get, .set = vsr_set + .active = vsr_active, .get2 = vsr_get, .set = vsr_set }, #endif #ifdef CONFIG_SPE [REGSET_SPE] = { .core_note_type = NT_PPC_SPE, .n = 35, .size = sizeof(u32), .align = sizeof(u32), - .active = evr_active, .get = evr_get, .set = evr_set + .active = evr_active, .get2 = evr_get, .set = evr_set }, #endif #ifdef CONFIG_PPC_TRANSACTIONAL_MEM [REGSET_TM_CGPR] = { .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG, .size = sizeof(long), .align = sizeof(long), - .active = tm_cgpr_active, .get = tm_cgpr_get, .set = tm_cgpr_set + .active = tm_cgpr_active, .get2 = tm_cgpr_get, .set = tm_cgpr_set }, [REGSET_TM_CFPR] = { .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG, .size = sizeof(double), .align = sizeof(double), - .active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set + .active = tm_cfpr_active, .get2 = tm_cfpr_get, .set = tm_cfpr_set }, [REGSET_TM_CVMX] = { .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX, .size = sizeof(vector128), .align = sizeof(vector128), - .active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set + .active = tm_cvmx_active, .get2 = tm_cvmx_get, .set = tm_cvmx_set }, [REGSET_TM_CVSX] = { .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX, .size = sizeof(double), .align = sizeof(double), - .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set + .active = tm_cvsx_active, .get2 = tm_cvsx_get, .set = tm_cvsx_set }, [REGSET_TM_SPR] = { .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG, .size = sizeof(u64), .align = sizeof(u64), - .active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set + .active = tm_spr_active, .get2 = tm_spr_get, .set = tm_spr_set }, [REGSET_TM_CTAR] = { .core_note_type = NT_PPC_TM_CTAR, .n = 1, .size = sizeof(u64), .align = sizeof(u64), - .active = tm_tar_active, .get = tm_tar_get, .set = tm_tar_set + .active = tm_tar_active, .get2 = tm_tar_get, .set = tm_tar_set }, [REGSET_TM_CPPR] = { .core_note_type = NT_PPC_TM_CPPR, .n = 1, .size = sizeof(u64), .align = sizeof(u64), - .active = tm_ppr_active, .get = tm_ppr_get, .set = tm_ppr_set + .active = tm_ppr_active, .get2 = tm_ppr_get, .set = tm_ppr_set }, [REGSET_TM_CDSCR] = { .core_note_type = NT_PPC_TM_CDSCR, .n = 1, .size = sizeof(u64), .align = sizeof(u64), - .active = tm_dscr_active, .get = tm_dscr_get, .set = tm_dscr_set + .active = tm_dscr_active, .get2 = tm_dscr_get, .set = tm_dscr_set }, #endif #ifdef CONFIG_PPC64 [REGSET_PPR] = { .core_note_type = NT_PPC_PPR, .n = 1, .size = sizeof(u64), .align = sizeof(u64), - .get = ppr_get, .set = ppr_set + .get2 = ppr_get, .set = ppr_set }, [REGSET_DSCR] = { .core_note_type = NT_PPC_DSCR, .n = 1, .size = sizeof(u64), .align = sizeof(u64), - .get = dscr_get, .set = dscr_set + .get2 = dscr_get, .set = dscr_set }, #endif #ifdef CONFIG_PPC_BOOK3S_64 [REGSET_TAR] = { .core_note_type = NT_PPC_TAR, .n = 1, .size = sizeof(u64), .align = sizeof(u64), - .get = tar_get, .set = tar_set + .get2 = tar_get, .set = tar_set }, [REGSET_EBB] = { .core_note_type = NT_PPC_EBB, .n = ELF_NEBB, .size = sizeof(u64), .align = sizeof(u64), - .active = ebb_active, .get = ebb_get, .set = ebb_set + .active = ebb_active, .get2 = ebb_get, .set = ebb_set }, [REGSET_PMR] = { .core_note_type = NT_PPC_PMU, .n = ELF_NPMU, .size = sizeof(u64), .align = sizeof(u64), - .active = pmu_active, .get = pmu_get, .set = pmu_set + .active = pmu_active, .get2 = pmu_get, .set = pmu_set }, #endif #ifdef CONFIG_PPC_MEM_KEYS [REGSET_PKEY] = { .core_note_type = NT_PPC_PKEY, .n = ELF_NPKEY, .size = sizeof(u64), .align = sizeof(u64), - .active = pkey_active, .get = pkey_get, .set = pkey_set + .active = pkey_active, .get2 = pkey_get, .set = pkey_set }, #endif }; @@ -646,49 +627,16 @@ const struct user_regset_view user_ppc_native_view = { int gpr32_get_common(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf, - unsigned long *regs) + struct membuf to, unsigned long *regs) { - compat_ulong_t *k = kbuf; - compat_ulong_t __user *u = ubuf; - compat_ulong_t reg; - - pos /= sizeof(reg); - count /= sizeof(reg); - - if (kbuf) - for (; count > 0 && pos < PT_MSR; --count) - *k++ = regs[pos++]; - else - for (; count > 0 && pos < PT_MSR; --count) - if (__put_user((compat_ulong_t)regs[pos++], u++)) - return -EFAULT; - - if (count > 0 && pos == PT_MSR) { - reg = get_user_msr(target); - if (kbuf) - *k++ = reg; - else if (__put_user(reg, u++)) - return -EFAULT; - ++pos; - --count; - } - - if (kbuf) - for (; count > 0 && pos < PT_REGS_COUNT; --count) - *k++ = regs[pos++]; - else - for (; count > 0 && pos < PT_REGS_COUNT; --count) - if (__put_user((compat_ulong_t)regs[pos++], u++)) - return -EFAULT; + int i; - kbuf = k; - ubuf = u; - pos *= sizeof(reg); - count *= sizeof(reg); - return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, - PT_REGS_COUNT * sizeof(reg), -1); + for (i = 0; i < PT_MSR; i++) + membuf_store(&to, (u32)regs[i]); + membuf_store(&to, (u32)get_user_msr(target)); + for (i++ ; i < PT_REGS_COUNT; i++) + membuf_store(&to, (u32)regs[i]); + return membuf_zero(&to, (ELF_NGREG - PT_REGS_COUNT) * sizeof(u32)); } int gpr32_set_common(struct task_struct *target, @@ -761,8 +709,7 @@ int gpr32_set_common(struct task_struct *target, static int gpr32_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) + struct membuf to) { int i; @@ -777,7 +724,7 @@ static int gpr32_get(struct task_struct *target, for (i = 14; i < 32; i++) target->thread.regs->gpr[i] = NV_REG_POISON; } - return gpr32_get_common(target, regset, pos, count, kbuf, ubuf, + return gpr32_get_common(target, regset, to, &target->thread.regs->gpr[0]); } @@ -801,25 +748,25 @@ static const struct user_regset compat_regsets[] = { [REGSET_GPR] = { .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, .size = sizeof(compat_long_t), .align = sizeof(compat_long_t), - .get = gpr32_get, .set = gpr32_set + .get2 = gpr32_get, .set = gpr32_set }, [REGSET_FPR] = { .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, .size = sizeof(double), .align = sizeof(double), - .get = fpr_get, .set = fpr_set + .get2 = fpr_get, .set = fpr_set }, #ifdef CONFIG_ALTIVEC [REGSET_VMX] = { .core_note_type = NT_PPC_VMX, .n = 34, .size = sizeof(vector128), .align = sizeof(vector128), - .active = vr_active, .get = vr_get, .set = vr_set + .active = vr_active, .get2 = vr_get, .set = vr_set }, #endif #ifdef CONFIG_SPE [REGSET_SPE] = { .core_note_type = NT_PPC_SPE, .n = 35, .size = sizeof(u32), .align = sizeof(u32), - .active = evr_active, .get = evr_get, .set = evr_set + .active = evr_active, .get2 = evr_get, .set = evr_set }, #endif #ifdef CONFIG_PPC_TRANSACTIONAL_MEM @@ -827,66 +774,66 @@ static const struct user_regset compat_regsets[] = { .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG, .size = sizeof(long), .align = sizeof(long), .active = tm_cgpr_active, - .get = tm_cgpr32_get, .set = tm_cgpr32_set + .get2 = tm_cgpr32_get, .set = tm_cgpr32_set }, [REGSET_TM_CFPR] = { .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG, .size = sizeof(double), .align = sizeof(double), - .active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set + .active = tm_cfpr_active, .get2 = tm_cfpr_get, .set = tm_cfpr_set }, [REGSET_TM_CVMX] = { .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX, .size = sizeof(vector128), .align = sizeof(vector128), - .active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set + .active = tm_cvmx_active, .get2 = tm_cvmx_get, .set = tm_cvmx_set }, [REGSET_TM_CVSX] = { .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX, .size = sizeof(double), .align = sizeof(double), - .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set + .active = tm_cvsx_active, .get2 = tm_cvsx_get, .set = tm_cvsx_set }, [REGSET_TM_SPR] = { .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG, .size = sizeof(u64), .align = sizeof(u64), - .active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set + .active = tm_spr_active, .get2 = tm_spr_get, .set = tm_spr_set }, [REGSET_TM_CTAR] = { .core_note_type = NT_PPC_TM_CTAR, .n = 1, .size = sizeof(u64), .align = sizeof(u64), - .active = tm_tar_active, .get = tm_tar_get, .set = tm_tar_set + .active = tm_tar_active, .get2 = tm_tar_get, .set = tm_tar_set }, [REGSET_TM_CPPR] = { .core_note_type = NT_PPC_TM_CPPR, .n = 1, .size = sizeof(u64), .align = sizeof(u64), - .active = tm_ppr_active, .get = tm_ppr_get, .set = tm_ppr_set + .active = tm_ppr_active, .get2 = tm_ppr_get, .set = tm_ppr_set }, [REGSET_TM_CDSCR] = { .core_note_type = NT_PPC_TM_CDSCR, .n = 1, .size = sizeof(u64), .align = sizeof(u64), - .active = tm_dscr_active, .get = tm_dscr_get, .set = tm_dscr_set + .active = tm_dscr_active, .get2 = tm_dscr_get, .set = tm_dscr_set }, #endif #ifdef CONFIG_PPC64 [REGSET_PPR] = { .core_note_type = NT_PPC_PPR, .n = 1, .size = sizeof(u64), .align = sizeof(u64), - .get = ppr_get, .set = ppr_set + .get2 = ppr_get, .set = ppr_set }, [REGSET_DSCR] = { .core_note_type = NT_PPC_DSCR, .n = 1, .size = sizeof(u64), .align = sizeof(u64), - .get = dscr_get, .set = dscr_set + .get2 = dscr_get, .set = dscr_set }, #endif #ifdef CONFIG_PPC_BOOK3S_64 [REGSET_TAR] = { .core_note_type = NT_PPC_TAR, .n = 1, .size = sizeof(u64), .align = sizeof(u64), - .get = tar_get, .set = tar_set + .get2 = tar_get, .set = tar_set }, [REGSET_EBB] = { .core_note_type = NT_PPC_EBB, .n = ELF_NEBB, .size = sizeof(u64), .align = sizeof(u64), - .active = ebb_active, .get = ebb_get, .set = ebb_set + .active = ebb_active, .get2 = ebb_get, .set = ebb_set }, #endif }; diff --git a/arch/powerpc/kernel/ptrace/ptrace-vsx.c b/arch/powerpc/kernel/ptrace/ptrace-vsx.c index d53466d49cc0..1da4303128ef 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-vsx.c +++ b/arch/powerpc/kernel/ptrace/ptrace-vsx.c @@ -19,7 +19,7 @@ * }; */ int fpr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { u64 buf[33]; int i; @@ -30,7 +30,7 @@ int fpr_get(struct task_struct *target, const struct user_regset *regset, for (i = 0; i < 32 ; i++) buf[i] = target->thread.TS_FPR(i); buf[32] = target->thread.fp_state.fpscr; - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1); + return membuf_write(&to, buf, 33 * sizeof(u64)); } /* @@ -95,10 +95,10 @@ int vsr_active(struct task_struct *target, const struct user_regset *regset) * }; */ int vsr_get(struct task_struct *target, const struct user_regset *regset, - unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) + struct membuf to) { u64 buf[32]; - int ret, i; + int i; flush_tmregs_to_thread(target); flush_fp_to_thread(target); @@ -108,10 +108,7 @@ int vsr_get(struct task_struct *target, const struct user_regset *regset, for (i = 0; i < 32 ; i++) buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET]; - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - buf, 0, 32 * sizeof(double)); - - return ret; + return membuf_write(&to, buf, 32 * sizeof(double)); } /* -- 2.11.0