Skip to content

Commit 8f03292

Browse files
author
Al Viro
committed
sparc64: get rid of odd callers of copy_regset_to_user()
same as for sparc32, and that's it - no more caller of ->get() with non-zero pos. Signed-off-by: Al Viro <[email protected]>
1 parent 87d8053 commit 8f03292

File tree

1 file changed

+136
-39
lines changed

1 file changed

+136
-39
lines changed

arch/sparc/kernel/ptrace_64.c

Lines changed: 136 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ static int genregs64_get(struct task_struct *target,
258258
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
259259
regs->u_regs,
260260
0, 16 * sizeof(u64));
261-
if (!ret && count && pos < (32 * sizeof(u64))) {
261+
if (!ret && count) {
262262
struct reg_window window;
263263

264264
if (regwindow64_get(target, regs, &window))
@@ -506,6 +506,57 @@ static const struct user_regset sparc64_regsets[] = {
506506
},
507507
};
508508

509+
static int getregs64_get(struct task_struct *target,
510+
const struct user_regset *regset,
511+
unsigned int pos, unsigned int count,
512+
void *kbuf, void __user *ubuf)
513+
{
514+
const struct pt_regs *regs = task_pt_regs(target);
515+
int ret;
516+
517+
if (target == current)
518+
flushw_user();
519+
520+
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
521+
regs->u_regs + 1,
522+
0, 15 * sizeof(u64));
523+
if (!ret)
524+
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
525+
15 * sizeof(u64), 16 * sizeof(u64));
526+
if (!ret) {
527+
/* TSTATE, TPC, TNPC */
528+
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
529+
&regs->tstate,
530+
16 * sizeof(u64),
531+
19 * sizeof(u64));
532+
}
533+
if (!ret) {
534+
unsigned long y = regs->y;
535+
536+
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
537+
&y,
538+
19 * sizeof(u64),
539+
20 * sizeof(u64));
540+
}
541+
return ret;
542+
}
543+
544+
static const struct user_regset ptrace64_regsets[] = {
545+
/* Format is:
546+
* G1 --> G7
547+
* O0 --> O7
548+
* 0
549+
* TSTATE, TPC, TNPC, Y
550+
*/
551+
[REGSET_GENERAL] = {
552+
.n = 20, .size = sizeof(u64), .get = getregs64_get,
553+
},
554+
};
555+
556+
static const struct user_regset_view ptrace64_view = {
557+
.regsets = ptrace64_regsets, .n = ARRAY_SIZE(ptrace64_regsets)
558+
};
559+
509560
static const struct user_regset_view user_sparc64_view = {
510561
.name = "sparc64", .e_machine = EM_SPARCV9,
511562
.regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets)
@@ -533,7 +584,7 @@ static int genregs32_get(struct task_struct *target,
533584
for (; count > 0 && pos < 16; count--)
534585
*k++ = regs->u_regs[pos++];
535586

536-
if (count && pos < 32) {
587+
if (count) {
537588
if (get_from_target(target, regs->u_regs[UREG_I6],
538589
uregs, sizeof(uregs)))
539590
return -EFAULT;
@@ -545,7 +596,7 @@ static int genregs32_get(struct task_struct *target,
545596
for (; count > 0 && pos < 16; count--)
546597
if (put_user((compat_ulong_t) regs->u_regs[pos++], u++))
547598
return -EFAULT;
548-
if (count && pos < 32) {
599+
if (count) {
549600
if (get_from_target(target, regs->u_regs[UREG_I6],
550601
uregs, sizeof(uregs)))
551602
return -EFAULT;
@@ -840,6 +891,76 @@ static const struct user_regset sparc32_regsets[] = {
840891
},
841892
};
842893

894+
static int getregs_get(struct task_struct *target,
895+
const struct user_regset *regset,
896+
unsigned int pos, unsigned int count,
897+
void *kbuf, void __user *ubuf)
898+
{
899+
const struct pt_regs *regs = task_pt_regs(target);
900+
u32 uregs[19];
901+
int i;
902+
903+
if (target == current)
904+
flushw_user();
905+
906+
uregs[0] = tstate_to_psr(regs->tstate);
907+
uregs[1] = regs->tpc;
908+
uregs[2] = regs->tnpc;
909+
uregs[3] = regs->y;
910+
for (i = 1; i < 16; i++)
911+
uregs[3 + i] = regs->u_regs[i];
912+
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
913+
uregs,
914+
0, 19 * sizeof(u32));
915+
}
916+
917+
static int getfpregs_get(struct task_struct *target,
918+
const struct user_regset *regset,
919+
unsigned int pos, unsigned int count,
920+
void *kbuf, void __user *ubuf)
921+
{
922+
const unsigned long *fpregs = task_thread_info(target)->fpregs;
923+
unsigned long fprs;
924+
compat_ulong_t fsr;
925+
int ret = 0;
926+
927+
if (target == current)
928+
save_and_clear_fpu();
929+
930+
fprs = task_thread_info(target)->fpsaved[0];
931+
if (fprs & FPRS_FEF) {
932+
fsr = task_thread_info(target)->xfsr[0];
933+
} else {
934+
fsr = 0;
935+
}
936+
937+
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
938+
fpregs,
939+
0, 32 * sizeof(u32));
940+
if (!ret)
941+
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
942+
&fsr,
943+
32 * sizeof(u32),
944+
33 * sizeof(u32));
945+
if (!ret)
946+
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
947+
33 * sizeof(u32), 68 * sizeof(u32));
948+
return ret;
949+
}
950+
951+
static const struct user_regset ptrace32_regsets[] = {
952+
[REGSET_GENERAL] = {
953+
.n = 19, .size = sizeof(u32), .get = getregs_get,
954+
},
955+
[REGSET_FP] = {
956+
.n = 68, .size = sizeof(u32), .get = getfpregs_get,
957+
},
958+
};
959+
960+
static const struct user_regset_view ptrace32_view = {
961+
.regsets = ptrace32_regsets, .n = ARRAY_SIZE(ptrace32_regsets)
962+
};
963+
843964
static const struct user_regset_view user_sparc32_view = {
844965
.name = "sparc", .e_machine = EM_SPARC,
845966
.regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
@@ -889,15 +1010,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
8891010
break;
8901011

8911012
case PTRACE_GETREGS:
892-
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
893-
32 * sizeof(u32),
894-
4 * sizeof(u32),
895-
&pregs->psr);
896-
if (!ret)
897-
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
898-
1 * sizeof(u32),
899-
15 * sizeof(u32),
900-
&pregs->u_regs[0]);
1013+
ret = copy_regset_to_user(child, &ptrace32_view,
1014+
REGSET_GENERAL, 0,
1015+
19 * sizeof(u32),
1016+
pregs);
9011017
break;
9021018

