mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 01:54:09 +08:00
xtensa: complete ptrace handling of register windows
Compute WindowBase and WindowMask registers correctly on ptrace calls. Work done earlier by Maxim, Christian and Marc. Signed-off-by: Marc Gauthier <marc@tensilica.com> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Signed-off-by: Chris Zankel <chris@zankel.net>
This commit is contained in:
parent
e6ffe17ec4
commit
4b2bb03f10
@ -53,9 +53,8 @@ int ptrace_getregs(struct task_struct *child, void __user *uregs)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(child);
|
||||
xtensa_gregset_t __user *gregset = uregs;
|
||||
unsigned long wm = regs->wmask;
|
||||
unsigned long wb = regs->windowbase;
|
||||
int live, i;
|
||||
int i;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t)))
|
||||
return -EIO;
|
||||
@ -68,12 +67,9 @@ int ptrace_getregs(struct task_struct *child, void __user *uregs)
|
||||
__put_user(regs->windowstart, &gregset->windowstart);
|
||||
__put_user(regs->windowbase, &gregset->windowbase);
|
||||
|
||||
live = (wm & 2) ? 4 : (wm & 4) ? 8 : (wm & 8) ? 12 : 16;
|
||||
|
||||
for (i = 0; i < live; i++)
|
||||
__put_user(regs->areg[i],gregset->a+((wb*4+i)%XCHAL_NUM_AREGS));
|
||||
for (i = XCHAL_NUM_AREGS - (wm >> 4) * 4; i < XCHAL_NUM_AREGS; i++)
|
||||
__put_user(regs->areg[i],gregset->a+((wb*4+i)%XCHAL_NUM_AREGS));
|
||||
for (i = 0; i < XCHAL_NUM_AREGS; i++)
|
||||
__put_user(regs->areg[i],
|
||||
gregset->a + ((wb * 4 + i) % XCHAL_NUM_AREGS));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -84,7 +80,7 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs)
|
||||
xtensa_gregset_t *gregset = uregs;
|
||||
const unsigned long ps_mask = PS_CALLINC_MASK | PS_OWB_MASK;
|
||||
unsigned long ps;
|
||||
unsigned long wb;
|
||||
unsigned long wb, ws;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t)))
|
||||
return -EIO;
|
||||
@ -94,7 +90,7 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs)
|
||||
__get_user(regs->lbeg, &gregset->lbeg);
|
||||
__get_user(regs->lend, &gregset->lend);
|
||||
__get_user(regs->lcount, &gregset->lcount);
|
||||
__get_user(regs->windowstart, &gregset->windowstart);
|
||||
__get_user(ws, &gregset->windowstart);
|
||||
__get_user(wb, &gregset->windowbase);
|
||||
|
||||
regs->ps = (regs->ps & ~ps_mask) | (ps & ps_mask) | (1 << PS_EXCM_BIT);
|
||||
@ -102,13 +98,24 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs)
|
||||
if (wb >= XCHAL_NUM_AREGS / 4)
|
||||
return -EFAULT;
|
||||
|
||||
regs->windowbase = wb;
|
||||
if (wb != regs->windowbase || ws != regs->windowstart) {
|
||||
unsigned long rotws, wmask;
|
||||
|
||||
rotws = (((ws | (ws << WSBITS)) >> wb) &
|
||||
((1 << WSBITS) - 1)) & ~1;
|
||||
wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) |
|
||||
(rotws & 0xF) | 1;
|
||||
regs->windowbase = wb;
|
||||
regs->windowstart = ws;
|
||||
regs->wmask = wmask;
|
||||
}
|
||||
|
||||
if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4,
|
||||
gregset->a, wb * 16))
|
||||
gregset->a, wb * 16))
|
||||
return -EFAULT;
|
||||
|
||||
if (__copy_from_user(regs->areg, gregset->a + wb*4, (WSBITS-wb) * 16))
|
||||
if (__copy_from_user(regs->areg, gregset->a + wb * 4,
|
||||
(WSBITS - wb) * 16))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user