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)
static int genregs_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
const struct pt_regs *ptregs = task_pt_regs(target);
const struct callee_regs *cregs = task_callee_regs(target);
int ret = 0;
unsigned int stop_pc_val;
#define REG_O_CHUNK(START, END, PTR) \
if (!ret) \
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, PTR, \
offsetof(struct user_regs_struct, START), \
offsetof(struct user_regs_struct, END));
#define REG_O_ONE(LOC, PTR) \
if (!ret) \
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, PTR, \
offsetof(struct user_regs_struct, LOC), \
offsetof(struct user_regs_struct, LOC) + 4);
#define REG_O_ZERO(LOC) \
if (!ret) \
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, \
offsetof(struct user_regs_struct, LOC), \
offsetof(struct user_regs_struct, LOC) + 4);
membuf_zero(&to, 4); // pad
membuf_store(&to, ptregs->bta);
membuf_store(&to, ptregs->lp_start);
membuf_store(&to, ptregs->lp_end);
membuf_store(&to, ptregs->lp_count);
membuf_store(&to, ptregs->status32);
membuf_store(&to, ptregs->ret);
membuf_store(&to, ptregs->blink);
membuf_store(&to, ptregs->fp);
membuf_store(&to, ptregs->r26); // gp
membuf_store(&to, ptregs->r12);
membuf_store(&to, ptregs->r11);
membuf_store(&to, ptregs->r10);
membuf_store(&to, ptregs->r9);
membuf_store(&to, ptregs->r8);
membuf_store(&to, ptregs->r7);
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)) {
stop_pc_val = target->thread.fault_address;
pr_debug("\t\tstop_pc (brk-pt)\n");
......@@ -96,10 +72,7 @@ static int genregs_get(struct task_struct *target,
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,
......@@ -184,25 +157,20 @@ static int genregs_set(struct task_struct *target,
#ifdef CONFIG_ISA_ARCV2
static int arcv2regs_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
const struct pt_regs *regs = task_pt_regs(target);
int ret, copy_sz;
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)
* 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 membuf_write(&to, &regs->r30, sizeof(struct user_regs_arcv2));
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,
......@@ -237,7 +205,7 @@ static const struct user_regset arc_regsets[] = {
.n = ELF_NGREG,
.size = sizeof(unsigned long),
.align = sizeof(unsigned long),
.get = genregs_get,
.regset_get = genregs_get,
.set = genregs_set,
},
#ifdef CONFIG_ISA_ARCV2
......@@ -246,7 +214,7 @@ static const struct user_regset arc_regsets[] = {
.n = ELF_ARCV2REG,
.size = sizeof(unsigned long),
.align = sizeof(unsigned long),
.get = arcv2regs_get,
.regset_get = arcv2regs_get,
.set = arcv2regs_set,
},
#endif
......
......@@ -569,14 +569,9 @@ static int ptrace_sethbpregs(struct task_struct *tsk, long num,
static int gpr_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
struct pt_regs *regs = task_pt_regs(target);
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
regs,
0, sizeof(*regs));
return membuf_write(&to, task_pt_regs(target), sizeof(struct pt_regs));
}
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,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&task_thread_info(target)->fpstate,
0, sizeof(struct user_fp));
return membuf_write(&to, &task_thread_info(target)->fpstate,
sizeof(struct user_fp));
}
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
*
* 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,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
int ret;
struct thread_info *thread = task_thread_info(target);
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);
vfp_sync_hwstate(thread);
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&vfp->fpregs,
user_fpregs_offset,
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));
membuf_write(&to, vfp->fpregs, sizeof(vfp->fpregs));
membuf_zero(&to, user_fpscr_offset - sizeof(vfp->fpregs));
return membuf_store(&to, vfp->fpscr);
}
/*
......@@ -739,7 +711,7 @@ static const struct user_regset arm_regsets[] = {
.n = ELF_NGREG,
.size = sizeof(u32),
.align = sizeof(u32),
.get = gpr_get,
.regset_get = gpr_get,
.set = gpr_set
},
[REGSET_FPR] = {
......@@ -751,7 +723,7 @@ static const struct user_regset arm_regsets[] = {
.n = sizeof(struct user_fp) / sizeof(u32),
.size = sizeof(u32),
.align = sizeof(u32),
.get = fpa_get,
.regset_get = fpa_get,
.set = fpa_set
},
#ifdef CONFIG_VFP
......@@ -764,7 +736,7 @@ static const struct user_regset arm_regsets[] = {
.n = ARM_VFPREGS_SIZE / sizeof(u32),
.size = sizeof(u32),
.align = sizeof(u32),
.get = vfp_get,
.regset_get = vfp_get,
.set = vfp_set
},
#endif /* CONFIG_VFP */
......
This diff is collapsed.
......@@ -57,14 +57,9 @@ static inline int put_reg(struct task_struct *task,
static int gpr_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
struct pt_regs *regs = task_pt_regs(target);
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
regs,
0, sizeof(*regs));
return membuf_write(&to, task_pt_regs(target), sizeof(struct pt_regs));
}
enum c6x_regset {
......@@ -77,7 +72,7 @@ static const struct user_regset c6x_regsets[] = {
.n = ELF_NGREG,
.size = sizeof(u32),
.align = sizeof(u32),
.get = gpr_get,
.regset_get = gpr_get,
},
};
......
......@@ -76,17 +76,14 @@ enum csky_regset {
static int gpr_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
struct pt_regs *regs;
regs = task_pt_regs(target);
struct pt_regs *regs = task_pt_regs(target);
/* Abiv1 regs->tls is fake and we need sync here. */
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,
......@@ -114,8 +111,7 @@ static int gpr_set(struct task_struct *target,
static 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)
{
struct user_fp *regs = (struct user_fp *)&target->thread.user_fp;
......@@ -131,9 +127,9 @@ static int fpr_get(struct task_struct *target,
for (i = 0; i < 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
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
return membuf_write(&to, regs, sizeof(*regs));
#endif
}
......@@ -173,16 +169,16 @@ static const struct user_regset csky_regsets[] = {
.n = sizeof(struct pt_regs) / sizeof(u32),
.size = sizeof(u32),
.align = sizeof(u32),
.get = &gpr_get,
.set = &gpr_set,
.regset_get = gpr_get,
.set = gpr_set,
},
[REGSET_FPR] = {
.core_note_type = NT_PRFPREG,
.n = sizeof(struct user_fp) / sizeof(u32),
.size = sizeof(u32),
.align = sizeof(u32),
.get = &fpr_get,
.set = &fpr_set,
.regset_get = fpr_get,
.set = fpr_set,
},
};
......
......@@ -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,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
int r;
struct user_regs_struct regs;
long *reg = (long *)&regs;
/* build user regs in buffer */
BUILD_BUG_ON(sizeof(regs) % sizeof(long) != 0);
for (r = 0; r < sizeof(regs) / sizeof(long); r++)
*reg++ = h8300_get_reg(target, r);
BUILD_BUG_ON(sizeof(struct user_regs_struct) % sizeof(long) != 0);
for (r = 0; r < ELF_NGREG; r++)
membuf_store(&to, h8300_get_reg(target, r));
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&regs, 0, sizeof(regs));
return 0;
}
static int regs_set(struct task_struct *target,
......@@ -139,7 +134,7 @@ static const struct user_regset h8300_regsets[] = {
.n = ELF_NGREG,
.size = sizeof(long),
.align = sizeof(long),
.get = regs_get,
.regset_get = regs_get,
.set = regs_set,
},
};
......
......@@ -35,58 +35,38 @@ void user_disable_single_step(struct task_struct *child)
static int genregs_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
srtuct membuf to)
{
int ret;
unsigned int dummy;
struct pt_regs *regs = task_pt_regs(target);
if (!regs)
return -EIO;
/* The general idea here is that the copyout must happen in
* exactly the same order in which the userspace expects these
* regs. Now, the sequence in userspace does not match the
* sequence in the kernel, so everything past the 32 gprs
* happens one at a time.
*/
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&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));
membuf_write(&to, &regs->r00, 32*sizeof(unsigned long));
/* Must be exactly same sequence as struct user_regs_struct */
ONEXT(&regs->sa0, sa0);
ONEXT(&regs->lc0, lc0);
ONEXT(&regs->sa1, sa1);
ONEXT(&regs->lc1, lc1);
ONEXT(&regs->m0, m0);
ONEXT(&regs->m1, m1);
ONEXT(&regs->usr, usr);
ONEXT(&regs->preds, p3_0);
ONEXT(&regs->gp, gp);
ONEXT(&regs->ugp, ugp);
ONEXT(&pt_elr(regs), pc);
dummy = pt_cause(regs);
ONEXT(&dummy, cause);
ONEXT(&pt_badva(regs), badva);
membuf_store(&to, regs->sa0);
membuf_store(&to, regs->lc0);
membuf_store(&to, regs->sa1);
membuf_store(&to, regs->lc1);
membuf_store(&to, regs->m0);
membuf_store(&to, regs->m1);
membuf_store(&to, regs->usr);
membuf_store(&to, regs->p3_0);
membuf_store(&to, regs->gp);
membuf_store(&to, regs->ugp);
membuf_store(&to, pt_elr(regs)); // pc
membuf_store(&to, (unsigned long)pt_cause(regs)); // cause
membuf_store(&to, pt_badva(regs)); // badva
#if CONFIG_HEXAGON_ARCH_VERSION >=4
ONEXT(&regs->cs0, cs0);
ONEXT(&regs->cs1, cs1);
membuf_store(&to, regs->cs0);
membuf_store(&to, regs->cs1);
return membuf_zero(&to, sizeof(unsigned long));
#else
return membuf_zero(&to, 3 * sizeof(unsigned long));
#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,
......@@ -159,7 +139,7 @@ static const struct user_regset hexagon_regsets[] = {
.n = ELF_NGREG,
.size = sizeof(unsigned long),
.align = sizeof(unsigned long),
.get = genregs_get,
.regset_get = genregs_get,
.set = genregs_set,
},
};
......
This diff is collapsed.
This diff is collapsed.
......@@ -13,11 +13,10 @@ enum nds32_regset {
static int gpr_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user * ubuf)
struct membuf to)
{
struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs;
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);
return membuf_write(&to, &task_pt_regs(target)->user_regs,
sizeof(struct user_pt_regs));
}
static int gpr_set(struct task_struct *target, const struct user_regset *regset,
......@@ -41,7 +40,7 @@ static const struct user_regset nds32_regsets[] = {
.n = sizeof(struct user_pt_regs) / sizeof(u32),
.size = sizeof(elf_greg_t),
.align = sizeof(elf_greg_t),
.get = gpr_get,
.regset_get = gpr_get,
.set = gpr_set}
};
......
......@@ -21,45 +21,24 @@
static int genregs_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
const struct pt_regs *regs = task_pt_regs(target);
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) \
if (!ret) \
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, PTR, \
START * 4, (END * 4) + 4);
REG_O_ZERO_RANGE(PTR_R0, PTR_R0);
REG_O_RANGE(&regs->r1, PTR_R1, PTR_R7);
REG_O_RANGE(&regs->r8, PTR_R8, PTR_R15);
REG_O_RANGE(sw, PTR_R16, PTR_R23);
REG_O_ZERO_RANGE(PTR_R24, PTR_R25); /* et and bt */
REG_O_ONE(&regs->gp, PTR_GP);
REG_O_ONE(&regs->sp, PTR_SP);
REG_O_ONE(&regs->fp, PTR_FP);
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;
membuf_zero(&to, 4); // R0
membuf_write(&to, &regs->r1, 7 * 4); // R1..R7
membuf_write(&to, &regs->r8, 8 * 4); // R8..R15
membuf_write(&to, sw, 8 * 4); // R16..R23
membuf_zero(&to, 2 * 4); /* et and bt */
membuf_store(&to, regs->gp);
membuf_store(&to, regs->sp);
membuf_store(&to, regs->fp);
membuf_store(&to, regs->ea);
membuf_zero(&to, 4); // PTR_BA
membuf_store(&to, regs->ra);
membuf_store(&to, regs->ea); /* use ea for PC */
return membuf_zero(&to, (NUM_PTRACE_REG - PTR_PC) * 4);
}
/*
......@@ -121,7 +100,7 @@ static const struct user_regset nios2_regsets[] = {
.n = NUM_PTRACE_REG,
.size = sizeof(unsigned long),
.align = sizeof(unsigned long),
.get = genregs_get,
.regset_get = genregs_get,
.set = genregs_set,
}
};
......
......@@ -44,29 +44,15 @@
*/
static int genregs_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user * ubuf)
struct membuf to)
{
const struct pt_regs *regs = task_pt_regs(target);
int ret;
/* r0 */
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 0, 4);
if (!ret)
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
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;
membuf_zero(&to, 4);
membuf_write(&to, regs->gpr + 1, 31 * 4);
membuf_store(&to, regs->pc);
return membuf_store(&to, regs->sr);
}
/*
......@@ -114,7 +100,7 @@ static const struct user_regset or1k_regsets[] = {
.n = ELF_NGREG,
.size = sizeof(long),
.align = sizeof(long),
.get = genregs_get,
.regset_get = genregs_get,
.set = genregs_set,
},
};
......
......@@ -391,31 +391,11 @@ void do_syscall_trace_exit(struct pt_regs *regs)
static 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)
{
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;
ubuf = u;
pos *= sizeof(reg);
count *= sizeof(reg);
return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
ELF_NFPREG * sizeof(reg), -1);
return membuf_write(&to, regs->fr, ELF_NFPREG * sizeof(__u64));
}
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)
static int gpr_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
struct pt_regs *regs = task_regs(target);
unsigned long *k = kbuf;
unsigned long __user *u = ubuf;
unsigned long reg;
unsigned int pos;
pos /= sizeof(reg);
count /= sizeof(reg);
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);
for (pos = 0; pos < ELF_NGREG; pos++)
membuf_store(&to, get_reg(regs, pos));
return 0;
}
static int gpr_set(struct task_struct *target,
......@@ -588,12 +552,12 @@ static const struct user_regset native_regsets[] = {
[REGSET_GENERAL] = {
.core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
.size = sizeof(long), .align = sizeof(long),
.get = gpr_get, .set = gpr_set
.regset_get = gpr_get, .set = gpr_set
},
[REGSET_FP] = {
.core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
.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 = {
static int gpr32_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
struct pt_regs *regs = task_regs(target);
compat_ulong_t *k = kbuf;
compat_ulong_t __user *u = ubuf;
compat_ulong_t reg;
pos /= sizeof(reg);
count /= sizeof(reg);
unsigned int pos;
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((compat_ulong_t) get_reg(regs, pos++), u++))
return -EFAULT;
for (pos = 0; pos < ELF_NGREG; pos++)
membuf_store(&to, (compat_ulong_t)get_reg(regs, pos));
kbuf = k;
ubuf = u;
pos *= sizeof(reg);
count *= sizeof(reg);
return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
ELF_NGREG * sizeof(reg), -1);
return 0;
}
static int gpr32_set(struct task_struct *target,
......@@ -672,12 +620,12 @@ static const struct user_regset compat_regsets[] = {
[REGSET_GENERAL] = {
.core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
.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] = {
.core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
.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)
* };
*/
int vr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
struct membuf to)
{
int ret;
union {
elf_vrreg_t reg;
u32 word;
} vrsave;
flush_altivec_to_thread(target);
BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
offsetof(struct thread_vr_state, vr[32]));
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&target->thread.vr_state, 0,
33 * sizeof(vector128));
if (!ret) {
membuf_write(&to, &target->thread.vr_state, 33 * sizeof(vector128));
/*
* Copy out only the low-order word of vrsave.
*/
int start, end;
union {
elf_vrreg_t reg;
u32 word;
} vrsave;
memset(&vrsave, 0, sizeof(vrsave));
vrsave.word = target->thread.vrsave;
start = 33 * sizeof(vector128);
end = start + sizeof(vrsave);
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
start, end);
}
return ret;
return membuf_write(&to, &vrsave, sizeof(vrsave));
}
/*
......
......@@ -63,8 +63,7 @@ enum powerpc_regset {
/* ptrace-(no)vsx */
int fpr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
user_regset_get2_fn fpr_get;
int fpr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf);
......@@ -72,8 +71,7 @@ int fpr_set(struct task_struct *target, const struct user_regset *regset,
/* ptrace-vsx */
int vsr_active(struct task_struct *target, const struct user_regset *regset);
int vsr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
user_regset_get2_fn vsr_get;
int vsr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf);
......@@ -81,8 +79,7 @@ int vsr_set(struct task_struct *target, const struct user_regset *regset,
/* ptrace-altivec */
int vr_active(struct task_struct *target, const struct user_regset *regset);
int vr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
user_regset_get2_fn vr_get;
int vr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf);
......@@ -90,8 +87,7 @@ int vr_set(struct task_struct *target, const struct user_regset *regset,
/* ptrace-spe */
int evr_active(struct task_struct *target, const struct user_regset *regset);
int evr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
user_regset_get2_fn evr_get;
int evr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf);
......@@ -100,8 +96,7 @@ int evr_set(struct task_struct *target, const struct user_regset *regset,
int gpr32_get_common(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf,
struct membuf to,
unsigned long *regs);
int gpr32_set_common(struct task_struct *target,
const struct user_regset *regset,
......@@ -118,55 +113,46 @@ static inline void flush_tmregs_to_thread(struct task_struct *tsk) { }
#endif
int tm_cgpr_active(struct task_struct *target, const struct user_regset *regset);
int tm_cgpr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
user_regset_get2_fn tm_cgpr_get;
int tm_cgpr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf);
int tm_cfpr_active(struct task_struct *target, const struct user_regset *regset);
int tm_cfpr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
user_regset_get2_fn tm_cfpr_get;
int tm_cfpr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf);
int tm_cvmx_active(struct task_struct *target, const struct user_regset *regset);
int tm_cvmx_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
user_regset_get2_fn tm_cvmx_get;
int tm_cvmx_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf);
int tm_cvsx_active(struct task_struct *target, const struct user_regset *regset);
int tm_cvsx_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
user_regset_get2_fn tm_cvsx_get;
int tm_cvsx_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf);
int tm_spr_active(struct task_struct *target, const struct user_regset *regset);
int tm_spr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
user_regset_get2_fn tm_spr_get;
int tm_spr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf);
int tm_tar_active(struct task_struct *target, const struct user_regset *regset);
int tm_tar_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
user_regset_get2_fn tm_tar_get;
int tm_tar_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf);
int tm_ppr_active(struct task_struct *target, const struct user_regset *regset);
int tm_ppr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
user_regset_get2_fn tm_ppr_get;
int tm_ppr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf);
int tm_dscr_active(struct task_struct *target, const struct user_regset *regset);
int tm_dscr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
user_regset_get2_fn tm_dscr_get;
int tm_dscr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf);
int tm_cgpr32_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
user_regset_get2_fn tm_cgpr32_get;
int tm_cgpr32_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf);
......
......@@ -19,15 +19,14 @@
* };
*/
int fpr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
struct membuf to)
{
BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
offsetof(struct thread_fp_state, fpr[32]));
flush_fp_to_thread(target);
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&target->thread.fp_state, 0, -1);
return membuf_write(&to, &target->thread.fp_state, 33 * sizeof(u64));
}
/*
......
......@@ -23,25 +23,17 @@ int evr_active(struct task_struct *target, const struct user_regset *regset)
}
int evr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
struct membuf to)
{
int ret;
flush_spe_to_thread(target);
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&target->thread.evr,
0, sizeof(target->thread.evr));
membuf_write(&to, &target->thread.evr, sizeof(target->thread.evr));
BUILD_BUG_ON(offsetof(struct thread_struct, acc) + sizeof(u64) !=
offsetof(struct thread_struct, spefscr));
if (!ret)
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&target->thread.acc,
sizeof(target->thread.evr), -1);
return ret;
return membuf_write(&to, &target->thread.acc,
sizeof(u64) + sizeof(u32));
}
int evr_set(struct task_struct *target, const struct user_regset *regset,
......
This diff is collapsed.
This diff is collapsed.
......@@ -19,7 +19,7 @@
* };
*/
int fpr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
struct membuf to)
{
u64 buf[33];
int i;
......@@ -30,7 +30,7 @@ int fpr_get(struct task_struct *target, const struct user_regset *regset,
for (i = 0; i < 32 ; i++)
buf[i] = target->thread.TS_FPR(i);
buf[32] = target->thread.fp_state.fpscr;
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
return membuf_write(&to, buf, 33 * sizeof(u64));
}
/*
......@@ -95,10 +95,10 @@ int vsr_active(struct task_struct *target, const struct user_regset *regset)
* };
*/
int vsr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
struct membuf to)
{
u64 buf[32];
int ret, i;
int i;
flush_tmregs_to_thread(target);
flush_fp_to_thread(target);
......@@ -108,10 +108,7 @@ int vsr_get(struct task_struct *target, const struct user_regset *regset,
for (i = 0; i < 32 ; i++)
buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
buf, 0, 32 * sizeof(double));
return ret;
return membuf_write(&to, buf, 32 * sizeof(double));
}
/*
......
......@@ -30,13 +30,10 @@ enum riscv_regset {
static int riscv_gpr_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
struct pt_regs *regs;
regs = task_pt_regs(target);
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
return membuf_write(&to, task_pt_regs(target),
sizeof(struct user_regs_struct));
}
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
static int riscv_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)
{
int ret;
struct __riscv_d_ext_state *fstate = &target->thread.fstate;
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, fstate, 0,
offsetof(struct __riscv_d_ext_state, fcsr));
if (!ret) {
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, fstate, 0,
offsetof(struct __riscv_d_ext_state, fcsr) +
sizeof(fstate->fcsr));
}
return ret;
membuf_write(&to, fstate, offsetof(struct __riscv_d_ext_state, fcsr));
membuf_store(&to, fstate->fcsr);
return membuf_zero(&to, 4); // explicitly pad
}
static int riscv_fpr_set(struct task_struct *target,
......@@ -98,8 +87,8 @@ static const struct user_regset riscv_user_regset[] = {
.n = ELF_NGREG,
.size = sizeof(elf_greg_t),
.align = sizeof(elf_greg_t),
.get = &riscv_gpr_get,
.set = &riscv_gpr_set,
.regset_get = riscv_gpr_get,
.set = riscv_gpr_set,
},
#ifdef CONFIG_FPU
[REGSET_F] = {
......@@ -107,8 +96,8 @@ static const struct user_regset riscv_user_regset[] = {
.n = ELF_NFPREG,
.size = sizeof(elf_fpreg_t),
.align = sizeof(elf_fpreg_t),
.get = &riscv_fpr_get,
.set = &riscv_fpr_set,
.regset_get = riscv_fpr_get,
.set = riscv_fpr_set,
},
#endif
};
......
This diff is collapsed.
......@@ -103,9 +103,8 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
fpvalid = !!tsk_used_math(tsk);
if (fpvalid)
fpvalid = !fpregs_get(tsk, NULL, 0,
sizeof(struct user_fpu_struct),
fpu, NULL);
fpvalid = !fpregs_get(tsk, NULL,
(struct membuf){fpu, sizeof(*fpu)});
#endif
return fpvalid;
......
......@@ -134,26 +134,11 @@ void ptrace_disable(struct task_struct *child)
static int genregs_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
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,
......@@ -182,8 +167,7 @@ static int genregs_set(struct task_struct *target,
#ifdef CONFIG_SH_FPU
int fpregs_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;
......@@ -191,12 +175,8 @@ int fpregs_get(struct task_struct *target,
if (ret)
return ret;
if ((boot_cpu_data.flags & CPU_HAS_FPU))
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&target->thread.xstate->hardfpu, 0, -1);
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
&target->thread.xstate->softfpu, 0, -1);
return membuf_write(&to, target->thread.xstate,
sizeof(struct user_fpu_struct));
}
static int fpregs_set(struct task_struct *target,
......@@ -230,20 +210,12 @@ static int fpregs_active(struct task_struct *target,
#ifdef CONFIG_SH_DSP
static int dspregs_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
const struct pt_dspregs *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,
......@@ -324,7 +296,7 @@ static const struct user_regset sh_regsets[] = {
.n = ELF_NGREG,
.size = sizeof(long),
.align = sizeof(long),
.get = genregs_get,
.regset_get = genregs_get,
.set = genregs_set,
},
......@@ -334,7 +306,7 @@ static const struct user_regset sh_regsets[] = {
.n = sizeof(struct user_fpu_struct) / sizeof(long),
.size = sizeof(long),
.align = sizeof(long),
.get = fpregs_get,
.regset_get = fpregs_get,
.set = fpregs_set,
.active = fpregs_active,
},
......@@ -345,7 +317,7 @@ static const struct user_regset sh_regsets[] = {
.n = sizeof(struct pt_dspregs) / sizeof(long),
.size = sizeof(long),
.align = sizeof(long),
.get = dspregs_get,
.regset_get = dspregs_get,
.set = dspregs_set,
.active = dspregs_active,
},
......
......@@ -83,41 +83,25 @@ static int regwindow32_set(struct task_struct *target,
static int genregs32_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
const struct pt_regs *regs = target->thread.kregs;
u32 uregs[16];
int ret;
if (target == current)
flush_user_windows();
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
regs->u_regs,
0, 16 * sizeof(u32));
if (ret || !count)
return ret;
if (pos < 32 * sizeof(u32)) {
membuf_write(&to, regs->u_regs, 16 * sizeof(u32));
if (!to.left)
return 0;
if (regwindow32_get(target, regs, uregs))
return -EFAULT;
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
uregs,
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));
membuf_write(&to, uregs, 16 * sizeof(u32));
membuf_store(&to, regs->psr);
membuf_store(&to, regs->pc);
membuf_store(&to, regs->npc);
membuf_store(&to, regs->y);
return membuf_zero(&to, 2 * sizeof(u32));
}
static int genregs32_set(struct task_struct *target,
......@@ -139,7 +123,6 @@ static int genregs32_set(struct task_struct *target,
if (ret || !count)
return ret;
if (pos < 32 * sizeof(u32)) {
if (regwindow32_get(target, regs, uregs))
return -EFAULT;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
......@@ -151,7 +134,7 @@ static int genregs32_set(struct task_struct *target,
return -EFAULT;
if (!count)
return 0;
}
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&psr,
32 * sizeof(u32), 33 * sizeof(u32));
......@@ -182,46 +165,18 @@ static int genregs32_set(struct task_struct *target,
static int fpregs32_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
const unsigned long *fpregs = target->thread.float_regs;
int ret = 0;
#if 0
if (target == current)
save_and_clear_fpu();
#endif
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
fpregs,
0, 32 * sizeof(u32));
if (!ret)
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;
membuf_write(&to, target->thread.float_regs, 32 * sizeof(u32));
membuf_zero(&to, sizeof(u32));
membuf_write(&to, &target->thread.fsr, sizeof(u32));
membuf_store(&to, (u32)((1 << 8) | (8 << 16)));
return membuf_zero(&to, 64 * sizeof(u32));
}
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,
32 * sizeof(u32),
33 * sizeof(u32));
if (!ret && count > 0) {
if (!ret)
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&target->thread.fsr,
33 * sizeof(u32),
34 * sizeof(u32));
}
if (!ret)
ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
34 * sizeof(u32), -1);
......@@ -268,7 +221,7 @@ static const struct user_regset sparc32_regsets[] = {
.core_note_type = NT_PRSTATUS,
.n = 38,
.size = sizeof(u32), .align = sizeof(u32),
.get = genregs32_get, .set = genregs32_set
.regset_get = genregs32_get, .set = genregs32_set
},
/* Format is:
* F0 --> F31
......@@ -284,8 +237,102 @@ static const struct user_regset sparc32_regsets[] = {
.core_note_type = NT_PRFPREG,
.n = 99,
.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 = {
......@@ -315,74 +362,44 @@ long arch_ptrace(struct task_struct *child, long request,
{
unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4];
void __user *addr2p;
const struct user_regset_view *view;
struct pt_regs __user *pregs;
struct fps __user *fps;
int ret;
view = task_user_regset_view(current);
addr2p = (void __user *) addr2;
pregs = (struct pt_regs __user *) addr;
fps = (struct fps __user *) addr;
switch(request) {
case PTRACE_GETREGS: {
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
32 * sizeof(u32),
4 * sizeof(u32),
&pregs->psr);
if (!ret)
copy_regset_to_user(child, view, REGSET_GENERAL,
1 * sizeof(u32),
15 * sizeof(u32),
&pregs->u_regs[0]);
ret = copy_regset_to_user(child, &ptrace32_view,
REGSET_GENERAL, 0,
19 * sizeof(u32),
pregs);
break;
}
case PTRACE_SETREGS: {
ret = copy_regset_from_user(child, view, REGSET_GENERAL,
32 * sizeof(u32),
4 * sizeof(u32),
&pregs->psr);
if (!ret)
copy_regset_from_user(child, view, REGSET_GENERAL,
1 * sizeof(u32),
15 * sizeof(u32),
&pregs->u_regs[0]);
ret = copy_regset_from_user(child, &ptrace32_view,
REGSET_GENERAL, 0,
19 * sizeof(u32),
pregs);
break;
}
case PTRACE_GETFPREGS: {
ret = copy_regset_to_user(child, view, REGSET_FP,
0 * sizeof(u32),
32 * sizeof(u32),
&fps->regs[0]);
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;
}
ret = copy_regset_to_user(child, &ptrace32_view,
REGSET_FP, 0,
68 * sizeof(u32),
fps);
break;
}
case PTRACE_SETFPREGS: {
ret = copy_regset_from_user(child, view, REGSET_FP,
0 * sizeof(u32),
32 * sizeof(u32),
&fps->regs[0]);
if (!ret)
ret = copy_regset_from_user(child, view, REGSET_FP,
ret = copy_regset_from_user(child, &ptrace32_view,
REGSET_FP, 0,
33 * sizeof(u32),
1 * sizeof(u32),
&fps->fsr);
fps);
break;
}
......
This diff is collapsed.
......@@ -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_all(struct fpu *fpu);
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:
......
......@@ -8,7 +8,7 @@
#include <linux/regset.h>
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;
extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set,
xstateregs_set;
......
......@@ -104,8 +104,8 @@ void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr);
const void *get_xsave_field_ptr(int xfeature_nr);
int using_compacted_format(void);
int xfeature_size(int xfeature_nr);
int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int offset, unsigned int size);
int copy_xstate_to_user(void __user *ubuf, struct xregs_state *xsave, unsigned int offset, unsigned int size);
struct membuf;
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_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf);
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)
ia32_fxstate &= (IS_ENABLED(CONFIG_X86_32) ||
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))
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:
/*
* 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,
}
int regset_tls_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
struct membuf to)
{
const struct desc_struct *tls;
struct user_desc v;
int pos;
if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
(pos % sizeof(struct user_desc)) != 0 ||
(count % sizeof(struct user_desc)) != 0)
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;
}
for (pos = 0, tls = target->thread.tls_array; to.left; pos++, tls++) {
fill_user_desc(&v, GDT_ENTRY_TLS_MIN + pos, tls);
membuf_write(&to, &v, sizeof(v));
}
return 0;
}
......
......@@ -12,7 +12,7 @@
#include <linux/regset.h>
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;
#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 \
extable.o params.o \
kthread.o sys_ni.o nsproxy.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_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