Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=42086cec3263b8c015ca3faa01e8190f0e3ff445
Commit:     42086cec3263b8c015ca3faa01e8190f0e3ff445
Parent:     bdd362ff4ff8dc0c697ce87dbb337f3b7341fc46
Author:     Chris Zankel <[EMAIL PROTECTED]>
AuthorDate: Mon Jan 28 15:55:01 2008 -0800
Committer:  Chris Zankel <[EMAIL PROTECTED]>
CommitDate: Wed Feb 13 17:45:36 2008 -0800

    [XTENSA] Allow debugger to modify the WINDOWBASE register.
    
    For the 'return' command, GDB needs to adjust WINDOWBASE.
    In case WB is different from 0, we need to rotate the
    window register file and update WINDOWSTART and WMASK.
    This patch also removes some ret|= statements for
    __get_user/__put_user as the address range was alrady
    checked a couple of lines earlier.
    
    Signed-off-by: Chris Zankel <[EMAIL PROTECTED]>
---
 arch/xtensa/kernel/ptrace.c |   66 ++++++++++++++++++++++--------------------
 include/asm-xtensa/elf.h    |    3 +-
 2 files changed, 37 insertions(+), 32 deletions(-)

diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index f6669d6..9486882 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -43,32 +43,29 @@ 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 wb = regs->windowbase;
-       unsigned long ws = regs->windowstart;
        unsigned long wm = regs->wmask;
-       int ret = 0;
-       int live, last;
+       unsigned long wb = regs->windowbase;
+       int live, i;
 
        if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t)))
                return -EIO;
 
-       /* Norm windowstart to a windowbase of 0. */
-
-       ws = ((ws>>wb) | (ws<<(WSBITS-wb))) & ((1<<WSBITS)-1);
-
-       ret |= __put_user(regs->pc, &gregset->pc);
-       ret |= __put_user(regs->ps & ~(1 << PS_EXCM_BIT), &gregset->ps);
-       ret |= __put_user(regs->lbeg, &gregset->lbeg);
-       ret |= __put_user(regs->lend, &gregset->lend);
-       ret |= __put_user(regs->lcount, &gregset->lcount);
-       ret |= __put_user(ws, &gregset->windowstart);
+       __put_user(regs->pc, &gregset->pc);
+       __put_user(regs->ps & ~(1 << PS_EXCM_BIT), &gregset->ps);
+       __put_user(regs->lbeg, &gregset->lbeg);
+       __put_user(regs->lend, &gregset->lend);
+       __put_user(regs->lcount, &gregset->lcount);
+       __put_user(regs->windowstart, &gregset->windowstart);
+       __put_user(regs->windowbase, &gregset->windowbase);
 
        live = (wm & 2) ? 4 : (wm & 4) ? 8 : (wm & 8) ? 12 : 16;
-       last = XCHAL_NUM_AREGS - (wm >> 4) * 4;
-       ret |= __copy_to_user(gregset->a, regs->areg, live * 4);
-       ret |= __copy_to_user(gregset->a + last, regs->areg + last, (wm>>4)*16);
 
-       return ret ? -EFAULT : 0;
+       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));
+
+       return 0;
 }
 
 int ptrace_setregs(struct task_struct *child, void __user *uregs)
@@ -76,28 +73,35 @@ int ptrace_setregs(struct task_struct *child, void __user 
*uregs)
        struct pt_regs *regs = task_pt_regs(child);
        xtensa_gregset_t *gregset = uregs;
        const unsigned long ps_mask = PS_CALLINC_MASK | PS_OWB_MASK;
-       unsigned long wm = regs->wmask;
        unsigned long ps;
-       int ret = 0;
-       int live, last;
+       unsigned long wb;
 
        if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t)))
                return -EIO;
 
-       ret |= __get_user(regs->pc, &gregset->pc);
-       ret |= __get_user(ps, &gregset->ps);
-       ret |= __get_user(regs->lbeg, &gregset->lbeg);
-       ret |= __get_user(regs->lend, &gregset->lend);
-       ret |= __get_user(regs->lcount, &gregset->lcount);
+       __get_user(regs->pc, &gregset->pc);
+       __get_user(ps, &gregset->ps);
+       __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(wb, &gregset->windowbase);
 
        regs->ps = (regs->ps & ~ps_mask) | (ps & ps_mask) | (1 << PS_EXCM_BIT);
 
-       live = (wm & 2) ? 4 : (wm & 4) ? 8 : (wm & 8) ? 12 : 16;
-       last = XCHAL_NUM_AREGS - (wm >> 4) * 4;
-       ret |= __copy_from_user(regs->areg, gregset->a, live * 4);
-       ret |= __copy_from_user(regs->areg+last, gregset->a+last, (wm>>4)*16);
+       if (wb >= XCHAL_NUM_AREGS / 4)
+               return -EFAULT;
 
-       return ret ? -EFAULT : 0;
+       regs->windowbase = wb;
+
+       if (wb != 0 &&  __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4,
+                                        gregset->a, wb * 16))
+               return -EFAULT;
+
+       if (__copy_from_user(regs->areg, gregset->a + wb*4, (WSBITS-wb) * 16))
+               return -EFAULT;
+
+       return 0;
 }
 
 
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
index 11103e0..ca6e510 100644
--- a/include/asm-xtensa/elf.h
+++ b/include/asm-xtensa/elf.h
@@ -82,7 +82,8 @@ typedef struct {
        elf_greg_t lcount;
        elf_greg_t sar;
        elf_greg_t windowstart;
-       elf_greg_t reserved[9+48];
+       elf_greg_t windowbase;
+       elf_greg_t reserved[8+48];
        elf_greg_t a[64];
 } xtensa_gregset_t;
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to