162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _ASM_STACKTRACE_H
362306a36Sopenharmony_ci#define _ASM_STACKTRACE_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <asm/ptrace.h>
662306a36Sopenharmony_ci#include <asm/asm.h>
762306a36Sopenharmony_ci#include <linux/stringify.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#ifdef CONFIG_KALLSYMS
1062306a36Sopenharmony_ciextern int raw_show_trace;
1162306a36Sopenharmony_ciextern unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
1262306a36Sopenharmony_ci				  unsigned long pc, unsigned long *ra);
1362306a36Sopenharmony_ciextern unsigned long unwind_stack_by_address(unsigned long stack_page,
1462306a36Sopenharmony_ci					     unsigned long *sp,
1562306a36Sopenharmony_ci					     unsigned long pc,
1662306a36Sopenharmony_ci					     unsigned long *ra);
1762306a36Sopenharmony_ci#else
1862306a36Sopenharmony_ci#define raw_show_trace 1
1962306a36Sopenharmony_cistatic inline unsigned long unwind_stack(struct task_struct *task,
2062306a36Sopenharmony_ci	unsigned long *sp, unsigned long pc, unsigned long *ra)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	return 0;
2362306a36Sopenharmony_ci}
2462306a36Sopenharmony_ci#endif
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define STR_PTR_LA    __stringify(PTR_LA)
2762306a36Sopenharmony_ci#define STR_LONG_S    __stringify(LONG_S)
2862306a36Sopenharmony_ci#define STR_LONG_L    __stringify(LONG_L)
2962306a36Sopenharmony_ci#define STR_LONGSIZE  __stringify(LONGSIZE)
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define STORE_ONE_REG(r) \
3262306a36Sopenharmony_ci    STR_LONG_S   " $" __stringify(r)",("STR_LONGSIZE"*"__stringify(r)")(%1)\n\t"
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic __always_inline void prepare_frametrace(struct pt_regs *regs)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci#ifndef CONFIG_KALLSYMS
3762306a36Sopenharmony_ci	/*
3862306a36Sopenharmony_ci	 * Remove any garbage that may be in regs (specially func
3962306a36Sopenharmony_ci	 * addresses) to avoid show_raw_backtrace() to report them
4062306a36Sopenharmony_ci	 */
4162306a36Sopenharmony_ci	memset(regs, 0, sizeof(*regs));
4262306a36Sopenharmony_ci#endif
4362306a36Sopenharmony_ci	__asm__ __volatile__(
4462306a36Sopenharmony_ci		".set push\n\t"
4562306a36Sopenharmony_ci		".set noat\n\t"
4662306a36Sopenharmony_ci		/* Store $1 so we can use it */
4762306a36Sopenharmony_ci		STR_LONG_S " $1,"STR_LONGSIZE"(%1)\n\t"
4862306a36Sopenharmony_ci		/* Store the PC */
4962306a36Sopenharmony_ci		"1: " STR_PTR_LA " $1, 1b\n\t"
5062306a36Sopenharmony_ci		STR_LONG_S " $1,%0\n\t"
5162306a36Sopenharmony_ci		STORE_ONE_REG(2)
5262306a36Sopenharmony_ci		STORE_ONE_REG(3)
5362306a36Sopenharmony_ci		STORE_ONE_REG(4)
5462306a36Sopenharmony_ci		STORE_ONE_REG(5)
5562306a36Sopenharmony_ci		STORE_ONE_REG(6)
5662306a36Sopenharmony_ci		STORE_ONE_REG(7)
5762306a36Sopenharmony_ci		STORE_ONE_REG(8)
5862306a36Sopenharmony_ci		STORE_ONE_REG(9)
5962306a36Sopenharmony_ci		STORE_ONE_REG(10)
6062306a36Sopenharmony_ci		STORE_ONE_REG(11)
6162306a36Sopenharmony_ci		STORE_ONE_REG(12)
6262306a36Sopenharmony_ci		STORE_ONE_REG(13)
6362306a36Sopenharmony_ci		STORE_ONE_REG(14)
6462306a36Sopenharmony_ci		STORE_ONE_REG(15)
6562306a36Sopenharmony_ci		STORE_ONE_REG(16)
6662306a36Sopenharmony_ci		STORE_ONE_REG(17)
6762306a36Sopenharmony_ci		STORE_ONE_REG(18)
6862306a36Sopenharmony_ci		STORE_ONE_REG(19)
6962306a36Sopenharmony_ci		STORE_ONE_REG(20)
7062306a36Sopenharmony_ci		STORE_ONE_REG(21)
7162306a36Sopenharmony_ci		STORE_ONE_REG(22)
7262306a36Sopenharmony_ci		STORE_ONE_REG(23)
7362306a36Sopenharmony_ci		STORE_ONE_REG(24)
7462306a36Sopenharmony_ci		STORE_ONE_REG(25)
7562306a36Sopenharmony_ci		STORE_ONE_REG(26)
7662306a36Sopenharmony_ci		STORE_ONE_REG(27)
7762306a36Sopenharmony_ci		STORE_ONE_REG(28)
7862306a36Sopenharmony_ci		STORE_ONE_REG(29)
7962306a36Sopenharmony_ci		STORE_ONE_REG(30)
8062306a36Sopenharmony_ci		STORE_ONE_REG(31)
8162306a36Sopenharmony_ci		/* Restore $1 */
8262306a36Sopenharmony_ci		STR_LONG_L " $1,"STR_LONGSIZE"(%1)\n\t"
8362306a36Sopenharmony_ci		".set pop\n\t"
8462306a36Sopenharmony_ci		: "=m" (regs->cp0_epc)
8562306a36Sopenharmony_ci		: "r" (regs->regs)
8662306a36Sopenharmony_ci		: "memory");
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci#endif /* _ASM_STACKTRACE_H */
90