This source file includes following definitions.
- in_ivt_code
- next_frame
- do_ia64_backtrace
- ia64_backtrace
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <linux/oprofile.h>
14 #include <linux/sched.h>
15 #include <linux/mm.h>
16 #include <asm/ptrace.h>
17
18
19
20
21
22
23
24
25
26 typedef struct
27 {
28 unsigned int depth;
29 struct pt_regs *regs;
30 struct unw_frame_info frame;
31 unsigned long *prev_pfs_loc;
32 } ia64_backtrace_t;
33
34
35 static __inline__ int in_ivt_code(unsigned long pc)
36 {
37 extern char ia64_ivt[];
38 return (pc >= (u_long)ia64_ivt && pc < (u_long)ia64_ivt+32768);
39 }
40
41
42
43
44 static __inline__ int next_frame(ia64_backtrace_t *bt)
45 {
46
47
48
49
50
51 if (in_ivt_code(bt->frame.ip))
52 return 0;
53
54
55
56
57
58
59
60
61
62 if (bt->prev_pfs_loc && bt->regs && bt->frame.pfs_loc == bt->prev_pfs_loc)
63 bt->frame.pfs_loc = &bt->regs->ar_pfs;
64 bt->prev_pfs_loc = NULL;
65
66 return unw_unwind(&bt->frame) == 0;
67 }
68
69
70 static void do_ia64_backtrace(struct unw_frame_info *info, void *vdata)
71 {
72 ia64_backtrace_t *bt = vdata;
73 struct switch_stack *sw;
74 int count = 0;
75 u_long pc, sp;
76
77 sw = (struct switch_stack *)(info+1);
78
79 sw = (struct switch_stack *)(((unsigned long)sw + 15) & ~15);
80
81 unw_init_frame_info(&bt->frame, current, sw);
82
83
84 do {
85 unw_get_sp(&bt->frame, &sp);
86 if (sp >= (u_long)bt->regs)
87 break;
88 if (!next_frame(bt))
89 return;
90 } while (count++ < 200);
91
92
93 while (bt->depth-- && next_frame(bt)) {
94 unw_get_ip(&bt->frame, &pc);
95 oprofile_add_trace(pc);
96 if (unw_is_intr_frame(&bt->frame)) {
97
98
99
100
101
102
103
104
105
106 break;
107 }
108 }
109 }
110
111 void
112 ia64_backtrace(struct pt_regs * const regs, unsigned int depth)
113 {
114 ia64_backtrace_t bt;
115 unsigned long flags;
116
117
118
119
120
121
122 if (user_mode(regs))
123 return;
124
125 bt.depth = depth;
126 bt.regs = regs;
127 bt.prev_pfs_loc = NULL;
128 local_irq_save(flags);
129 unw_init_running(do_ia64_backtrace, &bt);
130 local_irq_restore(flags);
131 }