Commit 0afc2edfada50980bec999f94dcea26ebad3dda6

Authored by Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
  [SPARC32]: Use regsets in arch_ptrace().
  [SPARC64]: Use regsets in arch_ptrace().
  [SPARC32]: Use regsets for ELF core dumping.
  [SPARC64]: Use regsets for ELF core dumping.
  [SPARC64]: Remove unintentional ptrace debugging messages.
  [SPARC]: Move over to arch_ptrace().
  [SPARC]: Remove PTRACE_SUN* handling.
  [SPARC]: Kill DEBUG_PTRACE code.
  [SPARC32]: Add user regset support.
  [SPARC64]: Add user regsets.
  [SPARC64]: Fix booting on non-zero cpu.

Showing 11 changed files Side-by-side Diff

arch/sparc/kernel/entry.S
... ... @@ -1224,23 +1224,6 @@
1224 1224 call c_sys_nis_syscall
1225 1225 mov %l5, %o7
1226 1226  
1227   - .align 4
1228   - .globl sys_ptrace
1229   -sys_ptrace:
1230   - call do_ptrace
1231   - add %sp, STACKFRAME_SZ, %o0
1232   -
1233   - ld [%curptr + TI_FLAGS], %l5
1234   - andcc %l5, _TIF_SYSCALL_TRACE, %g0
1235   - be 1f
1236   - nop
1237   -
1238   - call syscall_trace
1239   - nop
1240   -
1241   -1:
1242   - RESTORE_ALL
1243   -
1244 1227 .align 4
1245 1228 .globl sys_execve
1246 1229 sys_execve:
arch/sparc/kernel/ptrace.c
1 1 /* ptrace.c: Sparc process tracing support.
2 2 *
3   - * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
  3 + * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
4 4 *
5 5 * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
6 6 * and David Mosberger.
7 7  
8 8  
9 9  
10 10  
11 11  
12 12  
13 13  
14 14  
15 15  
16 16  
17 17  
18 18  
19 19  
20 20  
21 21  
22 22  
23 23  
24 24  
25 25  
26 26  
27 27  
28 28  
29 29  
30 30  
31 31  
32 32  
33 33  
34 34  
35 35  
36 36  
37 37  
38 38  
39 39  
40 40  
41 41  
42 42  
43 43  
44 44  
45 45  
... ... @@ -19,389 +19,343 @@
19 19 #include <linux/smp_lock.h>
20 20 #include <linux/security.h>
21 21 #include <linux/signal.h>
  22 +#include <linux/regset.h>
  23 +#include <linux/elf.h>
22 24  
23 25 #include <asm/pgtable.h>
24 26 #include <asm/system.h>
25 27 #include <asm/uaccess.h>
26 28  
27   -#define MAGIC_CONSTANT 0x80000000
  29 +/* #define ALLOW_INIT_TRACING */
28 30  
29   -
30   -/* Returning from ptrace is a bit tricky because the syscall return
31   - * low level code assumes any value returned which is negative and
32   - * is a valid errno will mean setting the condition codes to indicate
33   - * an error return. This doesn't work, so we have this hook.
  31 +/*
  32 + * Called by kernel/ptrace.c when detaching..
  33 + *
  34 + * Make sure single step bits etc are not set.
34 35 */
35   -static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
  36 +void ptrace_disable(struct task_struct *child)
36 37 {
37   - regs->u_regs[UREG_I0] = error;
38   - regs->psr |= PSR_C;
39   - regs->pc = regs->npc;
40   - regs->npc += 4;
  38 + /* nothing to do */
41 39 }
42 40  
43   -static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
44   -{
45   - regs->u_regs[UREG_I0] = value;
46   - regs->psr &= ~PSR_C;
47   - regs->pc = regs->npc;
48   - regs->npc += 4;
49   -}
  41 +enum sparc_regset {
  42 + REGSET_GENERAL,
  43 + REGSET_FP,
  44 +};
50 45  
51   -static void
52   -pt_succ_return_linux(struct pt_regs *regs, unsigned long value, long __user *addr)
  46 +static int genregs32_get(struct task_struct *target,
  47 + const struct user_regset *regset,
  48 + unsigned int pos, unsigned int count,
  49 + void *kbuf, void __user *ubuf)
53 50 {
54   - if (put_user(value, addr)) {
55   - pt_error_return(regs, EFAULT);
56   - return;
57   - }
58   - regs->u_regs[UREG_I0] = 0;
59   - regs->psr &= ~PSR_C;
60   - regs->pc = regs->npc;
61   - regs->npc += 4;
62   -}
  51 + const struct pt_regs *regs = target->thread.kregs;
  52 + unsigned long __user *reg_window;
  53 + unsigned long *k = kbuf;
  54 + unsigned long __user *u = ubuf;
  55 + unsigned long reg;
63 56  
64   -static void
65   -pt_os_succ_return (struct pt_regs *regs, unsigned long val, long __user *addr)
66   -{
67   - if (current->personality == PER_SUNOS)
68   - pt_succ_return (regs, val);
69   - else
70   - pt_succ_return_linux (regs, val, addr);
71   -}
  57 + if (target == current)
  58 + flush_user_windows();
72 59  
73   -/* Fuck me gently with a chainsaw... */
74   -static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset,
75   - struct task_struct *tsk, long __user *addr)
76   -{
77   - struct pt_regs *cregs = tsk->thread.kregs;
78   - struct thread_info *t = task_thread_info(tsk);
79   - int v;
80   -
81   - if(offset >= 1024)
82   - offset -= 1024; /* whee... */
83   - if(offset & ((sizeof(unsigned long) - 1))) {
84   - pt_error_return(regs, EIO);
85   - return;
86   - }
87   - if(offset >= 16 && offset < 784) {
88   - offset -= 16; offset >>= 2;
89   - pt_os_succ_return(regs, *(((unsigned long *)(&t->reg_window[0]))+offset), addr);
90   - return;
91   - }
92   - if(offset >= 784 && offset < 832) {
93   - offset -= 784; offset >>= 2;
94   - pt_os_succ_return(regs, *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset), addr);
95   - return;
96   - }
97   - switch(offset) {
98   - case 0:
99   - v = t->ksp;
100   - break;
101   - case 4:
102   - v = t->kpc;
103   - break;
104   - case 8:
105   - v = t->kpsr;
106   - break;
107   - case 12:
108   - v = t->uwinmask;
109   - break;
110   - case 832:
111   - v = t->w_saved;
112   - break;
113   - case 896:
114   - v = cregs->u_regs[UREG_I0];
115   - break;
116   - case 900:
117   - v = cregs->u_regs[UREG_I1];
118   - break;
119   - case 904:
120   - v = cregs->u_regs[UREG_I2];
121   - break;
122   - case 908:
123   - v = cregs->u_regs[UREG_I3];
124   - break;
125   - case 912:
126   - v = cregs->u_regs[UREG_I4];
127   - break;
128   - case 916:
129   - v = cregs->u_regs[UREG_I5];
130   - break;
131   - case 920:
132   - v = cregs->u_regs[UREG_I6];
133   - break;
134   - case 924:
135   - if(tsk->thread.flags & MAGIC_CONSTANT)
136   - v = cregs->u_regs[UREG_G1];
137   - else
138   - v = 0;
139   - break;
140   - case 940:
141   - v = cregs->u_regs[UREG_I0];
142   - break;
143   - case 944:
144   - v = cregs->u_regs[UREG_I1];
145   - break;
  60 + pos /= sizeof(reg);
  61 + count /= sizeof(reg);
146 62  
147   - case 948:
148   - /* Isn't binary compatibility _fun_??? */
149   - if(cregs->psr & PSR_C)
150   - v = cregs->u_regs[UREG_I0] << 24;
151   - else
152   - v = 0;
153   - break;
  63 + if (kbuf) {
  64 + for (; count > 0 && pos < 16; count--)
  65 + *k++ = regs->u_regs[pos++];
154 66  
155   - /* Rest of them are completely unsupported. */
156   - default:
157   - printk("%s [%d]: Wants to read user offset %ld\n",
158   - current->comm, task_pid_nr(current), offset);
159   - pt_error_return(regs, EIO);
160   - return;
  67 + reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
  68 + for (; count > 0 && pos < 32; count--) {
  69 + if (get_user(*k++, &reg_window[pos++]))
  70 + return -EFAULT;
  71 + }
  72 + } else {
  73 + for (; count > 0 && pos < 16; count--) {
  74 + if (put_user(regs->u_regs[pos++], u++))
  75 + return -EFAULT;
  76 + }
  77 +
  78 + reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
  79 + for (; count > 0 && pos < 32; count--) {
  80 + if (get_user(reg, &reg_window[pos++]) ||
  81 + put_user(reg, u++))
  82 + return -EFAULT;
  83 + }
161 84 }
162   - if (current->personality == PER_SUNOS)
163   - pt_succ_return (regs, v);
164   - else
165   - pt_succ_return_linux (regs, v, addr);
166   - return;
  85 + while (count > 0) {
  86 + switch (pos) {
  87 + case 32: /* PSR */
  88 + reg = regs->psr;
  89 + break;
  90 + case 33: /* PC */
  91 + reg = regs->pc;
  92 + break;
  93 + case 34: /* NPC */
  94 + reg = regs->npc;
  95 + break;
  96 + case 35: /* Y */
  97 + reg = regs->y;
  98 + break;
  99 + case 36: /* WIM */
  100 + case 37: /* TBR */
  101 + reg = 0;
  102 + break;
  103 + default:
  104 + goto finish;
  105 + }
  106 +
  107 + if (kbuf)
  108 + *k++ = reg;
  109 + else if (put_user(reg, u++))
  110 + return -EFAULT;
  111 + pos++;
  112 + count--;
  113 + }
  114 +finish:
  115 + pos *= sizeof(reg);
  116 + count *= sizeof(reg);
  117 +
  118 + return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  119 + 38 * sizeof(reg), -1);
167 120 }
168 121  
169   -static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset,
170   - struct task_struct *tsk)
  122 +static int genregs32_set(struct task_struct *target,
  123 + const struct user_regset *regset,
  124 + unsigned int pos, unsigned int count,
  125 + const void *kbuf, const void __user *ubuf)
