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,76 +18,52 @@ static struct callee_regs *task_callee_regs(struct task_struct *tsk) ...@@ -18,76 +18,52 @@ 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);
membuf_store(&to, ptregs->r4);
membuf_store(&to, ptregs->r3);
membuf_store(&to, ptregs->r2);
membuf_store(&to, ptregs->r1);
membuf_store(&to, ptregs->r0);
membuf_store(&to, ptregs->sp);
membuf_zero(&to, 4); // pad2
membuf_store(&to, cregs->r25);
membuf_store(&to, cregs->r24);
membuf_store(&to, cregs->r23);
membuf_store(&to, cregs->r22);
membuf_store(&to, cregs->r21);
membuf_store(&to, cregs->r20);
membuf_store(&to, cregs->r19);
membuf_store(&to, cregs->r18);
membuf_store(&to, cregs->r17);
membuf_store(&to, cregs->r16);
membuf_store(&to, cregs->r15);
membuf_store(&to, cregs->r14);
membuf_store(&to, cregs->r13);
membuf_store(&to, target->thread.fault_address); // efa
REG_O_ZERO(pad);
REG_O_ONE(scratch.bta, &ptregs->bta);
REG_O_ONE(scratch.lp_start, &ptregs->lp_start);
REG_O_ONE(scratch.lp_end, &ptregs->lp_end);
REG_O_ONE(scratch.lp_count, &ptregs->lp_count);
REG_O_ONE(scratch.status32, &ptregs->status32);
REG_O_ONE(scratch.ret, &ptregs->ret);
REG_O_ONE(scratch.blink, &ptregs->blink);
REG_O_ONE(scratch.fp, &ptregs->fp);
REG_O_ONE(scratch.gp, &ptregs->r26);
REG_O_ONE(scratch.r12, &ptregs->r12);
REG_O_ONE(scratch.r11, &ptregs->r11);
REG_O_ONE(scratch.r10, &ptregs->r10);
REG_O_ONE(scratch.r9, &ptregs->r9);
REG_O_ONE(scratch.r8, &ptregs->r8);
REG_O_ONE(scratch.r7, &ptregs->r7);
REG_O_ONE(scratch.r6, &ptregs->r6);
REG_O_ONE(scratch.r5, &ptregs->r5);
REG_O_ONE(scratch.r4, &ptregs->r4);
REG_O_ONE(scratch.r3, &ptregs->r3);
REG_O_ONE(scratch.r2, &ptregs->r2);
REG_O_ONE(scratch.r1, &ptregs->r1);
REG_O_ONE(scratch.r0, &ptregs->r0);
REG_O_ONE(scratch.sp, &ptregs->sp);
REG_O_ZERO(pad2);
REG_O_ONE(callee.r25, &cregs->r25);
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)) { if (in_brkpt_trap(ptregs)) {
stop_pc_val = target->thread.fault_address; stop_pc_val = target->thread.fault_address;
pr_debug("\t\tstop_pc (brk-pt)\n"); pr_debug("\t\tstop_pc (brk-pt)\n");
...@@ -96,10 +72,7 @@ static int genregs_get(struct task_struct *target, ...@@ -96,10 +72,7 @@ static int genregs_get(struct task_struct *target,
pr_debug("\t\tstop_pc (others)\n"); pr_debug("\t\tstop_pc (others)\n");
} }
REG_O_ONE(stop_pc, &stop_pc_val); return membuf_store(&to, stop_pc_val); // stop_pc
}
return ret;
} }
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
copy_sz = 4; /* r30 only */
/* /*
* itemized copy not needed like above as layout of regs (r30,r58,r59) * 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) * is exactly same in kernel (pt_regs) and userspace (user_regs_arcv2)
*/ */
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &regs->r30, return membuf_write(&to, &regs->r30, sizeof(struct user_regs_arcv2));
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);
count /= sizeof(reg);
if (kbuf) for (pos = 0; pos < ELF_NGREG; pos++)
for (; count > 0 && pos < ELF_NGREG; --count) membuf_store(&to, (compat_ulong_t)get_reg(regs, pos));
*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; return 0;
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));
if (!ret) {
/* /*
* Copy out only the low-order word of vrsave. * 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)); memset(&vrsave, 0, sizeof(vrsave));
vrsave.word = target->thread.vrsave; vrsave.word = target->thread.vrsave;
return membuf_write(&to, &vrsave, sizeof(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,8 +96,7 @@ int evr_set(struct task_struct *target, const struct user_regset *regset, ...@@ -100,8 +96,7 @@ 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,
...@@ -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,
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; return membuf_write(&to, regs, sizeof(struct pt_regs));
} }
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,
0, sizeof(struct pt_dspregs));
if (!ret)
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
sizeof(struct pt_dspregs), -1);
return ret; return membuf_write(&to, regs, sizeof(struct pt_dspregs));
} }
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)
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_copyout(&pos, &count, &kbuf, &ubuf, membuf_write(&to, uregs, 16 * sizeof(u32));
uregs, membuf_store(&to, regs->psr);
16 * sizeof(u32), 32 * sizeof(u32)); membuf_store(&to, regs->pc);
if (ret || !count) membuf_store(&to, regs->npc);
return ret; membuf_store(&to, regs->y);
} return membuf_zero(&to, 2 * sizeof(u32));
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,7 +123,6 @@ static int genregs32_set(struct task_struct *target, ...@@ -139,7 +123,6 @@ 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,
...@@ -151,7 +134,7 @@ static int genregs32_set(struct task_struct *target, ...@@ -151,7 +134,7 @@ static int genregs32_set(struct task_struct *target,
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,8 +237,102 @@ static const struct user_regset sparc32_regsets[] = { ...@@ -284,8 +237,102 @@ 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 = {
...@@ -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),
&fps->regs[0]);
if (!ret)
ret = copy_regset_from_user(child, view, REGSET_FP,
33 * sizeof(u32), 33 * sizeof(u32),
1 * sizeof(u32), fps);
&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,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#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.
...@@ -256,36 +256,16 @@ int regset_tls_active(struct task_struct *target, ...@@ -256,36 +256,16 @@ int regset_tls_active(struct task_struct *target,
} }
int regset_tls_get(struct task_struct *target, const struct user_regset *regset, int regset_tls_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
const struct desc_struct *tls; const struct desc_struct *tls;
struct user_desc v;
int pos;
if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) || for (pos = 0, tls = target->thread.tls_array; to.left; pos++, tls++) {
(pos % sizeof(struct user_desc)) != 0 || fill_user_desc(&v, GDT_ENTRY_TLS_MIN + pos, tls);
(count % sizeof(struct user_desc)) != 0) membuf_write(&to, &v, sizeof(v));
return -EINVAL;
pos /= sizeof(struct user_desc);
count /= sizeof(struct user_desc);
tls = &target->thread.tls_array[pos];
if (kbuf) {
struct user_desc *info = kbuf;
while (count-- > 0)
fill_user_desc(info++, GDT_ENTRY_TLS_MIN + pos++,
tls++);
} else {
struct user_desc __user *u_info = ubuf;
while (count-- > 0) {
struct user_desc info;
fill_user_desc(&info, GDT_ENTRY_TLS_MIN + pos++, tls++);
if (__copy_to_user(u_info++, &info, sizeof(info)))
return -EFAULT;
}
} }
return 0; return 0;
} }
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <linux/regset.h> #include <linux/regset.h>
extern user_regset_active_fn regset_tls_active; extern user_regset_active_fn regset_tls_active;
extern user_regset_get_fn regset_tls_get; extern user_regset_get2_fn regset_tls_get;
extern user_regset_set_fn regset_tls_set; extern user_regset_set_fn regset_tls_set;
#endif /* _ARCH_X86_KERNEL_TLS_H */ #endif /* _ARCH_X86_KERNEL_TLS_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -10,7 +10,7 @@ obj-y = fork.o exec_domain.o panic.o \ ...@@ -10,7 +10,7 @@ obj-y = fork.o exec_domain.o panic.o \
extable.o params.o \ extable.o params.o \
kthread.o sys_ni.o nsproxy.o \ kthread.o sys_ni.o nsproxy.o \
notifier.o ksysfs.o cred.o reboot.o \ notifier.o ksysfs.o cred.o reboot.o \
async.o range.o smpboot.o ucount.o async.o range.o smpboot.o ucount.o regset.o
obj-$(CONFIG_BPFILTER) += usermode_driver.o obj-$(CONFIG_BPFILTER) += usermode_driver.o
obj-$(CONFIG_MODULES) += kmod.o obj-$(CONFIG_MODULES) += kmod.o
......
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