[POWERPC] Use user_regset accessors for altivec regs
[deliverable/linux.git] / arch / powerpc / kernel / ptrace.c
CommitLineData
1da177e4 1/*
1da177e4
LT
2 * PowerPC version
3 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
4 *
5 * Derived from "arch/m68k/kernel/ptrace.c"
6 * Copyright (C) 1994 by Hamish Macdonald
7 * Taken from linux/kernel/ptrace.c and modified for M680x0.
8 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
9 *
10 * Modified by Cort Dougan (cort@hq.fsmlabs.com)
b123923d 11 * and Paul Mackerras (paulus@samba.org).
1da177e4
LT
12 *
13 * This file is subject to the terms and conditions of the GNU General
14 * Public License. See the file README.legal in the main directory of
15 * this archive for more details.
16 */
17
18#include <linux/kernel.h>
19#include <linux/sched.h>
20#include <linux/mm.h>
21#include <linux/smp.h>
1da177e4
LT
22#include <linux/errno.h>
23#include <linux/ptrace.h>
f65255e8 24#include <linux/regset.h>
3caf06c6 25#include <linux/elf.h>
1da177e4
LT
26#include <linux/user.h>
27#include <linux/security.h>
7ed20e1a 28#include <linux/signal.h>
ea9c102c
DW
29#include <linux/seccomp.h>
30#include <linux/audit.h>
e8a30302 31#ifdef CONFIG_PPC32
ea9c102c 32#include <linux/module.h>
e8a30302 33#endif
1da177e4
LT
34
35#include <asm/uaccess.h>
36#include <asm/page.h>
37#include <asm/pgtable.h>
38#include <asm/system.h>
21a62902 39
abd06505
BH
40/*
41 * does not yet catch signals sent when the child dies.
42 * in exit.c or in signal.c.
43 */
44
45/*
46 * Set of msr bits that gdb can change on behalf of a process.
47 */
48#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
49#define MSR_DEBUGCHANGE 0
1da177e4 50#else
abd06505 51#define MSR_DEBUGCHANGE (MSR_SE | MSR_BE)
1da177e4 52#endif
acd89828 53
1da177e4 54/*
abd06505 55 * Max register writeable via put_reg
1da177e4 56 */
abd06505
BH
57#ifdef CONFIG_PPC32
58#define PT_MAX_PUT_REG PT_MQ
59#else
60#define PT_MAX_PUT_REG PT_CCR
61#endif
1da177e4 62
865418d8
BH
63/*
64 * Get contents of register REGNO in task TASK.
65 */
66unsigned long ptrace_get_reg(struct task_struct *task, int regno)
67{
68 unsigned long tmp = 0;
69
70 if (task->thread.regs == NULL)
71 return -EIO;
72
73 if (regno == PT_MSR) {
74 tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
abd06505 75 return tmp | task->thread.fpexc_mode;
865418d8
BH
76 }
77
78 if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
79 return ((unsigned long *)task->thread.regs)[regno];
80
81 return -EIO;
82}
83
84/*
85 * Write contents of register REGNO in task TASK.
86 */
87int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
88{
89 if (task->thread.regs == NULL)
90 return -EIO;
91
912000e7 92 if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) {
865418d8
BH
93 if (regno == PT_MSR)
94 data = (data & MSR_DEBUGCHANGE)
95 | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
912000e7
BH
96 /* We prevent mucking around with the reserved area of trap
97 * which are used internally by the kernel
98 */
99 if (regno == PT_TRAP)
100 data &= 0xfff0;
865418d8
BH
101 ((unsigned long *)task->thread.regs)[regno] = data;
102 return 0;
103 }
104 return -EIO;
105}
106
107
f65255e8
RM
108static int fpr_get(struct task_struct *target, const struct user_regset *regset,
109 unsigned int pos, unsigned int count,
110 void *kbuf, void __user *ubuf)
111{
112 flush_fp_to_thread(target);
113
114 BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) !=
115 offsetof(struct thread_struct, fpr[32]));
116
117 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
118 &target->thread.fpr, 0, -1);
119}
120
121static int fpr_set(struct task_struct *target, const struct user_regset *regset,
122 unsigned int pos, unsigned int count,
123 const void *kbuf, const void __user *ubuf)
124{
125 flush_fp_to_thread(target);
126
127 BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) !=
128 offsetof(struct thread_struct, fpr[32]));
129
130 return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
131 &target->thread.fpr, 0, -1);
132}
133
865418d8
BH
134static int get_fpregs(void __user *data, struct task_struct *task,
135 int has_fpscr)
136{
137 unsigned int count = has_fpscr ? 33 : 32;
f65255e8 138 if (!access_ok(VERIFY_WRITE, data, count * sizeof(double)))
865418d8 139 return -EFAULT;
f65255e8 140 return fpr_get(task, NULL, 0, count * sizeof(double), NULL, data);
865418d8
BH
141}
142
143static int set_fpregs(void __user *data, struct task_struct *task,
144 int has_fpscr)
145{
146 unsigned int count = has_fpscr ? 33 : 32;
f65255e8 147 if (!access_ok(VERIFY_READ, data, count * sizeof(double)))
865418d8 148 return -EFAULT;
f65255e8 149 return fpr_set(task, NULL, 0, count * sizeof(double), NULL, data);
865418d8
BH
150}
151
152
153#ifdef CONFIG_ALTIVEC
154/*
155 * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
156 * The transfer totals 34 quadword. Quadwords 0-31 contain the
157 * corresponding vector registers. Quadword 32 contains the vscr as the
158 * last word (offset 12) within that quadword. Quadword 33 contains the
159 * vrsave as the first word (offset 0) within the quadword.
160 *
161 * This definition of the VMX state is compatible with the current PPC32
162 * ptrace interface. This allows signal handling and ptrace to use the
163 * same structures. This also simplifies the implementation of a bi-arch
164 * (combined (32- and 64-bit) gdb.
165 */
166
3caf06c6
RM
167static int vr_active(struct task_struct *target,
168 const struct user_regset *regset)
169{
170 flush_altivec_to_thread(target);
171 return target->thread.used_vr ? regset->n : 0;
172}
173
174static int vr_get(struct task_struct *target, const struct user_regset *regset,
175 unsigned int pos, unsigned int count,
176 void *kbuf, void __user *ubuf)
177{
178 int ret;
179
180 flush_altivec_to_thread(target);
181
182 BUILD_BUG_ON(offsetof(struct thread_struct, vscr) !=
183 offsetof(struct thread_struct, vr[32]));
184
185 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
186 &target->thread.vr, 0,
187 33 * sizeof(vector128));
188 if (!ret) {
189 /*
190 * Copy out only the low-order word of vrsave.
191 */
192 union {
193 elf_vrreg_t reg;
194 u32 word;
195 } vrsave;
196 memset(&vrsave, 0, sizeof(vrsave));
197 vrsave.word = target->thread.vrsave;
198 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
199 33 * sizeof(vector128), -1);
200 }
201
202 return ret;
203}
204
205static int vr_set(struct task_struct *target, const struct user_regset *regset,
206 unsigned int pos, unsigned int count,
207 const void *kbuf, const void __user *ubuf)
208{
209 int ret;
210
211 flush_altivec_to_thread(target);
212
213 BUILD_BUG_ON(offsetof(struct thread_struct, vscr) !=
214 offsetof(struct thread_struct, vr[32]));
215
216 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
217 &target->thread.vr, 0, 33 * sizeof(vector128));
218 if (!ret && count > 0) {
219 /*
220 * We use only the first word of vrsave.
221 */
222 union {
223 elf_vrreg_t reg;
224 u32 word;
225 } vrsave;
226 memset(&vrsave, 0, sizeof(vrsave));
227 vrsave.word = target->thread.vrsave;
228 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
229 33 * sizeof(vector128), -1);
230 if (!ret)
231 target->thread.vrsave = vrsave.word;
232 }
233
234 return ret;
235}
236
865418d8
BH
237/*
238 * Get contents of AltiVec register state in task TASK
239 */
240static int get_vrregs(unsigned long __user *data, struct task_struct *task)
241{
3caf06c6
RM
242 if (!access_ok(VERIFY_WRITE, data,
243 33 * sizeof(vector128) + sizeof(u32)))
865418d8
BH
244 return -EFAULT;
245
3caf06c6
RM
246 return vr_get(task, NULL, 0, 33 * sizeof(vector128) + sizeof(u32),
247 NULL, data);
865418d8
BH
248}
249
250/*
251 * Write contents of AltiVec register state into task TASK.
252 */
253static int set_vrregs(struct task_struct *task, unsigned long __user *data)
254{
3caf06c6 255 if (!access_ok(VERIFY_READ, data, 33 * sizeof(vector128) + sizeof(u32)))
865418d8
BH
256 return -EFAULT;
257
3caf06c6
RM
258 return vr_set(task, NULL, 0, 33 * sizeof(vector128) + sizeof(u32),
259 NULL, data);
865418d8
BH
260}
261#endif /* CONFIG_ALTIVEC */
262
263#ifdef CONFIG_SPE
264
265/*
266 * For get_evrregs/set_evrregs functions 'data' has the following layout:
267 *
268 * struct {
269 * u32 evr[32];
270 * u64 acc;
271 * u32 spefscr;
272 * }
273 */
274
275/*
276 * Get contents of SPE register state in task TASK.
277 */
278static int get_evrregs(unsigned long *data, struct task_struct *task)
279{
280 int i;
281
282 if (!access_ok(VERIFY_WRITE, data, 35 * sizeof(unsigned long)))
283 return -EFAULT;
284
285 /* copy SPEFSCR */
286 if (__put_user(task->thread.spefscr, &data[34]))
287 return -EFAULT;
288
289 /* copy SPE registers EVR[0] .. EVR[31] */
290 for (i = 0; i < 32; i++, data++)
291 if (__put_user(task->thread.evr[i], data))
292 return -EFAULT;
293
294 /* copy ACC */
295 if (__put_user64(task->thread.acc, (unsigned long long *)data))
296 return -EFAULT;
297
298 return 0;
299}
300
301/*
302 * Write contents of SPE register state into task TASK.
303 */
304static int set_evrregs(struct task_struct *task, unsigned long *data)
305{
306 int i;
307
308 if (!access_ok(VERIFY_READ, data, 35 * sizeof(unsigned long)))
309 return -EFAULT;
310
311 /* copy SPEFSCR */
312 if (__get_user(task->thread.spefscr, &data[34]))
313 return -EFAULT;
314
315 /* copy SPE registers EVR[0] .. EVR[31] */
316 for (i = 0; i < 32; i++, data++)
317 if (__get_user(task->thread.evr[i], data))
318 return -EFAULT;
319 /* copy ACC */
320 if (__get_user64(task->thread.acc, (unsigned long long*)data))
321 return -EFAULT;
322
323 return 0;
324}
325#endif /* CONFIG_SPE */
326
327
2a84b0d7 328void user_enable_single_step(struct task_struct *task)
865418d8
BH
329{
330 struct pt_regs *regs = task->thread.regs;
331
332 if (regs != NULL) {
333#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
334 task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
335 regs->msr |= MSR_DE;
336#else
337 regs->msr |= MSR_SE;
338#endif
339 }
340 set_tsk_thread_flag(task, TIF_SINGLESTEP);
341}
342
2a84b0d7 343void user_disable_single_step(struct task_struct *task)
865418d8
BH
344{
345 struct pt_regs *regs = task->thread.regs;
346
347 if (regs != NULL) {
348#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
349 task->thread.dbcr0 = 0;
350 regs->msr &= ~MSR_DE;
351#else
352 regs->msr &= ~MSR_SE;
353#endif
354 }
355 clear_tsk_thread_flag(task, TIF_SINGLESTEP);
356}
357
abd06505
BH
358static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
359 unsigned long data)
360{
361 /* We only support one DABR and no IABRS at the moment */
362 if (addr > 0)
363 return -EINVAL;
364
365 /* The bottom 3 bits are flags */
366 if ((data & ~0x7UL) >= TASK_SIZE)
367 return -EIO;
368
369 /* Ensure translation is on */
370 if (data && !(data & DABR_TRANSLATION))
371 return -EIO;
372
373 task->thread.dabr = data;
374 return 0;
375}
abd06505 376
1da177e4
LT
377/*
378 * Called by kernel/ptrace.c when detaching..
379 *
380 * Make sure single step bits etc are not set.
381 */
382void ptrace_disable(struct task_struct *child)
383{
384 /* make sure the single step bit is not set. */
2a84b0d7 385 user_disable_single_step(child);
1da177e4
LT
386}
387
e17666ba
BH
388/*
389 * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
390 * we mark them as obsolete now, they will be removed in a future version
391 */
392static long arch_ptrace_old(struct task_struct *child, long request, long addr,
393 long data)
394{
395 int ret = -EPERM;
396
397 switch(request) {
398 case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
399 int i;
400 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
401 unsigned long __user *tmp = (unsigned long __user *)addr;
402
fabca2c0 403 CHECK_FULL_REGS(child->thread.regs);
e17666ba
BH
404 for (i = 0; i < 32; i++) {
405 ret = put_user(*reg, tmp);
406 if (ret)
407 break;
408 reg++;
409 tmp++;
410 }
411 break;
412 }
413
414 case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
415 int i;
416 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
417 unsigned long __user *tmp = (unsigned long __user *)addr;
418
fabca2c0 419 CHECK_FULL_REGS(child->thread.regs);
e17666ba
BH
420 for (i = 0; i < 32; i++) {
421 ret = get_user(*reg, tmp);
422 if (ret)
423 break;
424 reg++;
425 tmp++;
426 }
427 break;
428 }
429
430 case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
431 flush_fp_to_thread(child);
432 ret = get_fpregs((void __user *)addr, child, 0);
433 break;
434 }
435
436 case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
437 flush_fp_to_thread(child);
438 ret = set_fpregs((void __user *)addr, child, 0);
439 break;
440 }
441
442 }
443 return ret;
444}
445
481bed45 446long arch_ptrace(struct task_struct *child, long request, long addr, long data)
1da177e4 447{
1da177e4
LT
448 int ret = -EPERM;
449
1da177e4
LT
450 switch (request) {
451 /* when I and D space are separate, these will need to be fixed. */
452 case PTRACE_PEEKTEXT: /* read word at location addr. */
76647323
AD
453 case PTRACE_PEEKDATA:
454 ret = generic_ptrace_peekdata(child, addr, data);
1da177e4 455 break;
1da177e4
LT
456
457 /* read the word at location addr in the USER area. */
1da177e4
LT
458 case PTRACE_PEEKUSR: {
459 unsigned long index, tmp;
460
461 ret = -EIO;
462 /* convert to index and check */
e8a30302 463#ifdef CONFIG_PPC32
1da177e4 464 index = (unsigned long) addr >> 2;
e8a30302
SR
465 if ((addr & 3) || (index > PT_FPSCR)
466 || (child->thread.regs == NULL))
467#else
468 index = (unsigned long) addr >> 3;
469 if ((addr & 7) || (index > PT_FPSCR))
470#endif
1da177e4
LT
471 break;
472
473 CHECK_FULL_REGS(child->thread.regs);
474 if (index < PT_FPR0) {
865418d8 475 tmp = ptrace_get_reg(child, (int) index);
1da177e4 476 } else {
e8a30302 477 flush_fp_to_thread(child);
1da177e4
LT
478 tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
479 }
480 ret = put_user(tmp,(unsigned long __user *) data);
481 break;
482 }
483
484 /* If I and D space are separate, this will have to be fixed. */
485 case PTRACE_POKETEXT: /* write the word at location addr. */
486 case PTRACE_POKEDATA:
f284ce72 487 ret = generic_ptrace_pokedata(child, addr, data);
1da177e4
LT
488 break;
489
490 /* write the word at location addr in the USER area */
491 case PTRACE_POKEUSR: {
492 unsigned long index;
493
494 ret = -EIO;
495 /* convert to index and check */
e8a30302 496#ifdef CONFIG_PPC32
1da177e4 497 index = (unsigned long) addr >> 2;
e8a30302
SR
498 if ((addr & 3) || (index > PT_FPSCR)
499 || (child->thread.regs == NULL))
500#else
501 index = (unsigned long) addr >> 3;
502 if ((addr & 7) || (index > PT_FPSCR))
503#endif
1da177e4
LT
504 break;
505
506 CHECK_FULL_REGS(child->thread.regs);
1da177e4 507 if (index < PT_FPR0) {
865418d8 508 ret = ptrace_put_reg(child, index, data);
1da177e4 509 } else {
e8a30302 510 flush_fp_to_thread(child);
1da177e4
LT
511 ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
512 ret = 0;
513 }
514 break;
515 }
516
e8a30302
SR
517 case PTRACE_GET_DEBUGREG: {
518 ret = -EINVAL;
519 /* We only support one DABR and no IABRS at the moment */
520 if (addr > 0)
521 break;
522 ret = put_user(child->thread.dabr,
523 (unsigned long __user *)data);
524 break;
525 }
526
527 case PTRACE_SET_DEBUGREG:
528 ret = ptrace_set_debugreg(child, addr, data);
529 break;
e8a30302 530
e17666ba
BH
531#ifdef CONFIG_PPC64
532 case PTRACE_GETREGS64:
533#endif
534 case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
535 int ui;
536 if (!access_ok(VERIFY_WRITE, (void __user *)data,
537 sizeof(struct pt_regs))) {
538 ret = -EIO;
539 break;
540 }
fabca2c0 541 CHECK_FULL_REGS(child->thread.regs);
e17666ba
BH
542 ret = 0;
543 for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
865418d8 544 ret |= __put_user(ptrace_get_reg(child, ui),
e17666ba
BH
545 (unsigned long __user *) data);
546 data += sizeof(long);
e8a30302
SR
547 }
548 break;
549 }
550
e17666ba
BH
551#ifdef CONFIG_PPC64
552 case PTRACE_SETREGS64:
553#endif
554 case PTRACE_SETREGS: { /* Set all gp regs in the child. */
555 unsigned long tmp;
556 int ui;
557 if (!access_ok(VERIFY_READ, (void __user *)data,
558 sizeof(struct pt_regs))) {
559 ret = -EIO;
560 break;
561 }
fabca2c0 562 CHECK_FULL_REGS(child->thread.regs);
e17666ba
BH
563 ret = 0;
564 for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
565 ret = __get_user(tmp, (unsigned long __user *) data);
e8a30302
SR
566 if (ret)
567 break;
865418d8 568 ptrace_put_reg(child, ui, tmp);
e17666ba 569 data += sizeof(long);
e8a30302
SR
570 }
571 break;
572 }
573
e17666ba 574 case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */
e8a30302 575 flush_fp_to_thread(child);
e17666ba 576 ret = get_fpregs((void __user *)data, child, 1);
e8a30302
SR
577 break;
578 }
579
e17666ba 580 case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */
e8a30302 581 flush_fp_to_thread(child);
e17666ba 582 ret = set_fpregs((void __user *)data, child, 1);
e8a30302
SR
583 break;
584 }
e8a30302 585
1da177e4
LT
586#ifdef CONFIG_ALTIVEC
587 case PTRACE_GETVRREGS:
588 /* Get the child altivec register state. */
e8a30302 589 flush_altivec_to_thread(child);
1da177e4
LT
590 ret = get_vrregs((unsigned long __user *)data, child);
591 break;
592
593 case PTRACE_SETVRREGS:
594 /* Set the child altivec register state. */
e8a30302 595 flush_altivec_to_thread(child);
1da177e4
LT
596 ret = set_vrregs(child, (unsigned long __user *)data);
597 break;
598#endif
599#ifdef CONFIG_SPE
600 case PTRACE_GETEVRREGS:
601 /* Get the child spe register state. */
5e14d21e 602 flush_spe_to_thread(child);
1da177e4
LT
603 ret = get_evrregs((unsigned long __user *)data, child);
604 break;
605
606 case PTRACE_SETEVRREGS:
607 /* Set the child spe register state. */
608 /* this is to clear the MSR_SPE bit to force a reload
609 * of register state from memory */
5e14d21e 610 flush_spe_to_thread(child);
1da177e4
LT
611 ret = set_evrregs(child, (unsigned long __user *)data);
612 break;
613#endif
614
e17666ba
BH
615 /* Old reverse args ptrace callss */
616 case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
617 case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
618 case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
619 case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */
620 ret = arch_ptrace_old(child, request, addr, data);
621 break;
622
1da177e4
LT
623 default:
624 ret = ptrace_request(child, request, addr, data);
625 break;
626 }
1da177e4
LT
627 return ret;
628}
629
ea9c102c 630static void do_syscall_trace(void)
1da177e4 631{
ea9c102c
DW
632 /* the 0x80 provides a way for the tracing parent to distinguish
633 between a syscall stop and SIGTRAP delivery */
1da177e4
LT
634 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
635 ? 0x80 : 0));
636
637 /*
638 * this isn't the same as continuing with a signal, but it will do
639 * for normal use. strace only continues with a signal if the
640 * stopping signal is not SIGTRAP. -brl
641 */
642 if (current->exit_code) {
643 send_sig(current->exit_code, current, 1);
644 current->exit_code = 0;
645 }
646}
ea9c102c
DW
647
648void do_syscall_trace_enter(struct pt_regs *regs)
649{
e8a30302 650 secure_computing(regs->gpr[0]);
e8a30302 651
ea9c102c
DW
652 if (test_thread_flag(TIF_SYSCALL_TRACE)
653 && (current->ptrace & PT_PTRACED))
654 do_syscall_trace();
655
cfcd1705
DW
656 if (unlikely(current->audit_context)) {
657#ifdef CONFIG_PPC64
658 if (!test_thread_flag(TIF_32BIT))
659 audit_syscall_entry(AUDIT_ARCH_PPC64,
660 regs->gpr[0],
661 regs->gpr[3], regs->gpr[4],
662 regs->gpr[5], regs->gpr[6]);
663 else
e8a30302 664#endif
cfcd1705
DW
665 audit_syscall_entry(AUDIT_ARCH_PPC,
666 regs->gpr[0],
667 regs->gpr[3] & 0xffffffff,
668 regs->gpr[4] & 0xffffffff,
669 regs->gpr[5] & 0xffffffff,
670 regs->gpr[6] & 0xffffffff);
671 }
ea9c102c
DW
672}
673
674void do_syscall_trace_leave(struct pt_regs *regs)
675{
ea9c102c 676 if (unlikely(current->audit_context))
4b9c876a 677 audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
ea9c102c
DW
678 regs->result);
679
e8a30302 680 if ((test_thread_flag(TIF_SYSCALL_TRACE)
1bd79336 681 || test_thread_flag(TIF_SINGLESTEP))
ea9c102c
DW
682 && (current->ptrace & PT_PTRACED))
683 do_syscall_trace();
684}
This page took 0.401524 seconds and 5 git commands to generate.