171 126 {
172   - struct pt_regs *cregs = tsk->thread.kregs;
173   - struct thread_info *t = task_thread_info(tsk);
174   - unsigned long value = regs->u_regs[UREG_I3];
  127 + struct pt_regs *regs = target->thread.kregs;
  128 + unsigned long __user *reg_window;
  129 + const unsigned long *k = kbuf;
  130 + const unsigned long __user *u = ubuf;
  131 + unsigned long reg;
175 132  
176   - if(offset >= 1024)
177   - offset -= 1024; /* whee... */
178   - if(offset & ((sizeof(unsigned long) - 1)))
179   - goto failure;
180   - if(offset >= 16 && offset < 784) {
181   - offset -= 16; offset >>= 2;
182   - *(((unsigned long *)(&t->reg_window[0]))+offset) = value;
183   - goto success;
184   - }
185   - if(offset >= 784 && offset < 832) {
186   - offset -= 784; offset >>= 2;
187   - *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset) = value;
188   - goto success;
189   - }
190   - switch(offset) {
191   - case 896:
192   - cregs->u_regs[UREG_I0] = value;
193   - break;
194   - case 900:
195   - cregs->u_regs[UREG_I1] = value;
196   - break;
197   - case 904:
198   - cregs->u_regs[UREG_I2] = value;
199   - break;
200   - case 908:
201   - cregs->u_regs[UREG_I3] = value;
202   - break;
203   - case 912:
204   - cregs->u_regs[UREG_I4] = value;
205   - break;
206   - case 916:
207   - cregs->u_regs[UREG_I5] = value;
208   - break;
209   - case 920:
210   - cregs->u_regs[UREG_I6] = value;
211   - break;
212   - case 924:
213   - cregs->u_regs[UREG_I7] = value;
214   - break;
215   - case 940:
216   - cregs->u_regs[UREG_I0] = value;
217   - break;
218   - case 944:
219   - cregs->u_regs[UREG_I1] = value;
220   - break;
  133 + if (target == current)
  134 + flush_user_windows();
221 135  
222   - /* Rest of them are completely unsupported or "no-touch". */
223   - default:
224   - printk("%s [%d]: Wants to write user offset %ld\n",
225   - current->comm, task_pid_nr(current), offset);
226   - goto failure;
  136 + pos /= sizeof(reg);
  137 + count /= sizeof(reg);
  138 +
  139 + if (kbuf) {
  140 + for (; count > 0 && pos < 16; count--)
  141 + regs->u_regs[pos++] = *k++;
  142 +
  143 + reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
  144 + for (; count > 0 && pos < 32; count--) {
  145 + if (put_user(*k++, &reg_window[pos++]))
  146 + return -EFAULT;
  147 + }
  148 + } else {
  149 + for (; count > 0 && pos < 16; count--) {
  150 + if (get_user(reg, u++))
  151 + return -EFAULT;
  152 + regs->u_regs[pos++] = reg;
  153 + }
  154 +
  155 + reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
  156 + for (; count > 0 && pos < 32; count--) {
  157 + if (get_user(reg, u++) ||
  158 + put_user(reg, &reg_window[pos++]))
  159 + return -EFAULT;
  160 + }
227 161 }
228   -success:
229   - pt_succ_return(regs, 0);
230   - return;
231   -failure:
232   - pt_error_return(regs, EIO);
233   - return;
234   -}
  162 + while (count > 0) {
  163 + unsigned long psr;
235 164  
236   -/* #define ALLOW_INIT_TRACING */
237   -/* #define DEBUG_PTRACE */
  165 + if (kbuf)
  166 + reg = *k++;
  167 + else if (get_user(reg, u++))
  168 + return -EFAULT;
238 169  
239   -#ifdef DEBUG_PTRACE
240   -char *pt_rq [] = {
241   - /* 0 */ "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSR",
242   - /* 4 */ "POKETEXT", "POKEDATA", "POKEUSR", "CONT",
243   - /* 8 */ "KILL", "SINGLESTEP", "SUNATTACH", "SUNDETACH",
244   - /* 12 */ "GETREGS", "SETREGS", "GETFPREGS", "SETFPREGS",
245   - /* 16 */ "READDATA", "WRITEDATA", "READTEXT", "WRITETEXT",
246   - /* 20 */ "GETFPAREGS", "SETFPAREGS", "unknown", "unknown",
247   - /* 24 */ "SYSCALL", ""
248   -};
249   -#endif
  170 + switch (pos) {
  171 + case 32: /* PSR */
  172 + psr = regs->psr;
  173 + psr &= ~PSR_ICC;
  174 + psr |= (reg & PSR_ICC);
  175 + regs->psr = psr;
  176 + break;
  177 + case 33: /* PC */
  178 + regs->pc = reg;
  179 + break;
  180 + case 34: /* NPC */
  181 + regs->npc = reg;
  182 + break;
  183 + case 35: /* Y */
  184 + regs->y = reg;
  185 + break;
  186 + case 36: /* WIM */
  187 + case 37: /* TBR */
  188 + break;
  189 + default:
  190 + goto finish;
  191 + }
250 192  
251   -/*
252   - * Called by kernel/ptrace.c when detaching..
253   - *
254   - * Make sure single step bits etc are not set.
255   - */
256   -void ptrace_disable(struct task_struct *child)
257   -{
258   - /* nothing to do */
  193 + pos++;
  194 + count--;
  195 + }
  196 +finish:
  197 + pos *= sizeof(reg);
  198 + count *= sizeof(reg);
  199 +
  200 + return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  201 + 38 * sizeof(reg), -1);
259 202 }
260 203  
261   -asmlinkage void do_ptrace(struct pt_regs *regs)
  204 +static int fpregs32_get(struct task_struct *target,
  205 + const struct user_regset *regset,
  206 + unsigned int pos, unsigned int count,
  207 + void *kbuf, void __user *ubuf)
262 208 {
263   - unsigned long request = regs->u_regs[UREG_I0];
264   - unsigned long pid = regs->u_regs[UREG_I1];
265   - unsigned long addr = regs->u_regs[UREG_I2];
266   - unsigned long data = regs->u_regs[UREG_I3];
267   - unsigned long addr2 = regs->u_regs[UREG_I4];
268   - struct task_struct *child;
269   - int ret;
  209 + const unsigned long *fpregs = target->thread.float_regs;
  210 + int ret = 0;
270 211  
271   - lock_kernel();
272   -#ifdef DEBUG_PTRACE
273   - {
274   - char *s;
  212 +#if 0
  213 + if (target == current)
  214 + save_and_clear_fpu();
  215 +#endif
275 216  
276   - if ((request >= 0) && (request <= 24))
277   - s = pt_rq [request];
278   - else
279   - s = "unknown";
  217 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  218 + fpregs,
  219 + 0, 32 * sizeof(u32));
280 220  
281   - if (request == PTRACE_POKEDATA && data == 0x91d02001){
282   - printk ("do_ptrace: breakpoint pid=%d, addr=%08lx addr2=%08lx\n",
283   - pid, addr, addr2);
284   - } else
285   - printk("do_ptrace: rq=%s(%d) pid=%d addr=%08lx data=%08lx addr2=%08lx\n",
286   - s, (int) request, (int) pid, addr, data, addr2);
287   - }
288   -#endif
  221 + if (!ret)
  222 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  223 + 32 * sizeof(u32),
  224 + 33 * sizeof(u32));
  225 + if (!ret)
  226 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  227 + &target->thread.fsr,
  228 + 33 * sizeof(u32),
  229 + 34 * sizeof(u32));
289 230  
290   - if (request == PTRACE_TRACEME) {
291   - ret = ptrace_traceme();
292   - if (ret < 0)
293   - pt_error_return(regs, -ret);
294   - else
295   - pt_succ_return(regs, 0);
296   - goto out;
297   - }
  231 + if (!ret) {
  232 + unsigned long val;
298 233  
299   - child = ptrace_get_task_struct(pid);
300   - if (IS_ERR(child)) {
301   - ret = PTR_ERR(child);
302   - pt_error_return(regs, -ret);
303   - goto out;
  234 + val = (1 << 8) | (8 << 16);
  235 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  236 + &val,
  237 + 34 * sizeof(u32),
  238 + 35 * sizeof(u32));
304 239 }
305 240  
306   - if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
307   - || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
308   - if (ptrace_attach(child)) {
309   - pt_error_return(regs, EPERM);
310   - goto out_tsk;
311   - }
312   - pt_succ_return(regs, 0);
313   - goto out_tsk;
314   - }
  241 + if (!ret)
  242 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  243 + 35 * sizeof(u32), -1);
315 244  
316   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
317   - if (ret < 0) {
318   - pt_error_return(regs, -ret);
319   - goto out_tsk;
320   - }
  245 + return ret;
  246 +}
321 247  
322   - switch(request) {
323   - case PTRACE_PEEKTEXT: /* read word at location addr. */
324   - case PTRACE_PEEKDATA: {
325   - unsigned long tmp;
  248 +static int fpregs32_set(struct task_struct *target,
  249 + const struct user_regset *regset,
  250 + unsigned int pos, unsigned int count,
  251 + const void *kbuf, const void __user *ubuf)
  252 +{
  253 + unsigned long *fpregs = target->thread.float_regs;
  254 + int ret;
326 255  
327   - if (access_process_vm(child, addr,
328   - &tmp, sizeof(tmp), 0) == sizeof(tmp))
329   - pt_os_succ_return(regs, tmp, (long __user *)data);
330   - else
331   - pt_error_return(regs, EIO);
332   - goto out_tsk;
  256 +#if 0
  257 + if (target == current)
  258 + save_and_clear_fpu();
  259 +#endif
  260 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  261 + fpregs,
  262 + 0, 32 * sizeof(u32));
  263 + if (!ret)
  264 + user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  265 + 32 * sizeof(u32),
  266 + 33 * sizeof(u32));
  267 + if (!ret && count > 0) {
  268 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  269 + &target->thread.fsr,
  270 + 33 * sizeof(u32),
  271 + 34 * sizeof(u32));
333 272 }
334 273  
335   - case PTRACE_PEEKUSR:
336   - read_sunos_user(regs, addr, child, (long __user *) data);
337   - goto out_tsk;
  274 + if (!ret)
  275 + ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  276 + 34 * sizeof(u32), -1);
  277 + return ret;
  278 +}
338 279  
339   - case PTRACE_POKEUSR:
340   - write_sunos_user(regs, addr, child);
341   - goto out_tsk;
  280 +static const struct user_regset sparc32_regsets[] = {
  281 + /* Format is:
  282 + * G0 --> G7
  283 + * O0 --> O7
  284 + * L0 --> L7
  285 + * I0 --> I7
  286 + * PSR, PC, nPC, Y, WIM, TBR
  287 + */
  288 + [REGSET_GENERAL] = {
  289 + .core_note_type = NT_PRSTATUS,
  290 + .n = 38 * sizeof(u32),
  291 + .size = sizeof(u32), .align = sizeof(u32),
  292 + .get = genregs32_get, .set = genregs32_set
  293 + },
  294 + /* Format is:
  295 + * F0 --> F31
  296 + * empty 32-bit word
  297 + * FSR (32--bit word)
  298 + * FPU QUEUE COUNT (8-bit char)
  299 + * FPU QUEUE ENTRYSIZE (8-bit char)
  300 + * FPU ENABLED (8-bit char)
  301 + * empty 8-bit char
  302 + * FPU QUEUE (64 32-bit ints)
  303 + */
  304 + [REGSET_FP] = {
  305 + .core_note_type = NT_PRFPREG,
  306 + .n = 99 * sizeof(u32),
  307 + .size = sizeof(u32), .align = sizeof(u32),
  308 + .get = fpregs32_get, .set = fpregs32_set
  309 + },
  310 +};
342 311  
343   - case PTRACE_POKETEXT: /* write the word at location addr. */
344   - case PTRACE_POKEDATA: {
345   - if (access_process_vm(child, addr,
346   - &data, sizeof(data), 1) == sizeof(data))
347   - pt_succ_return(regs, 0);
348   - else
349   - pt_error_return(regs, EIO);
350   - goto out_tsk;
351   - }
  312 +static const struct user_regset_view user_sparc32_view = {
  313 + .name = "sparc", .e_machine = EM_SPARC,
  314 + .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
  315 +};
