Commit 19b39c38 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'work.regset' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull ptrace regset updates from Al Viro:
 "Internal regset API changes:

   - regularize copy_regset_{to,from}_user() callers

   - switch to saner calling conventions for ->get()

   - kill user_regset_copyout()

  The ->put() side of things will have to wait for the next cycle,
  unfortunately.

  The balance is about -1KLoC and replacements for ->get() instances are
  a lot saner"

* 'work.regset' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (41 commits)
  regset: kill user_regset_copyout{,_zero}()
  regset(): kill ->get_size()
  regset: kill ->get()
  csky: switch to ->regset_get()
  xtensa: switch to ->regset_get()
  parisc: switch to ->regset_get()
  nds32: switch to ->regset_get()
  nios2: switch to ->regset_get()
  hexagon: switch to ->regset_get()
  h8300: switch to ->regset_get()
  openrisc: switch to ->regset_get()
  riscv: switch to ->regset_get()
  c6x: switch to ->regset_get()
  ia64: switch to ->regset_get()
  arc: switch to ->regset_get()
  arm: switch to ->regset_get()
  sh: convert to ->regset_get()
  arm64: switch to ->regset_get()
  mips: switch to ->regset_get()
  sparc: switch to ->regset_get()
  ...
parents 995909a4 ce327e1c
...@@ -18,88 +18,61 @@ static struct callee_regs *task_callee_regs(struct task_struct *tsk) ...@@ -18,88 +18,61 @@ static struct callee_regs *task_callee_regs(struct task_struct *tsk)
static int genregs_get(struct task_struct *target, static int genregs_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
const struct pt_regs *ptregs = task_pt_regs(target); const struct pt_regs *ptregs = task_pt_regs(target);
const struct callee_regs *cregs = task_callee_regs(target); const struct callee_regs *cregs = task_callee_regs(target);
int ret = 0;
unsigned int stop_pc_val; unsigned int stop_pc_val;
#define REG_O_CHUNK(START, END, PTR) \ membuf_zero(&to, 4); // pad
if (!ret) \ membuf_store(&to, ptregs->bta);
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, PTR, \ membuf_store(&to, ptregs->lp_start);
offsetof(struct user_regs_struct, START), \ membuf_store(&to, ptregs->lp_end);
offsetof(struct user_regs_struct, END)); membuf_store(&to, ptregs->lp_count);
membuf_store(&to, ptregs->status32);
#define REG_O_ONE(LOC, PTR) \ membuf_store(&to, ptregs->ret);
if (!ret) \ membuf_store(&to, ptregs->blink);
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, PTR, \ membuf_store(&to, ptregs->fp);
offsetof(struct user_regs_struct, LOC), \ membuf_store(&to, ptregs->r26); // gp
offsetof(struct user_regs_struct, LOC) + 4); membuf_store(&to, ptregs->r12);
membuf_store(&to, ptregs->r11);
#define REG_O_ZERO(LOC) \ membuf_store(&to, ptregs->r10);
if (!ret) \ membuf_store(&to, ptregs->r9);
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, \ membuf_store(&to, ptregs->r8);
offsetof(struct user_regs_struct, LOC), \ membuf_store(&to, ptregs->r7);
offsetof(struct user_regs_struct, LOC) + 4); membuf_store(&to, ptregs->r6);
membuf_store(&to, ptregs->r5);
REG_O_ZERO(pad); membuf_store(&to, ptregs->r4);
REG_O_ONE(scratch.bta, &ptregs->bta); membuf_store(&to, ptregs->r3);
REG_O_ONE(scratch.lp_start, &ptregs->lp_start); membuf_store(&to, ptregs->r2);
REG_O_ONE(scratch.lp_end, &ptregs->lp_end); membuf_store(&to, ptregs->r1);
REG_O_ONE(scratch.lp_count, &ptregs->lp_count); membuf_store(&to, ptregs->r0);
REG_O_ONE(scratch.status32, &ptregs->status32); membuf_store(&to, ptregs->sp);
REG_O_ONE(scratch.ret, &ptregs->ret); membuf_zero(&to, 4); // pad2
REG_O_ONE(scratch.blink, &ptregs->blink); membuf_store(&to, cregs->r25);
REG_O_ONE(scratch.fp, &ptregs->fp); membuf_store(&to, cregs->r24);
REG_O_ONE(scratch.gp, &ptregs->r26); membuf_store(&to, cregs->r23);
REG_O_ONE(scratch.r12, &ptregs->r12); membuf_store(&to, cregs->r22);
REG_O_ONE(scratch.r11, &ptregs->r11); membuf_store(&to, cregs->r21);
REG_O_ONE(scratch.r10, &ptregs->r10); membuf_store(&to, cregs->r20);
REG_O_ONE(scratch.r9, &ptregs->r9); membuf_store(&to, cregs->r19);
REG_O_ONE(scratch.r8, &ptregs->r8); membuf_store(&to, cregs->r18);
REG_O_ONE(scratch.r7, &ptregs->r7); membuf_store(&to, cregs->r17);
REG_O_ONE(scratch.r6, &ptregs->r6); membuf_store(&to, cregs->r16);
REG_O_ONE(scratch.r5, &ptregs->r5); membuf_store(&to, cregs->r15);
REG_O_ONE(scratch.r4, &ptregs->r4); membuf_store(&to, cregs->r14);
REG_O_ONE(scratch.r3, &ptregs->r3); membuf_store(&to, cregs->r13);
REG_O_ONE(scratch.r2, &ptregs->r2); membuf_store(&to, target->thread.fault_address); // efa
REG_O_ONE(scratch.r1, &ptregs->r1);
REG_O_ONE(scratch.r0, &ptregs->r0); if (in_brkpt_trap(ptregs)) {
REG_O_ONE(scratch.sp, &ptregs->sp); stop_pc_val = target->thread.fault_address;
pr_debug("\t\tstop_pc (brk-pt)\n");
REG_O_ZERO(pad2); } else {
stop_pc_val = ptregs->ret;
REG_O_ONE(callee.r25, &cregs->r25); pr_debug("\t\tstop_pc (others)\n");
REG_O_ONE(callee.r24, &cregs->r24);
REG_O_ONE(callee.r23, &cregs->r23);
REG_O_ONE(callee.r22, &cregs->r22);
REG_O_ONE(callee.r21, &cregs->r21);
REG_O_ONE(callee.r20, &cregs->r20);
REG_O_ONE(callee.r19, &cregs->r19);
REG_O_ONE(callee.r18, &cregs->r18);
REG_O_ONE(callee.r17, &cregs->r17);
REG_O_ONE(callee.r16, &cregs->r16);
REG_O_ONE(callee.r15, &cregs->r15);
REG_O_ONE(callee.r14, &cregs->r14);
REG_O_ONE(callee.r13, &cregs->r13);
REG_O_ONE(efa, &target->thread.fault_address);
if (!ret) {
if (in_brkpt_trap(ptregs)) {
stop_pc_val = target->thread.fault_address;
pr_debug("\t\tstop_pc (brk-pt)\n");
} else {
stop_pc_val = ptregs->ret;
pr_debug("\t\tstop_pc (others)\n");
}
REG_O_ONE(stop_pc, &stop_pc_val);
} }
return ret; return membuf_store(&to, stop_pc_val); // stop_pc
} }
static int genregs_set(struct task_struct *target, static int genregs_set(struct task_struct *target,
...@@ -184,25 +157,20 @@ static int genregs_set(struct task_struct *target, ...@@ -184,25 +157,20 @@ static int genregs_set(struct task_struct *target,
#ifdef CONFIG_ISA_ARCV2 #ifdef CONFIG_ISA_ARCV2
static int arcv2regs_get(struct task_struct *target, static int arcv2regs_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
const struct pt_regs *regs = task_pt_regs(target); const struct pt_regs *regs = task_pt_regs(target);
int ret, copy_sz;
if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS)) if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS))
copy_sz = sizeof(struct user_regs_arcv2); /*
else * itemized copy not needed like above as layout of regs (r30,r58,r59)
copy_sz = 4; /* r30 only */ * is exactly same in kernel (pt_regs) and userspace (user_regs_arcv2)
*/
return membuf_write(&to, &regs->r30, sizeof(struct user_regs_arcv2));
/*
* itemized copy not needed like above as layout of regs (r30,r58,r59)
* is exactly same in kernel (pt_regs) and userspace (user_regs_arcv2)
*/
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &regs->r30,
0, copy_sz);
return ret; membuf_write(&to, &regs->r30, 4); /* r30 only */
return membuf_zero(&to, sizeof(struct user_regs_arcv2) - 4);
} }
static int arcv2regs_set(struct task_struct *target, static int arcv2regs_set(struct task_struct *target,
...@@ -237,7 +205,7 @@ static const struct user_regset arc_regsets[] = { ...@@ -237,7 +205,7 @@ static const struct user_regset arc_regsets[] = {
.n = ELF_NGREG, .n = ELF_NGREG,
.size = sizeof(unsigned long), .size = sizeof(unsigned long),
.align = sizeof(unsigned long), .align = sizeof(unsigned long),
.get = genregs_get, .regset_get = genregs_get,
.set = genregs_set, .set = genregs_set,
}, },
#ifdef CONFIG_ISA_ARCV2 #ifdef CONFIG_ISA_ARCV2
...@@ -246,7 +214,7 @@ static const struct user_regset arc_regsets[] = { ...@@ -246,7 +214,7 @@ static const struct user_regset arc_regsets[] = {
.n = ELF_ARCV2REG, .n = ELF_ARCV2REG,
.size = sizeof(unsigned long), .size = sizeof(unsigned long),
.align = sizeof(unsigned long), .align = sizeof(unsigned long),
.get = arcv2regs_get, .regset_get = arcv2regs_get,
.set = arcv2regs_set, .set = arcv2regs_set,
}, },
#endif #endif
......
...@@ -569,14 +569,9 @@ static int ptrace_sethbpregs(struct task_struct *tsk, long num, ...@@ -569,14 +569,9 @@ static int ptrace_sethbpregs(struct task_struct *tsk, long num,
static int gpr_get(struct task_struct *target, static int gpr_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
struct pt_regs *regs = task_pt_regs(target); return membuf_write(&to, task_pt_regs(target), sizeof(struct pt_regs));
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
regs,
0, sizeof(*regs));
} }
static int gpr_set(struct task_struct *target, static int gpr_set(struct task_struct *target,
...@@ -602,12 +597,10 @@ static int gpr_set(struct task_struct *target, ...@@ -602,12 +597,10 @@ static int gpr_set(struct task_struct *target,
static int fpa_get(struct task_struct *target, static int fpa_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, return membuf_write(&to, &task_thread_info(target)->fpstate,
&task_thread_info(target)->fpstate, sizeof(struct user_fp));
0, sizeof(struct user_fp));
} }
static int fpa_set(struct task_struct *target, static int fpa_set(struct task_struct *target,
...@@ -642,41 +635,20 @@ static int fpa_set(struct task_struct *target, ...@@ -642,41 +635,20 @@ static int fpa_set(struct task_struct *target,
* vfp_set() ignores this chunk * vfp_set() ignores this chunk
* *
* 1 word for the FPSCR * 1 word for the FPSCR
*
* The bounds-checking logic built into user_regset_copyout and friends
* means that we can make a simple sequence of calls to map the relevant data
* to/from the specified slice of the user regset structure.
*/ */
static int vfp_get(struct task_struct *target, static int vfp_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
int ret;
struct thread_info *thread = task_thread_info(target); struct thread_info *thread = task_thread_info(target);
struct vfp_hard_struct const *vfp = &thread->vfpstate.hard; struct vfp_hard_struct const *vfp = &thread->vfpstate.hard;
const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);
const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
vfp_sync_hwstate(thread); vfp_sync_hwstate(thread);
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, membuf_write(&to, vfp->fpregs, sizeof(vfp->fpregs));
&vfp->fpregs, membuf_zero(&to, user_fpscr_offset - sizeof(vfp->fpregs));
user_fpregs_offset, return membuf_store(&to, vfp->fpscr);
user_fpregs_offset + sizeof(vfp->fpregs));
if (ret)
return ret;
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
user_fpregs_offset + sizeof(vfp->fpregs),
user_fpscr_offset);
if (ret)
return ret;
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&vfp->fpscr,
user_fpscr_offset,
user_fpscr_offset + sizeof(vfp->fpscr));
} }
/* /*
...@@ -739,7 +711,7 @@ static const struct user_regset arm_regsets[] = { ...@@ -739,7 +711,7 @@ static const struct user_regset arm_regsets[] = {
.n = ELF_NGREG, .n = ELF_NGREG,
.size = sizeof(u32), .size = sizeof(u32),
.align = sizeof(u32), .align = sizeof(u32),
.get = gpr_get, .regset_get = gpr_get,
.set = gpr_set .set = gpr_set
}, },
[REGSET_FPR] = { [REGSET_FPR] = {
...@@ -751,7 +723,7 @@ static const struct user_regset arm_regsets[] = { ...@@ -751,7 +723,7 @@ static const struct user_regset arm_regsets[] = {
.n = sizeof(struct user_fp) / sizeof(u32), .n = sizeof(struct user_fp) / sizeof(u32),
.size = sizeof(u32), .size = sizeof(u32),
.align = sizeof(u32), .align = sizeof(u32),
.get = fpa_get, .regset_get = fpa_get,
.set = fpa_set .set = fpa_set
}, },
#ifdef CONFIG_VFP #ifdef CONFIG_VFP
...@@ -764,7 +736,7 @@ static const struct user_regset arm_regsets[] = { ...@@ -764,7 +736,7 @@ static const struct user_regset arm_regsets[] = {
.n = ARM_VFPREGS_SIZE / sizeof(u32), .n = ARM_VFPREGS_SIZE / sizeof(u32),
.size = sizeof(u32), .size = sizeof(u32),
.align = sizeof(u32), .align = sizeof(u32),
.get = vfp_get, .regset_get = vfp_get,
.set = vfp_set .set = vfp_set
}, },
#endif /* CONFIG_VFP */ #endif /* CONFIG_VFP */
......
This diff is collapsed.
...@@ -57,14 +57,9 @@ static inline int put_reg(struct task_struct *task, ...@@ -57,14 +57,9 @@ static inline int put_reg(struct task_struct *task,
static int gpr_get(struct task_struct *target, static int gpr_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
struct pt_regs *regs = task_pt_regs(target); return membuf_write(&to, task_pt_regs(target), sizeof(struct pt_regs));
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
regs,
0, sizeof(*regs));
} }
enum c6x_regset { enum c6x_regset {
...@@ -77,7 +72,7 @@ static const struct user_regset c6x_regsets[] = { ...@@ -77,7 +72,7 @@ static const struct user_regset c6x_regsets[] = {
.n = ELF_NGREG, .n = ELF_NGREG,
.size = sizeof(u32), .size = sizeof(u32),
.align = sizeof(u32), .align = sizeof(u32),
.get = gpr_get, .regset_get = gpr_get,
}, },
}; };
......
...@@ -76,17 +76,14 @@ enum csky_regset { ...@@ -76,17 +76,14 @@ enum csky_regset {
static int gpr_get(struct task_struct *target, static int gpr_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
struct pt_regs *regs; struct pt_regs *regs = task_pt_regs(target);
regs = task_pt_regs(target);
/* Abiv1 regs->tls is fake and we need sync here. */ /* Abiv1 regs->tls is fake and we need sync here. */
regs->tls = task_thread_info(target)->tp_value; regs->tls = task_thread_info(target)->tp_value;
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, 0, -1); return membuf_write(&to, regs, sizeof(regs));
} }
static int gpr_set(struct task_struct *target, static int gpr_set(struct task_struct *target,
...@@ -114,8 +111,7 @@ static int gpr_set(struct task_struct *target, ...@@ -114,8 +111,7 @@ static int gpr_set(struct task_struct *target,
static int fpr_get(struct task_struct *target, static int fpr_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
struct user_fp *regs = (struct user_fp *)&target->thread.user_fp; struct user_fp *regs = (struct user_fp *)&target->thread.user_fp;
...@@ -131,9 +127,9 @@ static int fpr_get(struct task_struct *target, ...@@ -131,9 +127,9 @@ static int fpr_get(struct task_struct *target,
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++)
tmp.vr[64 + i] = regs->vr[32 + i]; tmp.vr[64 + i] = regs->vr[32 + i];
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &tmp, 0, -1); return membuf_write(&to, &tmp, sizeof(tmp));
#else #else
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, 0, -1); return membuf_write(&to, regs, sizeof(*regs));
#endif #endif
} }
...@@ -173,16 +169,16 @@ static const struct user_regset csky_regsets[] = { ...@@ -173,16 +169,16 @@ static const struct user_regset csky_regsets[] = {
.n = sizeof(struct pt_regs) / sizeof(u32), .n = sizeof(struct pt_regs) / sizeof(u32),
.size = sizeof(u32), .size = sizeof(u32),
.align = sizeof(u32), .align = sizeof(u32),
.get = &gpr_get, .regset_get = gpr_get,
.set = &gpr_set, .set = gpr_set,
}, },
[REGSET_FPR] = { [REGSET_FPR] = {
.core_note_type = NT_PRFPREG, .core_note_type = NT_PRFPREG,
.n = sizeof(struct user_fp) / sizeof(u32), .n = sizeof(struct user_fp) / sizeof(u32),
.size = sizeof(u32), .size = sizeof(u32),
.align = sizeof(u32), .align = sizeof(u32),
.get = &fpr_get, .regset_get = fpr_get,
.set = &fpr_set, .set = fpr_set,
}, },
}; };
......
...@@ -87,20 +87,15 @@ int h8300_put_reg(struct task_struct *task, int regno, unsigned long data) ...@@ -87,20 +87,15 @@ int h8300_put_reg(struct task_struct *task, int regno, unsigned long data)
static int regs_get(struct task_struct *target, static int regs_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
int r; int r;
struct user_regs_struct regs;
long *reg = (long *)&regs;
/* build user regs in buffer */ BUILD_BUG_ON(sizeof(struct user_regs_struct) % sizeof(long) != 0);
BUILD_BUG_ON(sizeof(regs) % sizeof(long) != 0); for (r = 0; r < ELF_NGREG; r++)
for (r = 0; r < sizeof(regs) / sizeof(long); r++) membuf_store(&to, h8300_get_reg(target, r));
*reg++ = h8300_get_reg(target, r);
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, return 0;
&regs, 0, sizeof(regs));
} }
static int regs_set(struct task_struct *target, static int regs_set(struct task_struct *target,
...@@ -139,7 +134,7 @@ static const struct user_regset h8300_regsets[] = { ...@@ -139,7 +134,7 @@ static const struct user_regset h8300_regsets[] = {
.n = ELF_NGREG, .n = ELF_NGREG,
.size = sizeof(long), .size = sizeof(long),
.align = sizeof(long), .align = sizeof(long),
.get = regs_get, .regset_get = regs_get,
.set = regs_set, .set = regs_set,
}, },
}; };
......
...@@ -35,58 +35,38 @@ void user_disable_single_step(struct task_struct *child) ...@@ -35,58 +35,38 @@ void user_disable_single_step(struct task_struct *child)
static int genregs_get(struct task_struct *target, static int genregs_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, srtuct membuf to)
void *kbuf, void __user *ubuf)
{ {
int ret;
unsigned int dummy;
struct pt_regs *regs = task_pt_regs(target); struct pt_regs *regs = task_pt_regs(target);
if (!regs)
return -EIO;
/* The general idea here is that the copyout must happen in /* The general idea here is that the copyout must happen in
* exactly the same order in which the userspace expects these * exactly the same order in which the userspace expects these
* regs. Now, the sequence in userspace does not match the * regs. Now, the sequence in userspace does not match the
* sequence in the kernel, so everything past the 32 gprs * sequence in the kernel, so everything past the 32 gprs
* happens one at a time. * happens one at a time.
*/ */
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, membuf_write(&to, &regs->r00, 32*sizeof(unsigned long));
&regs->r00, 0, 32*sizeof(unsigned long));
#define ONEXT(KPT_REG, USR_REG) \
if (!ret) \
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, \
KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
offsetof(struct user_regs_struct, USR_REG) + \
sizeof(unsigned long));
/* Must be exactly same sequence as struct user_regs_struct */ /* Must be exactly same sequence as struct user_regs_struct */
ONEXT(&regs->sa0, sa0); membuf_store(&to, regs->sa0);
ONEXT(&regs->lc0, lc0); membuf_store(&to, regs->lc0);
ONEXT(&regs->sa1, sa1); membuf_store(&to, regs->sa1);
ONEXT(&regs->lc1, lc1); membuf_store(&to, regs->lc1);
ONEXT(&regs->m0, m0); membuf_store(&to, regs->m0);
ONEXT(&regs->m1, m1); membuf_store(&to, regs->m1);
ONEXT(&regs->usr, usr); membuf_store(&to, regs->usr);
ONEXT(&regs->preds, p3_0); membuf_store(&to, regs->p3_0);
ONEXT(&regs->gp, gp); membuf_store(&to, regs->gp);
ONEXT(&regs->ugp, ugp); membuf_store(&to, regs->ugp);
ONEXT(&pt_elr(regs), pc); membuf_store(&to, pt_elr(regs)); // pc
dummy = pt_cause(regs); membuf_store(&to, (unsigned long)pt_cause(regs)); // cause
ONEXT(&dummy, cause); membuf_store(&to, pt_badva(regs)); // badva
ONEXT(&pt_badva(regs), badva);
#if CONFIG_HEXAGON_ARCH_VERSION >=4 #if CONFIG_HEXAGON_ARCH_VERSION >=4
ONEXT(&regs->cs0, cs0); membuf_store(&to, regs->cs0);
ONEXT(&regs->cs1, cs1); membuf_store(&to, regs->cs1);
return membuf_zero(&to, sizeof(unsigned long));
#else
return membuf_zero(&to, 3 * sizeof(unsigned long));
#endif #endif
/* Pad the rest with zeros, if needed */
if (!ret)
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
offsetof(struct user_regs_struct, pad1), -1);
return ret;
} }
static int genregs_set(struct task_struct *target, static int genregs_set(struct task_struct *target,
...@@ -159,7 +139,7 @@ static const struct user_regset hexagon_regsets[] = { ...@@ -159,7 +139,7 @@ static const struct user_regset hexagon_regsets[] = {
.n = ELF_NGREG, .n = ELF_NGREG,
.size = sizeof(unsigned long), .size = sizeof(unsigned long),
.align = sizeof(unsigned long), .align = sizeof(unsigned long),
.get = genregs_get, .regset_get = genregs_get,
.set = genregs_set, .set = genregs_set,
}, },
}; };
......
This diff is collapsed.
This diff is collapsed.
...@@ -13,11 +13,10 @@ enum nds32_regset { ...@@ -13,11 +13,10 @@ enum nds32_regset {
static int gpr_get(struct task_struct *target, static int gpr_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user * ubuf)
{ {
struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs; return membuf_write(&to, &task_pt_regs(target)->user_regs,
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1); sizeof(struct user_pt_regs));
} }
static int gpr_set(struct task_struct *target, const struct user_regset *regset, static int gpr_set(struct task_struct *target, const struct user_regset *regset,
...@@ -41,7 +40,7 @@ static const struct user_regset nds32_regsets[] = { ...@@ -41,7 +40,7 @@ static const struct user_regset nds32_regsets[] = {
.n = sizeof(struct user_pt_regs) / sizeof(u32), .n = sizeof(struct user_pt_regs) / sizeof(u32),
.size = sizeof(elf_greg_t), .size = sizeof(elf_greg_t),
.align = sizeof(elf_greg_t), .align = sizeof(elf_greg_t),
.get = gpr_get, .regset_get = gpr_get,
.set = gpr_set} .set = gpr_set}
}; };
......
...@@ -21,45 +21,24 @@ ...@@ -21,45 +21,24 @@
static int genregs_get(struct task_struct *target, static int genregs_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
const struct pt_regs *regs = task_pt_regs(target); const struct pt_regs *regs = task_pt_regs(target);
const struct switch_stack *sw = (struct switch_stack *)regs - 1; const struct switch_stack *sw = (struct switch_stack *)regs - 1;
int ret = 0;
#define REG_O_ZERO_RANGE(START, END) \
if (!ret) \
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, \
START * 4, (END * 4) + 4);
#define REG_O_ONE(PTR, LOC) \
if (!ret) \
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, PTR, \
LOC * 4, (LOC * 4) + 4);
#define REG_O_RANGE(PTR, START, END) \ membuf_zero(&to, 4); // R0
if (!ret) \ membuf_write(&to, &regs->r1, 7 * 4); // R1..R7
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, PTR, \ membuf_write(&to, &regs->r8, 8 * 4); // R8..R15
START * 4, (END * 4) + 4); membuf_write(&to, sw, 8 * 4); // R16..R23
membuf_zero(&to, 2 * 4); /* et and bt */
REG_O_ZERO_RANGE(PTR_R0, PTR_R0); membuf_store(&to, regs->gp);
REG_O_RANGE(&regs->r1, PTR_R1, PTR_R7); membuf_store(&to, regs->sp);
REG_O_RANGE(&regs->r8, PTR_R8, PTR_R15); membuf_store(&to, regs->fp);
REG_O_RANGE(sw, PTR_R16, PTR_R23); membuf_store(&to, regs->ea);
REG_O_ZERO_RANGE(PTR_R24, PTR_R25); /* et and bt */ membuf_zero(&to, 4); // PTR_BA
REG_O_ONE(&regs->gp, PTR_GP); membuf_store(&to, regs->ra);
REG_O_ONE(&regs->sp, PTR_SP); membuf_store(&to, regs->ea); /* use ea for PC */
REG_O_ONE(&regs->fp, PTR_FP); return membuf_zero(&to, (NUM_PTRACE_REG - PTR_PC) * 4);
REG_O_ONE(&regs->ea, PTR_EA);
REG_O_ZERO_RANGE(PTR_BA, PTR_BA);
REG_O_ONE(&regs->ra, PTR_RA);
REG_O_ONE(&regs->ea, PTR_PC); /* use ea for PC */
if (!ret)
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
PTR_STATUS * 4, -1);
return ret;
} }
/* /*
...@@ -121,7 +100,7 @@ static const struct user_regset nios2_regsets[] = { ...@@ -121,7 +100,7 @@ static const struct user_regset nios2_regsets[] = {
.n = NUM_PTRACE_REG, .n = NUM_PTRACE_REG,
.size = sizeof(unsigned long), .size = sizeof(unsigned long),
.align = sizeof(unsigned long), .align = sizeof(unsigned long),
.get = genregs_get, .regset_get = genregs_get,
.set = genregs_set, .set = genregs_set,
} }
}; };
......
...@@ -44,29 +44,15 @@ ...@@ -44,29 +44,15 @@
*/ */
static int genregs_get(struct task_struct *target, static int genregs_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user * ubuf)
{ {
const struct pt_regs *regs = task_pt_regs(target); const struct pt_regs *regs = task_pt_regs(target);
int ret;
/* r0 */ /* r0 */
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 0, 4); membuf_zero(&to, 4);
membuf_write(&to, regs->gpr + 1, 31 * 4);
if (!ret) membuf_store(&to, regs->pc);
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, return membuf_store(&to, regs->sr);
regs->gpr+1, 4, 4*32);
if (!ret)
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&regs->pc, 4*32, 4*33);
if (!ret)
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&regs->sr, 4*33, 4*34);
if (!ret)
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
4*34, -1);
return ret;
} }
/* /*
...@@ -114,7 +100,7 @@ static const struct user_regset or1k_regsets[] = { ...@@ -114,7 +100,7 @@ static const struct user_regset or1k_regsets[] = {
.n = ELF_NGREG, .n = ELF_NGREG,
.size = sizeof(long), .size = sizeof(long),
.align = sizeof(long), .align = sizeof(long),
.get = genregs_get, .regset_get = genregs_get,
.set = genregs_set, .set = genregs_set,
}, },
}; };
......
...@@ -391,31 +391,11 @@ void do_syscall_trace_exit(struct pt_regs *regs) ...@@ -391,31 +391,11 @@ void do_syscall_trace_exit(struct pt_regs *regs)
static int fpr_get(struct task_struct *target, static int fpr_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
struct pt_regs *regs = task_regs(target); struct pt_regs *regs = task_regs(target);
__u64 *k = kbuf;
__u64 __user *u = ubuf;
__u64 reg;
pos /= sizeof(reg);
count /= sizeof(reg);
if (kbuf)
for (; count > 0 && pos < ELF_NFPREG; --count)
*k++ = regs->fr[pos++];
else
for (; count > 0 && pos < ELF_NFPREG; --count)
if (__put_user(regs->fr[pos++], u++))
return -EFAULT;
kbuf = k; return membuf_write(&to, regs->fr, ELF_NFPREG * sizeof(__u64));
ubuf = u;
pos *= sizeof(reg);
count *= sizeof(reg);
return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
ELF_NFPREG * sizeof(reg), -1);
} }
static int fpr_set(struct task_struct *target, static int fpr_set(struct task_struct *target,
...@@ -527,30 +507,14 @@ static void set_reg(struct pt_regs *regs, int num, unsigned long val) ...@@ -527,30 +507,14 @@ static void set_reg(struct pt_regs *regs, int num, unsigned long val)
static int gpr_get(struct task_struct *target, static int gpr_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
struct pt_regs *regs = task_regs(target); struct pt_regs *regs = task_regs(target);
unsigned long *k = kbuf; unsigned int pos;
unsigned long __user *u = ubuf;
unsigned long reg;
pos /= sizeof(reg); for (pos = 0; pos < ELF_NGREG; pos++)
count /= sizeof(reg); membuf_store(&to, get_reg(regs, pos));
return 0;
if (kbuf)
for (; count > 0 && pos < ELF_NGREG; --count)
*k++ = get_reg(regs, pos++);
else
for (; count > 0 && pos < ELF_NGREG; --count)
if (__put_user(get_reg(regs, pos++), u++))
return -EFAULT;
kbuf = k;
ubuf = u;
pos *= sizeof(reg);
count *= sizeof(reg);
return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
ELF_NGREG * sizeof(reg), -1);
} }
static int gpr_set(struct task_struct *target, static int gpr_set(struct task_struct *target,
...@@ -588,12 +552,12 @@ static const struct user_regset native_regsets[] = { ...@@ -588,12 +552,12 @@ static const struct user_regset native_regsets[] = {
[REGSET_GENERAL] = { [REGSET_GENERAL] = {
.core_note_type = NT_PRSTATUS, .n = ELF_NGREG, .core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
.size = sizeof(long), .align = sizeof(long), .size = sizeof(long), .align = sizeof(long),
.get = gpr_get, .set = gpr_set .regset_get = gpr_get, .set = gpr_set
}, },
[REGSET_FP] = { [REGSET_FP] = {
.core_note_type = NT_PRFPREG, .n = ELF_NFPREG, .core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
.size = sizeof(__u64), .align = sizeof(__u64), .size = sizeof(__u64), .align = sizeof(__u64),
.get = fpr_get, .set = fpr_set .regset_get = fpr_get, .set = fpr_set
} }
}; };
...@@ -607,31 +571,15 @@ static const struct user_regset_view user_parisc_native_view = { ...@@ -607,31 +571,15 @@ static const struct user_regset_view user_parisc_native_view = {
static int gpr32_get(struct task_struct *target, static int gpr32_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
struct pt_regs *regs = task_regs(target); struct pt_regs *regs = task_regs(target);
compat_ulong_t *k = kbuf; unsigned int pos;
compat_ulong_t __user *u = ubuf;
compat_ulong_t reg;
pos /= sizeof(reg); for (pos = 0; pos < ELF_NGREG; pos++)
count /= sizeof(reg); membuf_store(&to, (compat_ulong_t)get_reg(regs, pos));
if (kbuf) return 0;
for (; count > 0 && pos < ELF_NGREG; --count)
*k++ = get_reg(regs, pos++);
else
for (; count > 0 && pos < ELF_NGREG; --count)
if (__put_user((compat_ulong_t) get_reg(regs, pos++), u++))
return -EFAULT;
kbuf = k;
ubuf = u;
pos *= sizeof(reg);
count *= sizeof(reg);
return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
ELF_NGREG * sizeof(reg), -1);
} }
static int gpr32_set(struct task_struct *target, static int gpr32_set(struct task_struct *target,
...@@ -672,12 +620,12 @@ static const struct user_regset compat_regsets[] = { ...@@ -672,12 +620,12 @@ static const struct user_regset compat_regsets[] = {
[REGSET_GENERAL] = { [REGSET_GENERAL] = {
.core_note_type = NT_PRSTATUS, .n = ELF_NGREG, .core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
.size = sizeof(compat_long_t), .align = sizeof(compat_long_t), .size = sizeof(compat_long_t), .align = sizeof(compat_long_t),
.get = gpr32_get, .set = gpr32_set .regset_get = gpr32_get, .set = gpr32_set
}, },
[REGSET_FP] = { [REGSET_FP] = {
.core_note_type = NT_PRFPREG, .n = ELF_NFPREG, .core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
.size = sizeof(__u64), .align = sizeof(__u64), .size = sizeof(__u64), .align = sizeof(__u64),
.get = fpr_get, .set = fpr_set .regset_get = fpr_get, .set = fpr_set
} }
}; };
......
...@@ -41,38 +41,25 @@ int vr_active(struct task_struct *target, const struct user_regset *regset) ...@@ -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, 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); flush_altivec_to_thread(target);
BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) != BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
offsetof(struct thread_vr_state, vr[32])); offsetof(struct thread_vr_state, vr[32]));
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, membuf_write(&to, &target->thread.vr_state, 33 * sizeof(vector128));
&target->thread.vr_state, 0, /*
33 * sizeof(vector128)); * Copy out only the low-order word of vrsave.
if (!ret) { */
/* memset(&vrsave, 0, sizeof(vrsave));
* Copy out only the low-order word of vrsave. vrsave.word = target->thread.vrsave;
*/ return membuf_write(&to, &vrsave, sizeof(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;
} }
/* /*
......
...@@ -63,8 +63,7 @@ enum powerpc_regset { ...@@ -63,8 +63,7 @@ enum powerpc_regset {
/* ptrace-(no)vsx */ /* ptrace-(no)vsx */
int fpr_get(struct task_struct *target, const struct user_regset *regset, user_regset_get2_fn fpr_get;
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
int fpr_set(struct task_struct *target, const struct user_regset *regset, int fpr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf); const void *kbuf, const void __user *ubuf);
...@@ -72,8 +71,7 @@ int fpr_set(struct task_struct *target, const struct user_regset *regset, ...@@ -72,8 +71,7 @@ int fpr_set(struct task_struct *target, const struct user_regset *regset,
/* ptrace-vsx */ /* ptrace-vsx */
int vsr_active(struct task_struct *target, const struct user_regset *regset); int vsr_active(struct task_struct *target, const struct user_regset *regset);
int vsr_get(struct task_struct *target, const struct user_regset *regset, user_regset_get2_fn vsr_get;
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
int vsr_set(struct task_struct *target, const struct user_regset *regset, int vsr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf); const void *kbuf, const void __user *ubuf);
...@@ -81,8 +79,7 @@ int vsr_set(struct task_struct *target, const struct user_regset *regset, ...@@ -81,8 +79,7 @@ int vsr_set(struct task_struct *target, const struct user_regset *regset,
/* ptrace-altivec */ /* ptrace-altivec */
int vr_active(struct task_struct *target, const struct user_regset *regset); int vr_active(struct task_struct *target, const struct user_regset *regset);
int vr_get(struct task_struct *target, const struct user_regset *regset, user_regset_get2_fn vr_get;
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
int vr_set(struct task_struct *target, const struct user_regset *regset, int vr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf); const void *kbuf, const void __user *ubuf);
...@@ -90,8 +87,7 @@ int vr_set(struct task_struct *target, const struct user_regset *regset, ...@@ -90,8 +87,7 @@ int vr_set(struct task_struct *target, const struct user_regset *regset,
/* ptrace-spe */ /* ptrace-spe */
int evr_active(struct task_struct *target, const struct user_regset *regset); int evr_active(struct task_struct *target, const struct user_regset *regset);
int evr_get(struct task_struct *target, const struct user_regset *regset, user_regset_get2_fn evr_get;
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
int evr_set(struct task_struct *target, const struct user_regset *regset, int evr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf); const void *kbuf, const void __user *ubuf);
...@@ -100,9 +96,8 @@ int evr_set(struct task_struct *target, const struct user_regset *regset, ...@@ -100,9 +96,8 @@ int evr_set(struct task_struct *target, const struct user_regset *regset,
int gpr32_get_common(struct task_struct *target, int gpr32_get_common(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to,
void *kbuf, void __user *ubuf, unsigned long *regs);
unsigned long *regs);
int gpr32_set_common(struct task_struct *target, int gpr32_set_common(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
...@@ -118,55 +113,46 @@ static inline void flush_tmregs_to_thread(struct task_struct *tsk) { } ...@@ -118,55 +113,46 @@ static inline void flush_tmregs_to_thread(struct task_struct *tsk) { }
#endif #endif
int tm_cgpr_active(struct task_struct *target, const struct user_regset *regset); 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, user_regset_get2_fn tm_cgpr_get;
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
int tm_cgpr_set(struct task_struct *target, const struct user_regset *regset, int tm_cgpr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf); const void *kbuf, const void __user *ubuf);
int tm_cfpr_active(struct task_struct *target, const struct user_regset *regset); 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, user_regset_get2_fn tm_cfpr_get;
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
int tm_cfpr_set(struct task_struct *target, const struct user_regset *regset, int tm_cfpr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf); const void *kbuf, const void __user *ubuf);
int tm_cvmx_active(struct task_struct *target, const struct user_regset *regset); 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, user_regset_get2_fn tm_cvmx_get;
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
int tm_cvmx_set(struct task_struct *target, const struct user_regset *regset, int tm_cvmx_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf); const void *kbuf, const void __user *ubuf);
int tm_cvsx_active(struct task_struct *target, const struct user_regset *regset); 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, user_regset_get2_fn tm_cvsx_get;
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
int tm_cvsx_set(struct task_struct *target, const struct user_regset *regset, int tm_cvsx_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf); const void *kbuf, const void __user *ubuf);
int tm_spr_active(struct task_struct *target, const struct user_regset *regset); 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, user_regset_get2_fn tm_spr_get;
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
int tm_spr_set(struct task_struct *target, const struct user_regset *regset, int tm_spr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf); const void *kbuf, const void __user *ubuf);
int tm_tar_active(struct task_struct *target, const struct user_regset *regset); 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, user_regset_get2_fn tm_tar_get;
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
int tm_tar_set(struct task_struct *target, const struct user_regset *regset, int tm_tar_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf); const void *kbuf, const void __user *ubuf);
int tm_ppr_active(struct task_struct *target, const struct user_regset *regset); 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, user_regset_get2_fn tm_ppr_get;
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
int tm_ppr_set(struct task_struct *target, const struct user_regset *regset, int tm_ppr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf); const void *kbuf, const void __user *ubuf);
int tm_dscr_active(struct task_struct *target, const struct user_regset *regset); 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, user_regset_get2_fn tm_dscr_get;
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
int tm_dscr_set(struct task_struct *target, const struct user_regset *regset, int tm_dscr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf); const void *kbuf, const void __user *ubuf);
int tm_cgpr32_get(struct task_struct *target, const struct user_regset *regset, user_regset_get2_fn tm_cgpr32_get;
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
int tm_cgpr32_set(struct task_struct *target, const struct user_regset *regset, int tm_cgpr32_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf); const void *kbuf, const void __user *ubuf);
......
...@@ -19,15 +19,14 @@ ...@@ -19,15 +19,14 @@
* }; * };
*/ */
int fpr_get(struct task_struct *target, const struct user_regset *regset, 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) != BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
offsetof(struct thread_fp_state, fpr[32])); offsetof(struct thread_fp_state, fpr[32]));
flush_fp_to_thread(target); flush_fp_to_thread(target);
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, return membuf_write(&to, &target->thread.fp_state, 33 * sizeof(u64));
&target->thread.fp_state, 0, -1);
} }
/* /*
......
...@@ -23,25 +23,17 @@ int evr_active(struct task_struct *target, const struct user_regset *regset) ...@@ -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, 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); flush_spe_to_thread(target);
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, membuf_write(&to, &target->thread.evr, sizeof(target->thread.evr));
&target->thread.evr,
0, sizeof(target->thread.evr));
BUILD_BUG_ON(offsetof(struct thread_struct, acc) + sizeof(u64) != BUILD_BUG_ON(offsetof(struct thread_struct, acc) + sizeof(u64) !=
offsetof(struct thread_struct, spefscr)); offsetof(struct thread_struct, spefscr));
if (!ret) return membuf_write(&to, &target->thread.acc,
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, sizeof(u64) + sizeof(u32));
&target->thread.acc,
sizeof(target->thread.evr), -1);
return ret;
} }
int evr_set(struct task_struct *target, const struct user_regset *regset, int evr_set(struct task_struct *target, const struct user_regset *regset,
......
This diff is collapsed.
This diff is collapsed.
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
* }; * };
*/ */
int fpr_get(struct task_struct *target, const struct user_regset *regset, 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]; u64 buf[33];
int i; int i;
...@@ -30,7 +30,7 @@ int fpr_get(struct task_struct *target, const struct user_regset *regset, ...@@ -30,7 +30,7 @@ int fpr_get(struct task_struct *target, const struct user_regset *regset,
for (i = 0; i < 32 ; i++) for (i = 0; i < 32 ; i++)
buf[i] = target->thread.TS_FPR(i); buf[i] = target->thread.TS_FPR(i);
buf[32] = target->thread.fp_state.fpscr; 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) ...@@ -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, 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]; u64 buf[32];
int ret, i; int i;
flush_tmregs_to_thread(target); flush_tmregs_to_thread(target);
flush_fp_to_thread(target); flush_fp_to_thread(target);
...@@ -108,10 +108,7 @@ int vsr_get(struct task_struct *target, const struct user_regset *regset, ...@@ -108,10 +108,7 @@ int vsr_get(struct task_struct *target, const struct user_regset *regset,
for (i = 0; i < 32 ; i++) for (i = 0; i < 32 ; i++)
buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET]; buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, return membuf_write(&to, buf, 32 * sizeof(double));
buf, 0, 32 * sizeof(double));
return ret;
} }
/* /*
......
...@@ -30,13 +30,10 @@ enum riscv_regset { ...@@ -30,13 +30,10 @@ enum riscv_regset {
static int riscv_gpr_get(struct task_struct *target, static int riscv_gpr_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
struct pt_regs *regs; return membuf_write(&to, task_pt_regs(target),
sizeof(struct user_regs_struct));
regs = task_pt_regs(target);
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
} }
static int riscv_gpr_set(struct task_struct *target, static int riscv_gpr_set(struct task_struct *target,
...@@ -55,21 +52,13 @@ static int riscv_gpr_set(struct task_struct *target, ...@@ -55,21 +52,13 @@ static int riscv_gpr_set(struct task_struct *target,
#ifdef CONFIG_FPU #ifdef CONFIG_FPU
static int riscv_fpr_get(struct task_struct *target, static int riscv_fpr_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
int ret;
struct __riscv_d_ext_state *fstate = &target->thread.fstate; struct __riscv_d_ext_state *fstate = &target->thread.fstate;
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, fstate, 0, membuf_write(&to, fstate, offsetof(struct __riscv_d_ext_state, fcsr));
offsetof(struct __riscv_d_ext_state, fcsr)); membuf_store(&to, fstate->fcsr);
if (!ret) { return membuf_zero(&to, 4); // explicitly pad
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, fstate, 0,
offsetof(struct __riscv_d_ext_state, fcsr) +
sizeof(fstate->fcsr));
}
return ret;
} }
static int riscv_fpr_set(struct task_struct *target, static int riscv_fpr_set(struct task_struct *target,
...@@ -98,8 +87,8 @@ static const struct user_regset riscv_user_regset[] = { ...@@ -98,8 +87,8 @@ static const struct user_regset riscv_user_regset[] = {
.n = ELF_NGREG, .n = ELF_NGREG,
.size = sizeof(elf_greg_t), .size = sizeof(elf_greg_t),
.align = sizeof(elf_greg_t), .align = sizeof(elf_greg_t),
.get = &riscv_gpr_get, .regset_get = riscv_gpr_get,
.set = &riscv_gpr_set, .set = riscv_gpr_set,
}, },
#ifdef CONFIG_FPU #ifdef CONFIG_FPU
[REGSET_F] = { [REGSET_F] = {
...@@ -107,8 +96,8 @@ static const struct user_regset riscv_user_regset[] = { ...@@ -107,8 +96,8 @@ static const struct user_regset riscv_user_regset[] = {
.n = ELF_NFPREG, .n = ELF_NFPREG,
.size = sizeof(elf_fpreg_t), .size = sizeof(elf_fpreg_t),
.align = sizeof(elf_fpreg_t), .align = sizeof(elf_fpreg_t),
.get = &riscv_fpr_get, .regset_get = riscv_fpr_get,
.set = &riscv_fpr_set, .set = riscv_fpr_set,
}, },
#endif #endif
}; };
......
This diff is collapsed.
...@@ -103,9 +103,8 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) ...@@ -103,9 +103,8 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
fpvalid = !!tsk_used_math(tsk); fpvalid = !!tsk_used_math(tsk);
if (fpvalid) if (fpvalid)
fpvalid = !fpregs_get(tsk, NULL, 0, fpvalid = !fpregs_get(tsk, NULL,
sizeof(struct user_fpu_struct), (struct membuf){fpu, sizeof(*fpu)});
fpu, NULL);
#endif #endif
return fpvalid; return fpvalid;
......
...@@ -134,26 +134,11 @@ void ptrace_disable(struct task_struct *child) ...@@ -134,26 +134,11 @@ void ptrace_disable(struct task_struct *child)
static int genregs_get(struct task_struct *target, static int genregs_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
const struct pt_regs *regs = task_pt_regs(target); const struct pt_regs *regs = task_pt_regs(target);
int ret;
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, return membuf_write(&to, regs, sizeof(struct pt_regs));
regs->regs,
0, 16 * sizeof(unsigned long));
if (!ret)
/* PC, PR, SR, GBR, MACH, MACL, TRA */
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&regs->pc,
offsetof(struct pt_regs, pc),
sizeof(struct pt_regs));
if (!ret)
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
sizeof(struct pt_regs), -1);
return ret;
} }
static int genregs_set(struct task_struct *target, static int genregs_set(struct task_struct *target,
...@@ -182,8 +167,7 @@ static int genregs_set(struct task_struct *target, ...@@ -182,8 +167,7 @@ static int genregs_set(struct task_struct *target,
#ifdef CONFIG_SH_FPU #ifdef CONFIG_SH_FPU
int fpregs_get(struct task_struct *target, int fpregs_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
int ret; int ret;
...@@ -191,12 +175,8 @@ int fpregs_get(struct task_struct *target, ...@@ -191,12 +175,8 @@ int fpregs_get(struct task_struct *target,
if (ret) if (ret)
return ret; return ret;
if ((boot_cpu_data.flags & CPU_HAS_FPU)) return membuf_write(&to, target->thread.xstate,
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, sizeof(struct user_fpu_struct));
&target->thread.xstate->hardfpu, 0, -1);
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&target->thread.xstate->softfpu, 0, -1);
} }
static int fpregs_set(struct task_struct *target, static int fpregs_set(struct task_struct *target,
...@@ -230,20 +210,12 @@ static int fpregs_active(struct task_struct *target, ...@@ -230,20 +210,12 @@ static int fpregs_active(struct task_struct *target,
#ifdef CONFIG_SH_DSP #ifdef CONFIG_SH_DSP
static int dspregs_get(struct task_struct *target, static int dspregs_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
const struct pt_dspregs *regs = const struct pt_dspregs *regs =
(struct pt_dspregs *)&target->thread.dsp_status.dsp_regs; (struct pt_dspregs *)&target->thread.dsp_status.dsp_regs;
int ret;
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, return membuf_write(&to, regs, sizeof(struct pt_dspregs));
0, sizeof(struct pt_dspregs));
if (!ret)
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
sizeof(struct pt_dspregs), -1);
return ret;
} }
static int dspregs_set(struct task_struct *target, static int dspregs_set(struct task_struct *target,
...@@ -324,7 +296,7 @@ static const struct user_regset sh_regsets[] = { ...@@ -324,7 +296,7 @@ static const struct user_regset sh_regsets[] = {
.n = ELF_NGREG, .n = ELF_NGREG,
.size = sizeof(long), .size = sizeof(long),
.align = sizeof(long), .align = sizeof(long),
.get = genregs_get, .regset_get = genregs_get,
.set = genregs_set, .set = genregs_set,
}, },
...@@ -334,7 +306,7 @@ static const struct user_regset sh_regsets[] = { ...@@ -334,7 +306,7 @@ static const struct user_regset sh_regsets[] = {
.n = sizeof(struct user_fpu_struct) / sizeof(long), .n = sizeof(struct user_fpu_struct) / sizeof(long),
.size = sizeof(long), .size = sizeof(long),
.align = sizeof(long), .align = sizeof(long),
.get = fpregs_get, .regset_get = fpregs_get,
.set = fpregs_set, .set = fpregs_set,
.active = fpregs_active, .active = fpregs_active,
}, },
...@@ -345,7 +317,7 @@ static const struct user_regset sh_regsets[] = { ...@@ -345,7 +317,7 @@ static const struct user_regset sh_regsets[] = {
.n = sizeof(struct pt_dspregs) / sizeof(long), .n = sizeof(struct pt_dspregs) / sizeof(long),
.size = sizeof(long), .size = sizeof(long),
.align = sizeof(long), .align = sizeof(long),
.get = dspregs_get, .regset_get = dspregs_get,
.set = dspregs_set, .set = dspregs_set,
.active = dspregs_active, .active = dspregs_active,
}, },
......
...@@ -83,41 +83,25 @@ static int regwindow32_set(struct task_struct *target, ...@@ -83,41 +83,25 @@ static int regwindow32_set(struct task_struct *target,
static int genregs32_get(struct task_struct *target, static int genregs32_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
const struct pt_regs *regs = target->thread.kregs; const struct pt_regs *regs = target->thread.kregs;
u32 uregs[16]; u32 uregs[16];
int ret;
if (target == current) if (target == current)
flush_user_windows(); flush_user_windows();
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, membuf_write(&to, regs->u_regs, 16 * sizeof(u32));
regs->u_regs, if (!to.left)
0, 16 * sizeof(u32)); return 0;
if (ret || !count) if (regwindow32_get(target, regs, uregs))
return ret; return -EFAULT;
membuf_write(&to, uregs, 16 * sizeof(u32));
if (pos < 32 * sizeof(u32)) { membuf_store(&to, regs->psr);
if (regwindow32_get(target, regs, uregs)) membuf_store(&to, regs->pc);
return -EFAULT; membuf_store(&to, regs->npc);
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, membuf_store(&to, regs->y);
uregs, return membuf_zero(&to, 2 * sizeof(u32));
16 * sizeof(u32), 32 * sizeof(u32));
if (ret || !count)
return ret;
}
uregs[0] = regs->psr;
uregs[1] = regs->pc;
uregs[2] = regs->npc;
uregs[3] = regs->y;
uregs[4] = 0; /* WIM */
uregs[5] = 0; /* TBR */
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
uregs,
32 * sizeof(u32), 38 * sizeof(u32));
} }
static int genregs32_set(struct task_struct *target, static int genregs32_set(struct task_struct *target,
...@@ -139,19 +123,18 @@ static int genregs32_set(struct task_struct *target, ...@@ -139,19 +123,18 @@ static int genregs32_set(struct task_struct *target,
if (ret || !count) if (ret || !count)
return ret; return ret;
if (pos < 32 * sizeof(u32)) { if (regwindow32_get(target, regs, uregs))
if (regwindow32_get(target, regs, uregs)) return -EFAULT;
return -EFAULT; ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs,
uregs, 16 * sizeof(u32), 32 * sizeof(u32));
16 * sizeof(u32), 32 * sizeof(u32)); if (ret)
if (ret) return ret;
return ret; if (regwindow32_set(target, regs, uregs))
if (regwindow32_set(target, regs, uregs)) return -EFAULT;
return -EFAULT; if (!count)
if (!count) return 0;
return 0;
}
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&psr, &psr,
32 * sizeof(u32), 33 * sizeof(u32)); 32 * sizeof(u32), 33 * sizeof(u32));
...@@ -182,46 +165,18 @@ static int genregs32_set(struct task_struct *target, ...@@ -182,46 +165,18 @@ static int genregs32_set(struct task_struct *target,
static int fpregs32_get(struct task_struct *target, static int fpregs32_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
const unsigned long *fpregs = target->thread.float_regs;
int ret = 0;
#if 0 #if 0
if (target == current) if (target == current)
save_and_clear_fpu(); save_and_clear_fpu();
#endif #endif
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, membuf_write(&to, target->thread.float_regs, 32 * sizeof(u32));
fpregs, membuf_zero(&to, sizeof(u32));
0, 32 * sizeof(u32)); membuf_write(&to, &target->thread.fsr, sizeof(u32));
membuf_store(&to, (u32)((1 << 8) | (8 << 16)));
if (!ret) return membuf_zero(&to, 64 * sizeof(u32));
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
32 * sizeof(u32),
33 * sizeof(u32));
if (!ret)
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&target->thread.fsr,
33 * sizeof(u32),
34 * sizeof(u32));
if (!ret) {
unsigned long val;
val = (1 << 8) | (8 << 16);
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&val,
34 * sizeof(u32),
35 * sizeof(u32));
}
if (!ret)
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
35 * sizeof(u32), -1);
return ret;
} }
static int fpregs32_set(struct task_struct *target, static int fpregs32_set(struct task_struct *target,
...@@ -243,13 +198,11 @@ static int fpregs32_set(struct task_struct *target, ...@@ -243,13 +198,11 @@ static int fpregs32_set(struct task_struct *target,
user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
32 * sizeof(u32), 32 * sizeof(u32),
33 * sizeof(u32)); 33 * sizeof(u32));
if (!ret && count > 0) { if (!ret)
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&target->thread.fsr, &target->thread.fsr,
33 * sizeof(u32), 33 * sizeof(u32),
34 * sizeof(u32)); 34 * sizeof(u32));
}
if (!ret) if (!ret)
ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
34 * sizeof(u32), -1); 34 * sizeof(u32), -1);
...@@ -268,7 +221,7 @@ static const struct user_regset sparc32_regsets[] = { ...@@ -268,7 +221,7 @@ static const struct user_regset sparc32_regsets[] = {
.core_note_type = NT_PRSTATUS, .core_note_type = NT_PRSTATUS,
.n = 38, .n = 38,
.size = sizeof(u32), .align = sizeof(u32), .size = sizeof(u32), .align = sizeof(u32),
.get = genregs32_get, .set = genregs32_set .regset_get = genregs32_get, .set = genregs32_set
}, },
/* Format is: /* Format is:
* F0 --> F31 * F0 --> F31
...@@ -284,10 +237,104 @@ static const struct user_regset sparc32_regsets[] = { ...@@ -284,10 +237,104 @@ static const struct user_regset sparc32_regsets[] = {
.core_note_type = NT_PRFPREG, .core_note_type = NT_PRFPREG,
.n = 99, .n = 99,
.size = sizeof(u32), .align = sizeof(u32), .size = sizeof(u32), .align = sizeof(u32),
.get = fpregs32_get, .set = fpregs32_set .regset_get = fpregs32_get, .set = fpregs32_set
},
};
static int getregs_get(struct task_struct *target,
const struct user_regset *regset,
struct membuf to)
{
const struct pt_regs *regs = target->thread.kregs;
if (target == current)
flush_user_windows();
membuf_store(&to, regs->psr);
membuf_store(&to, regs->pc);
membuf_store(&to, regs->npc);
membuf_store(&to, regs->y);
return membuf_write(&to, regs->u_regs + 1, 15 * sizeof(u32));
}
static int setregs_set(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf)
{
struct pt_regs *regs = target->thread.kregs;
u32 v[4];
int ret;
if (target == current)
flush_user_windows();
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
v,
0, 4 * sizeof(u32));
if (ret)
return ret;
regs->psr = (regs->psr & ~(PSR_ICC | PSR_SYSCALL)) |
(v[0] & (PSR_ICC | PSR_SYSCALL));
regs->pc = v[1];
regs->npc = v[2];
regs->y = v[3];
return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
regs->u_regs + 1,
4 * sizeof(u32) , 19 * sizeof(u32));
}
static int getfpregs_get(struct task_struct *target,
const struct user_regset *regset,
struct membuf to)
{
#if 0
if (target == current)
save_and_clear_fpu();
#endif
membuf_write(&to, &target->thread.float_regs, 32 * sizeof(u32));
membuf_write(&to, &target->thread.fsr, sizeof(u32));
return membuf_zero(&to, 35 * sizeof(u32));
}
static int setfpregs_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 *fpregs = target->thread.float_regs;
int ret;
#if 0
if (target == current)
save_and_clear_fpu();
#endif
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
fpregs,
0, 32 * sizeof(u32));
if (ret)
return ret;
return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&target->thread.fsr,
32 * sizeof(u32),
33 * sizeof(u32));
}
static const struct user_regset ptrace32_regsets[] = {
[REGSET_GENERAL] = {
.n = 19, .size = sizeof(u32),
.regset_get = getregs_get, .set = setregs_set,
},
[REGSET_FP] = {
.n = 68, .size = sizeof(u32),
.regset_get = getfpregs_get, .set = setfpregs_set,
}, },
}; };
static const struct user_regset_view ptrace32_view = {
.regsets = ptrace32_regsets, .n = ARRAY_SIZE(ptrace32_regsets)
};
static const struct user_regset_view user_sparc32_view = { static const struct user_regset_view user_sparc32_view = {
.name = "sparc", .e_machine = EM_SPARC, .name = "sparc", .e_machine = EM_SPARC,
.regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets) .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
...@@ -315,74 +362,44 @@ long arch_ptrace(struct task_struct *child, long request, ...@@ -315,74 +362,44 @@ long arch_ptrace(struct task_struct *child, long request,
{ {
unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4]; unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4];
void __user *addr2p; void __user *addr2p;
const struct user_regset_view *view;
struct pt_regs __user *pregs; struct pt_regs __user *pregs;
struct fps __user *fps; struct fps __user *fps;
int ret; int ret;
view = task_user_regset_view(current);
addr2p = (void __user *) addr2; addr2p = (void __user *) addr2;
pregs = (struct pt_regs __user *) addr; pregs = (struct pt_regs __user *) addr;
fps = (struct fps __user *) addr; fps = (struct fps __user *) addr;
switch(request) { switch(request) {
case PTRACE_GETREGS: { case PTRACE_GETREGS: {
ret = copy_regset_to_user(child, view, REGSET_GENERAL, ret = copy_regset_to_user(child, &ptrace32_view,
32 * sizeof(u32), REGSET_GENERAL, 0,
4 * sizeof(u32), 19 * sizeof(u32),
&pregs->psr); pregs);
if (!ret)
copy_regset_to_user(child, view, REGSET_GENERAL,
1 * sizeof(u32),
15 * sizeof(u32),
&pregs->u_regs[0]);
break; break;
} }
case PTRACE_SETREGS: { case PTRACE_SETREGS: {
ret = copy_regset_from_user(child, view, REGSET_GENERAL, ret = copy_regset_from_user(child, &ptrace32_view,
32 * sizeof(u32), REGSET_GENERAL, 0,
4 * sizeof(u32), 19 * sizeof(u32),
&pregs->psr); pregs);
if (!ret)
copy_regset_from_user(child, view, REGSET_GENERAL,
1 * sizeof(u32),
15 * sizeof(u32),
&pregs->u_regs[0]);
break; break;
} }
case PTRACE_GETFPREGS: { case PTRACE_GETFPREGS: {
ret = copy_regset_to_user(child, view, REGSET_FP, ret = copy_regset_to_user(child, &ptrace32_view,
0 * sizeof(u32), REGSET_FP, 0,
32 * sizeof(u32), 68 * sizeof(u32),
&fps->regs[0]); fps);
if (!ret)
ret = copy_regset_to_user(child, view, REGSET_FP,
33 * sizeof(u32),
1 * sizeof(u32),
&fps->fsr);
if (!ret) {
if (__put_user(0, &fps->fpqd) ||
__put_user(0, &fps->flags) ||
__put_user(0, &fps->extra) ||
clear_user(fps->fpq, sizeof(fps->fpq)))
ret = -EFAULT;
}
break; break;
} }
case PTRACE_SETFPREGS: { case PTRACE_SETFPREGS: {
ret = copy_regset_from_user(child, view, REGSET_FP, ret = copy_regset_from_user(child, &ptrace32_view,
0 * sizeof(u32), REGSET_FP, 0,
32 * sizeof(u32), 33 * sizeof(u32),
&fps->regs[0]); fps);
if (!ret)
ret = copy_regset_from_user(child, view, REGSET_FP,
33 * sizeof(u32),
1 * sizeof(u32),
&fps->fsr);
break; break;
} }
......
This diff is collapsed.
...@@ -34,7 +34,6 @@ extern int fpu__copy(struct task_struct *dst, struct task_struct *src); ...@@ -34,7 +34,6 @@ extern int fpu__copy(struct task_struct *dst, struct task_struct *src);
extern void fpu__clear_user_states(struct fpu *fpu); extern void fpu__clear_user_states(struct fpu *fpu);
extern void fpu__clear_all(struct fpu *fpu); extern void fpu__clear_all(struct fpu *fpu);
extern int fpu__exception_code(struct fpu *fpu, int trap_nr); extern int fpu__exception_code(struct fpu *fpu, int trap_nr);
extern int dump_fpu(struct pt_regs *ptregs, struct user_i387_struct *fpstate);
/* /*
* Boot time FPU initialization functions: * Boot time FPU initialization functions:
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
#include <linux/regset.h> #include <linux/regset.h>
extern user_regset_active_fn regset_fpregs_active, regset_xregset_fpregs_active; extern user_regset_active_fn regset_fpregs_active, regset_xregset_fpregs_active;
extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get, extern user_regset_get2_fn fpregs_get, xfpregs_get, fpregs_soft_get,
xstateregs_get; xstateregs_get;
extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set, extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set,
xstateregs_set; xstateregs_set;
......
...@@ -104,8 +104,8 @@ void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr); ...@@ -104,8 +104,8 @@ void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr);
const void *get_xsave_field_ptr(int xfeature_nr); const void *get_xsave_field_ptr(int xfeature_nr);
int using_compacted_format(void); int using_compacted_format(void);
int xfeature_size(int xfeature_nr); int xfeature_size(int xfeature_nr);
int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int offset, unsigned int size); struct membuf;
int copy_xstate_to_user(void __user *ubuf, struct xregs_state *xsave, unsigned int offset, unsigned int size); void copy_xstate_to_kernel(struct membuf to, struct xregs_state *xsave);
int copy_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf); int copy_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf);
int copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf); int copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf);
void copy_supervisor_to_kernel(struct xregs_state *xsave); void copy_supervisor_to_kernel(struct xregs_state *xsave);
......
This diff is collapsed.
...@@ -170,14 +170,15 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size) ...@@ -170,14 +170,15 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
ia32_fxstate &= (IS_ENABLED(CONFIG_X86_32) || ia32_fxstate &= (IS_ENABLED(CONFIG_X86_32) ||
IS_ENABLED(CONFIG_IA32_EMULATION)); IS_ENABLED(CONFIG_IA32_EMULATION));
if (!static_cpu_has(X86_FEATURE_FPU)) {
struct user_i387_ia32_struct fp;
fpregs_soft_get(current, NULL, (struct membuf){.p = &fp,
.left = sizeof(fp)});
return copy_to_user(buf, &fp, sizeof(fp)) ? -EFAULT : 0;
}
if (!access_ok(buf, size)) if (!access_ok(buf, size))
return -EACCES; return -EACCES;
if (!static_cpu_has(X86_FEATURE_FPU))
return fpregs_soft_get(current, NULL, 0,
sizeof(struct user_i387_ia32_struct), NULL,
(struct _fpstate_32 __user *) buf) ? -1 : 1;
retry: retry:
/* /*
* Load the FPU registers if they are not valid for the current task. * Load the FPU registers if they are not valid for the current task.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment