183 * The architecture-independent dump_stack generator
184 */
185 void dump_stack(void)
186 {
187 unsigned long bp;
188 unsigned long stack;
189
190 bp = stack_frame(current, NULL); //在这边得到当前进程的 bp 值。
191 printk("Pid: %d, comm: %.20s %s %s %.*s\n",
192 current->pid, current->comm, print_tainted(),
193 init_utsname()->release,
194 (int)strcspn(init_utsname()->version, " "),
195 init_utsname()->version);
196 show_trace(NULL, NULL, &stack, bp) ;// 打印出函数调用栈,见下面
197 }
171 void show_trace(struct task_struct *task, struct pt_regs *regs,
172 unsigned long *stack, unsigned long bp)
173 {
174 show_trace_log_lvl(task, regs, stack, bp, "");
175 }
163 void 164 show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
165 unsigned long *stack, unsigned long bp, char *log_lvl)
166 {
167 printk("%sCall Trace:\n", log_lvl);
168 dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);// 说明dump_trace 是跟踪单个 cpu的。
169 }
20 void dump_trace(struct task_struct *task, struct pt_regs *regs,
21 unsigned long *stack, unsigned long bp,
22 const struct stacktrace_ops *ops, void *data)
23 {
24 int graph = 0;
25
26 if (!task)
27 task = current;
28
29 if (!stack) {
30 unsigned long dummy;
31
32 stack = &dummy;
33 if (task && task != current)
34 stack = (unsigned long *)task->thread.sp;
35 }
36
37 if (!bp)
38 bp = stack_frame(task, regs);
for (;;) {
41 struct thread_info *context;
42
43 context = (struct thread_info *)
44 ((unsigned long)stack & (~(THREAD_SIZE - 1)));
45 bp = ops->walk_stack(context, stack, bp, ops, data, NULL, &graph);
46
47 stack = (unsigned long *)context->previous_esp;
48 if (!stack)
49 break;
50 if (ops->stack(data, "IRQ") < 0)
51 break;
52 touch_nmi_watchdog();
53 }
54 }
88 unsigned long
89 print_context_stack(struct thread_info *tinfo,
90 unsigned long *stack, unsigned long bp,
91 const struct stacktrace_ops *ops, void *data,
92 unsigned long *end, int *graph)
93 {
94 struct stack_frame *frame = (struct stack_frame *)bp;
95
96 while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) {
97 unsigned long addr;
98
99 addr = *stack;
100 if (__kernel_text_address(addr)) {
101 if ((unsigned long) stack == bp + sizeof(long)) {
102 ops->address(data, addr, 1);//在此打印,第三个参数为1代表可信,函数定义就是 print_trace_address,
103 frame = frame->next_frame;
104 bp = (unsigned long) frame;
105 } else {
106 ops->address(data, addr, 0);
107 }
108 print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
109 }
110 stack++;
111 }
112 return bp;
113 }
147 /*
148 * Print one address/symbol entries per line.
149 */
150 static void print_trace_address(void *data, unsigned long addr, int reliable)
151 {
/ * touch_nmi_watchdog - restart NMI watchdog timeout.
/** If the architecture supports the NMI watchdog, touch_nmi_watchdog()* may be used to reset the timeout - for code which intentionally* disables interrupts for a long time. This call is stateless.
152 touch_nmi_watchdog();
153 printk(data); // data为空
154 printk_address(addr, reliable);
155 }
59 static inline unsigned long
60 stack_frame(struct task_struct *task, struct pt_regs *regs)
61 {
62 unsigned long bp;
63
64 if (regs)
65 return regs->bp;
66
67 if (task == current) {
68 /* Grab bp right from our regs */
69 get_bp(bp);
70 return bp;
71 }
72
73 /* bp is the last reg pushed by switch_to */
74 return *(unsigned long *)task->thread.sp;
75 }
#define get_bp(bp) asm("movl %%ebp, %0" : "=r" (bp) :) //学了一招! 把ebp 放到变量 bp 中。
35 void arch_trigger_all_cpu_backtrace(void)
36 {
37 int i;
38
39 if (test_and_set_bit(0, &backtrace_flag))
40 /*
41 * If there is already a trigger_all_cpu_backtrace() in progress
42 * (backtrace_flag == 1), don't output double cpu dump infos.
43 */
44 return;
45
46 cpumask_copy(to_cpumask(backtrace_mask), cpu_online_mask);
47
48 printk(KERN_INFO "sending NMI to all CPUs:\n");
49 apic->send_IPI_all(NMI_VECTOR);
50
51 /* Wait for up to 10 seconds for all CPUs to do the backtrace */
52 for (i = 0; i < 10 * 1000; i++) {
53 if (cpumask_empty(to_cpumask(backtrace_mask)))
54 break;
55 mdelay(1);
56 }
57
58 clear_bit(0, &backtrace_flag);
59 smp_mb__after_clear_bit();
60 }