352 316  
  317 +const struct user_regset_view *task_user_regset_view(struct task_struct *task)
  318 +{
  319 + return &user_sparc32_view;
  320 +}
  321 +
  322 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
  323 +{
  324 + unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4];
  325 + const struct user_regset_view *view;
  326 + int ret;
  327 +
  328 + view = task_user_regset_view(child);
  329 +
  330 + switch(request) {
353 331 case PTRACE_GETREGS: {
354 332 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
355   - struct pt_regs *cregs = child->thread.kregs;
356   - int rval;
357 333  
358   - if (!access_ok(VERIFY_WRITE, pregs, sizeof(struct pt_regs))) {
359   - rval = -EFAULT;
360   - pt_error_return(regs, -rval);
361   - goto out_tsk;
362   - }
363   - __put_user(cregs->psr, (&pregs->psr));
364   - __put_user(cregs->pc, (&pregs->pc));
365   - __put_user(cregs->npc, (&pregs->npc));
366   - __put_user(cregs->y, (&pregs->y));
367   - for(rval = 1; rval < 16; rval++)
368   - __put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]));
369   - pt_succ_return(regs, 0);
370   -#ifdef DEBUG_PTRACE
371   - printk ("PC=%x nPC=%x o7=%x\n", cregs->pc, cregs->npc, cregs->u_regs [15]);
372   -#endif
373   - goto out_tsk;
  334 + ret = copy_regset_to_user(child, view, REGSET_GENERAL,
  335 + 32 * sizeof(u32),
  336 + 4 * sizeof(u32),
  337 + &pregs->psr);
  338 + if (!ret)
  339 + copy_regset_to_user(child, view, REGSET_GENERAL,
  340 + 1 * sizeof(u32),
  341 + 15 * sizeof(u32),
  342 + &pregs->u_regs[0]);
  343 + break;
374 344 }
375 345  
376 346 case PTRACE_SETREGS: {
377 347 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
378   - struct pt_regs *cregs = child->thread.kregs;
379   - unsigned long psr, pc, npc, y;
380   - int i;
381 348  
382   - /* Must be careful, tracing process can only set certain
383   - * bits in the psr.
384   - */
385   - if (!access_ok(VERIFY_READ, pregs, sizeof(struct pt_regs))) {
386   - pt_error_return(regs, EFAULT);
387   - goto out_tsk;
388   - }
389   - __get_user(psr, (&pregs->psr));
390   - __get_user(pc, (&pregs->pc));
391   - __get_user(npc, (&pregs->npc));
392   - __get_user(y, (&pregs->y));
393   - psr &= PSR_ICC;
394   - cregs->psr &= ~PSR_ICC;
395   - cregs->psr |= psr;
396   - if (!((pc | npc) & 3)) {
397   - cregs->pc = pc;
398   - cregs->npc =npc;
399   - }
400   - cregs->y = y;
401   - for(i = 1; i < 16; i++)
402   - __get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]));
403   - pt_succ_return(regs, 0);
404   - goto out_tsk;
  349 + ret = copy_regset_from_user(child, view, REGSET_GENERAL,
  350 + 32 * sizeof(u32),
  351 + 4 * sizeof(u32),
  352 + &pregs->psr);
  353 + if (!ret)
  354 + copy_regset_from_user(child, view, REGSET_GENERAL,
  355 + 1 * sizeof(u32),
  356 + 15 * sizeof(u32),
  357 + &pregs->u_regs[0]);
  358 + break;
405 359 }
406 360  
407 361 case PTRACE_GETFPREGS: {
408 362  
409 363  
... ... @@ -417,26 +371,25 @@
417 371 } fpq[16];
418 372 };
419 373 struct fps __user *fps = (struct fps __user *) addr;
420   - int i;
421 374  
422   - if (!access_ok(VERIFY_WRITE, fps, sizeof(struct fps))) {
423   - i = -EFAULT;
424   - pt_error_return(regs, -i);
425   - goto out_tsk;
  375 + ret = copy_regset_to_user(child, view, REGSET_FP,
  376 + 0 * sizeof(u32),
  377 + 32 * sizeof(u32),
  378 + &fps->regs[0]);
  379 + if (!ret)
  380 + ret = copy_regset_to_user(child, view, REGSET_FP,
  381 + 33 * sizeof(u32),
  382 + 1 * sizeof(u32),
  383 + &fps->fsr);
  384 +
  385 + if (!ret) {
  386 + if (__put_user(0, &fps->fpqd) ||
  387 + __put_user(0, &fps->flags) ||
  388 + __put_user(0, &fps->extra) ||
  389 + clear_user(fps->fpq, sizeof(fps->fpq)))
  390 + ret = -EFAULT;
426 391 }
427   - for(i = 0; i < 32; i++)
428   - __put_user(child->thread.float_regs[i], (&fps->regs[i]));
429   - __put_user(child->thread.fsr, (&fps->fsr));
430   - __put_user(child->thread.fpqdepth, (&fps->fpqd));
431   - __put_user(0, (&fps->flags));
432   - __put_user(0, (&fps->extra));
433   - for(i = 0; i < 16; i++) {
434   - __put_user(child->thread.fpqueue[i].insn_addr,
435   - (&fps->fpq[i].insnaddr));
436   - __put_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn));
437   - }
438   - pt_succ_return(regs, 0);
439   - goto out_tsk;
  392 + break;
440 393 }
441 394  
442 395 case PTRACE_SETFPREGS: {
443 396  
444 397  
445 398  
446 399  
447 400  
448 401  
449 402  
450 403  
451 404  
... ... @@ -452,137 +405,55 @@
452 405 } fpq[16];
453 406 };
454 407 struct fps __user *fps = (struct fps __user *) addr;
455   - int i;
456 408  
457   - if (!access_ok(VERIFY_READ, fps, sizeof(struct fps))) {
458   - i = -EFAULT;
459   - pt_error_return(regs, -i);
460   - goto out_tsk;
461   - }
462   - copy_from_user(&child->thread.float_regs[0], &fps->regs[0], (32 * sizeof(unsigned long)));
463   - __get_user(child->thread.fsr, (&fps->fsr));
464   - __get_user(child->thread.fpqdepth, (&fps->fpqd));
465   - for(i = 0; i < 16; i++) {
466   - __get_user(child->thread.fpqueue[i].insn_addr,
467   - (&fps->fpq[i].insnaddr));
468   - __get_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn));
469   - }
470   - pt_succ_return(regs, 0);
471   - goto out_tsk;
  409 + ret = copy_regset_from_user(child, view, REGSET_FP,
  410 + 0 * sizeof(u32),
  411 + 32 * sizeof(u32),
  412 + &fps->regs[0]);
  413 + if (!ret)
  414 + ret = copy_regset_from_user(child, view, REGSET_FP,
  415 + 33 * sizeof(u32),
  416 + 1 * sizeof(u32),
  417 + &fps->fsr);
  418 + break;
472 419 }
473 420  
474 421 case PTRACE_READTEXT:
475   - case PTRACE_READDATA: {
476   - int res = ptrace_readdata(child, addr,
477   - (void __user *) addr2, data);
  422 + case PTRACE_READDATA:
  423 + ret = ptrace_readdata(child, addr,
  424 + (void __user *) addr2, data);
478 425  
479   - if (res == data) {
480   - pt_succ_return(regs, 0);
481   - goto out_tsk;
482   - }
483   - /* Partial read is an IO failure */
484   - if (res >= 0)
485   - res = -EIO;
486   - pt_error_return(regs, -res);
487   - goto out_tsk;
488   - }
  426 + if (ret == data)
  427 + ret = 0;
  428 + else if (ret >= 0)
  429 + ret = -EIO;
  430 + break;
489 431  
490 432 case PTRACE_WRITETEXT:
491   - case PTRACE_WRITEDATA: {
492   - int res = ptrace_writedata(child, (void __user *) addr2,
493   - addr, data);
  433 + case PTRACE_WRITEDATA:
  434 + ret = ptrace_writedata(child, (void __user *) addr2,
  435 + addr, data);
494 436  
495   - if (res == data) {
496   - pt_succ_return(regs, 0);
497   - goto out_tsk;
498   - }
499   - /* Partial write is an IO failure */
500   - if (res >= 0)
501   - res = -EIO;
502   - pt_error_return(regs, -res);
503   - goto out_tsk;
504   - }
  437 + if (ret == data)
  438 + ret = 0;
  439 + else if (ret >= 0)
  440 + ret = -EIO;
  441 + break;
505 442  
506   - case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
507   - addr = 1;
508   -
509   - case PTRACE_CONT: { /* restart after signal. */
510   - if (!valid_signal(data)) {
511   - pt_error_return(regs, EIO);
512   - goto out_tsk;
513   - }
514   -
515   - if (request == PTRACE_SYSCALL)
516   - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
517   - else
518   - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
519   -
520   - child->exit_code = data;
521   -#ifdef DEBUG_PTRACE
522   - printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n",
523   - child->comm, child->pid, child->exit_code,
524   - child->thread.kregs->pc,
525   - child->thread.kregs->npc);
526   -#endif
527   - wake_up_process(child);
528   - pt_succ_return(regs, 0);
529   - goto out_tsk;
  443 + default:
  444 + ret = ptrace_request(child, request, addr, data);
  445 + break;
530 446 }
531 447  
532   -/*
533   - * make the child exit. Best I can do is send it a sigkill.
534   - * perhaps it should be put in the status that it wants to
535   - * exit.
536   - */
537   - case PTRACE_KILL: {
538   - if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
539   - pt_succ_return(regs, 0);
540   - goto out_tsk;
541   - }
542   - wake_up_process(child);
543   - child->exit_code = SIGKILL;
544   - pt_succ_return(regs, 0);
545   - goto out_tsk;
546   - }
547   -
548   - case PTRACE_SUNDETACH: { /* detach a process that was attached. */
549   - int err = ptrace_detach(child, data);
550   - if (err) {
551   - pt_error_return(regs, EIO);
552   - goto out_tsk;
553   - }
554   - pt_succ_return(regs, 0);
555   - goto out_tsk;
556   - }
557   -
558   - /* PTRACE_DUMPCORE unsupported... */
559   -
560   - default: {
561   - int err = ptrace_request(child, request, addr, data);
562   - if (err)
563   - pt_error_return(regs, -err);
564   - else
565   - pt_succ_return(regs, 0);
566   - goto out_tsk;
567   - }
568   - }
569   -out_tsk:
570   - if (child)
571   - put_task_struct(child);
572   -out:
573   - unlock_kernel();
  448 + return ret;
