aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/xtensa/kernel/ptrace.c66
-rw-r--r--include/asm-xtensa/elf.h3
2 files changed, 37 insertions, 32 deletions
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index f6669d605125..9486882ef0af 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)
43{ 43{
44 struct pt_regs *regs = task_pt_regs(child); 44 struct pt_regs *regs = task_pt_regs(child);
45 xtensa_gregset_t __user *gregset = uregs; 45 xtensa_gregset_t __user *gregset = uregs;
46 unsigned long wb = regs->windowbase;
47 unsigned long ws = regs->windowstart;
48 unsigned long wm = regs->wmask; 46 unsigned long wm = regs->wmask;
49 int ret = 0; 47 unsigned long wb = regs->windowbase;
50 int live, last; 48 int live, i;
51 49
52 if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t))) 50 if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t)))
53 return -EIO; 51 return -EIO;
54 52
55 /* Norm windowstart to a windowbase of 0. */ 53 __put_user(regs->pc, &gregset->pc);
56 54 __put_user(regs->ps & ~(1 << PS_EXCM_BIT), &gregset->ps);
57 ws = ((ws>>wb) | (ws<<(WSBITS-wb))) & ((1<<WSBITS)-1); 55 __put_user(regs->lbeg, &gregset->lbeg);
58 56 __put_user(regs->lend, &gregset->lend);
59 ret |= __put_user(regs->pc, &gregset->pc); 57 __put_user(regs->lcount, &gregset->lcount);
60 ret |= __put_user(regs->ps & ~(1 << PS_EXCM_BIT), &gregset->ps); 58 __put_user(regs->windowstart, &gregset->windowstart);
61 ret |= __put_user(regs->lbeg, &gregset->lbeg); 59 __put_user(regs->windowbase, &gregset->windowbase);
62 ret |= __put_user(regs->lend, &gregset->lend);
63 ret |= __put_user(regs->lcount, &gregset->lcount);
64 ret |= __put_user(ws, &gregset->windowstart);
65 60
66 live = (wm & 2) ? 4 : (wm & 4) ? 8 : (wm & 8) ? 12 : 16; 61 live = (wm & 2) ? 4 : (wm & 4) ? 8 : (wm & 8) ? 12 : 16;
67 last = XCHAL_NUM_AREGS - (wm >> 4) * 4;
68 ret |= __copy_to_user(gregset->a, regs->areg, live * 4);
69 ret |= __copy_to_user(gregset->a + last, regs->areg + last, (wm>>4)*16);
70 62
71 return ret ? -EFAULT : 0; 63 for (i = 0; i < live; i++)
64 __put_user(regs->areg[i],gregset->a+((wb*4+i)%XCHAL_NUM_AREGS));
65 for (i = XCHAL_NUM_AREGS - (wm >> 4) * 4; i < XCHAL_NUM_AREGS; i++)
66 __put_user(regs->areg[i],gregset->a+((wb*4+i)%XCHAL_NUM_AREGS));
67
68 return 0;
72} 69}
73 70
74int ptrace_setregs(struct task_struct *child, void __user *uregs) 71int ptrace_setregs(struct task_struct *child, void __user *uregs)
@@ -76,28 +73,35 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs)
76 struct pt_regs *regs = task_pt_regs(child); 73 struct pt_regs *regs = task_pt_regs(child);
77 xtensa_gregset_t *gregset = uregs; 74 xtensa_gregset_t *gregset = uregs;
78 const unsigned long ps_mask = PS_CALLINC_MASK | PS_OWB_MASK; 75 const unsigned long ps_mask = PS_CALLINC_MASK | PS_OWB_MASK;
79 unsigned long wm = regs->wmask;
80 unsigned long ps; 76 unsigned long ps;
81 int ret = 0; 77 unsigned long wb;
82 int live, last;
83 78
84 if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t))) 79 if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t)))
85 return -EIO; 80 return -EIO;
86 81
87 ret |= __get_user(regs->pc, &gregset->pc); 82 __get_user(regs->pc, &gregset->pc);
88 ret |= __get_user(ps, &gregset->ps); 83 __get_user(ps, &gregset->ps);
89 ret |= __get_user(regs->lbeg, &gregset->lbeg); 84 __get_user(regs->lbeg, &gregset->lbeg);
90 ret |= __get_user(regs->lend, &gregset->lend); 85 __get_user(regs->lend, &gregset->lend);
91 ret |= __get_user(regs->lcount, &gregset->lcount); 86 __get_user(regs->lcount, &gregset->lcount);
87 __get_user(regs->windowstart, &gregset->windowstart);
88 __get_user(wb, &gregset->windowbase);
92 89
93 regs->ps = (regs->ps & ~ps_mask) | (ps & ps_mask) | (1 << PS_EXCM_BIT); 90 regs->ps = (regs->ps & ~ps_mask) | (ps & ps_mask) | (1 << PS_EXCM_BIT);
94 91
95 live = (wm & 2) ? 4 : (wm & 4) ? 8 : (wm & 8) ? 12 : 16; 92 if (wb >= XCHAL_NUM_AREGS / 4)
96 last = XCHAL_NUM_AREGS - (wm >> 4) * 4; 93 return -EFAULT;
97 ret |= __copy_from_user(regs->areg, gregset->a, live * 4);
98 ret |= __copy_from_user(regs->areg+last, gregset->a+last, (wm>>4)*16);
99 94
100 return ret ? -EFAULT : 0; 95 regs->windowbase = wb;
96
97 if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4,
98 gregset->a, wb * 16))
99 return -EFAULT;
100
101 if (__copy_from_user(regs->areg, gregset->a + wb*4, (WSBITS-wb) * 16))
102 return -EFAULT;
103
104 return 0;
101} 105}
102 106
103 107
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
index 11103e07d028..ca6e5101a2cb 100644
--- a/include/asm-xtensa/elf.h
+++ b/include/asm-xtensa/elf.h
@@ -82,7 +82,8 @@ typedef struct {
82 elf_greg_t lcount; 82 elf_greg_t lcount;
83 elf_greg_t sar; 83 elf_greg_t sar;
84 elf_greg_t windowstart; 84 elf_greg_t windowstart;
85 elf_greg_t reserved[9+48]; 85 elf_greg_t windowbase;
86 elf_greg_t reserved[8+48];
86 elf_greg_t a[64]; 87 elf_greg_t a[64];
87} xtensa_gregset_t; 88} xtensa_gregset_t;
88 89