diff options
-rw-r--r-- | arch/xtensa/kernel/ptrace.c | 66 | ||||
-rw-r--r-- | 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 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 | ||
74 | int ptrace_setregs(struct task_struct *child, void __user *uregs) | 71 | int 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 | ||