1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * Provide a default dump_stack() function for architectures 41da177e4SLinus Torvalds * which don't implement their own. 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds #include <linux/kernel.h> 822f4e66dSStephen Boyd #include <linux/buildid.h> 98bc3bcc9SPaul Gortmaker #include <linux/export.h> 10196779b9STejun Heo #include <linux/sched.h> 11b17b0153SIngo Molnar #include <linux/sched/debug.h> 12b58d9774SAlex Thorlton #include <linux/smp.h> 13b58d9774SAlex Thorlton #include <linux/atomic.h> 14e36df28fSDave Young #include <linux/kexec.h> 15e36df28fSDave Young #include <linux/utsname.h> 16a8b62fd0SPeter Zijlstra #include <linux/stop_machine.h> 17e36df28fSDave Young 18e36df28fSDave Young static char dump_stack_arch_desc_str[128]; 19e36df28fSDave Young 20e36df28fSDave Young /** 21e36df28fSDave Young * dump_stack_set_arch_desc - set arch-specific str to show with task dumps 22e36df28fSDave Young * @fmt: printf-style format string 23e36df28fSDave Young * @...: arguments for the format string 24e36df28fSDave Young * 25e36df28fSDave Young * The configured string will be printed right after utsname during task 26e36df28fSDave Young * dumps. Usually used to add arch-specific system identifiers. If an 27e36df28fSDave Young * arch wants to make use of such an ID string, it should initialize this 28e36df28fSDave Young * as soon as possible during boot. 29e36df28fSDave Young */ 30e36df28fSDave Young void __init dump_stack_set_arch_desc(const char *fmt, ...) 31e36df28fSDave Young { 32e36df28fSDave Young va_list args; 33e36df28fSDave Young 34e36df28fSDave Young va_start(args, fmt); 35e36df28fSDave Young vsnprintf(dump_stack_arch_desc_str, sizeof(dump_stack_arch_desc_str), 36e36df28fSDave Young fmt, args); 37e36df28fSDave Young va_end(args); 38e36df28fSDave Young } 39e36df28fSDave Young 4022f4e66dSStephen Boyd #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) 4122f4e66dSStephen Boyd #define BUILD_ID_FMT " %20phN" 4222f4e66dSStephen Boyd #define BUILD_ID_VAL vmlinux_build_id 4322f4e66dSStephen Boyd #else 4422f4e66dSStephen Boyd #define BUILD_ID_FMT "%s" 4522f4e66dSStephen Boyd #define BUILD_ID_VAL "" 4622f4e66dSStephen Boyd #endif 4722f4e66dSStephen Boyd 48e36df28fSDave Young /** 49e36df28fSDave Young * dump_stack_print_info - print generic debug info for dump_stack() 50e36df28fSDave Young * @log_lvl: log level 51e36df28fSDave Young * 52e36df28fSDave Young * Arch-specific dump_stack() implementations can use this function to 53e36df28fSDave Young * print out the same debug information as the generic dump_stack(). 54e36df28fSDave Young */ 55e36df28fSDave Young void dump_stack_print_info(const char *log_lvl) 56e36df28fSDave Young { 5722f4e66dSStephen Boyd printk("%sCPU: %d PID: %d Comm: %.20s %s%s %s %.*s" BUILD_ID_FMT "\n", 58e36df28fSDave Young log_lvl, raw_smp_processor_id(), current->pid, current->comm, 59e36df28fSDave Young kexec_crash_loaded() ? "Kdump: loaded " : "", 60e36df28fSDave Young print_tainted(), 61e36df28fSDave Young init_utsname()->release, 62e36df28fSDave Young (int)strcspn(init_utsname()->version, " "), 6322f4e66dSStephen Boyd init_utsname()->version, BUILD_ID_VAL); 64e36df28fSDave Young 65e36df28fSDave Young if (dump_stack_arch_desc_str[0] != '\0') 66e36df28fSDave Young printk("%sHardware name: %s\n", 67e36df28fSDave Young log_lvl, dump_stack_arch_desc_str); 68e36df28fSDave Young 69e36df28fSDave Young print_worker_info(log_lvl, current); 70a8b62fd0SPeter Zijlstra print_stop_info(log_lvl, current); 71e36df28fSDave Young } 72e36df28fSDave Young 73e36df28fSDave Young /** 74e36df28fSDave Young * show_regs_print_info - print generic debug info for show_regs() 75e36df28fSDave Young * @log_lvl: log level 76e36df28fSDave Young * 77e36df28fSDave Young * show_regs() implementations can use this function to print out generic 78e36df28fSDave Young * debug information. 79e36df28fSDave Young */ 80e36df28fSDave Young void show_regs_print_info(const char *log_lvl) 81e36df28fSDave Young { 82e36df28fSDave Young dump_stack_print_info(log_lvl); 83e36df28fSDave Young } 84b58d9774SAlex Thorlton 854469c0f1SAlexander Potapenko static void __dump_stack(const char *log_lvl) 86b58d9774SAlex Thorlton { 874469c0f1SAlexander Potapenko dump_stack_print_info(log_lvl); 884469c0f1SAlexander Potapenko show_stack(NULL, NULL, log_lvl); 89b58d9774SAlex Thorlton } 901da177e4SLinus Torvalds 91196779b9STejun Heo /** 9283a29bebSRandy Dunlap * dump_stack_lvl - dump the current task information and its stack trace 9383a29bebSRandy Dunlap * @log_lvl: log level 94196779b9STejun Heo * 95196779b9STejun Heo * Architectures can override this implementation by implementing its own. 96196779b9STejun Heo */ 974469c0f1SAlexander Potapenko asmlinkage __visible void dump_stack_lvl(const char *log_lvl) 981da177e4SLinus Torvalds { 99d7ce3692SEric Dumazet unsigned long flags; 100b58d9774SAlex Thorlton 101b58d9774SAlex Thorlton /* 102b58d9774SAlex Thorlton * Permit this cpu to perform nested stack dumps while serialising 103b58d9774SAlex Thorlton * against other CPUs 104b58d9774SAlex Thorlton */ 105*faebd693SJohn Ogness printk_cpu_sync_get_irqsave(flags); 1064469c0f1SAlexander Potapenko __dump_stack(log_lvl); 107*faebd693SJohn Ogness printk_cpu_sync_put_irqrestore(flags); 108b58d9774SAlex Thorlton } 1094469c0f1SAlexander Potapenko EXPORT_SYMBOL(dump_stack_lvl); 1104469c0f1SAlexander Potapenko 1114469c0f1SAlexander Potapenko asmlinkage __visible void dump_stack(void) 1124469c0f1SAlexander Potapenko { 1134469c0f1SAlexander Potapenko dump_stack_lvl(KERN_DEFAULT); 1144469c0f1SAlexander Potapenko } 1151da177e4SLinus Torvalds EXPORT_SYMBOL(dump_stack); 116