18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  Copyright (C) 1991, 1992  Linus Torvalds
48c2ecf20Sopenharmony_ci *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#ifndef _ASM_X86_STACKTRACE_H
88c2ecf20Sopenharmony_ci#define _ASM_X86_STACKTRACE_H
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
118c2ecf20Sopenharmony_ci#include <linux/ptrace.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <asm/cpu_entry_area.h>
148c2ecf20Sopenharmony_ci#include <asm/switch_to.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cienum stack_type {
178c2ecf20Sopenharmony_ci	STACK_TYPE_UNKNOWN,
188c2ecf20Sopenharmony_ci	STACK_TYPE_TASK,
198c2ecf20Sopenharmony_ci	STACK_TYPE_IRQ,
208c2ecf20Sopenharmony_ci	STACK_TYPE_SOFTIRQ,
218c2ecf20Sopenharmony_ci	STACK_TYPE_ENTRY,
228c2ecf20Sopenharmony_ci	STACK_TYPE_EXCEPTION,
238c2ecf20Sopenharmony_ci	STACK_TYPE_EXCEPTION_LAST = STACK_TYPE_EXCEPTION + N_EXCEPTION_STACKS-1,
248c2ecf20Sopenharmony_ci};
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistruct stack_info {
278c2ecf20Sopenharmony_ci	enum stack_type type;
288c2ecf20Sopenharmony_ci	unsigned long *begin, *end, *next_sp;
298c2ecf20Sopenharmony_ci};
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cibool in_task_stack(unsigned long *stack, struct task_struct *task,
328c2ecf20Sopenharmony_ci		   struct stack_info *info);
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cibool in_entry_stack(unsigned long *stack, struct stack_info *info);
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ciint get_stack_info(unsigned long *stack, struct task_struct *task,
378c2ecf20Sopenharmony_ci		   struct stack_info *info, unsigned long *visit_mask);
388c2ecf20Sopenharmony_cibool get_stack_info_noinstr(unsigned long *stack, struct task_struct *task,
398c2ecf20Sopenharmony_ci			    struct stack_info *info);
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ciconst char *stack_type_name(enum stack_type type);
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistatic inline bool on_stack(struct stack_info *info, void *addr, size_t len)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	void *begin = info->begin;
468c2ecf20Sopenharmony_ci	void *end   = info->end;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	return (info->type != STACK_TYPE_UNKNOWN &&
498c2ecf20Sopenharmony_ci		addr >= begin && addr < end &&
508c2ecf20Sopenharmony_ci		addr + len > begin && addr + len <= end);
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_32
548c2ecf20Sopenharmony_ci#define STACKSLOTS_PER_LINE 8
558c2ecf20Sopenharmony_ci#else
568c2ecf20Sopenharmony_ci#define STACKSLOTS_PER_LINE 4
578c2ecf20Sopenharmony_ci#endif
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#ifdef CONFIG_FRAME_POINTER
608c2ecf20Sopenharmony_cistatic inline unsigned long *
618c2ecf20Sopenharmony_ciget_frame_pointer(struct task_struct *task, struct pt_regs *regs)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	if (regs)
648c2ecf20Sopenharmony_ci		return (unsigned long *)regs->bp;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	if (task == current)
678c2ecf20Sopenharmony_ci		return __builtin_frame_address(0);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	return &((struct inactive_task_frame *)task->thread.sp)->bp;
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci#else
728c2ecf20Sopenharmony_cistatic inline unsigned long *
738c2ecf20Sopenharmony_ciget_frame_pointer(struct task_struct *task, struct pt_regs *regs)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	return NULL;
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci#endif /* CONFIG_FRAME_POINTER */
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistatic inline unsigned long *
808c2ecf20Sopenharmony_ciget_stack_pointer(struct task_struct *task, struct pt_regs *regs)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	if (regs)
838c2ecf20Sopenharmony_ci		return (unsigned long *)regs->sp;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	if (task == current)
868c2ecf20Sopenharmony_ci		return __builtin_frame_address(0);
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	return (unsigned long *)task->thread.sp;
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_civoid show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
928c2ecf20Sopenharmony_ci			unsigned long *stack, const char *log_lvl);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci/* The form of the top of the frame on the stack */
958c2ecf20Sopenharmony_cistruct stack_frame {
968c2ecf20Sopenharmony_ci	struct stack_frame *next_frame;
978c2ecf20Sopenharmony_ci	unsigned long return_address;
988c2ecf20Sopenharmony_ci};
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_cistruct stack_frame_ia32 {
1018c2ecf20Sopenharmony_ci    u32 next_frame;
1028c2ecf20Sopenharmony_ci    u32 return_address;
1038c2ecf20Sopenharmony_ci};
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_civoid show_opcodes(struct pt_regs *regs, const char *loglvl);
1068c2ecf20Sopenharmony_civoid show_ip(struct pt_regs *regs, const char *loglvl);
1078c2ecf20Sopenharmony_ci#endif /* _ASM_X86_STACKTRACE_H */
108