9031019
case PTRACE_SETREGS:
@@ -913,22 +1029,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
9131029
break;
9141030

9151031
case PTRACE_GETFPREGS:
916-
ret = copy_regset_to_user(child, view, REGSET_FP,
917-
0 * sizeof(u32),
918-
32 * sizeof(u32),
919-
&fps->regs[0]);
920-
if (!ret)
921-
ret = copy_regset_to_user(child, view, REGSET_FP,
922-
33 * sizeof(u32),
923-
1 * sizeof(u32),
924-
&fps->fsr);
925-
if (!ret) {
926-
if (__put_user(0, &fps->flags) ||
927-
__put_user(0, &fps->extra) ||
928-
__put_user(0, &fps->fpqd) ||
929-
clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
930-
ret = -EFAULT;
931-
}
1032+
ret = copy_regset_to_user(child, &ptrace32_view,
1033+
REGSET_FP, 0,
1034+
68 * sizeof(u32),
1035+
fps);
9321036
break;
9331037

9341038
case PTRACE_SETFPREGS:
@@ -999,17 +1103,10 @@ long arch_ptrace(struct task_struct *child, long request,
9991103
break;
10001104

10011105
case PTRACE_GETREGS64:
1002-
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
1003-
1 * sizeof(u64),
1004-
15 * sizeof(u64),
1005-
&pregs->u_regs[0]);
1006-
if (!ret) {
1007-
/* XXX doesn't handle 'y' register correctly XXX */
1008-
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
1009-
32 * sizeof(u64),
1010-
4 * sizeof(u64),
1011-
&pregs->tstate);
1012-
}
1106+
ret = copy_regset_to_user(child, &ptrace64_view,
1107+
REGSET_GENERAL, 0,
1108+
19 * sizeof(u64),
1109+
pregs);
10131110
break;
10141111

10151112
case PTRACE_SETREGS64:

0 commit comments

Comments
 (0)