574 449 }
575 450  
576 451 asmlinkage void syscall_trace(void)
577 452 {
578   -#ifdef DEBUG_PTRACE
579   - printk("%s [%d]: syscall_trace\n", current->comm, current->pid);
580   -#endif
581 453 if (!test_thread_flag(TIF_SYSCALL_TRACE))
582 454 return;
583 455 if (!(current->ptrace & PT_PTRACED))
584 456 return;
585   - current->thread.flags ^= MAGIC_CONSTANT;
586 457 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
587 458 ? 0x80 : 0));
588 459 /*
... ... @@ -590,10 +461,6 @@
590 461 * for normal use. strace only continues with a signal if the
591 462 * stopping signal is not SIGTRAP. -brl
592 463 */
593   -#ifdef DEBUG_PTRACE
594   - printk("%s [%d]: syscall_trace exit= %x\n", current->comm,
595   - current->pid, current->exit_code);
596   -#endif
597 464 if (current->exit_code) {
598 465 send_sig (current->exit_code, current, 1);
599 466 current->exit_code = 0;
arch/sparc64/kernel/binfmt_elf32.c
1 1 /*
2 2 * binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra.
3 3 *
4   - * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@davemloft.net)
  4 + * Copyright (C) 1995, 1996, 1997, 1998, 2008 David S. Miller (davem@davemloft.net)
5 5 * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz)
6 6 */
7 7  
... ... @@ -9,13 +9,6 @@
9 9 #define ELF_CLASS ELFCLASS32
10 10 #define ELF_DATA ELFDATA2MSB;
11 11  
12   -/* For the most part we present code dumps in the format
13   - * Solaris does.
14   - */
15   -typedef unsigned int elf_greg_t;
16   -#define ELF_NGREG 38
17   -typedef elf_greg_t elf_gregset_t[ELF_NGREG];
18   -
19 12 /* Format is:
20 13 * G0 --> G7
21 14 * O0 --> O7
... ... @@ -23,25 +16,9 @@
23 16 * I0 --> I7
24 17 * PSR, PC, nPC, Y, WIM, TBR
25 18 */
26   -#include <asm/psrcompat.h>
27   -#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \
28   -do { unsigned int *dest = &(__elf_regs[0]); \
29   - struct pt_regs *src = (__pt_regs); \
30   - unsigned int __user *sp; \
31   - int i; \
32   - for(i = 0; i < 16; i++) \
33   - dest[i] = (unsigned int) src->u_regs[i];\
34   - /* Don't try this at home kids... */ \
35   - sp = (unsigned int __user *) (src->u_regs[14] & \
36   - 0x00000000fffffffc); \
37   - for(i = 0; i < 16; i++) \
38   - __get_user(dest[i+16], &sp[i]); \
39   - dest[32] = tstate_to_psr(src->tstate); \
40   - dest[33] = (unsigned int) src->tpc; \
41   - dest[34] = (unsigned int) src->tnpc; \
42   - dest[35] = src->y; \
43   - dest[36] = dest[37] = 0; /* XXX */ \
44   -} while(0);
  19 +typedef unsigned int elf_greg_t;
  20 +#define ELF_NGREG 38
  21 +typedef elf_greg_t elf_gregset_t[ELF_NGREG];
45 22  
46 23 typedef struct {
47 24 union {
arch/sparc64/kernel/entry.S
... ... @@ -1477,10 +1477,6 @@
1477 1477 add %o7, 1f-.-4, %o7
1478 1478 nop
1479 1479 #endif
1480   -sys_ptrace: add %sp, PTREGS_OFF, %o0
1481   - call do_ptrace
1482   - add %o7, 1f-.-4, %o7
1483   - nop
1484 1480 .align 32
1485 1481 1: ldx [%curptr + TI_FLAGS], %l5
1486 1482 andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
arch/sparc64/kernel/head.S
... ... @@ -632,10 +632,35 @@
632 632 /* Not reached... */
633 633  
634 634 1:
  635 + /* If we boot on a non-zero cpu, all of the per-cpu
  636 + * variable references we make before setting up the
  637 + * per-cpu areas will use a bogus offset. Put a
  638 + * compensating factor into __per_cpu_base to handle
  639 + * this cleanly.
  640 + *
  641 + * What the per-cpu code calculates is:
  642 + *
  643 + * __per_cpu_base + (cpu << __per_cpu_shift)
  644 + *
  645 + * These two variables are zero initially, so to
  646 + * make it all cancel out to zero we need to put
  647 + * "0 - (cpu << 0)" into __per_cpu_base so that the
  648 + * above formula evaluates to zero.
  649 + *
  650 + * We cannot even perform a printk() until this stuff
  651 + * is setup as that calls cpu_clock() which uses
  652 + * per-cpu variables.
  653 + */
  654 + sub %g0, %o0, %o1
  655 + sethi %hi(__per_cpu_base), %o2
  656 + stx %o1, [%o2 + %lo(__per_cpu_base)]
635 657 #else
636 658 mov 0, %o0
637 659 #endif
638 660 sth %o0, [%g6 + TI_CPU]
  661 +
  662 + call prom_init_report
  663 + nop
639 664  
640 665 /* Off we go.... */
641 666 call start_kernel
arch/sparc64/kernel/ptrace.c
Changes suppressed. Click to show
1 1 /* ptrace.c: Sparc process tracing support.
2 2 *
3   - * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
  3 + * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
4 4 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5 5 *
6 6 * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
... ... @@ -22,6 +22,9 @@
22 22 #include <linux/seccomp.h>
23 23 #include <linux/audit.h>
24 24 #include <linux/signal.h>
  25 +#include <linux/regset.h>
  26 +#include <linux/compat.h>
  27 +#include <linux/elf.h>
25 28  
26 29 #include <asm/asi.h>
27 30 #include <asm/pgtable.h>
28 31  
29 32  
... ... @@ -33,71 +36,8 @@
33 36 #include <asm/page.h>
34 37 #include <asm/cpudata.h>
35 38  
36   -/* Returning from ptrace is a bit tricky because the syscall return
37   - * low level code assumes any value returned which is negative and
38   - * is a valid errno will mean setting the condition codes to indicate
39   - * an error return. This doesn't work, so we have this hook.
40   - */
41   -static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
42   -{
43   - regs->u_regs[UREG_I0] = error;
44   - regs->tstate |= (TSTATE_ICARRY | TSTATE_XCARRY);
45   - regs->tpc = regs->tnpc;
46   - regs->tnpc += 4;
47   -}
48   -
49   -static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
50   -{
51   - regs->u_regs[UREG_I0] = value;
52   - regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
53   - regs->tpc = regs->tnpc;
54   - regs->tnpc += 4;
55   -}
56   -
57   -static inline void
58   -pt_succ_return_linux(struct pt_regs *regs, unsigned long value, void __user *addr)
59   -{
60   - if (test_thread_flag(TIF_32BIT)) {
61   - if (put_user(value, (unsigned int __user *) addr)) {
62   - pt_error_return(regs, EFAULT);
63   - return;
64   - }
65   - } else {
66   - if (put_user(value, (long __user *) addr)) {
67   - pt_error_return(regs, EFAULT);
68   - return;
69   - }
70   - }
71   - regs->u_regs[UREG_I0] = 0;
72   - regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
73   - regs->tpc = regs->tnpc;
74   - regs->tnpc += 4;
75   -}
76   -
77   -static void
78   -pt_os_succ_return (struct pt_regs *regs, unsigned long val, void __user *addr)
79   -{
80   - if (current->personality == PER_SUNOS)
81   - pt_succ_return (regs, val);
82   - else
83   - pt_succ_return_linux (regs, val, addr);
84   -}
85   -
86 39 /* #define ALLOW_INIT_TRACING */
87   -/* #define DEBUG_PTRACE */
88 40  
89   -#ifdef DEBUG_PTRACE
90   -char *pt_rq [] = {
91   - /* 0 */ "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSR",
92   - /* 4 */ "POKETEXT", "POKEDATA", "POKEUSR", "CONT",
93   - /* 8 */ "KILL", "SINGLESTEP", "SUNATTACH", "SUNDETACH",
94   - /* 12 */ "GETREGS", "SETREGS", "GETFPREGS", "SETFPREGS",
95   - /* 16 */ "READDATA", "WRITEDATA", "READTEXT", "WRITETEXT",
96   - /* 20 */ "GETFPAREGS", "SETFPAREGS", "unknown", "unknown",
97   - /* 24 */ "SYSCALL", ""
98   -};
99   -#endif
100   -
101 41 /*
102 42 * Called by kernel/ptrace.c when detaching..
103 43 *
104 44  
105 45  
106 46  
107 47  
108 48  
109 49  
110 50  
111 51  
112 52  
113 53  
114 54  
115 55  
116 56  
117 57  
118 58  
119 59  
120 60  
121 61  
122 62  
123 63  
124 64  
125 65  
126 66  
127 67  
128 68  
129 69  
130 70  
131 71  
132 72  
133 73  
134 74  
135 75  
136 76  
137 77  
138 78  
139 79  
140 80  
141 81  
... ... @@ -167,267 +107,709 @@
167 107 }
168 108 }
169 109  
170   -asmlinkage void do_ptrace(struct pt_regs *regs)
  110 +enum sparc_regset {
  111 + REGSET_GENERAL,
  112 + REGSET_FP,
  113 +};
  114 +
  115 +static int genregs64_get(struct task_struct *target,
  116 + const struct user_regset *regset,
  117 + unsigned int pos, unsigned int count,
  118 + void *kbuf, void __user *ubuf)
171 119 {
172   - int request = regs->u_regs[UREG_I0];
173   - pid_t pid = regs->u_regs[UREG_I1];
174   - unsigned long addr = regs->u_regs[UREG_I2];
175   - unsigned long data = regs->u_regs[UREG_I3];
176   - unsigned long addr2 = regs->u_regs[UREG_I4];
177   - struct task_struct *child;
  120 + const struct pt_regs *regs = task_pt_regs(target);
178 121 int ret;
179 122  
180   - if (test_thread_flag(TIF_32BIT)) {
181   - addr &= 0xffffffffUL;
182   - data &= 0xffffffffUL;
183   - addr2 &= 0xffffffffUL;
  123 + if (target == current)
  124 + flushw_user();
  125 +
  126 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  127 + regs->u_regs,
  128 + 0, 16 * sizeof(u64));
  129 + if (!ret) {
  130 + unsigned long __user *reg_window = (unsigned long __user *)
  131 + (regs->u_regs[UREG_I6] + STACK_BIAS);
  132 + unsigned long window[16];
  133 +
  134 + if (copy_from_user(window, reg_window, sizeof(window)))
  135 + return -EFAULT;
  136 +
  137 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  138 + window,
  139 + 16 * sizeof(u64),
  140 + 32 * sizeof(u64));
184 141 }
185   - lock_kernel();
186   -#ifdef DEBUG_PTRACE
187   - {
188   - char *s;
189 142  
190   - if ((request >= 0) && (request <= 24))
191   - s = pt_rq [request];
192   - else
193   - s = "unknown";
  143 + if (!ret) {
  144 + /* TSTATE, TPC, TNPC */
  145 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  146 + &regs->tstate,
  147 + 32 * sizeof(u64),
  148 + 35 * sizeof(u64));
  149 + }
194 150  
195   - if (request == PTRACE_POKEDATA && data == 0x91d02001){
196   - printk ("do_ptrace: breakpoint pid=%d, addr=%016lx addr2=%016lx\n",
197   - pid, addr, addr2);
198   - } else
199   - printk("do_ptrace: rq=%s(%d) pid=%d addr=%016lx data=%016lx addr2=%016lx\n",
200   - s, request, pid, addr, data, addr2);
  151 + if (!ret) {
  152 + unsigned long y = regs->y;
  153 +
  154 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  155 + &y,
  156 + 35 * sizeof(u64),
  157 + 36 * sizeof(u64));
201 158 }
202   -#endif
203   - if (request == PTRACE_TRACEME) {
204   - ret = ptrace_traceme();
205   - if (ret < 0)
206   - pt_error_return(regs, -ret);
  159 +
  160 + if (!ret)
  161 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  162 + 36 * sizeof(u64), -1);
  163 +
  164 + return ret;
  165 +}
  166 +
  167 +static int genregs64_set(struct task_struct *target,
  168 + const struct user_regset *regset,
  169 + unsigned int pos, unsigned int count,
  170 + const void *kbuf, const void __user *ubuf)
  171 +{
  172 + struct pt_regs *regs = task_pt_regs(target);
  173 + int ret;
  174 +
  175 + if (target == current)
  176 + flushw_user();
  177 +
  178 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  179 + regs->u_regs,
  180 + 0, 16 * sizeof(u64));
  181 + if (!ret && count > 0) {
  182 + unsigned long __user *reg_window = (unsigned long __user *)
  183 + (regs->u_regs[UREG_I6] + STACK_BIAS);
  184 + unsigned long window[16];
  185 +
  186 + if (copy_from_user(window, reg_window, sizeof(window)))
  187 + return -EFAULT;
  188 +
  189 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  190 + window,
  191 + 16 * sizeof(u64),
  192 + 32 * sizeof(u64));
  193 + if (!ret &&
  194 + copy_to_user(reg_window, window, sizeof(window)))
  195 + return -EFAULT;
  196 + }
  197 +
  198 + if (!ret && count > 0) {
  199 + unsigned long tstate;
  200 +
  201 + /* TSTATE */
  202 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  203 + &tstate,
  204 + 32 * sizeof(u64),
  205 + 33 * sizeof(u64));
  206 + if (!ret) {
  207 + /* Only the condition codes can be modified
  208 + * in the %tstate register.
  209 + */
  210 + tstate &= (TSTATE_ICC | TSTATE_XCC);
  211 + regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
  212 + regs->tstate |= tstate;
  213 + }
  214 + }
  215 +
  216 + if (!ret) {
  217 + /* TPC, TNPC */
  218 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  219 + &regs->tpc,
  220 + 33 * sizeof(u64),
  221 + 35 * sizeof(u64));
  222 + }
  223 +
  224 + if (!ret) {
  225 + unsigned long y;
  226 +
  227 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  228 + &y,
  229 + 35 * sizeof(u64),
  230 + 36 * sizeof(u64));
  231 + if (!ret)
  232 + regs->y = y;
  233 + }
  234 +
  235 + if (!ret)
  236 + ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  237 + 36 * sizeof(u64), -1);
  238 +
  239 + return ret;
  240 +}
  241 +
  242 +static int fpregs64_get(struct task_struct *target,
  243 + const struct user_regset *regset,
  244 + unsigned int pos, unsigned int count,
  245 + void *kbuf, void __user *ubuf)
  246 +{
  247 + const unsigned long *fpregs = task_thread_info(target)->fpregs;
  248 + unsigned long fprs, fsr, gsr;
  249 + int ret;
  250 +
  251 + if (target == current)
  252 + save_and_clear_fpu();
  253 +
  254 + fprs = task_thread_info(target)->fpsaved[0];
  255 +
  256 + if (fprs & FPRS_DL)
  257 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  258 + fpregs,
  259 + 0, 16 * sizeof(u64));
  260 + else
  261 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  262 + 0,
  263 + 16 * sizeof(u64));
  264 +
  265 + if (!ret) {
  266 + if (fprs & FPRS_DU)
  267 + ret = user_regset_copyout(&pos, &count,
  268 + &kbuf, &ubuf,
  269 + fpregs + 16,
  270 + 16 * sizeof(u64),
  271 + 32 * sizeof(u64));
207 272 else
208   - pt_succ_return(regs, 0);
209   - goto out;
  273 + ret = user_regset_copyout_zero(&pos, &count,
  274 + &kbuf, &ubuf,
  275 + 16 * sizeof(u64),
  276 + 32 * sizeof(u64));
210 277 }
211 278  
212   - child = ptrace_get_task_struct(pid);
213   - if (IS_ERR(child)) {
214   - ret = PTR_ERR(child);
215   - pt_error_return(regs, -ret);
216   - goto out;
  279 + if (fprs & FPRS_FEF) {
  280 + fsr = task_thread_info(target)->xfsr[0];
  281 + gsr = task_thread_info(target)->gsr[0];
  282 + } else {
  283 + fsr = gsr = 0;
217 284 }
218 285  
219   - if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
220   - || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
221   - if (ptrace_attach(child)) {
222   - pt_error_return(regs, EPERM);
223   - goto out_tsk;
  286 + if (!ret)
  287 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  288 + &fsr,
  289 + 32 * sizeof(u64),
  290 + 33 * sizeof(u64));
  291 + if (!ret)
  292 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  293 + &gsr,
  294 + 33 * sizeof(u64),
  295 + 34 * sizeof(u64));
  296 + if (!ret)
  297 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  298 + &fprs,
  299 + 34 * sizeof(u64),
  300 + 35 * sizeof(u64));
  301 +
  302 + if (!ret)
  303 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  304 + 35 * sizeof(u64), -1);
  305 +
  306 + return ret;
  307 +}
  308 +
  309 +static int fpregs64_set(struct task_struct *target,
  310 + const struct user_regset *regset,
  311 + unsigned int pos, unsigned int count,
  312 + const void *kbuf, const void __user *ubuf)
  313 +{
  314 + unsigned long *fpregs = task_thread_info(target)->fpregs;
  315 + unsigned long fprs;
  316 + int ret;
  317 +
  318 + if (target == current)
  319 + save_and_clear_fpu();
  320 +
  321 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  322 + fpregs,
  323 + 0, 32 * sizeof(u64));
  324 + if (!ret)
  325 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  326 + task_thread_info(target)->xfsr,
  327 + 32 * sizeof(u64),
  328 + 33 * sizeof(u64));
  329 + if (!ret)
  330 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  331 + task_thread_info(target)->gsr,
  332 + 33 * sizeof(u64),
  333 + 34 * sizeof(u64));
  334 +
  335 + fprs = task_thread_info(target)->fpsaved[0];
  336 + if (!ret && count > 0) {
  337 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  338 + &fprs,
  339 + 34 * sizeof(u64),
  340 + 35 * sizeof(u64));
  341 + }
  342 +
  343 + fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU);
  344 + task_thread_info(target)->fpsaved[0] = fprs;
  345 +
  346 + if (!ret)
  347 + ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  348 + 35 * sizeof(u64), -1);
  349 + return ret;
  350 +}
  351 +
  352 +static const struct user_regset sparc64_regsets[] = {
  353 + /* Format is:
  354 + * G0 --> G7
  355 + * O0 --> O7
  356 + * L0 --> L7
  357 + * I0 --> I7
  358 + * TSTATE, TPC, TNPC, Y
  359 + */
  360 + [REGSET_GENERAL] = {
  361 + .core_note_type = NT_PRSTATUS,
  362 + .n = 36 * sizeof(u64),
  363 + .size = sizeof(u64), .align = sizeof(u64),
  364 + .get = genregs64_get, .set = genregs64_set
  365 + },
  366 + /* Format is:
  367 + * F0 --> F63
  368 + * FSR
  369 + * GSR
  370 + * FPRS
  371 + */
  372 + [REGSET_FP] = {
  373 + .core_note_type = NT_PRFPREG,
  374 + .n = 35 * sizeof(u64),
  375 + .size = sizeof(u64), .align = sizeof(u64),
  376 + .get = fpregs64_get, .set = fpregs64_set
  377 + },
  378 +};
  379 +
  380 +static const struct user_regset_view user_sparc64_view = {
  381 + .name = "sparc64", .e_machine = EM_SPARCV9,
  382 + .regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets)
  383 +};
  384 +
  385 +static int genregs32_get(struct task_struct *target,
  386 + const struct user_regset *regset,
  387 + unsigned int pos, unsigned int count,
  388 + void *kbuf, void __user *ubuf)
  389 +{
  390 + const struct pt_regs *regs = task_pt_regs(target);
  391 + compat_ulong_t __user *reg_window;
  392 + compat_ulong_t *k = kbuf;
  393 + compat_ulong_t __user *u = ubuf;
  394 + compat_ulong_t reg;
  395 +
  396 + if (target == current)
  397 + flushw_user();
  398 +
  399 + pos /= sizeof(reg);
  400 + count /= sizeof(reg);
  401 +
  402 + if (kbuf) {
  403 + for (; count > 0 && pos < 16; count--)
  404 + *k++ = regs->u_regs[pos++];
  405 +
  406 + reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
  407 + for (; count > 0 && pos < 32; count--) {
  408 + if (get_user(*k++, &reg_window[pos++]))
  409 + return -EFAULT;
224 410 }
225   - pt_succ_return(regs, 0);
226   - goto out_tsk;
  411 + } else {
  412 + for (; count > 0 && pos < 16; count--) {
  413 + if (put_user((compat_ulong_t) regs->u_regs[pos++], u++))
  414 + return -EFAULT;
  415 + }
  416 +
  417 + reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
  418 + for (; count > 0 && pos < 32; count--) {
  419 + if (get_user(reg, &reg_window[pos++]) ||
  420 + put_user(reg, u++))
  421 + return -EFAULT;
  422 + }
227 423 }
  424 + while (count > 0) {
  425 + switch (pos) {
  426 + case 32: /* PSR */
  427 + reg = tstate_to_psr(regs->tstate);
  428 + break;
  429 + case 33: /* PC */
  430 + reg = regs->tpc;
  431 + break;
  432 + case 34: /* NPC */
  433 + reg = regs->tnpc;
  434 + break;
  435 + case 35: /* Y */
  436 + reg = regs->y;
  437 + break;
  438 + case 36: /* WIM */
  439 + case 37: /* TBR */
  440 + reg = 0;
  441 + break;
  442 + default:
  443 + goto finish;
  444 + }
228 445  
229   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
230   - if (ret < 0) {
231   - pt_error_return(regs, -ret);
232   - goto out_tsk;
  446 + if (kbuf)
  447 + *k++ = reg;
  448 + else if (put_user(reg, u++))
  449 + return -EFAULT;
  450 + pos++;
  451 + count--;
233 452 }
  453 +finish:
  454 + pos *= sizeof(reg);
  455 + count *= sizeof(reg);
234 456  
235   - if (!(test_thread_flag(TIF_32BIT)) &&
236   - ((request == PTRACE_READDATA64) ||
237   - (request == PTRACE_WRITEDATA64) ||
238   - (request == PTRACE_READTEXT64) ||
239   - (request == PTRACE_WRITETEXT64) ||
240   - (request == PTRACE_PEEKTEXT64) ||
241   - (request == PTRACE_POKETEXT64) ||
242   - (request == PTRACE_PEEKDATA64) ||
243   - (request == PTRACE_POKEDATA64))) {
244   - addr = regs->u_regs[UREG_G2];
245   - addr2 = regs->u_regs[UREG_G3];
246   - request -= 30; /* wheee... */
  457 + return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  458 + 38 * sizeof(reg), -1);
  459 +}
  460 +
  461 +static int genregs32_set(struct task_struct *target,
  462 + const struct user_regset *regset,
  463 + unsigned int pos, unsigned int count,
  464 + const void *kbuf, const void __user *ubuf)
  465 +{
  466 + struct pt_regs *regs = task_pt_regs(target);
  467 + compat_ulong_t __user *reg_window;
  468 + const compat_ulong_t *k = kbuf;
  469 + const compat_ulong_t __user *u = ubuf;
  470 + compat_ulong_t reg;
  471 +
  472 + if (target == current)
  473 + flushw_user();
  474 +
  475 + pos /= sizeof(reg);
  476 + count /= sizeof(reg);
  477 +
  478 + if (kbuf) {
  479 + for (; count > 0 && pos < 16; count--)
  480 + regs->u_regs[pos++] = *k++;
  481 +
  482 + reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
  483 + for (; count > 0 && pos < 32; count--) {
  484 + if (put_user(*k++, &reg_window[pos++]))
  485 + return -EFAULT;
  486 + }
  487 + } else {
  488 + for (; count > 0 && pos < 16; count--) {
  489 + if (get_user(reg, u++))
  490 + return -EFAULT;
  491 + regs->u_regs[pos++] = reg;
  492 + }
  493 +
  494 + reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
  495 + for (; count > 0 && pos < 32; count--) {
  496 + if (get_user(reg, u++) ||
  497 + put_user(reg, &reg_window[pos++]))
  498 + return -EFAULT;
  499 + }
247 500 }
  501 + while (count > 0) {
  502 + unsigned long tstate;
248 503  
  504 + if (kbuf)
  505 + reg = *k++;
  506 + else if (get_user(reg, u++))
  507 + return -EFAULT;
  508 +
  509 + switch (pos) {
  510 + case 32: /* PSR */
  511 + tstate = regs->tstate;
  512 + tstate &= ~(TSTATE_ICC | TSTATE_XCC);
  513 + tstate |= psr_to_tstate_icc(reg);
  514 + regs->tstate = tstate;
  515 + break;
  516 + case 33: /* PC */
  517 + regs->tpc = reg;
  518 + break;
  519 + case 34: /* NPC */
  520 + regs->tnpc = reg;
  521 + break;
  522 + case 35: /* Y */
  523 + regs->y = reg;
  524 + break;
  525 + case 36: /* WIM */
  526 + case 37: /* TBR */
  527 + break;
  528 + default:
  529 + goto finish;
  530 + }
  531 +
  532 + pos++;
  533 + count--;
  534 + }
  535 +finish:
  536 + pos *= sizeof(reg);
  537 + count *= sizeof(reg);
  538 +
  539 + return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  540 + 38 * sizeof(reg), -1);
  541 +}
  542 +
  543 +static int fpregs32_get(struct task_struct *target,
  544 + const struct user_regset *regset,
  545 + unsigned int pos, unsigned int count,
  546 + void *kbuf, void __user *ubuf)
  547 +{
  548 + const unsigned long *fpregs = task_thread_info(target)->fpregs;
  549 + compat_ulong_t enabled;
  550 + unsigned long fprs;
  551 + compat_ulong_t fsr;
  552 + int ret = 0;
  553 +
  554 + if (target == current)
  555 + save_and_clear_fpu();
  556 +
  557 + fprs = task_thread_info(target)->fpsaved[0];
  558 + if (fprs & FPRS_FEF) {
  559 + fsr = task_thread_info(target)->xfsr[0];
  560 + enabled = 1;
  561 + } else {
  562 + fsr = 0;
  563 + enabled = 0;
  564 + }
  565 +
  566 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  567 + fpregs,
  568 + 0, 32 * sizeof(u32));
  569 +
  570 + if (!ret)
  571 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  572 + 32 * sizeof(u32),
  573 + 33 * sizeof(u32));
  574 + if (!ret)
  575 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  576 + &fsr,
  577 + 33 * sizeof(u32),
  578 + 34 * sizeof(u32));
  579 +
  580 + if (!ret) {
  581 + compat_ulong_t val;
  582 +
  583 + val = (enabled << 8) | (8 << 16);
  584 + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  585 + &val,
  586 + 34 * sizeof(u32),
  587 + 35 * sizeof(u32));
  588 + }
  589 +
  590 + if (!ret)
  591 + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  592 + 35 * sizeof(u32), -1);
  593 +
  594 + return ret;
  595 +}
  596 +
  597 +static int fpregs32_set(struct task_struct *target,
  598 + const struct user_regset *regset,
  599 + unsigned int pos, unsigned int count,
  600 + const void *kbuf, const void __user *ubuf)
  601 +{
  602 + unsigned long *fpregs = task_thread_info(target)->fpregs;
  603 + unsigned long fprs;
  604 + int ret;
  605 +
  606 + if (target == current)
  607 + save_and_clear_fpu();
  608 +
  609 + fprs = task_thread_info(target)->fpsaved[0];
  610 +
  611 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  612 + fpregs,
  613 + 0, 32 * sizeof(u32));
  614 + if (!ret)
  615 + user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  616 + 32 * sizeof(u32),
  617 + 33 * sizeof(u32));
  618 + if (!ret && count > 0) {
  619 + compat_ulong_t fsr;
  620 + unsigned long val;
  621 +
  622 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  623 + &fsr,
  624 + 33 * sizeof(u32),
  625 + 34 * sizeof(u32));
  626 + if (!ret) {
  627 + val = task_thread_info(target)->xfsr[0];
  628 + val &= 0xffffffff00000000UL;
  629 + val |= fsr;
  630 + task_thread_info(target)->xfsr[0] = val;
  631 + }
  632 + }
  633 +
  634 + fprs |= (FPRS_FEF | FPRS_DL);
  635 + task_thread_info(target)->fpsaved[0] = fprs;
  636 +
  637 + if (!ret)
  638 + ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  639 + 34 * sizeof(u32), -1);
  640 + return ret;
  641 +}
  642 +
  643 +static const struct user_regset sparc32_regsets[] = {
  644 + /* Format is:
  645 + * G0 --> G7
  646 + * O0 --> O7
  647 + * L0 --> L7
  648 + * I0 --> I7
  649 + * PSR, PC, nPC, Y, WIM, TBR
  650 + */
  651 + [REGSET_GENERAL] = {
  652 + .core_note_type = NT_PRSTATUS,
  653 + .n = 38 * sizeof(u32),
  654 + .size = sizeof(u32), .align = sizeof(u32),
  655 + .get = genregs32_get, .set = genregs32_set
  656 + },
  657 + /* Format is:
  658 + * F0 --> F31
  659 + * empty 32-bit word
  660 + * FSR (32--bit word)
  661 + * FPU QUEUE COUNT (8-bit char)
  662 + * FPU QUEUE ENTRYSIZE (8-bit char)
  663 + * FPU ENABLED (8-bit char)
  664 + * empty 8-bit char
  665 + * FPU QUEUE (64 32-bit ints)
  666 + */
  667 + [REGSET_FP] = {
  668 + .core_note_type = NT_PRFPREG,
  669 + .n = 99 * sizeof(u32),
  670 + .size = sizeof(u32), .align = sizeof(u32),
  671 + .get = fpregs32_get, .set = fpregs32_set
  672 + },
  673 +};
  674 +
  675 +static const struct user_regset_view user_sparc32_view = {
  676 + .name = "sparc", .e_machine = EM_SPARC,
  677 + .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
  678 +};
  679 +
  680 +const struct user_regset_view *task_user_regset_view(struct task_struct *task)
  681 +{
  682 + if (test_tsk_thread_flag(task, TIF_32BIT))
  683 + return &user_sparc32_view;
  684 + return &user_sparc64_view;
  685 +}
  686 +
  687 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
  688 +{
  689 + long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
  690 + const struct user_regset_view *view;
  691 + int ret;
  692 +
  693 + if (test_thread_flag(TIF_32BIT))
  694 + addr2 &= 0xffffffffUL;
  695 +
  696 + view = task_user_regset_view(child);
  697 +
249 698 switch(request) {
250 699 case PTRACE_PEEKUSR:
251   - if (addr != 0)
252   - pt_error_return(regs, EIO);
253   - else
254   - pt_succ_return(regs, 0);
255   - goto out_tsk;
  700 + ret = (addr != 0) ? -EIO : 0;
  701 + break;
256 702  
257 703 case PTRACE_PEEKTEXT: /* read word at location addr. */
258 704 case PTRACE_PEEKDATA: {
259 705 unsigned long tmp64;
260 706 unsigned int tmp32;
261   - int res, copied;
  707 + int copied;
262 708  
263   - res = -EIO;
  709 + ret = -EIO;
264 710 if (test_thread_flag(TIF_32BIT)) {
265 711 copied = access_process_vm(child, addr,
266 712 &tmp32, sizeof(tmp32), 0);
267   - tmp64 = (unsigned long) tmp32;
268 713 if (copied == sizeof(tmp32))
269   - res = 0;
  714 + ret = put_user(tmp32,
  715 + (unsigned int __user *) data);
270 716 } else {
271 717 copied = access_process_vm(child, addr,
272 718 &tmp64, sizeof(tmp64), 0);
273 719 if (copied == sizeof(tmp64))
274   - res = 0;
  720 + ret = put_user(tmp64,
  721 + (unsigned long __user *) data);
275 722 }
276   - if (res < 0)
277   - pt_error_return(regs, -res);
278   - else
279   - pt_os_succ_return(regs, tmp64, (void __user *) data);
280   - goto out_tsk;
  723 + break;
281 724 }
282 725  
283 726 case PTRACE_POKETEXT: /* write the word at location addr. */
284 727 case PTRACE_POKEDATA: {
285 728 unsigned long tmp64;
286 729 unsigned int tmp32;
287   - int copied, res = -EIO;
  730 + int copied;
288 731  
  732 + ret = -EIO;
289 733 if (test_thread_flag(TIF_32BIT)) {
290 734 tmp32 = data;
291 735 copied = access_process_vm(child, addr,
292 736 &tmp32, sizeof(tmp32), 1);
293 737 if (copied == sizeof(tmp32))
294   - res = 0;
  738 + ret = 0;
295 739 } else {
296 740 tmp64 = data;
297 741 copied = access_process_vm(child, addr,
298 742 &tmp64, sizeof(tmp64), 1);
299 743 if (copied == sizeof(tmp64))
300   - res = 0;
  744 + ret = 0;
301 745 }
302   - if (res < 0)
303   - pt_error_return(regs, -res);
304   - else
305   - pt_succ_return(regs, res);
306   - goto out_tsk;
  746 + break;
307 747 }
308 748  
309 749 case PTRACE_GETREGS: {
310 750 struct pt_regs32 __user *pregs =
311 751 (struct pt_regs32 __user *) addr;
312   - struct pt_regs *cregs = task_pt_regs(child);
313   - int rval;
314 752  
315   - if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
316   - __put_user(cregs->tpc, (&pregs->pc)) ||
317   - __put_user(cregs->tnpc, (&pregs->npc)) ||
318   - __put_user(cregs->y, (&pregs->y))) {
319   - pt_error_return(regs, EFAULT);
320   - goto out_tsk;
321   - }
322   - for (rval = 1; rval < 16; rval++)
323   - if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
324   - pt_error_return(regs, EFAULT);
325   - goto out_tsk;
326   - }
327   - pt_succ_return(regs, 0);
328   -#ifdef DEBUG_PTRACE
329   - printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
330   -#endif
331   - goto out_tsk;
  753 + ret = copy_regset_to_user(child, view, REGSET_GENERAL,
  754 + 32 * sizeof(u32),
  755 + 4 * sizeof(u32),
  756 + &pregs->psr);
  757 + if (!ret)
  758 + ret = copy_regset_to_user(child, view, REGSET_GENERAL,
  759 + 1 * sizeof(u32),
  760 + 15 * sizeof(u32),
  761 + &pregs->u_regs[0]);
  762 + break;
332 763 }
333 764  
334 765 case PTRACE_GETREGS64: {
335 766 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
336   - struct pt_regs *cregs = task_pt_regs(child);
337   - unsigned long tpc = cregs->tpc;
338   - int rval;
339 767  
340   - if ((task_thread_info(child)->flags & _TIF_32BIT) != 0)
341   - tpc &= 0xffffffff;
342   - if (__put_user(cregs->tstate, (&pregs->tstate)) ||
343   - __put_user(tpc, (&pregs->tpc)) ||
344   - __put_user(cregs->tnpc, (&pregs->tnpc)) ||
345   - __put_user(cregs->y, (&pregs->y))) {
346   - pt_error_return(regs, EFAULT);
347   - goto out_tsk;
  768 + ret = copy_regset_to_user(child, view, REGSET_GENERAL,
  769 + 1 * sizeof(u64),
  770 + 15 * sizeof(u64),
  771 + &pregs->u_regs[0]);
  772 + if (!ret) {
  773 + /* XXX doesn't handle 'y' register correctly XXX */
  774 + ret = copy_regset_to_user(child, view, REGSET_GENERAL,
  775 + 32 * sizeof(u64),
  776 + 4 * sizeof(u64),
  777 + &pregs->tstate);
348 778 }
349   - for (rval = 1; rval < 16; rval++)
350   - if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
351   - pt_error_return(regs, EFAULT);
352   - goto out_tsk;
353   - }
354   - pt_succ_return(regs, 0);
355   -#ifdef DEBUG_PTRACE
356   - printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
357   -#endif
358   - goto out_tsk;
  779 + break;
359 780 }
360 781  
361 782 case PTRACE_SETREGS: {
362 783 struct pt_regs32 __user *pregs =
363 784 (struct pt_regs32 __user *) addr;
364   - struct pt_regs *cregs = task_pt_regs(child);
365   - unsigned int psr, pc, npc, y;
366   - int i;
367 785  
368   - /* Must be careful, tracing process can only set certain
369   - * bits in the psr.
370   - */
371   - if (__get_user(psr, (&pregs->psr)) ||
372   - __get_user(pc, (&pregs->pc)) ||
373   - __get_user(npc, (&pregs->npc)) ||
374   - __get_user(y, (&pregs->y))) {
375   - pt_error_return(regs, EFAULT);
376   - goto out_tsk;
377   - }
378   - cregs->tstate &= ~(TSTATE_ICC);
379   - cregs->tstate |= psr_to_tstate_icc(psr);
380   - if (!((pc | npc) & 3)) {
381   - cregs->tpc = pc;
382   - cregs->tnpc = npc;
383   - }
384   - cregs->y = y;
385   - for (i = 1; i < 16; i++) {
386   - if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
387   - pt_error_return(regs, EFAULT);
388   - goto out_tsk;
389   - }
390   - }
391   - pt_succ_return(regs, 0);
392   - goto out_tsk;
  786 + ret = copy_regset_from_user(child, view, REGSET_GENERAL,
  787 + 32 * sizeof(u32),
  788 + 4 * sizeof(u32),
  789 + &pregs->psr);
  790 + if (!ret)
  791 + ret = copy_regset_from_user(child, view, REGSET_GENERAL,
  792 + 1 * sizeof(u32),
  793 + 15 * sizeof(u32),
  794 + &pregs->u_regs[0]);
  795 + break;
