162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Provide a default dump_stack() function for architectures 462306a36Sopenharmony_ci * which don't implement their own. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/kernel.h> 862306a36Sopenharmony_ci#include <linux/buildid.h> 962306a36Sopenharmony_ci#include <linux/export.h> 1062306a36Sopenharmony_ci#include <linux/sched.h> 1162306a36Sopenharmony_ci#include <linux/sched/debug.h> 1262306a36Sopenharmony_ci#include <linux/smp.h> 1362306a36Sopenharmony_ci#include <linux/atomic.h> 1462306a36Sopenharmony_ci#include <linux/kexec.h> 1562306a36Sopenharmony_ci#include <linux/utsname.h> 1662306a36Sopenharmony_ci#include <linux/stop_machine.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic char dump_stack_arch_desc_str[128]; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/** 2162306a36Sopenharmony_ci * dump_stack_set_arch_desc - set arch-specific str to show with task dumps 2262306a36Sopenharmony_ci * @fmt: printf-style format string 2362306a36Sopenharmony_ci * @...: arguments for the format string 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * The configured string will be printed right after utsname during task 2662306a36Sopenharmony_ci * dumps. Usually used to add arch-specific system identifiers. If an 2762306a36Sopenharmony_ci * arch wants to make use of such an ID string, it should initialize this 2862306a36Sopenharmony_ci * as soon as possible during boot. 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_civoid __init dump_stack_set_arch_desc(const char *fmt, ...) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci va_list args; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci va_start(args, fmt); 3562306a36Sopenharmony_ci vsnprintf(dump_stack_arch_desc_str, sizeof(dump_stack_arch_desc_str), 3662306a36Sopenharmony_ci fmt, args); 3762306a36Sopenharmony_ci va_end(args); 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) 4162306a36Sopenharmony_ci#define BUILD_ID_FMT " %20phN" 4262306a36Sopenharmony_ci#define BUILD_ID_VAL vmlinux_build_id 4362306a36Sopenharmony_ci#else 4462306a36Sopenharmony_ci#define BUILD_ID_FMT "%s" 4562306a36Sopenharmony_ci#define BUILD_ID_VAL "" 4662306a36Sopenharmony_ci#endif 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/** 4962306a36Sopenharmony_ci * dump_stack_print_info - print generic debug info for dump_stack() 5062306a36Sopenharmony_ci * @log_lvl: log level 5162306a36Sopenharmony_ci * 5262306a36Sopenharmony_ci * Arch-specific dump_stack() implementations can use this function to 5362306a36Sopenharmony_ci * print out the same debug information as the generic dump_stack(). 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_civoid dump_stack_print_info(const char *log_lvl) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci printk("%sCPU: %d PID: %d Comm: %.20s %s%s %s %.*s" BUILD_ID_FMT "\n", 5862306a36Sopenharmony_ci log_lvl, raw_smp_processor_id(), current->pid, current->comm, 5962306a36Sopenharmony_ci kexec_crash_loaded() ? "Kdump: loaded " : "", 6062306a36Sopenharmony_ci print_tainted(), 6162306a36Sopenharmony_ci init_utsname()->release, 6262306a36Sopenharmony_ci (int)strcspn(init_utsname()->version, " "), 6362306a36Sopenharmony_ci init_utsname()->version, BUILD_ID_VAL); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if (dump_stack_arch_desc_str[0] != '\0') 6662306a36Sopenharmony_ci printk("%sHardware name: %s\n", 6762306a36Sopenharmony_ci log_lvl, dump_stack_arch_desc_str); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci print_worker_info(log_lvl, current); 7062306a36Sopenharmony_ci print_stop_info(log_lvl, current); 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/** 7462306a36Sopenharmony_ci * show_regs_print_info - print generic debug info for show_regs() 7562306a36Sopenharmony_ci * @log_lvl: log level 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci * show_regs() implementations can use this function to print out generic 7862306a36Sopenharmony_ci * debug information. 7962306a36Sopenharmony_ci */ 8062306a36Sopenharmony_civoid show_regs_print_info(const char *log_lvl) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci dump_stack_print_info(log_lvl); 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic void __dump_stack(const char *log_lvl) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci dump_stack_print_info(log_lvl); 8862306a36Sopenharmony_ci show_stack(NULL, NULL, log_lvl); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/** 9262306a36Sopenharmony_ci * dump_stack_lvl - dump the current task information and its stack trace 9362306a36Sopenharmony_ci * @log_lvl: log level 9462306a36Sopenharmony_ci * 9562306a36Sopenharmony_ci * Architectures can override this implementation by implementing its own. 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_ciasmlinkage __visible void dump_stack_lvl(const char *log_lvl) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci unsigned long flags; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* 10262306a36Sopenharmony_ci * Permit this cpu to perform nested stack dumps while serialising 10362306a36Sopenharmony_ci * against other CPUs 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_ci printk_cpu_sync_get_irqsave(flags); 10662306a36Sopenharmony_ci __dump_stack(log_lvl); 10762306a36Sopenharmony_ci printk_cpu_sync_put_irqrestore(flags); 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ciEXPORT_SYMBOL(dump_stack_lvl); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ciasmlinkage __visible void dump_stack(void) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci dump_stack_lvl(KERN_DEFAULT); 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ciEXPORT_SYMBOL(dump_stack); 116