x86: fix percpu_{to,from}_op()
[deliverable/linux.git] / arch / x86 / oprofile / backtrace.c
CommitLineData
1da177e4
LT
1/**
2 * @file backtrace.c
3 *
4 * @remark Copyright 2002 OProfile authors
5 * @remark Read the file COPYING
6 *
7 * @author John Levon
8 * @author David Smith
9 */
10
11#include <linux/oprofile.h>
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <asm/ptrace.h>
c34d1b4d 15#include <asm/uaccess.h>
574a6042 16#include <asm/stacktrace.h>
1da177e4 17
574a6042
JB
18static void backtrace_warning_symbol(void *data, char *msg,
19 unsigned long symbol)
20{
21 /* Ignore warnings */
22}
1da177e4 23
574a6042 24static void backtrace_warning(void *data, char *msg)
30379440 25{
574a6042
JB
26 /* Ignore warnings */
27}
30379440 28
574a6042
JB
29static int backtrace_stack(void *data, char *name)
30{
31 /* Yes, we want all stacks */
32 return 0;
33}
30379440 34
bc850d6b 35static void backtrace_address(void *data, unsigned long addr, int reliable)
574a6042
JB
36{
37 unsigned int *depth = data;
38
39 if ((*depth)--)
40 oprofile_add_trace(addr);
30379440
GB
41}
42
574a6042
JB
43static struct stacktrace_ops backtrace_ops = {
44 .warning = backtrace_warning,
45 .warning_symbol = backtrace_warning_symbol,
46 .stack = backtrace_stack,
47 .address = backtrace_address,
48};
49
50struct frame_head {
65ea5b03 51 struct frame_head *bp;
574a6042
JB
52 unsigned long ret;
53} __attribute__((packed));
54
0f019cc4 55static struct frame_head *dump_user_backtrace(struct frame_head *head)
1da177e4 56{
c34d1b4d 57 struct frame_head bufhead[2];
1da177e4 58
c34d1b4d
HD
59 /* Also check accessibility of one struct frame_head beyond */
60 if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
61 return NULL;
62 if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
1da177e4
LT
63 return NULL;
64
c34d1b4d 65 oprofile_add_trace(bufhead[0].ret);
1da177e4 66
c34d1b4d
HD
67 /* frame pointers should strictly progress back up the stack
68 * (towards higher addresses) */
65ea5b03 69 if (head >= bufhead[0].bp)
c34d1b4d 70 return NULL;
1da177e4 71
65ea5b03 72 return bufhead[0].bp;
1da177e4
LT
73}
74
1da177e4
LT
75void
76x86_backtrace(struct pt_regs * const regs, unsigned int depth)
77{
f1df280f 78 struct frame_head *head = (struct frame_head *)frame_pointer(regs);
f6e8e284 79 unsigned long stack = kernel_trap_sp(regs);
1da177e4 80
fa1e1bdf 81 if (!user_mode_vm(regs)) {
574a6042 82 if (depth)
5bc27dc2 83 dump_trace(NULL, regs, (unsigned long *)stack, 0,
574a6042 84 &backtrace_ops, &depth);
1da177e4
LT
85 return;
86 }
87
c34d1b4d 88 while (depth-- && head)
30379440 89 head = dump_user_backtrace(head);
1da177e4 90}
This page took 0.420441 seconds and 5 git commands to generate.