Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ptrace.c
Go to the documentation of this file.
1 /* MN10300 Process tracing
2  *
3  * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
4  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5  * Modified by David Howells ([email protected])
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public Licence
9  * as published by the Free Software Foundation; either version
10  * 2 of the Licence, or (at your option) any later version.
11  */
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/mm.h>
15 #include <linux/smp.h>
16 #include <linux/errno.h>
17 #include <linux/ptrace.h>
18 #include <linux/user.h>
19 #include <linux/regset.h>
20 #include <linux/elf.h>
21 #include <linux/tracehook.h>
22 #include <asm/uaccess.h>
23 #include <asm/pgtable.h>
24 #include <asm/processor.h>
25 #include <asm/cacheflush.h>
26 #include <asm/fpu.h>
27 #include <asm/asm-offsets.h>
28 
29 /*
30  * translate ptrace register IDs into struct pt_regs offsets
31  */
32 static const u8 ptrace_regid_to_frame[] = {
33  [PT_A3 << 2] = REG_A3,
34  [PT_A2 << 2] = REG_A2,
35  [PT_D3 << 2] = REG_D3,
36  [PT_D2 << 2] = REG_D2,
37  [PT_MCVF << 2] = REG_MCVF,
38  [PT_MCRL << 2] = REG_MCRL,
39  [PT_MCRH << 2] = REG_MCRH,
40  [PT_MDRQ << 2] = REG_MDRQ,
41  [PT_E1 << 2] = REG_E1,
42  [PT_E0 << 2] = REG_E0,
43  [PT_E7 << 2] = REG_E7,
44  [PT_E6 << 2] = REG_E6,
45  [PT_E5 << 2] = REG_E5,
46  [PT_E4 << 2] = REG_E4,
47  [PT_E3 << 2] = REG_E3,
48  [PT_E2 << 2] = REG_E2,
49  [PT_SP << 2] = REG_SP,
50  [PT_LAR << 2] = REG_LAR,
51  [PT_LIR << 2] = REG_LIR,
52  [PT_MDR << 2] = REG_MDR,
53  [PT_A1 << 2] = REG_A1,
54  [PT_A0 << 2] = REG_A0,
55  [PT_D1 << 2] = REG_D1,
56  [PT_D0 << 2] = REG_D0,
57  [PT_ORIG_D0 << 2] = REG_ORIG_D0,
58  [PT_EPSW << 2] = REG_EPSW,
59  [PT_PC << 2] = REG_PC,
60 };
61 
62 static inline int get_stack_long(struct task_struct *task, int offset)
63 {
64  return *(unsigned long *)
65  ((unsigned long) task->thread.uregs + offset);
66 }
67 
68 static inline
69 int put_stack_long(struct task_struct *task, int offset, unsigned long data)
70 {
71  unsigned long stack;
72 
73  stack = (unsigned long) task->thread.uregs + offset;
74  *(unsigned long *) stack = data;
75  return 0;
76 }
77 
78 /*
79  * retrieve the contents of MN10300 userspace general registers
80  */
81 static int genregs_get(struct task_struct *target,
82  const struct user_regset *regset,
83  unsigned int pos, unsigned int count,
84  void *kbuf, void __user *ubuf)
85 {
86  const struct pt_regs *regs = task_pt_regs(target);
87  int ret;
88 
89  /* we need to skip regs->next */
90  ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
91  regs, 0, PT_ORIG_D0 * sizeof(long));
92  if (ret < 0)
93  return ret;
94 
95  ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
96  &regs->orig_d0, PT_ORIG_D0 * sizeof(long),
97  NR_PTREGS * sizeof(long));
98  if (ret < 0)
99  return ret;
100 
101  return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
102  NR_PTREGS * sizeof(long), -1);
103 }
104 
105 /*
106  * update the contents of the MN10300 userspace general registers
107  */
108 static int genregs_set(struct task_struct *target,
109  const struct user_regset *regset,
110  unsigned int pos, unsigned int count,
111  const void *kbuf, const void __user *ubuf)
112 {
113  struct pt_regs *regs = task_pt_regs(target);
114  unsigned long tmp;
115  int ret;
116 
117  /* we need to skip regs->next */
118  ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
119  regs, 0, PT_ORIG_D0 * sizeof(long));
120  if (ret < 0)
121  return ret;
122 
123  ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
124  &regs->orig_d0, PT_ORIG_D0 * sizeof(long),
125  PT_EPSW * sizeof(long));
126  if (ret < 0)
127  return ret;
128 
129  /* we need to mask off changes to EPSW */
130  tmp = regs->epsw;
131  ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
132  &tmp, PT_EPSW * sizeof(long),
133  PT_PC * sizeof(long));
134  tmp &= EPSW_FLAG_V | EPSW_FLAG_C | EPSW_FLAG_N | EPSW_FLAG_Z;
135  tmp |= regs->epsw & ~(EPSW_FLAG_V | EPSW_FLAG_C | EPSW_FLAG_N |
136  EPSW_FLAG_Z);
137  regs->epsw = tmp;
138 
139  if (ret < 0)
140  return ret;
141 
142  /* and finally load the PC */
143  ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
144  &regs->pc, PT_PC * sizeof(long),
145  NR_PTREGS * sizeof(long));
146 
147  if (ret < 0)
148  return ret;
149 
150  return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
151  NR_PTREGS * sizeof(long), -1);
152 }
153 
154 /*
155  * retrieve the contents of MN10300 userspace FPU registers
156  */
157 static int fpuregs_get(struct task_struct *target,
158  const struct user_regset *regset,
159  unsigned int pos, unsigned int count,
160  void *kbuf, void __user *ubuf)
161 {
162  const struct fpu_state_struct *fpregs = &target->thread.fpu_state;
163  int ret;
164 
165  unlazy_fpu(target);
166 
167  ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
168  fpregs, 0, sizeof(*fpregs));
169  if (ret < 0)
170  return ret;
171 
172  return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
173  sizeof(*fpregs), -1);
174 }
175 
176 /*
177  * update the contents of the MN10300 userspace FPU registers
178  */
179 static int fpuregs_set(struct task_struct *target,
180  const struct user_regset *regset,
181  unsigned int pos, unsigned int count,
182  const void *kbuf, const void __user *ubuf)
183 {
184  struct fpu_state_struct fpu_state = target->thread.fpu_state;
185  int ret;
186 
187  ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
188  &fpu_state, 0, sizeof(fpu_state));
189  if (ret < 0)
190  return ret;
191 
192  fpu_kill_state(target);
193  target->thread.fpu_state = fpu_state;
194  set_using_fpu(target);
195 
196  return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
197  sizeof(fpu_state), -1);
198 }
199 
200 /*
201  * determine if the FPU registers have actually been used
202  */
203 static int fpuregs_active(struct task_struct *target,
204  const struct user_regset *regset)
205 {
206  return is_using_fpu(target) ? regset->n : 0;
207 }
208 
209 /*
210  * Define the register sets available on the MN10300 under Linux
211  */
215 };
216 
217 static const struct user_regset mn10300_regsets[] = {
218  /*
219  * General register format is:
220  * A3, A2, D3, D2, MCVF, MCRL, MCRH, MDRQ
221  * E1, E0, E7...E2, SP, LAR, LIR, MDR
222  * A1, A0, D1, D0, ORIG_D0, EPSW, PC
223  */
224  [REGSET_GENERAL] = {
225  .core_note_type = NT_PRSTATUS,
226  .n = ELF_NGREG,
227  .size = sizeof(long),
228  .align = sizeof(long),
229  .get = genregs_get,
230  .set = genregs_set,
231  },
232  /*
233  * FPU register format is:
234  * FS0-31, FPCR
235  */
236  [REGSET_FPU] = {
237  .core_note_type = NT_PRFPREG,
238  .n = sizeof(struct fpu_state_struct) / sizeof(long),
239  .size = sizeof(long),
240  .align = sizeof(long),
241  .get = fpuregs_get,
242  .set = fpuregs_set,
243  .active = fpuregs_active,
244  },
245 };
246 
247 static const struct user_regset_view user_mn10300_native_view = {
248  .name = "mn10300",
249  .e_machine = EM_MN10300,
250  .regsets = mn10300_regsets,
251  .n = ARRAY_SIZE(mn10300_regsets),
252 };
253 
255 {
256  return &user_mn10300_native_view;
257 }
258 
259 /*
260  * set the single-step bit
261  */
263 {
264 #ifndef CONFIG_MN10300_USING_JTAG
265  struct user *dummy = NULL;
266  long tmp;
267 
268  tmp = get_stack_long(child, (unsigned long) &dummy->regs.epsw);
269  tmp |= EPSW_T;
270  put_stack_long(child, (unsigned long) &dummy->regs.epsw, tmp);
271 #endif
272 }
273 
274 /*
275  * make sure the single-step bit is not set
276  */
278 {
279 #ifndef CONFIG_MN10300_USING_JTAG
280  struct user *dummy = NULL;
281  long tmp;
282 
283  tmp = get_stack_long(child, (unsigned long) &dummy->regs.epsw);
284  tmp &= ~EPSW_T;
285  put_stack_long(child, (unsigned long) &dummy->regs.epsw, tmp);
286 #endif
287 }
288 
290 {
292 }
293 
294 /*
295  * handle the arch-specific side of process tracing
296  */
298  unsigned long addr, unsigned long data)
299 {
300  unsigned long tmp;
301  int ret;
302  unsigned long __user *datap = (unsigned long __user *) data;
303 
304  switch (request) {
305  /* read the word at location addr in the USER area. */
306  case PTRACE_PEEKUSR:
307  ret = -EIO;
308  if ((addr & 3) || addr > sizeof(struct user) - 3)
309  break;
310 
311  tmp = 0; /* Default return condition */
312  if (addr < NR_PTREGS << 2)
313  tmp = get_stack_long(child,
314  ptrace_regid_to_frame[addr]);
315  ret = put_user(tmp, datap);
316  break;
317 
318  /* write the word at location addr in the USER area */
319  case PTRACE_POKEUSR:
320  ret = -EIO;
321  if ((addr & 3) || addr > sizeof(struct user) - 3)
322  break;
323 
324  ret = 0;
325  if (addr < NR_PTREGS << 2)
326  ret = put_stack_long(child, ptrace_regid_to_frame[addr],
327  data);
328  break;
329 
330  case PTRACE_GETREGS: /* Get all integer regs from the child. */
331  return copy_regset_to_user(child, &user_mn10300_native_view,
333  0, NR_PTREGS * sizeof(long),
334  datap);
335 
336  case PTRACE_SETREGS: /* Set all integer regs in the child. */
337  return copy_regset_from_user(child, &user_mn10300_native_view,
339  0, NR_PTREGS * sizeof(long),
340  datap);
341 
342  case PTRACE_GETFPREGS: /* Get the child FPU state. */
343  return copy_regset_to_user(child, &user_mn10300_native_view,
344  REGSET_FPU,
345  0, sizeof(struct fpu_state_struct),
346  datap);
347 
348  case PTRACE_SETFPREGS: /* Set the child FPU state. */
349  return copy_regset_from_user(child, &user_mn10300_native_view,
350  REGSET_FPU,
351  0, sizeof(struct fpu_state_struct),
352  datap);
353 
354  default:
355  ret = ptrace_request(child, request, addr, data);
356  break;
357  }
358 
359  return ret;
360 }
361 
362 /*
363  * handle tracing of system call entry
364  * - return the revised system call number or ULONG_MAX to cause ENOSYS
365  */
366 asmlinkage unsigned long syscall_trace_entry(struct pt_regs *regs)
367 {
368  if (tracehook_report_syscall_entry(regs))
369  /* tracing decided this syscall should not happen, so
370  * We'll return a bogus call number to get an ENOSYS
371  * error, but leave the original number in
372  * regs->orig_d0
373  */
374  return ULONG_MAX;
375 
376  return regs->orig_d0;
377 }
378 
379 /*
380  * handle tracing of system call exit
381  */
383 {
384  tracehook_report_syscall_exit(regs, 0);
385 }