393 796 }
394 797  
395 798 case PTRACE_SETREGS64: {
396 799 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
397   - struct pt_regs *cregs = task_pt_regs(child);
398   - unsigned long tstate, tpc, tnpc, y;
399   - int i;
400 800  
401   - /* Must be careful, tracing process can only set certain
402   - * bits in the psr.
403   - */
404   - if (__get_user(tstate, (&pregs->tstate)) ||
405   - __get_user(tpc, (&pregs->tpc)) ||
406   - __get_user(tnpc, (&pregs->tnpc)) ||
407   - __get_user(y, (&pregs->y))) {
408   - pt_error_return(regs, EFAULT);
409   - goto out_tsk;
  801 + ret = copy_regset_from_user(child, view, REGSET_GENERAL,
  802 + 1 * sizeof(u64),
  803 + 15 * sizeof(u64),
  804 + &pregs->u_regs[0]);
  805 + if (!ret) {
  806 + /* XXX doesn't handle 'y' register correctly XXX */
  807 + ret = copy_regset_from_user(child, view, REGSET_GENERAL,
  808 + 32 * sizeof(u64),
  809 + 4 * sizeof(u64),
  810 + &pregs->tstate);
410 811 }
411   - if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) {
412   - tpc &= 0xffffffff;
413   - tnpc &= 0xffffffff;
414   - }
415   - tstate &= (TSTATE_ICC | TSTATE_XCC);
416   - cregs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
417   - cregs->tstate |= tstate;
418   - if (!((tpc | tnpc) & 3)) {
419   - cregs->tpc = tpc;
420   - cregs->tnpc = tnpc;
421   - }
422   - cregs->y = y;
423   - for (i = 1; i < 16; i++) {
424   - if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
425   - pt_error_return(regs, EFAULT);
426   - goto out_tsk;
427   - }
428   - }
429   - pt_succ_return(regs, 0);
430   - goto out_tsk;
  812 + break;
