Blame view

lib/dump_stack.c 2.99 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
  /*
   * Provide a default dump_stack() function for architectures
   * which don't implement their own.
   */
  
  #include <linux/kernel.h>
8bc3bcc93   Paul Gortmaker   lib: reduce the u...
8
  #include <linux/export.h>
196779b9b   Tejun Heo   dump_stack: conso...
9
  #include <linux/sched.h>
b17b01533   Ingo Molnar   sched/headers: Pr...
10
  #include <linux/sched/debug.h>
b58d97743   Alex Thorlton   dump_stack: seria...
11
12
  #include <linux/smp.h>
  #include <linux/atomic.h>
e36df28f5   Dave Young   printk: move dump...
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  #include <linux/kexec.h>
  #include <linux/utsname.h>
  
  static char dump_stack_arch_desc_str[128];
  
  /**
   * dump_stack_set_arch_desc - set arch-specific str to show with task dumps
   * @fmt: printf-style format string
   * @...: arguments for the format string
   *
   * The configured string will be printed right after utsname during task
   * dumps.  Usually used to add arch-specific system identifiers.  If an
   * arch wants to make use of such an ID string, it should initialize this
   * as soon as possible during boot.
   */
  void __init dump_stack_set_arch_desc(const char *fmt, ...)
  {
  	va_list args;
  
  	va_start(args, fmt);
  	vsnprintf(dump_stack_arch_desc_str, sizeof(dump_stack_arch_desc_str),
  		  fmt, args);
  	va_end(args);
  }
  
  /**
   * dump_stack_print_info - print generic debug info for dump_stack()
   * @log_lvl: log level
   *
   * Arch-specific dump_stack() implementations can use this function to
   * print out the same debug information as the generic dump_stack().
   */
  void dump_stack_print_info(const char *log_lvl)
  {
  	printk("%sCPU: %d PID: %d Comm: %.20s %s%s %s %.*s
  ",
  	       log_lvl, raw_smp_processor_id(), current->pid, current->comm,
  	       kexec_crash_loaded() ? "Kdump: loaded " : "",
  	       print_tainted(),
  	       init_utsname()->release,
  	       (int)strcspn(init_utsname()->version, " "),
  	       init_utsname()->version);
  
  	if (dump_stack_arch_desc_str[0] != '\0')
  		printk("%sHardware name: %s
  ",
  		       log_lvl, dump_stack_arch_desc_str);
  
  	print_worker_info(log_lvl, current);
  }
  
  /**
   * show_regs_print_info - print generic debug info for show_regs()
   * @log_lvl: log level
   *
   * show_regs() implementations can use this function to print out generic
   * debug information.
   */
  void show_regs_print_info(const char *log_lvl)
  {
  	dump_stack_print_info(log_lvl);
  }
b58d97743   Alex Thorlton   dump_stack: seria...
75
76
77
78
79
80
  
  static void __dump_stack(void)
  {
  	dump_stack_print_info(KERN_DEFAULT);
  	show_stack(NULL, NULL);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81

196779b9b   Tejun Heo   dump_stack: conso...
82
83
84
85
86
  /**
   * dump_stack - dump the current task information and its stack trace
   *
   * Architectures can override this implementation by implementing its own.
   */
b58d97743   Alex Thorlton   dump_stack: seria...
87
88
  #ifdef CONFIG_SMP
  static atomic_t dump_lock = ATOMIC_INIT(-1);
722a9f929   Andi Kleen   asmlinkage: Add e...
89
  asmlinkage __visible void dump_stack(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
  {
d7ce36924   Eric Dumazet   dump_stack: avoid...
91
  	unsigned long flags;
b58d97743   Alex Thorlton   dump_stack: seria...
92
93
94
95
96
97
98
99
  	int was_locked;
  	int old;
  	int cpu;
  
  	/*
  	 * Permit this cpu to perform nested stack dumps while serialising
  	 * against other CPUs
  	 */
b58d97743   Alex Thorlton   dump_stack: seria...
100
  retry:
d7ce36924   Eric Dumazet   dump_stack: avoid...
101
  	local_irq_save(flags);
b58d97743   Alex Thorlton   dump_stack: seria...
102
103
104
105
106
107
108
  	cpu = smp_processor_id();
  	old = atomic_cmpxchg(&dump_lock, -1, cpu);
  	if (old == -1) {
  		was_locked = 0;
  	} else if (old == cpu) {
  		was_locked = 1;
  	} else {
d7ce36924   Eric Dumazet   dump_stack: avoid...
109
  		local_irq_restore(flags);
b58d97743   Alex Thorlton   dump_stack: seria...
110
111
112
113
114
115
116
117
  		cpu_relax();
  		goto retry;
  	}
  
  	__dump_stack();
  
  	if (!was_locked)
  		atomic_set(&dump_lock, -1);
d7ce36924   Eric Dumazet   dump_stack: avoid...
118
  	local_irq_restore(flags);
b58d97743   Alex Thorlton   dump_stack: seria...
119
120
  }
  #else
722a9f929   Andi Kleen   asmlinkage: Add e...
121
  asmlinkage __visible void dump_stack(void)
b58d97743   Alex Thorlton   dump_stack: seria...
122
123
  {
  	__dump_stack();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
  }
b58d97743   Alex Thorlton   dump_stack: seria...
125
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
  EXPORT_SYMBOL(dump_stack);