in kernel/ptrace.c [68:118]
static int gpr_set(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf)
{
int ret;
struct user_pt_regs newregs = {0};
struct pt_regs *regs;
const u32 ps_mask = PS_CALLINC_MASK | PS_OWB_MASK;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
if (ret)
return ret;
if (newregs.windowbase >= XCHAL_NUM_AREGS / 4)
return -EINVAL;
regs = task_pt_regs(target);
regs->pc = newregs.pc;
regs->ps = (regs->ps & ~ps_mask) | (newregs.ps & ps_mask);
regs->lbeg = newregs.lbeg;
regs->lend = newregs.lend;
regs->lcount = newregs.lcount;
regs->sar = newregs.sar;
regs->threadptr = newregs.threadptr;
if (newregs.syscall)
regs->syscall = newregs.syscall;
if (newregs.windowbase != regs->windowbase ||
newregs.windowstart != regs->windowstart) {
u32 rotws, wmask;
rotws = (((newregs.windowstart |
(newregs.windowstart << WSBITS)) >>
newregs.windowbase) &
((1 << WSBITS) - 1)) & ~1;
wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) |
(rotws & 0xF) | 1;
regs->windowbase = newregs.windowbase;
regs->windowstart = newregs.windowstart;
regs->wmask = wmask;
}
memcpy(regs->areg + XCHAL_NUM_AREGS - newregs.windowbase * 4,
newregs.a, newregs.windowbase * 16);
memcpy(regs->areg, newregs.a + newregs.windowbase * 4,
(WSBITS - newregs.windowbase) * 16);
return 0;
}