431 813 }
432 814  
433 815 case PTRACE_GETFPREGS: {
434 816  
435 817  
... ... @@ -443,20 +825,24 @@
443 825 } fpq[16];
444 826 };
445 827 struct fps __user *fps = (struct fps __user *) addr;
446   - unsigned long *fpregs = task_thread_info(child)->fpregs;
447 828  
448   - if (copy_to_user(&fps->regs[0], fpregs,
449   - (32 * sizeof(unsigned int))) ||
450   - __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) ||
451   - __put_user(0, (&fps->fpqd)) ||
452   - __put_user(0, (&fps->flags)) ||
453   - __put_user(0, (&fps->extra)) ||
454   - clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) {
455   - pt_error_return(regs, EFAULT);
456   - goto out_tsk;
  829 + ret = copy_regset_to_user(child, view, REGSET_FP,
  830 + 0 * sizeof(u32),
  831 + 32 * sizeof(u32),
  832 + &fps->regs[0]);
  833 + if (!ret)
  834 + ret = copy_regset_to_user(child, view, REGSET_FP,
  835 + 33 * sizeof(u32),
  836 + 1 * sizeof(u32),
  837 + &fps->fsr);
  838 + if (!ret) {
  839 + if (__put_user(0, &fps->flags) ||
  840 + __put_user(0, &fps->extra) ||
  841 + __put_user(0, &fps->fpqd) ||
  842 + clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
  843 + ret = -EFAULT;
457 844 }
458   - pt_succ_return(regs, 0);
459   - goto out_tsk;
  845 + break;
460 846 }
461 847  
462 848 case PTRACE_GETFPREGS64: {
463 849  
... ... @@ -465,16 +851,12 @@
465 851 unsigned long fsr;
466 852 };
467 853 struct fps __user *fps = (struct fps __user *) addr;
468   - unsigned long *fpregs = task_thread_info(child)->fpregs;
469 854  
470   - if (copy_to_user(&fps->regs[0], fpregs,
471   - (64 * sizeof(unsigned int))) ||
472   - __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) {
473   - pt_error_return(regs, EFAULT);
474   - goto out_tsk;
475   - }
476   - pt_succ_return(regs, 0);
477   - goto out_tsk;
  855 + ret = copy_regset_to_user(child, view, REGSET_FP,
  856 + 0 * sizeof(u64),
  857 + 33 * sizeof(u64),
  858 + fps);
  859 + break;
478 860 }
479 861  
480 862 case PTRACE_SETFPREGS: {
481 863  
... ... @@ -490,22 +872,17 @@
490 872 } fpq[16];
491 873 };
492 874 struct fps __user *fps = (struct fps __user *) addr;
493   - unsigned long *fpregs = task_thread_info(child)->fpregs;
494   - unsigned fsr;
495 875  
496   - if (copy_from_user(fpregs, &fps->regs[0],
497   - (32 * sizeof(unsigned int))) ||
498   - __get_user(fsr, (&fps->fsr))) {
499   - pt_error_return(regs, EFAULT);
500   - goto out_tsk;
501   - }
502   - task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL;
503   - task_thread_info(child)->xfsr[0] |= fsr;
504   - if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
505   - task_thread_info(child)->gsr[0] = 0;
506   - task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL);
507   - pt_succ_return(regs, 0);
508   - goto out_tsk;
  876 + ret = copy_regset_from_user(child, view, REGSET_FP,
  877 + 0 * sizeof(u32),
  878 + 32 * sizeof(u32),
  879 + &fps->regs[0]);
  880 + if (!ret)
  881 + ret = copy_regset_from_user(child, view, REGSET_FP,
  882 + 33 * sizeof(u32),
  883 + 1 * sizeof(u32),
  884 + &fps->fsr);
  885 + break;
