18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci#ifndef _ASM_STACKTRACE_H
68c2ecf20Sopenharmony_ci#define _ASM_STACKTRACE_H
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <asm/asm.h>
98c2ecf20Sopenharmony_ci#include <asm/ptrace.h>
108c2ecf20Sopenharmony_ci#include <asm/loongarchregs.h>
118c2ecf20Sopenharmony_ci#include <linux/stringify.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cienum stack_type {
148c2ecf20Sopenharmony_ci	STACK_TYPE_UNKNOWN,
158c2ecf20Sopenharmony_ci	STACK_TYPE_TASK,
168c2ecf20Sopenharmony_ci	STACK_TYPE_IRQ,
178c2ecf20Sopenharmony_ci};
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistruct stack_info {
208c2ecf20Sopenharmony_ci	enum stack_type type;
218c2ecf20Sopenharmony_ci	unsigned long begin, end, next_sp;
228c2ecf20Sopenharmony_ci};
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistruct stack_frame {
258c2ecf20Sopenharmony_ci	unsigned long	fp;
268c2ecf20Sopenharmony_ci	unsigned long	ra;
278c2ecf20Sopenharmony_ci};
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cibool in_task_stack(unsigned long stack, struct task_struct *task,
308c2ecf20Sopenharmony_ci			struct stack_info *info);
318c2ecf20Sopenharmony_cibool in_irq_stack(unsigned long stack, struct stack_info *info);
328c2ecf20Sopenharmony_ciint get_stack_info(unsigned long stack, struct task_struct *task,
338c2ecf20Sopenharmony_ci		   struct stack_info *info);
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define STR_LONG_L    __stringify(LONG_L)
368c2ecf20Sopenharmony_ci#define STR_LONG_S    __stringify(LONG_S)
378c2ecf20Sopenharmony_ci#define STR_LONGSIZE  __stringify(LONGSIZE)
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#define STORE_ONE_REG(r) \
408c2ecf20Sopenharmony_ci    STR_LONG_S   " $r" __stringify(r)", %1, "STR_LONGSIZE"*"__stringify(r)"\n\t"
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#define CSRRD_ONE_REG(reg) \
438c2ecf20Sopenharmony_ci    __stringify(csrrd) " %0, "__stringify(reg)"\n\t"
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic __always_inline void prepare_frametrace(struct pt_regs *regs)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	__asm__ __volatile__(
488c2ecf20Sopenharmony_ci		/* Save $r1 */
498c2ecf20Sopenharmony_ci		STORE_ONE_REG(1)
508c2ecf20Sopenharmony_ci		/* Use $r1 to save PC */
518c2ecf20Sopenharmony_ci		"pcaddi	$r1, 0\n\t"
528c2ecf20Sopenharmony_ci		STR_LONG_S " $r1, %0\n\t"
538c2ecf20Sopenharmony_ci		/* Restore $r1 */
548c2ecf20Sopenharmony_ci		STR_LONG_L " $r1, %1, "STR_LONGSIZE"\n\t"
558c2ecf20Sopenharmony_ci		STORE_ONE_REG(2)
568c2ecf20Sopenharmony_ci		STORE_ONE_REG(3)
578c2ecf20Sopenharmony_ci		STORE_ONE_REG(4)
588c2ecf20Sopenharmony_ci		STORE_ONE_REG(5)
598c2ecf20Sopenharmony_ci		STORE_ONE_REG(6)
608c2ecf20Sopenharmony_ci		STORE_ONE_REG(7)
618c2ecf20Sopenharmony_ci		STORE_ONE_REG(8)
628c2ecf20Sopenharmony_ci		STORE_ONE_REG(9)
638c2ecf20Sopenharmony_ci		STORE_ONE_REG(10)
648c2ecf20Sopenharmony_ci		STORE_ONE_REG(11)
658c2ecf20Sopenharmony_ci		STORE_ONE_REG(12)
668c2ecf20Sopenharmony_ci		STORE_ONE_REG(13)
678c2ecf20Sopenharmony_ci		STORE_ONE_REG(14)
688c2ecf20Sopenharmony_ci		STORE_ONE_REG(15)
698c2ecf20Sopenharmony_ci		STORE_ONE_REG(16)
708c2ecf20Sopenharmony_ci		STORE_ONE_REG(17)
718c2ecf20Sopenharmony_ci		STORE_ONE_REG(18)
728c2ecf20Sopenharmony_ci		STORE_ONE_REG(19)
738c2ecf20Sopenharmony_ci		STORE_ONE_REG(20)
748c2ecf20Sopenharmony_ci		STORE_ONE_REG(21)
758c2ecf20Sopenharmony_ci		STORE_ONE_REG(22)
768c2ecf20Sopenharmony_ci		STORE_ONE_REG(23)
778c2ecf20Sopenharmony_ci		STORE_ONE_REG(24)
788c2ecf20Sopenharmony_ci		STORE_ONE_REG(25)
798c2ecf20Sopenharmony_ci		STORE_ONE_REG(26)
808c2ecf20Sopenharmony_ci		STORE_ONE_REG(27)
818c2ecf20Sopenharmony_ci		STORE_ONE_REG(28)
828c2ecf20Sopenharmony_ci		STORE_ONE_REG(29)
838c2ecf20Sopenharmony_ci		STORE_ONE_REG(30)
848c2ecf20Sopenharmony_ci		STORE_ONE_REG(31)
858c2ecf20Sopenharmony_ci		: "=m" (regs->csr_era)
868c2ecf20Sopenharmony_ci		: "r" (regs->regs)
878c2ecf20Sopenharmony_ci		: "memory");
888c2ecf20Sopenharmony_ci	__asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_BADV) : "=r" (regs->csr_badvaddr));
898c2ecf20Sopenharmony_ci	__asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_CRMD) : "=r" (regs->csr_crmd));
908c2ecf20Sopenharmony_ci	__asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_PRMD) : "=r" (regs->csr_prmd));
918c2ecf20Sopenharmony_ci	__asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_EUEN) : "=r" (regs->csr_euen));
928c2ecf20Sopenharmony_ci	__asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_ECFG) : "=r" (regs->csr_ecfg));
938c2ecf20Sopenharmony_ci	__asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_ESTAT) : "=r" (regs->csr_estat));
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci#endif /* _ASM_STACKTRACE_H */
97