MIPS: Enable HAVE_ARCH_TRACEHOOK.
[deliverable/linux.git] / arch / mips / kernel / ptrace.c
CommitLineData
1da177e4
LT
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1992 Ross Biro
7 * Copyright (C) Linus Torvalds
8 * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
9 * Copyright (C) 1996 David S. Miller
10 * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
11 * Copyright (C) 1999 MIPS Technologies, Inc.
12 * Copyright (C) 2000 Ulf Carlsson
13 *
14 * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit
15 * binaries.
16 */
1da177e4 17#include <linux/compiler.h>
c3fc5cd5 18#include <linux/context_tracking.h>
7aeb753b 19#include <linux/elf.h>
1da177e4
LT
20#include <linux/kernel.h>
21#include <linux/sched.h>
22#include <linux/mm.h>
23#include <linux/errno.h>
24#include <linux/ptrace.h>
7aeb753b 25#include <linux/regset.h>
1da177e4 26#include <linux/smp.h>
1da177e4
LT
27#include <linux/user.h>
28#include <linux/security.h>
bc3d22c1 29#include <linux/tracehook.h>
293c5bd1
RB
30#include <linux/audit.h>
31#include <linux/seccomp.h>
1da177e4 32
f8280c8d 33#include <asm/byteorder.h>
1da177e4 34#include <asm/cpu.h>
e50c0a8f 35#include <asm/dsp.h>
1da177e4
LT
36#include <asm/fpu.h>
37#include <asm/mipsregs.h>
101b3531 38#include <asm/mipsmtregs.h>
1da177e4
LT
39#include <asm/pgtable.h>
40#include <asm/page.h>
1da177e4
LT
41#include <asm/uaccess.h>
42#include <asm/bootinfo.h>
ea3d710f 43#include <asm/reg.h>
1da177e4
LT
44
45/*
46 * Called by kernel/ptrace.c when detaching..
47 *
48 * Make sure single step bits etc are not set.
49 */
50void ptrace_disable(struct task_struct *child)
51{
0926bf95
DD
52 /* Don't load the watchpoint registers for the ex-child. */
53 clear_tsk_thread_flag(child, TIF_LOAD_WATCH);
1da177e4
LT
54}
55
ea3d710f 56/*
70342287 57 * Read a general register set. We always use the 64-bit format, even
ea3d710f
DJ
58 * for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
59 * Registers are sign extended to fill the available space.
60 */
49a89efb 61int ptrace_getregs(struct task_struct *child, __s64 __user *data)
ea3d710f
DJ
62{
63 struct pt_regs *regs;
64 int i;
65
66 if (!access_ok(VERIFY_WRITE, data, 38 * 8))
67 return -EIO;
68
40bc9c67 69 regs = task_pt_regs(child);
ea3d710f
DJ
70
71 for (i = 0; i < 32; i++)
62b14c24
AN
72 __put_user((long)regs->regs[i], data + i);
73 __put_user((long)regs->lo, data + EF_LO - EF_R0);
74 __put_user((long)regs->hi, data + EF_HI - EF_R0);
75 __put_user((long)regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
76 __put_user((long)regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0);
77 __put_user((long)regs->cp0_status, data + EF_CP0_STATUS - EF_R0);
78 __put_user((long)regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0);
ea3d710f
DJ
79
80 return 0;
81}
82
83/*
84 * Write a general register set. As for PTRACE_GETREGS, we always use
85 * the 64-bit format. On a 32-bit kernel only the lower order half
86 * (according to endianness) will be used.
87 */
49a89efb 88int ptrace_setregs(struct task_struct *child, __s64 __user *data)
ea3d710f
DJ
89{
90 struct pt_regs *regs;
91 int i;
92
93 if (!access_ok(VERIFY_READ, data, 38 * 8))
94 return -EIO;
95
40bc9c67 96 regs = task_pt_regs(child);
ea3d710f
DJ
97
98 for (i = 0; i < 32; i++)
49a89efb
RB
99 __get_user(regs->regs[i], data + i);
100 __get_user(regs->lo, data + EF_LO - EF_R0);
101 __get_user(regs->hi, data + EF_HI - EF_R0);
102 __get_user(regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
ea3d710f
DJ
103
104 /* badvaddr, status, and cause may not be written. */
105
106 return 0;
107}
108
49a89efb 109int ptrace_getfpregs(struct task_struct *child, __u32 __user *data)
ea3d710f
DJ
110{
111 int i;
e04582b7 112 unsigned int tmp;
ea3d710f
DJ
113
114 if (!access_ok(VERIFY_WRITE, data, 33 * 8))
115 return -EIO;
116
117 if (tsk_used_math(child)) {
118 fpureg_t *fregs = get_fpu_regs(child);
119 for (i = 0; i < 32; i++)
49a89efb 120 __put_user(fregs[i], i + (__u64 __user *) data);
ea3d710f
DJ
121 } else {
122 for (i = 0; i < 32; i++)
49a89efb 123 __put_user((__u64) -1, i + (__u64 __user *) data);
ea3d710f
DJ
124 }
125
49a89efb 126 __put_user(child->thread.fpu.fcr31, data + 64);
eae89076 127
e04582b7 128 preempt_disable();
ea3d710f 129 if (cpu_has_fpu) {
e04582b7 130 unsigned int flags;
ea3d710f 131
101b3531
RB
132 if (cpu_has_mipsmt) {
133 unsigned int vpflags = dvpe();
134 flags = read_c0_status();
135 __enable_fpu();
136 __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp));
137 write_c0_status(flags);
138 evpe(vpflags);
139 } else {
140 flags = read_c0_status();
141 __enable_fpu();
142 __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp));
143 write_c0_status(flags);
144 }
ea3d710f 145 } else {
e04582b7 146 tmp = 0;
ea3d710f 147 }
e04582b7 148 preempt_enable();
49a89efb 149 __put_user(tmp, data + 65);
ea3d710f
DJ
150
151 return 0;
152}
153
49a89efb 154int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
ea3d710f
DJ
155{
156 fpureg_t *fregs;
157 int i;
158
159 if (!access_ok(VERIFY_READ, data, 33 * 8))
160 return -EIO;
161
162 fregs = get_fpu_regs(child);
163
164 for (i = 0; i < 32; i++)
49a89efb 165 __get_user(fregs[i], i + (__u64 __user *) data);
ea3d710f 166
49a89efb 167 __get_user(child->thread.fpu.fcr31, data + 64);
ea3d710f
DJ
168
169 /* FIR may not be written. */
170
171 return 0;
172}
173
0926bf95
DD
174int ptrace_get_watch_regs(struct task_struct *child,
175 struct pt_watch_regs __user *addr)
176{
177 enum pt_watch_style style;
178 int i;
179
180 if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0)
181 return -EIO;
182 if (!access_ok(VERIFY_WRITE, addr, sizeof(struct pt_watch_regs)))
183 return -EIO;
184
185#ifdef CONFIG_32BIT
186 style = pt_watch_style_mips32;
187#define WATCH_STYLE mips32
188#else
189 style = pt_watch_style_mips64;
190#define WATCH_STYLE mips64
191#endif
192
193 __put_user(style, &addr->style);
194 __put_user(current_cpu_data.watch_reg_use_cnt,
195 &addr->WATCH_STYLE.num_valid);
196 for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) {
197 __put_user(child->thread.watch.mips3264.watchlo[i],
198 &addr->WATCH_STYLE.watchlo[i]);
199 __put_user(child->thread.watch.mips3264.watchhi[i] & 0xfff,
200 &addr->WATCH_STYLE.watchhi[i]);
201 __put_user(current_cpu_data.watch_reg_masks[i],
202 &addr->WATCH_STYLE.watch_masks[i]);
203 }
204 for (; i < 8; i++) {
205 __put_user(0, &addr->WATCH_STYLE.watchlo[i]);
206 __put_user(0, &addr->WATCH_STYLE.watchhi[i]);
207 __put_user(0, &addr->WATCH_STYLE.watch_masks[i]);
208 }
209
210 return 0;
211}
212
213int ptrace_set_watch_regs(struct task_struct *child,
214 struct pt_watch_regs __user *addr)
215{
216 int i;
217 int watch_active = 0;
218 unsigned long lt[NUM_WATCH_REGS];
219 u16 ht[NUM_WATCH_REGS];
220
221 if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0)
222 return -EIO;
223 if (!access_ok(VERIFY_READ, addr, sizeof(struct pt_watch_regs)))
224 return -EIO;
225 /* Check the values. */
226 for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) {
227 __get_user(lt[i], &addr->WATCH_STYLE.watchlo[i]);
228#ifdef CONFIG_32BIT
229 if (lt[i] & __UA_LIMIT)
230 return -EINVAL;
231#else
232 if (test_tsk_thread_flag(child, TIF_32BIT_ADDR)) {
233 if (lt[i] & 0xffffffff80000000UL)
234 return -EINVAL;
235 } else {
236 if (lt[i] & __UA_LIMIT)
237 return -EINVAL;
238 }
239#endif
240 __get_user(ht[i], &addr->WATCH_STYLE.watchhi[i]);
241 if (ht[i] & ~0xff8)
242 return -EINVAL;
243 }
244 /* Install them. */
245 for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) {
246 if (lt[i] & 7)
247 watch_active = 1;
248 child->thread.watch.mips3264.watchlo[i] = lt[i];
249 /* Set the G bit. */
250 child->thread.watch.mips3264.watchhi[i] = ht[i];
251 }
252
253 if (watch_active)
254 set_tsk_thread_flag(child, TIF_LOAD_WATCH);
255 else
256 clear_tsk_thread_flag(child, TIF_LOAD_WATCH);
257
258 return 0;
259}
260
7aeb753b
RB
261/* regset get/set implementations */
262
263static int gpr_get(struct task_struct *target,
264 const struct user_regset *regset,
265 unsigned int pos, unsigned int count,
266 void *kbuf, void __user *ubuf)
267{
268 struct pt_regs *regs = task_pt_regs(target);
269
270 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
271 regs, 0, sizeof(*regs));
272}
273
274static int gpr_set(struct task_struct *target,
275 const struct user_regset *regset,
276 unsigned int pos, unsigned int count,
277 const void *kbuf, const void __user *ubuf)
278{
279 struct pt_regs newregs;
280 int ret;
281
282 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
283 &newregs,
284 0, sizeof(newregs));
285 if (ret)
286 return ret;
287
288 *task_pt_regs(target) = newregs;
289
290 return 0;
291}
292
293static int fpr_get(struct task_struct *target,
294 const struct user_regset *regset,
295 unsigned int pos, unsigned int count,
296 void *kbuf, void __user *ubuf)
297{
298 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
299 &target->thread.fpu,
300 0, sizeof(elf_fpregset_t));
301 /* XXX fcr31 */
302}
303
304static int fpr_set(struct task_struct *target,
305 const struct user_regset *regset,
306 unsigned int pos, unsigned int count,
307 const void *kbuf, const void __user *ubuf)
308{
309 return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
310 &target->thread.fpu,
311 0, sizeof(elf_fpregset_t));
312 /* XXX fcr31 */
313}
314
315enum mips_regset {
316 REGSET_GPR,
317 REGSET_FPR,
318};
319
320static const struct user_regset mips_regsets[] = {
321 [REGSET_GPR] = {
322 .core_note_type = NT_PRSTATUS,
323 .n = ELF_NGREG,
324 .size = sizeof(unsigned int),
325 .align = sizeof(unsigned int),
326 .get = gpr_get,
327 .set = gpr_set,
328 },
329 [REGSET_FPR] = {
330 .core_note_type = NT_PRFPREG,
331 .n = ELF_NFPREG,
332 .size = sizeof(elf_fpreg_t),
333 .align = sizeof(elf_fpreg_t),
334 .get = fpr_get,
335 .set = fpr_set,
336 },
337};
338
339static const struct user_regset_view user_mips_view = {
340 .name = "mips",
341 .e_machine = ELF_ARCH,
342 .ei_osabi = ELF_OSABI,
343 .regsets = mips_regsets,
344 .n = ARRAY_SIZE(mips_regsets),
345};
346
347static const struct user_regset mips64_regsets[] = {
348 [REGSET_GPR] = {
349 .core_note_type = NT_PRSTATUS,
350 .n = ELF_NGREG,
351 .size = sizeof(unsigned long),
352 .align = sizeof(unsigned long),
353 .get = gpr_get,
354 .set = gpr_set,
355 },
356 [REGSET_FPR] = {
357 .core_note_type = NT_PRFPREG,
358 .n = ELF_NFPREG,
359 .size = sizeof(elf_fpreg_t),
360 .align = sizeof(elf_fpreg_t),
361 .get = fpr_get,
362 .set = fpr_set,
363 },
364};
365
366static const struct user_regset_view user_mips64_view = {
367 .name = "mips",
368 .e_machine = ELF_ARCH,
369 .ei_osabi = ELF_OSABI,
370 .regsets = mips64_regsets,
371 .n = ARRAY_SIZE(mips_regsets),
372};
373
374const struct user_regset_view *task_user_regset_view(struct task_struct *task)
375{
376#ifdef CONFIG_32BIT
377 return &user_mips_view;
378#endif
379
380#ifdef CONFIG_MIPS32_O32
381 if (test_thread_flag(TIF_32BIT_REGS))
382 return &user_mips_view;
383#endif
384
385 return &user_mips64_view;
386}
387
9b05a69e
NK
388long arch_ptrace(struct task_struct *child, long request,
389 unsigned long addr, unsigned long data)
1da177e4 390{
1da177e4 391 int ret;
fb671139
NK
392 void __user *addrp = (void __user *) addr;
393 void __user *datavp = (void __user *) data;
394 unsigned long __user *datalp = (void __user *) data;
1da177e4 395
1da177e4
LT
396 switch (request) {
397 /* when I and D space are separate, these will need to be fixed. */
398 case PTRACE_PEEKTEXT: /* read word at location addr. */
76647323
AD
399 case PTRACE_PEEKDATA:
400 ret = generic_ptrace_peekdata(child, addr, data);
1da177e4 401 break;
1da177e4
LT
402
403 /* Read the word at location addr in the USER area. */
404 case PTRACE_PEEKUSR: {
405 struct pt_regs *regs;
406 unsigned long tmp = 0;
407
40bc9c67 408 regs = task_pt_regs(child);
1da177e4
LT
409 ret = 0; /* Default return value. */
410
411 switch (addr) {
412 case 0 ... 31:
413 tmp = regs->regs[addr];
414 break;
415 case FPR_BASE ... FPR_BASE + 31:
416 if (tsk_used_math(child)) {
417 fpureg_t *fregs = get_fpu_regs(child);
418
875d43e7 419#ifdef CONFIG_32BIT
1da177e4
LT
420 /*
421 * The odd registers are actually the high
422 * order bits of the values stored in the even
423 * registers - unless we're using r2k_switch.S.
424 */
425 if (addr & 1)
426 tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32);
427 else
428 tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff);
429#endif
875d43e7 430#ifdef CONFIG_64BIT
1da177e4
LT
431 tmp = fregs[addr - FPR_BASE];
432#endif
433 } else {
434 tmp = -1; /* FP not yet used */
435 }
436 break;
437 case PC:
438 tmp = regs->cp0_epc;
439 break;
440 case CAUSE:
441 tmp = regs->cp0_cause;
442 break;
443 case BADVADDR:
444 tmp = regs->cp0_badvaddr;
445 break;
446 case MMHI:
447 tmp = regs->hi;
448 break;
449 case MMLO:
450 tmp = regs->lo;
451 break;
9693a853
FBH
452#ifdef CONFIG_CPU_HAS_SMARTMIPS
453 case ACX:
454 tmp = regs->acx;
455 break;
456#endif
1da177e4 457 case FPC_CSR:
eae89076 458 tmp = child->thread.fpu.fcr31;
1da177e4 459 break;
70342287 460 case FPC_EIR: { /* implementation / version register */
1da177e4 461 unsigned int flags;
41c594ab 462#ifdef CONFIG_MIPS_MT_SMTC
b7e4226e 463 unsigned long irqflags;
41c594ab
RB
464 unsigned int mtflags;
465#endif /* CONFIG_MIPS_MT_SMTC */
1da177e4 466
e04582b7
AN
467 preempt_disable();
468 if (!cpu_has_fpu) {
469 preempt_enable();
1da177e4 470 break;
e04582b7 471 }
1da177e4 472
41c594ab
RB
473#ifdef CONFIG_MIPS_MT_SMTC
474 /* Read-modify-write of Status must be atomic */
475 local_irq_save(irqflags);
476 mtflags = dmt();
477#endif /* CONFIG_MIPS_MT_SMTC */
101b3531
RB
478 if (cpu_has_mipsmt) {
479 unsigned int vpflags = dvpe();
480 flags = read_c0_status();
481 __enable_fpu();
482 __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
483 write_c0_status(flags);
484 evpe(vpflags);
485 } else {
486 flags = read_c0_status();
487 __enable_fpu();
488 __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
489 write_c0_status(flags);
490 }
41c594ab
RB
491#ifdef CONFIG_MIPS_MT_SMTC
492 emt(mtflags);
493 local_irq_restore(irqflags);
494#endif /* CONFIG_MIPS_MT_SMTC */
101b3531 495 preempt_enable();
1da177e4
LT
496 break;
497 }
c134a5ec
RB
498 case DSP_BASE ... DSP_BASE + 5: {
499 dspreg_t *dregs;
500
e50c0a8f
RB
501 if (!cpu_has_dsp) {
502 tmp = 0;
503 ret = -EIO;
481bed45 504 goto out;
e50c0a8f 505 }
6c355852
RB
506 dregs = __get_dsp_regs(child);
507 tmp = (unsigned long) (dregs[addr - DSP_BASE]);
e50c0a8f 508 break;
c134a5ec 509 }
e50c0a8f
RB
510 case DSP_CONTROL:
511 if (!cpu_has_dsp) {
512 tmp = 0;
513 ret = -EIO;
481bed45 514 goto out;
e50c0a8f
RB
515 }
516 tmp = child->thread.dsp.dspcontrol;
517 break;
1da177e4
LT
518 default:
519 tmp = 0;
520 ret = -EIO;
481bed45 521 goto out;
1da177e4 522 }
fb671139 523 ret = put_user(tmp, datalp);
1da177e4
LT
524 break;
525 }
526
527 /* when I and D space are separate, this will have to be fixed. */
528 case PTRACE_POKETEXT: /* write the word at location addr. */
529 case PTRACE_POKEDATA:
f284ce72 530 ret = generic_ptrace_pokedata(child, addr, data);
1da177e4
LT
531 break;
532
533 case PTRACE_POKEUSR: {
534 struct pt_regs *regs;
535 ret = 0;
40bc9c67 536 regs = task_pt_regs(child);
1da177e4
LT
537
538 switch (addr) {
539 case 0 ... 31:
540 regs->regs[addr] = data;
541 break;
542 case FPR_BASE ... FPR_BASE + 31: {
543 fpureg_t *fregs = get_fpu_regs(child);
544
545 if (!tsk_used_math(child)) {
546 /* FP not yet used */
eae89076
AN
547 memset(&child->thread.fpu, ~0,
548 sizeof(child->thread.fpu));
549 child->thread.fpu.fcr31 = 0;
1da177e4 550 }
875d43e7 551#ifdef CONFIG_32BIT
1da177e4
LT
552 /*
553 * The odd registers are actually the high order bits
554 * of the values stored in the even registers - unless
555 * we're using r2k_switch.S.
556 */
557 if (addr & 1) {
558 fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff;
559 fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32;
560 } else {
561 fregs[addr - FPR_BASE] &= ~0xffffffffLL;
562 fregs[addr - FPR_BASE] |= data;
563 }
564#endif
875d43e7 565#ifdef CONFIG_64BIT
1da177e4
LT
566 fregs[addr - FPR_BASE] = data;
567#endif
568 break;
569 }
570 case PC:
571 regs->cp0_epc = data;
572 break;
573 case MMHI:
574 regs->hi = data;
575 break;
576 case MMLO:
577 regs->lo = data;
578 break;
9693a853
FBH
579#ifdef CONFIG_CPU_HAS_SMARTMIPS
580 case ACX:
581 regs->acx = data;
582 break;
583#endif
1da177e4 584 case FPC_CSR:
eae89076 585 child->thread.fpu.fcr31 = data;
1da177e4 586 break;
c134a5ec
RB
587 case DSP_BASE ... DSP_BASE + 5: {
588 dspreg_t *dregs;
589
e50c0a8f
RB
590 if (!cpu_has_dsp) {
591 ret = -EIO;
592 break;
593 }
594
c134a5ec 595 dregs = __get_dsp_regs(child);
e50c0a8f
RB
596 dregs[addr - DSP_BASE] = data;
597 break;
c134a5ec 598 }
e50c0a8f
RB
599 case DSP_CONTROL:
600 if (!cpu_has_dsp) {
601 ret = -EIO;
602 break;
603 }
604 child->thread.dsp.dspcontrol = data;
605 break;
1da177e4
LT
606 default:
607 /* The rest are not allowed. */
608 ret = -EIO;
609 break;
610 }
611 break;
612 }
613
ea3d710f 614 case PTRACE_GETREGS:
fb671139 615 ret = ptrace_getregs(child, datavp);
ea3d710f
DJ
616 break;
617
618 case PTRACE_SETREGS:
fb671139 619 ret = ptrace_setregs(child, datavp);
ea3d710f
DJ
620 break;
621
622 case PTRACE_GETFPREGS:
fb671139 623 ret = ptrace_getfpregs(child, datavp);
ea3d710f
DJ
624 break;
625
626 case PTRACE_SETFPREGS:
fb671139 627 ret = ptrace_setfpregs(child, datavp);
ea3d710f
DJ
628 break;
629
3c37026d 630 case PTRACE_GET_THREAD_AREA:
fb671139 631 ret = put_user(task_thread_info(child)->tp_value, datalp);
3c37026d
RB
632 break;
633
0926bf95 634 case PTRACE_GET_WATCH_REGS:
fb671139 635 ret = ptrace_get_watch_regs(child, addrp);
0926bf95
DD
636 break;
637
638 case PTRACE_SET_WATCH_REGS:
fb671139 639 ret = ptrace_set_watch_regs(child, addrp);
0926bf95
DD
640 break;
641
1da177e4
LT
642 default:
643 ret = ptrace_request(child, request, addr, data);
644 break;
645 }
481bed45 646 out:
1da177e4
LT
647 return ret;
648}
649
67eb81e1 650static inline int audit_arch(void)
2fd6f58b 651{
f8280c8d 652 int arch = EM_MIPS;
875d43e7 653#ifdef CONFIG_64BIT
70342287 654 arch |= __AUDIT_ARCH_64BIT;
f8280c8d
RB
655#endif
656#if defined(__LITTLE_ENDIAN)
70342287 657 arch |= __AUDIT_ARCH_LE;
f8280c8d
RB
658#endif
659 return arch;
2fd6f58b 660}
661
1da177e4
LT
662/*
663 * Notification of system call entry/exit
664 * - triggered by current->work.syscall_trace
665 */
8b659a39 666asmlinkage void syscall_trace_enter(struct pt_regs *regs)
1da177e4 667{
c3fc5cd5
RB
668 user_exit();
669
293c5bd1 670 /* do the secure computing check first */
e4da89d0 671 secure_computing_strict(regs->regs[2]);
1da177e4 672
bc3d22c1
RB
673 if (test_thread_flag(TIF_SYSCALL_TRACE))
674 ptrace_report_syscall(regs);
293c5bd1 675
b05d8447
EP
676 audit_syscall_entry(audit_arch(), regs->regs[2],
677 regs->regs[4], regs->regs[5],
678 regs->regs[6], regs->regs[7]);
1da177e4 679}
8b659a39
RB
680
681/*
682 * Notification of system call entry/exit
683 * - triggered by current->work.syscall_trace
684 */
685asmlinkage void syscall_trace_leave(struct pt_regs *regs)
686{
c3fc5cd5
RB
687 /*
688 * We may come here right after calling schedule_user()
689 * or do_notify_resume(), in which case we can be in RCU
690 * user mode.
691 */
692 user_exit();
693
d7e7528b 694 audit_syscall_exit(regs);
8b659a39 695
bc3d22c1
RB
696 if (test_thread_flag(TIF_SYSCALL_TRACE))
697 tracehook_report_syscall_exit(regs, 0);
c3fc5cd5
RB
698
699 user_enter();
8b659a39 700}
This page took 0.735236 seconds and 5 git commands to generate.