509 886 }
510 887  
511 888 case PTRACE_SETFPREGS64: {
512 889  
513 890  
514 891  
515 892  
516 893  
517 894  
518 895  
519 896  
520 897  
521 898  
... ... @@ -514,134 +891,50 @@
514 891 unsigned long fsr;
515 892 };
516 893 struct fps __user *fps = (struct fps __user *) addr;
517   - unsigned long *fpregs = task_thread_info(child)->fpregs;
518 894  
519   - if (copy_from_user(fpregs, &fps->regs[0],
520   - (64 * sizeof(unsigned int))) ||
521   - __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) {
522   - pt_error_return(regs, EFAULT);
523   - goto out_tsk;
524   - }
525   - if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
526   - task_thread_info(child)->gsr[0] = 0;
527   - task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU);
528   - pt_succ_return(regs, 0);
529   - goto out_tsk;
  895 + ret = copy_regset_to_user(child, view, REGSET_FP,
  896 + 0 * sizeof(u64),
  897 + 33 * sizeof(u64),
  898 + fps);
  899 + break;
530 900 }
531 901  
532 902 case PTRACE_READTEXT:
533   - case PTRACE_READDATA: {
534   - int res = ptrace_readdata(child, addr,
535   - (char __user *)addr2, data);
536   - if (res == data) {
537   - pt_succ_return(regs, 0);
538   - goto out_tsk;
539   - }
540   - if (res >= 0)
541   - res = -EIO;
542   - pt_error_return(regs, -res);
543   - goto out_tsk;
544   - }
  903 + case PTRACE_READDATA:
  904 + ret = ptrace_readdata(child, addr,
  905 + (char __user *)addr2, data);
  906 + if (ret == data)
  907 + ret = 0;
  908 + else if (ret >= 0)
  909 + ret = -EIO;
  910 + break;
545 911  
546 912 case PTRACE_WRITETEXT:
547   - case PTRACE_WRITEDATA: {
548   - int res = ptrace_writedata(child, (char __user *) addr2,
549   - addr, data);
550   - if (res == data) {
551   - pt_succ_return(regs, 0);
552   - goto out_tsk;
553   - }
554   - if (res >= 0)
555   - res = -EIO;
556   - pt_error_return(regs, -res);
557   - goto out_tsk;
558   - }
559   - case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
560   - addr = 1;
  913 + case PTRACE_WRITEDATA:
  914 + ret = ptrace_writedata(child, (char __user *) addr2,
  915 + addr, data);
  916 + if (ret == data)
  917 + ret = 0;
  918 + else if (ret >= 0)
  919 + ret = -EIO;
  920 + break;
