Skip to content

Commit 87d8053

Browse files
author
Al Viro
committed
sparc32: get rid of odd callers of copy_regset_to_user()
the life is much simpler if copy_regset_to_user() (and ->get()) gets called only with pos == 0; sparc32 PTRACE_GETREGS and PTRACE_GETFPREGS are among the few things that use it to fetch pieces of regset _not_ starting at the beginning. It's actually easier to define a separate regset that would provide what we need, rather than trying to cobble that from the one PTRACE_GETREGSET uses. Extra ->get() instances do not amount to much code and once we get the conversion of ->get() to new API (dependent upon the lack of weird callers of ->get()) they'll shrink a lot, along with the rest of ->get() instances... Signed-off-by: Al Viro <[email protected]>
1 parent 030754c commit 87d8053

File tree

1 file changed

+82
-35
lines changed

1 file changed

+82
-35
lines changed

arch/sparc/kernel/ptrace_32.c

Lines changed: 82 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,13 @@ static int genregs32_get(struct task_struct *target,
9999
if (ret || !count)
100100
return ret;
101101

102-
if (pos < 32 * sizeof(u32)) {
103-
if (regwindow32_get(target, regs, uregs))
104-
return -EFAULT;
105-
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
106-
uregs,
107-
16 * sizeof(u32), 32 * sizeof(u32));
108-
if (ret || !count)
109-
return ret;
110-
}
102+
if (regwindow32_get(target, regs, uregs))
103+
return -EFAULT;
104+
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
105+
uregs,
106+
16 * sizeof(u32), 32 * sizeof(u32));
107+
if (ret)
108+
return ret;
111109

112110
uregs[0] = regs->psr;
113111
uregs[1] = regs->pc;
@@ -288,6 +286,73 @@ static const struct user_regset sparc32_regsets[] = {
288286
},
289287
};
290288

289+
static int getregs_get(struct task_struct *target,
290+
const struct user_regset *regset,
291+
unsigned int pos, unsigned int count,
292+
void *kbuf, void __user *ubuf)
293+
{
294+
const struct pt_regs *regs = target->thread.kregs;
295+
u32 v[4];
296+
int ret;
297+
298+
if (target == current)
299+
flush_user_windows();
300+
301+
v[0] = regs->psr;
302+
v[1] = regs->pc;
303+
v[2] = regs->npc;
304+
v[3] = regs->y;
305+
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
306+
v,
307+
0 * sizeof(u32), 4 * sizeof(u32));
308+
if (ret)
309+
return ret;
310+
311+
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
312+
regs->u_regs + 1,
313+
4 * sizeof(u32), 19 * sizeof(u32));
314+
}
315+
316+
static int getfpregs_get(struct task_struct *target,
317+
const struct user_regset *regset,
318+
unsigned int pos, unsigned int count,
319+
void *kbuf, void __user *ubuf)
320+
{
321+
const unsigned long *fpregs = target->thread.float_regs;
322+
int ret = 0;
323+
324+
#if 0
325+
if (target == current)
326+
save_and_clear_fpu();
327+
#endif
328+
329+
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
330+
fpregs,
331+
0, 32 * sizeof(u32));
332+
if (ret)
333+
return ret;
334+
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
335+
&target->thread.fsr,
336+
32 * sizeof(u32), 33 * sizeof(u32));
337+
if (ret)
338+
return ret;
339+
return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
340+
33 * sizeof(u32), 68 * sizeof(u32));
341+
}
342+
343+
static const struct user_regset ptrace32_regsets[] = {
344+
[REGSET_GENERAL] = {
345+
.n = 19, .size = sizeof(u32), .get = getregs_get,
346+
},
347+
[REGSET_FP] = {
348+
.n = 68, .size = sizeof(u32), .get = getfpregs_get,
349+
},
350+
};
351+
352+
static const struct user_regset_view ptrace32_view = {
353+
.regsets = ptrace32_regsets, .n = ARRAY_SIZE(ptrace32_regsets)
354+
};
355+
291356
static const struct user_regset_view user_sparc32_view = {
292357
.name = "sparc", .e_machine = EM_SPARC,
293358
.regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
@@ -327,15 +392,10 @@ long arch_ptrace(struct task_struct *child, long request,
327392

328393
switch(request) {
329394
case PTRACE_GETREGS: {
330-
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
331-
32 * sizeof(u32),
332-
4 * sizeof(u32),
333-
&pregs->psr);
334-
if (!ret)
335-
copy_regset_to_user(child, view, REGSET_GENERAL,
336-
1 * sizeof(u32),
337-
15 * sizeof(u32),
338-
&pregs->u_regs[0]);
395+
ret = copy_regset_to_user(child, &ptrace32_view,
396+
REGSET_GENERAL, 0,
397+
19 * sizeof(u32),
398+
pregs);
339399
break;
340400
}
341401

@@ -353,23 +413,10 @@ long arch_ptrace(struct task_struct *child, long request,
353413
}
354414

355415
case PTRACE_GETFPREGS: {
356-
ret = copy_regset_to_user(child, view, REGSET_FP,
357-
0 * sizeof(u32),
358-
32 * sizeof(u32),
359-
&fps->regs[0]);
360-
if (!ret)
361-
ret = copy_regset_to_user(child, view, REGSET_FP,
362-
33 * sizeof(u32),
363-
1 * sizeof(u32),
364-
&fps->fsr);
365-
366-
if (!ret) {
367-
if (__put_user(0, &fps->fpqd) ||
368-
__put_user(0, &fps->flags) ||
369-
__put_user(0, &fps->extra) ||
370-
clear_user(fps->fpq, sizeof(fps->fpq)))
371-
ret = -EFAULT;
372-
}
416+
ret = copy_regset_to_user(child, &ptrace32_view,
417+
REGSET_FP, 0,
418+
68 * sizeof(u32),
419+
fps);
373420
break;
374421
}
375422

0 commit comments

Comments
 (0)