aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-04-30 18:27:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 20:04:02 -0400
commit98e5e1bf722c4f976a860aed06dd365a56a34ee0 (patch)
tree0988172e9944009ce481fae24fb42732cb873df8
parentc90fe6bc0343f7c26b30c9f503b1d061636ac8ee (diff)
dump_stack: implement arch-specific hardware description in task dumps
x86 and ia64 can acquire extra hardware identification information from DMI and print it along with task dumps; however, the usage isn't consistent. * x86 show_regs() collects vendor, product and board strings and print them out with PID, comm and utsname. Some of the information is printed again later in the same dump. * warn_slowpath_common() explicitly accesses the DMI board and prints it out with "Hardware name:" label. This applies to both x86 and ia64 but is irrelevant on all other archs. * ia64 doesn't show DMI information on other non-WARN dumps. This patch introduces arch-specific hardware description used by dump_stack(). It can be set by calling dump_stack_set_arch_desc() during boot and, if exists, printed out in a separate line with "Hardware name:" label. dmi_set_dump_stack_arch_desc() is added which sets arch-specific description from DMI data. It uses dmi_ids_string[] which is set from dmi_present() used for DMI debug message. It is superset of the information x86 show_regs() is using. The function is called from x86 and ia64 boot code right after dmi_scan_machine(). This makes the explicit DMI handling in warn_slowpath_common() unnecessary. Removed. show_regs() isn't yet converted to use generic debug information printing and this patch doesn't remove the duplicate DMI handling in x86 show_regs(). The next patch will unify show_regs() handling and remove the duplication. An example WARN dump follows. WARNING: at kernel/workqueue.c:4841 init_workqueues+0x35/0x505() Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.9.0-rc1-work+ #3 Hardware name: empty empty/S3992, BIOS 080011 10/26/2007 0000000000000009 ffff88007c861e08 ffffffff81c614dc ffff88007c861e48 ffffffff8108f500 ffffffff82228240 0000000000000040 ffffffff8234a08e 0000000000000000 0000000000000000 0000000000000000 ffff88007c861e58 Call Trace: [<ffffffff81c614dc>] dump_stack+0x19/0x1b [<ffffffff8108f500>] warn_slowpath_common+0x70/0xa0 [<ffffffff8108f54a>] warn_slowpath_null+0x1a/0x20 [<ffffffff8234a0c3>] init_workqueues+0x35/0x505 ... v2: Use the same string as the debug message from dmi_present() which also contains BIOS information. Move hardware name into its own line as warn_slowpath_common() did. This change was suggested by Bjorn Helgaas. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: David S. Miller <davem@davemloft.net> Cc: Fengguang Wu <fengguang.wu@intel.com> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Jesper Nilsson <jesper.nilsson@axis.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Mike Frysinger <vapier@gentoo.org> Cc: Vineet Gupta <vgupta@synopsys.com> Cc: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/ia64/kernel/setup.c1
-rw-r--r--arch/x86/kernel/setup.c1
-rw-r--r--drivers/firmware/dmi_scan.c13
-rw-r--r--include/linux/dmi.h2
-rw-r--r--include/linux/printk.h5
-rw-r--r--kernel/panic.c6
-rw-r--r--kernel/printk.c26
7 files changed, 48 insertions, 6 deletions
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 2029cc0d2fc6..13bfdd22afc8 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -1063,6 +1063,7 @@ check_bugs (void)
1063static int __init run_dmi_scan(void) 1063static int __init run_dmi_scan(void)
1064{ 1064{
1065 dmi_scan_machine(); 1065 dmi_scan_machine();
1066 dmi_set_dump_stack_arch_desc();
1066 return 0; 1067 return 0;
1067} 1068}
1068core_initcall(run_dmi_scan); 1069core_initcall(run_dmi_scan);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 4689855c2f8a..56f7fcfe7fa2 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -996,6 +996,7 @@ void __init setup_arch(char **cmdline_p)
996 efi_init(); 996 efi_init();
997 997
998 dmi_scan_machine(); 998 dmi_scan_machine();
999 dmi_set_dump_stack_arch_desc();
999 1000
1000 /* 1001 /*
1001 * VMware detection requires dmi to be available, so this 1002 * VMware detection requires dmi to be available, so this
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 862b1d27a85b..98c62081c034 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -531,6 +531,19 @@ void __init dmi_scan_machine(void)
531} 531}
532 532
533/** 533/**
534 * dmi_set_dump_stack_arch_desc - set arch description for dump_stack()
535 *
536 * Invoke dump_stack_set_arch_desc() with DMI system information so that
537 * DMI identifiers are printed out on task dumps. Arch boot code should
538 * call this function after dmi_scan_machine() if it wants to print out DMI
539 * identifiers on task dumps.
540 */
541void __init dmi_set_dump_stack_arch_desc(void)
542{
543 dump_stack_set_arch_desc("%s", dmi_ids_string);
544}
545
546/**
534 * dmi_matches - check if dmi_system_id structure matches system DMI data 547 * dmi_matches - check if dmi_system_id structure matches system DMI data
535 * @dmi: pointer to the dmi_system_id structure to check 548 * @dmi: pointer to the dmi_system_id structure to check
536 */ 549 */
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index f156cca25ad0..b6eb7a05d58e 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -99,6 +99,7 @@ extern const char * dmi_get_system_info(int field);
99extern const struct dmi_device * dmi_find_device(int type, const char *name, 99extern const struct dmi_device * dmi_find_device(int type, const char *name,
100 const struct dmi_device *from); 100 const struct dmi_device *from);
101extern void dmi_scan_machine(void); 101extern void dmi_scan_machine(void);
102extern void dmi_set_dump_stack_arch_desc(void);
102extern bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp); 103extern bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp);
103extern int dmi_name_in_vendors(const char *str); 104extern int dmi_name_in_vendors(const char *str);
104extern int dmi_name_in_serial(const char *str); 105extern int dmi_name_in_serial(const char *str);
@@ -114,6 +115,7 @@ static inline const char * dmi_get_system_info(int field) { return NULL; }
114static inline const struct dmi_device * dmi_find_device(int type, const char *name, 115static inline const struct dmi_device * dmi_find_device(int type, const char *name,
115 const struct dmi_device *from) { return NULL; } 116 const struct dmi_device *from) { return NULL; }
116static inline void dmi_scan_machine(void) { return; } 117static inline void dmi_scan_machine(void) { return; }
118static inline void dmi_set_dump_stack_arch_desc(void) { }
117static inline bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp) 119static inline bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp)
118{ 120{
119 if (yearp) 121 if (yearp)
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 7ce1f878cf6a..47827c0a034d 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -145,6 +145,7 @@ extern void wake_up_klogd(void);
145 145
146void log_buf_kexec_setup(void); 146void log_buf_kexec_setup(void);
147void __init setup_log_buf(int early); 147void __init setup_log_buf(int early);
148void dump_stack_set_arch_desc(const char *fmt, ...);
148void dump_stack_print_info(const char *log_lvl); 149void dump_stack_print_info(const char *log_lvl);
149#else 150#else
150static inline __printf(1, 0) 151static inline __printf(1, 0)
@@ -184,6 +185,10 @@ static inline void setup_log_buf(int early)
184{ 185{
185} 186}
186 187
188static inline void dump_stack_set_arch_desc(const char *fmt, ...)
189{
190}
191
187static inline void dump_stack_print_info(const char *log_lvl) 192static inline void dump_stack_print_info(const char *log_lvl)
188{ 193{
189} 194}
diff --git a/kernel/panic.c b/kernel/panic.c
index 7c57cc9eee2c..167ec097ce8b 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -22,7 +22,6 @@
22#include <linux/sysrq.h> 22#include <linux/sysrq.h>
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/nmi.h> 24#include <linux/nmi.h>
25#include <linux/dmi.h>
26 25
27#define PANIC_TIMER_STEP 100 26#define PANIC_TIMER_STEP 100
28#define PANIC_BLINK_SPD 18 27#define PANIC_BLINK_SPD 18
@@ -400,13 +399,8 @@ struct slowpath_args {
400static void warn_slowpath_common(const char *file, int line, void *caller, 399static void warn_slowpath_common(const char *file, int line, void *caller,
401 unsigned taint, struct slowpath_args *args) 400 unsigned taint, struct slowpath_args *args)
402{ 401{
403 const char *board;
404
405 printk(KERN_WARNING "------------[ cut here ]------------\n"); 402 printk(KERN_WARNING "------------[ cut here ]------------\n");
406 printk(KERN_WARNING "WARNING: at %s:%d %pS()\n", file, line, caller); 403 printk(KERN_WARNING "WARNING: at %s:%d %pS()\n", file, line, caller);
407 board = dmi_get_system_info(DMI_PRODUCT_NAME);
408 if (board)
409 printk(KERN_WARNING "Hardware name: %s\n", board);
410 404
411 if (args) 405 if (args)
412 vprintk(args->fmt, args->args); 406 vprintk(args->fmt, args->args);
diff --git a/kernel/printk.c b/kernel/printk.c
index 70b4b94a0eca..73a96def4804 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -2851,6 +2851,28 @@ void kmsg_dump_rewind(struct kmsg_dumper *dumper)
2851} 2851}
2852EXPORT_SYMBOL_GPL(kmsg_dump_rewind); 2852EXPORT_SYMBOL_GPL(kmsg_dump_rewind);
2853 2853
2854static char dump_stack_arch_desc_str[128];
2855
2856/**
2857 * dump_stack_set_arch_desc - set arch-specific str to show with task dumps
2858 * @fmt: printf-style format string
2859 * @...: arguments for the format string
2860 *
2861 * The configured string will be printed right after utsname during task
2862 * dumps. Usually used to add arch-specific system identifiers. If an
2863 * arch wants to make use of such an ID string, it should initialize this
2864 * as soon as possible during boot.
2865 */
2866void __init dump_stack_set_arch_desc(const char *fmt, ...)
2867{
2868 va_list args;
2869
2870 va_start(args, fmt);
2871 vsnprintf(dump_stack_arch_desc_str, sizeof(dump_stack_arch_desc_str),
2872 fmt, args);
2873 va_end(args);
2874}
2875
2854/** 2876/**
2855 * dump_stack_print_info - print generic debug info for dump_stack() 2877 * dump_stack_print_info - print generic debug info for dump_stack()
2856 * @log_lvl: log level 2878 * @log_lvl: log level
@@ -2865,6 +2887,10 @@ void dump_stack_print_info(const char *log_lvl)
2865 print_tainted(), init_utsname()->release, 2887 print_tainted(), init_utsname()->release,
2866 (int)strcspn(init_utsname()->version, " "), 2888 (int)strcspn(init_utsname()->version, " "),
2867 init_utsname()->version); 2889 init_utsname()->version);
2890
2891 if (dump_stack_arch_desc_str[0] != '\0')
2892 printk("%sHardware name: %s\n",
2893 log_lvl, dump_stack_arch_desc_str);
2868} 2894}
2869 2895
2870#endif 2896#endif