561 921  
562   - case PTRACE_CONT: { /* restart after signal. */
563   - if (!valid_signal(data)) {
564   - pt_error_return(regs, EIO);
565   - goto out_tsk;
566   - }
567   -
568   - if (request == PTRACE_SYSCALL) {
569   - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
570   - } else {
571   - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
572   - }
573   -
574   - child->exit_code = data;
575   -#ifdef DEBUG_PTRACE
576   - printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", child->comm,
577   - child->pid, child->exit_code,
578   - task_pt_regs(child)->tpc,
579   - task_pt_regs(child)->tnpc);
580   -
581   -#endif
582   - wake_up_process(child);
583   - pt_succ_return(regs, 0);
584   - goto out_tsk;
585   - }
586   -
587   -/*
588   - * make the child exit. Best I can do is send it a sigkill.
589   - * perhaps it should be put in the status that it wants to
590   - * exit.
591   - */
592   - case PTRACE_KILL: {
593   - if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
594   - pt_succ_return(regs, 0);
595   - goto out_tsk;
596   - }
597   - child->exit_code = SIGKILL;
598   - wake_up_process(child);
599   - pt_succ_return(regs, 0);
600   - goto out_tsk;
601   - }
602   -
603   - case PTRACE_SUNDETACH: { /* detach a process that was attached. */
604   - int error = ptrace_detach(child, data);
605   - if (error) {
606   - pt_error_return(regs, EIO);
607   - goto out_tsk;
608   - }
609   - pt_succ_return(regs, 0);
610   - goto out_tsk;
611   - }
612   -
613   - /* PTRACE_DUMPCORE unsupported... */
614   -
615 922 case PTRACE_GETEVENTMSG: {
616   - int err;
617   -
618 923 if (test_thread_flag(TIF_32BIT))
619   - err = put_user(child->ptrace_message,
  924 + ret = put_user(child->ptrace_message,
620 925 (unsigned int __user *) data);
621 926 else
622   - err = put_user(child->ptrace_message,
  927 + ret = put_user(child->ptrace_message,
623 928 (unsigned long __user *) data);
624   - if (err)
625   - pt_error_return(regs, -err);
626   - else
627   - pt_succ_return(regs, 0);
628 929 break;
629 930 }
630 931  
631   - default: {
632   - int err = ptrace_request(child, request, addr, data);
633   - if (err)
634   - pt_error_return(regs, -err);
635   - else
636   - pt_succ_return(regs, 0);
637   - goto out_tsk;
  932 + default:
  933 + ret = ptrace_request(child, request, addr, data);
  934 + break;
638 935 }
639   - }
640   -out_tsk:
641   - if (child)
642   - put_task_struct(child);
643   -out:
644   - unlock_kernel();
  936 +
  937 + return ret;
645 938 }
646 939  
647 940 asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
arch/sparc64/prom/init.c
... ... @@ -48,7 +48,10 @@
48 48 prom_getstring(node, "version", prom_version, sizeof(prom_version));
49 49  
50 50 prom_printf("\n");
  51 +}
51 52  
  53 +void __init prom_init_report(void)
  54 +{
52 55 printk("PROMLIB: Sun IEEE Boot Prom '%s'\n", prom_version);
53 56 printk("PROMLIB: Root node compatible: %s\n", prom_root_compatible);
54 57 }
include/asm-sparc/elf.h
... ... @@ -65,8 +65,14 @@
65 65 #define HWCAP_SPARC_V9 16
66 66 #define HWCAP_SPARC_ULTRA3 32
67 67  
68   -/* For the most part we present code dumps in the format
69   - * Solaris does.
  68 +#define CORE_DUMP_USE_REGSET
  69 +
  70 +/* Format is:
  71 + * G0 --> G7
  72 + * O0 --> O7
  73 + * L0 --> L7
  74 + * I0 --> I7
  75 + * PSR, PC, nPC, Y, WIM, TBR
70 76 */
71 77 typedef unsigned long elf_greg_t;
72 78 #define ELF_NGREG 38
... ... @@ -86,34 +92,6 @@
86 92 } elf_fpregset_t;
87 93  
88 94 #include <asm/mbus.h>
89   -#include <asm/uaccess.h>
90   -
91   -/* Format is:
92   - * G0 --> G7
93   - * O0 --> O7
94   - * L0 --> L7
95   - * I0 --> I7
96   - * PSR, PC, nPC, Y, WIM, TBR
97   - */
98   -#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \
99   -do { unsigned long *dest = &(__elf_regs[0]); \
100   - struct pt_regs *src = (__pt_regs); \
101   - unsigned long __user *sp; \
102   - memcpy(&dest[0], &src->u_regs[0], \
103   - sizeof(unsigned long) * 16); \
104   - /* Don't try this at home kids... */ \
105   - sp = (unsigned long __user *) src->u_regs[14]; \
106   - copy_from_user(&dest[16], sp, \
107   - sizeof(unsigned long) * 16); \
108   - dest[32] = src->psr; \
109   - dest[33] = src->pc; \
110   - dest[34] = src->npc; \
111   - dest[35] = src->y; \
112   - dest[36] = dest[37] = 0; /* XXX */ \
113   -} while(0); /* Janitors: Don't touch this semicolon. */
114   -
115   -#define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs) \
116   - ({ ELF_CORE_COPY_REGS((*(__elf_regs)), (__tsk)->thread.kregs); 1; })
117 95  
118 96 /*
119 97 * This is used to ensure we don't load something for the wrong architecture.
include/asm-sparc/ptrace.h
... ... @@ -61,8 +61,6 @@
61 61  
62 62 #ifdef __KERNEL__
63 63  
64   -#define __ARCH_SYS_PTRACE 1
65   -
66 64 #define user_mode(regs) (!((regs)->psr & PSR_PS))
67 65 #define instruction_pointer(regs) ((regs)->pc)
68 66 unsigned long profile_pc(struct pt_regs *);
... ... @@ -151,8 +149,6 @@
151 149 #define SF_XXARG 0x5c
152 150  
153 151 /* Stuff for the ptrace system call */
154   -#define PTRACE_SUNATTACH 10
155   -#define PTRACE_SUNDETACH 11
156 152 #define PTRACE_GETREGS 12
157 153 #define PTRACE_SETREGS 13
158 154 #define PTRACE_GETFPREGS 14
... ... @@ -163,9 +159,6 @@
163 159 #define PTRACE_WRITETEXT 19
164 160 #define PTRACE_GETFPAREGS 20
165 161 #define PTRACE_SETFPAREGS 21
166   -
167   -#define PTRACE_GETUCODE 29 /* stupid bsd-ism */
168   -
169 162  
170 163 #endif /* !(_SPARC_PTRACE_H) */
include/asm-sparc64/elf.h
... ... @@ -70,6 +70,8 @@
70 70 #define HWCAP_SPARC_BLKINIT 64
71 71 #define HWCAP_SPARC_N2 128
72 72  
  73 +#define CORE_DUMP_USE_REGSET
  74 +
73 75 /*
74 76 * These are used to set parameters in the core dumps.
75 77 */
... ... @@ -78,10 +80,6 @@
78 80 #define ELF_CLASS ELFCLASS64
79 81 #define ELF_DATA ELFDATA2MSB
80 82  
81   -typedef unsigned long elf_greg_t;
82   -
83   -#define ELF_NGREG 36
84   -typedef elf_greg_t elf_gregset_t[ELF_NGREG];
85 83 /* Format of 64-bit elf_gregset_t is:
86 84 * G0 --> G7
87 85 * O0 --> O7
... ... @@ -92,24 +90,9 @@
92 90 * TNPC
93 91 * Y
94 92 */
95   -#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \
96   -do { unsigned long *dest = &(__elf_regs[0]); \
97   - struct pt_regs *src = (__pt_regs); \
98   - unsigned long __user *sp; \
99   - int i; \
100   - for(i = 0; i < 16; i++) \
101   - dest[i] = src->u_regs[i]; \
102   - /* Don't try this at home kids... */ \
103   - sp = (unsigned long __user *) \
104   - ((src->u_regs[14] + STACK_BIAS) \
105   - & 0xfffffffffffffff8UL); \
106   - for(i = 0; i < 16; i++) \
107   - __get_user(dest[i+16], &sp[i]); \
108   - dest[32] = src->tstate; \
109   - dest[33] = src->tpc; \
110   - dest[34] = src->tnpc; \
111   - dest[35] = src->y; \
112   -} while (0);
  93 +typedef unsigned long elf_greg_t;
  94 +#define ELF_NGREG 36
  95 +typedef elf_greg_t elf_gregset_t[ELF_NGREG];
113 96  
114 97 typedef struct {
115 98 unsigned long pr_regs[32];
... ... @@ -118,9 +101,6 @@
118 101 unsigned long pr_fprs;
119 102 } elf_fpregset_t;
120 103 #endif
121   -
122   -#define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs) \
123   - ({ ELF_CORE_COPY_REGS((*(__elf_regs)), task_pt_regs(__tsk)); 1; })
124 104  
125 105 /*
126 106 * This is used to ensure we don't load something for the wrong architecture.
include/asm-sparc64/ptrace.h
... ... @@ -95,8 +95,6 @@
95 95  
96 96 #ifdef __KERNEL__
97 97  
98   -#define __ARCH_SYS_PTRACE 1
99   -
100 98 #define force_successful_syscall_return() \
101 99 do { current_thread_info()->syscall_noerror = 1; \
102 100 } while (0)
... ... @@ -261,8 +259,6 @@
261 259 #define SF_XXARG 0x5c
262 260  
263 261 /* Stuff for the ptrace system call */
264   -#define PTRACE_SUNATTACH 10
265   -#define PTRACE_SUNDETACH 11
266 262 #define PTRACE_GETREGS 12
267 263 #define PTRACE_SETREGS 13
268 264 #define PTRACE_GETFPREGS 14
... ... @@ -283,20 +279,6 @@
283 279 /* PTRACE_SYSCALL is 24 */
284 280 #define PTRACE_GETFPREGS64 25
285 281 #define PTRACE_SETFPREGS64 26
286   -
287   -#define PTRACE_GETUCODE 29 /* stupid bsd-ism */
288   -
289   -/* These are for 32-bit processes debugging 64-bit ones.
290   - * Here addr and addr2 are passed in %g2 and %g3 respectively.
291   - */
292   -#define PTRACE_PEEKTEXT64 (30 + PTRACE_PEEKTEXT)
293   -#define PTRACE_POKETEXT64 (30 + PTRACE_POKETEXT)
294   -#define PTRACE_PEEKDATA64 (30 + PTRACE_PEEKDATA)
295   -#define PTRACE_POKEDATA64 (30 + PTRACE_POKEDATA)
296   -#define PTRACE_READDATA64 (30 + PTRACE_READDATA)
297   -#define PTRACE_WRITEDATA64 (30 + PTRACE_WRITEDATA)
298   -#define PTRACE_READTEXT64 (30 + PTRACE_READTEXT)
299   -#define PTRACE_WRITETEXT64 (30 + PTRACE_WRITETEXT)
300 282  
301 283 #endif /* !(_SPARC64_PTRACE_H) */