mirror of
https://github.com/torvalds/linux
synced 2024-10-23 19:57:28 +00:00
[SPARC64]: Use regsets in arch_ptrace().
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5a4924d7be
commit
9473272af3
|
@ -687,11 +687,14 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
|
||||||
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
||||||
{
|
{
|
||||||
long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
|
long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
|
||||||
int i, ret;
|
const struct user_regset_view *view;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (test_thread_flag(TIF_32BIT))
|
if (test_thread_flag(TIF_32BIT))
|
||||||
addr2 &= 0xffffffffUL;
|
addr2 &= 0xffffffffUL;
|
||||||
|
|
||||||
|
view = task_user_regset_view(child);
|
||||||
|
|
||||||
switch(request) {
|
switch(request) {
|
||||||
case PTRACE_PEEKUSR:
|
case PTRACE_PEEKUSR:
|
||||||
ret = (addr != 0) ? -EIO : 0;
|
ret = (addr != 0) ? -EIO : 0;
|
||||||
|
@ -746,111 +749,66 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
||||||
case PTRACE_GETREGS: {
|
case PTRACE_GETREGS: {
|
||||||
struct pt_regs32 __user *pregs =
|
struct pt_regs32 __user *pregs =
|
||||||
(struct pt_regs32 __user *) addr;
|
(struct pt_regs32 __user *) addr;
|
||||||
struct pt_regs *cregs = task_pt_regs(child);
|
|
||||||
|
|
||||||
ret = -EFAULT;
|
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
|
||||||
if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
|
32 * sizeof(u32),
|
||||||
__put_user(cregs->tpc, (&pregs->pc)) ||
|
4 * sizeof(u32),
|
||||||
__put_user(cregs->tnpc, (&pregs->npc)) ||
|
&pregs->psr);
|
||||||
__put_user(cregs->y, (&pregs->y)))
|
if (!ret)
|
||||||
break;
|
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
|
||||||
for (i = 1; i < 16; i++) {
|
1 * sizeof(u32),
|
||||||
if (__put_user(cregs->u_regs[i],
|
15 * sizeof(u32),
|
||||||
(&pregs->u_regs[i - 1])))
|
&pregs->u_regs[0]);
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == 16)
|
|
||||||
ret = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PTRACE_GETREGS64: {
|
case PTRACE_GETREGS64: {
|
||||||
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
|
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
|
||||||
struct pt_regs *cregs = task_pt_regs(child);
|
|
||||||
unsigned long tpc = cregs->tpc;
|
|
||||||
|
|
||||||
if ((task_thread_info(child)->flags & _TIF_32BIT) != 0)
|
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
|
||||||
tpc &= 0xffffffff;
|
1 * sizeof(u64),
|
||||||
|
15 * sizeof(u64),
|
||||||
ret = -EFAULT;
|
&pregs->u_regs[0]);
|
||||||
if (__put_user(cregs->tstate, (&pregs->tstate)) ||
|
if (!ret) {
|
||||||
__put_user(tpc, (&pregs->tpc)) ||
|
/* XXX doesn't handle 'y' register correctly XXX */
|
||||||
__put_user(cregs->tnpc, (&pregs->tnpc)) ||
|
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
|
||||||
__put_user(cregs->y, (&pregs->y)))
|
32 * sizeof(u64),
|
||||||
break;
|
4 * sizeof(u64),
|
||||||
for (i = 1; i < 16; i++) {
|
&pregs->tstate);
|
||||||
if (__put_user(cregs->u_regs[i],
|
|
||||||
(&pregs->u_regs[i - 1])))
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (i == 16)
|
|
||||||
ret = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PTRACE_SETREGS: {
|
case PTRACE_SETREGS: {
|
||||||
struct pt_regs32 __user *pregs =
|
struct pt_regs32 __user *pregs =
|
||||||
(struct pt_regs32 __user *) addr;
|
(struct pt_regs32 __user *) addr;
|
||||||
struct pt_regs *cregs = task_pt_regs(child);
|
|
||||||
unsigned int psr, pc, npc, y;
|
|
||||||
|
|
||||||
/* Must be careful, tracing process can only set certain
|
ret = copy_regset_from_user(child, view, REGSET_GENERAL,
|
||||||
* bits in the psr.
|
32 * sizeof(u32),
|
||||||
*/
|
4 * sizeof(u32),
|
||||||
ret = -EFAULT;
|
&pregs->psr);
|
||||||
if (__get_user(psr, (&pregs->psr)) ||
|
if (!ret)
|
||||||
__get_user(pc, (&pregs->pc)) ||
|
ret = copy_regset_from_user(child, view, REGSET_GENERAL,
|
||||||
__get_user(npc, (&pregs->npc)) ||
|
1 * sizeof(u32),
|
||||||
__get_user(y, (&pregs->y)))
|
15 * sizeof(u32),
|
||||||
break;
|
&pregs->u_regs[0]);
|
||||||
cregs->tstate &= ~(TSTATE_ICC);
|
|
||||||
cregs->tstate |= psr_to_tstate_icc(psr);
|
|
||||||
if (!((pc | npc) & 3)) {
|
|
||||||
cregs->tpc = pc;
|
|
||||||
cregs->tnpc = npc;
|
|
||||||
}
|
|
||||||
cregs->y = y;
|
|
||||||
for (i = 1; i < 16; i++) {
|
|
||||||
if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1])))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == 16)
|
|
||||||
ret = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PTRACE_SETREGS64: {
|
case PTRACE_SETREGS64: {
|
||||||
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
|
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
|
||||||
struct pt_regs *cregs = task_pt_regs(child);
|
|
||||||
unsigned long tstate, tpc, tnpc, y;
|
|
||||||
|
|
||||||
/* Must be careful, tracing process can only set certain
|
ret = copy_regset_from_user(child, view, REGSET_GENERAL,
|
||||||
* bits in the psr.
|
1 * sizeof(u64),
|
||||||
*/
|
15 * sizeof(u64),
|
||||||
ret = -EFAULT;
|
&pregs->u_regs[0]);
|
||||||
if (__get_user(tstate, (&pregs->tstate)) ||
|
if (!ret) {
|
||||||
__get_user(tpc, (&pregs->tpc)) ||
|
/* XXX doesn't handle 'y' register correctly XXX */
|
||||||
__get_user(tnpc, (&pregs->tnpc)) ||
|
ret = copy_regset_from_user(child, view, REGSET_GENERAL,
|
||||||
__get_user(y, (&pregs->y)))
|
32 * sizeof(u64),
|
||||||
break;
|
4 * sizeof(u64),
|
||||||
if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) {
|
&pregs->tstate);
|
||||||
tpc &= 0xffffffff;
|
|
||||||
tnpc &= 0xffffffff;
|
|
||||||
}
|
}
|
||||||
tstate &= (TSTATE_ICC | TSTATE_XCC);
|
|
||||||
cregs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
|
|
||||||
cregs->tstate |= tstate;
|
|
||||||
if (!((tpc | tnpc) & 3)) {
|
|
||||||
cregs->tpc = tpc;
|
|
||||||
cregs->tnpc = tnpc;
|
|
||||||
}
|
|
||||||
cregs->y = y;
|
|
||||||
for (i = 1; i < 16; i++) {
|
|
||||||
if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1])))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == 16)
|
|
||||||
ret = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -867,19 +825,23 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
||||||
} fpq[16];
|
} fpq[16];
|
||||||
};
|
};
|
||||||
struct fps __user *fps = (struct fps __user *) addr;
|
struct fps __user *fps = (struct fps __user *) addr;
|
||||||
unsigned long *fpregs = task_thread_info(child)->fpregs;
|
|
||||||
|
|
||||||
ret = -EFAULT;
|
ret = copy_regset_to_user(child, view, REGSET_FP,
|
||||||
if (copy_to_user(&fps->regs[0], fpregs,
|
0 * sizeof(u32),
|
||||||
(32 * sizeof(unsigned int))) ||
|
32 * sizeof(u32),
|
||||||
__put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) ||
|
&fps->regs[0]);
|
||||||
__put_user(0, (&fps->fpqd)) ||
|
if (!ret)
|
||||||
__put_user(0, (&fps->flags)) ||
|
ret = copy_regset_to_user(child, view, REGSET_FP,
|
||||||
__put_user(0, (&fps->extra)) ||
|
33 * sizeof(u32),
|
||||||
clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
|
1 * sizeof(u32),
|
||||||
break;
|
&fps->fsr);
|
||||||
|
if (!ret) {
|
||||||
ret = 0;
|
if (__put_user(0, &fps->flags) ||
|
||||||
|
__put_user(0, &fps->extra) ||
|
||||||
|
__put_user(0, &fps->fpqd) ||
|
||||||
|
clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
|
||||||
|
ret = -EFAULT;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -889,15 +851,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
||||||
unsigned long fsr;
|
unsigned long fsr;
|
||||||
};
|
};
|
||||||
struct fps __user *fps = (struct fps __user *) addr;
|
struct fps __user *fps = (struct fps __user *) addr;
|
||||||
unsigned long *fpregs = task_thread_info(child)->fpregs;
|
|
||||||
|
|
||||||
ret = -EFAULT;
|
ret = copy_regset_to_user(child, view, REGSET_FP,
|
||||||
if (copy_to_user(&fps->regs[0], fpregs,
|
0 * sizeof(u64),
|
||||||
(64 * sizeof(unsigned int))) ||
|
33 * sizeof(u64),
|
||||||
__put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)))
|
fps);
|
||||||
break;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -914,21 +872,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
||||||
} fpq[16];
|
} fpq[16];
|
||||||
};
|
};
|
||||||
struct fps __user *fps = (struct fps __user *) addr;
|
struct fps __user *fps = (struct fps __user *) addr;
|
||||||
unsigned long *fpregs = task_thread_info(child)->fpregs;
|
|
||||||
unsigned fsr;
|
|
||||||
|
|
||||||
ret = -EFAULT;
|
ret = copy_regset_from_user(child, view, REGSET_FP,
|
||||||
if (copy_from_user(fpregs, &fps->regs[0],
|
0 * sizeof(u32),
|
||||||
(32 * sizeof(unsigned int))) ||
|
32 * sizeof(u32),
|
||||||
__get_user(fsr, (&fps->fsr)))
|
&fps->regs[0]);
|
||||||
break;
|
if (!ret)
|
||||||
|
ret = copy_regset_from_user(child, view, REGSET_FP,
|
||||||
task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL;
|
33 * sizeof(u32),
|
||||||
task_thread_info(child)->xfsr[0] |= fsr;
|
1 * sizeof(u32),
|
||||||
if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
|
&fps->fsr);
|
||||||
task_thread_info(child)->gsr[0] = 0;
|
|
||||||
task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL);
|
|
||||||
ret = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -938,19 +891,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
||||||
unsigned long fsr;
|
unsigned long fsr;
|
||||||
};
|
};
|
||||||
struct fps __user *fps = (struct fps __user *) addr;
|
struct fps __user *fps = (struct fps __user *) addr;
|
||||||
unsigned long *fpregs = task_thread_info(child)->fpregs;
|
|
||||||
|
|
||||||
ret = -EFAULT;
|
ret = copy_regset_to_user(child, view, REGSET_FP,
|
||||||
if (copy_from_user(fpregs, &fps->regs[0],
|
0 * sizeof(u64),
|
||||||
(64 * sizeof(unsigned int))) ||
|
33 * sizeof(u64),
|
||||||
__get_user(task_thread_info(child)->xfsr[0], (&fps->fsr)))
|
fps);
|
||||||
break;
|
|
||||||
|
|
||||||
if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
|
|
||||||
task_thread_info(child)->gsr[0] = 0;
|
|
||||||
task_thread_info(child)->fpsaved[0] |=
|
|
||||||
(FPRS_FEF | FPRS_DL | FPRS_DU);
|
|
||||||
ret = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue