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