18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2020 Loongson Technology Co., Ltd.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci#ifndef _ASM_STACKFRAME_H
68c2ecf20Sopenharmony_ci#define _ASM_STACKFRAME_H
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/threads.h>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <asm/addrspace.h>
118c2ecf20Sopenharmony_ci#include <asm/asm.h>
128c2ecf20Sopenharmony_ci#include <asm/asmmacro.h>
138c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h>
148c2ecf20Sopenharmony_ci#include <asm/loongarchregs.h>
158c2ecf20Sopenharmony_ci#include <asm/thread_info.h>
168c2ecf20Sopenharmony_ci#include <asm/unwind_hints.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/* Make the addition of cfi info a little easier. */
198c2ecf20Sopenharmony_ci	.macro cfi_rel_offset reg offset=0 docfi=0
208c2ecf20Sopenharmony_ci	.if \docfi
218c2ecf20Sopenharmony_ci	.cfi_rel_offset \reg, \offset
228c2ecf20Sopenharmony_ci	.endif
238c2ecf20Sopenharmony_ci	.endm
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	.macro cfi_st reg offset=0 docfi=0
268c2ecf20Sopenharmony_ci	cfi_rel_offset \reg, \offset, \docfi
278c2ecf20Sopenharmony_ci	LONG_S	\reg, sp, \offset
288c2ecf20Sopenharmony_ci	.endm
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	.macro cfi_restore reg offset=0 docfi=0
318c2ecf20Sopenharmony_ci	.if \docfi
328c2ecf20Sopenharmony_ci	.cfi_restore \reg
338c2ecf20Sopenharmony_ci	.endif
348c2ecf20Sopenharmony_ci	.endm
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	.macro cfi_ld reg offset=0 docfi=0
378c2ecf20Sopenharmony_ci	LONG_L	\reg, sp, \offset
388c2ecf20Sopenharmony_ci	cfi_restore \reg \offset \docfi
398c2ecf20Sopenharmony_ci	.endm
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci/* Jump to the runtime virtual address. */
428c2ecf20Sopenharmony_ci	.macro JUMP_VIRT_ADDR temp1 temp2
438c2ecf20Sopenharmony_ci	li.d	\temp1, CACHE_BASE
448c2ecf20Sopenharmony_ci	pcaddi	\temp2, 0
458c2ecf20Sopenharmony_ci	or	\temp1, \temp1, \temp2
468c2ecf20Sopenharmony_ci	jirl	zero, \temp1, 0xc
478c2ecf20Sopenharmony_ci	.endm
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	.macro BACKUP_T0T1
508c2ecf20Sopenharmony_ci	csrwr	t0, EXCEPTION_KS0
518c2ecf20Sopenharmony_ci	csrwr	t1, EXCEPTION_KS1
528c2ecf20Sopenharmony_ci	.endm
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	.macro RELOAD_T0T1
558c2ecf20Sopenharmony_ci	csrrd   t0, EXCEPTION_KS0
568c2ecf20Sopenharmony_ci	csrrd   t1, EXCEPTION_KS1
578c2ecf20Sopenharmony_ci	.endm
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	.macro	SAVE_TEMP docfi=0
608c2ecf20Sopenharmony_ci	RELOAD_T0T1
618c2ecf20Sopenharmony_ci	cfi_st	t0, PT_R12, \docfi
628c2ecf20Sopenharmony_ci	cfi_st	t1, PT_R13, \docfi
638c2ecf20Sopenharmony_ci	cfi_st	t2, PT_R14, \docfi
648c2ecf20Sopenharmony_ci	cfi_st	t3, PT_R15, \docfi
658c2ecf20Sopenharmony_ci	cfi_st	t4, PT_R16, \docfi
668c2ecf20Sopenharmony_ci	cfi_st	t5, PT_R17, \docfi
678c2ecf20Sopenharmony_ci	cfi_st	t6, PT_R18, \docfi
688c2ecf20Sopenharmony_ci	cfi_st	t7, PT_R19, \docfi
698c2ecf20Sopenharmony_ci	cfi_st	t8, PT_R20, \docfi
708c2ecf20Sopenharmony_ci	.endm
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	.macro	SAVE_STATIC docfi=0
738c2ecf20Sopenharmony_ci	cfi_st	s0, PT_R23, \docfi
748c2ecf20Sopenharmony_ci	cfi_st	s1, PT_R24, \docfi
758c2ecf20Sopenharmony_ci	cfi_st	s2, PT_R25, \docfi
768c2ecf20Sopenharmony_ci	cfi_st	s3, PT_R26, \docfi
778c2ecf20Sopenharmony_ci	cfi_st	s4, PT_R27, \docfi
788c2ecf20Sopenharmony_ci	cfi_st	s5, PT_R28, \docfi
798c2ecf20Sopenharmony_ci	cfi_st	s6, PT_R29, \docfi
808c2ecf20Sopenharmony_ci	cfi_st	s7, PT_R30, \docfi
818c2ecf20Sopenharmony_ci	cfi_st	s8, PT_R31, \docfi
828c2ecf20Sopenharmony_ci	.endm
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci/*
858c2ecf20Sopenharmony_ci * get_saved_sp returns the SP for the current CPU by looking in the
868c2ecf20Sopenharmony_ci * kernelsp array for it. It stores the current sp in t0 and loads the
878c2ecf20Sopenharmony_ci * new value in sp.
888c2ecf20Sopenharmony_ci */
898c2ecf20Sopenharmony_ci	.macro	get_saved_sp docfi=0
908c2ecf20Sopenharmony_ci	la.abs	  t1, kernelsp
918c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
928c2ecf20Sopenharmony_ci	csrrd	  t0, PERCPU_BASE_KS
938c2ecf20Sopenharmony_ci	LONG_ADD  t1, t1, t0
948c2ecf20Sopenharmony_ci#endif
958c2ecf20Sopenharmony_ci	move	  t0, sp
968c2ecf20Sopenharmony_ci	.if \docfi
978c2ecf20Sopenharmony_ci	.cfi_register sp, t0
988c2ecf20Sopenharmony_ci	.endif
998c2ecf20Sopenharmony_ci	LONG_L	  sp, t1, 0
1008c2ecf20Sopenharmony_ci	.endm
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	.macro	set_saved_sp stackp temp temp2
1038c2ecf20Sopenharmony_ci	la.abs	  \temp, kernelsp
1048c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
1058c2ecf20Sopenharmony_ci	LONG_ADD  \temp, \temp, u0
1068c2ecf20Sopenharmony_ci#endif
1078c2ecf20Sopenharmony_ci	LONG_S	  \stackp, \temp, 0
1088c2ecf20Sopenharmony_ci	.endm
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	.macro	SAVE_SOME docfi=0
1118c2ecf20Sopenharmony_ci	csrrd	t1, LOONGARCH_CSR_PRMD
1128c2ecf20Sopenharmony_ci	andi	t1, t1, 0x3	/* extract pplv bit */
1138c2ecf20Sopenharmony_ci	move	t0, sp
1148c2ecf20Sopenharmony_ci	beqz	t1, 8f
1158c2ecf20Sopenharmony_ci	/* Called from user mode, new stack. */
1168c2ecf20Sopenharmony_ci	get_saved_sp docfi=\docfi
1178c2ecf20Sopenharmony_ci8:
1188c2ecf20Sopenharmony_ci	PTR_ADDI sp, sp, -PT_SIZE
1198c2ecf20Sopenharmony_ci	.if \docfi
1208c2ecf20Sopenharmony_ci	.cfi_def_cfa sp,0
1218c2ecf20Sopenharmony_ci	.endif
1228c2ecf20Sopenharmony_ci	cfi_st	t0, PT_R3, \docfi
1238c2ecf20Sopenharmony_ci	cfi_rel_offset  sp, PT_R3, \docfi
1248c2ecf20Sopenharmony_ci	LONG_S	zero, sp, PT_R0
1258c2ecf20Sopenharmony_ci	csrrd	t0, LOONGARCH_CSR_PRMD
1268c2ecf20Sopenharmony_ci	LONG_S	t0, sp, PT_PRMD
1278c2ecf20Sopenharmony_ci	csrrd	t0, LOONGARCH_CSR_CRMD
1288c2ecf20Sopenharmony_ci	LONG_S	t0, sp, PT_CRMD
1298c2ecf20Sopenharmony_ci	csrrd	t0, LOONGARCH_CSR_EUEN
1308c2ecf20Sopenharmony_ci	LONG_S  t0, sp, PT_EUEN
1318c2ecf20Sopenharmony_ci	csrrd	t0, LOONGARCH_CSR_ECFG
1328c2ecf20Sopenharmony_ci	LONG_S	t0, sp, PT_ECFG
1338c2ecf20Sopenharmony_ci	csrrd	t0, LOONGARCH_CSR_ESTAT
1348c2ecf20Sopenharmony_ci	PTR_S	t0, sp, PT_ESTAT
1358c2ecf20Sopenharmony_ci	cfi_st	ra, PT_R1, \docfi
1368c2ecf20Sopenharmony_ci	cfi_st	a0, PT_R4, \docfi
1378c2ecf20Sopenharmony_ci	cfi_st	a1, PT_R5, \docfi
1388c2ecf20Sopenharmony_ci	cfi_st	a2, PT_R6, \docfi
1398c2ecf20Sopenharmony_ci	cfi_st	a3, PT_R7, \docfi
1408c2ecf20Sopenharmony_ci	cfi_st	a4, PT_R8, \docfi
1418c2ecf20Sopenharmony_ci	cfi_st	a5, PT_R9, \docfi
1428c2ecf20Sopenharmony_ci	cfi_st	a6, PT_R10, \docfi
1438c2ecf20Sopenharmony_ci	cfi_st	a7, PT_R11, \docfi
1448c2ecf20Sopenharmony_ci	csrrd	ra, LOONGARCH_CSR_ERA
1458c2ecf20Sopenharmony_ci	LONG_S	ra, sp, PT_ERA
1468c2ecf20Sopenharmony_ci	.if \docfi
1478c2ecf20Sopenharmony_ci	.cfi_rel_offset ra, PT_ERA
1488c2ecf20Sopenharmony_ci	.endif
1498c2ecf20Sopenharmony_ci	cfi_st	tp, PT_R2, \docfi
1508c2ecf20Sopenharmony_ci	cfi_st	fp, PT_R22, \docfi
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	/* Set thread_info if we're coming from user mode */
1538c2ecf20Sopenharmony_ci	csrrd	t0, LOONGARCH_CSR_PRMD
1548c2ecf20Sopenharmony_ci	andi	t0, t0, 0x3	/* extract pplv bit */
1558c2ecf20Sopenharmony_ci	beqz	t0, 9f
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	li.d	tp, ~_THREAD_MASK
1588c2ecf20Sopenharmony_ci	and	tp, tp, sp
1598c2ecf20Sopenharmony_ci	cfi_st  u0, PT_R21, \docfi
1608c2ecf20Sopenharmony_ci	csrrd	u0, PERCPU_BASE_KS
1618c2ecf20Sopenharmony_ci9:
1628c2ecf20Sopenharmony_ci#ifdef CONFIG_KGDB
1638c2ecf20Sopenharmony_ci	li.w	t0, CSR_CRMD_WE
1648c2ecf20Sopenharmony_ci	csrxchg	t0, t0, LOONGARCH_CSR_CRMD
1658c2ecf20Sopenharmony_ci#endif
1668c2ecf20Sopenharmony_ci	UNWIND_HINT_REGS
1678c2ecf20Sopenharmony_ci	.endm
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	.macro	SAVE_ALL docfi=0
1708c2ecf20Sopenharmony_ci	SAVE_SOME \docfi
1718c2ecf20Sopenharmony_ci	SAVE_TEMP \docfi
1728c2ecf20Sopenharmony_ci	SAVE_STATIC \docfi
1738c2ecf20Sopenharmony_ci	.endm
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	.macro	RESTORE_TEMP docfi=0
1768c2ecf20Sopenharmony_ci	cfi_ld	t0, PT_R12, \docfi
1778c2ecf20Sopenharmony_ci	cfi_ld	t1, PT_R13, \docfi
1788c2ecf20Sopenharmony_ci	cfi_ld	t2, PT_R14, \docfi
1798c2ecf20Sopenharmony_ci	cfi_ld	t3, PT_R15, \docfi
1808c2ecf20Sopenharmony_ci	cfi_ld	t4, PT_R16, \docfi
1818c2ecf20Sopenharmony_ci	cfi_ld	t5, PT_R17, \docfi
1828c2ecf20Sopenharmony_ci	cfi_ld	t6, PT_R18, \docfi
1838c2ecf20Sopenharmony_ci	cfi_ld	t7, PT_R19, \docfi
1848c2ecf20Sopenharmony_ci	cfi_ld	t8, PT_R20, \docfi
1858c2ecf20Sopenharmony_ci	.endm
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	.macro	RESTORE_STATIC docfi=0
1888c2ecf20Sopenharmony_ci	cfi_ld	s0, PT_R23, \docfi
1898c2ecf20Sopenharmony_ci	cfi_ld	s1, PT_R24, \docfi
1908c2ecf20Sopenharmony_ci	cfi_ld	s2, PT_R25, \docfi
1918c2ecf20Sopenharmony_ci	cfi_ld	s3, PT_R26, \docfi
1928c2ecf20Sopenharmony_ci	cfi_ld	s4, PT_R27, \docfi
1938c2ecf20Sopenharmony_ci	cfi_ld	s5, PT_R28, \docfi
1948c2ecf20Sopenharmony_ci	cfi_ld	s6, PT_R29, \docfi
1958c2ecf20Sopenharmony_ci	cfi_ld	s7, PT_R30, \docfi
1968c2ecf20Sopenharmony_ci	cfi_ld	s8, PT_R31, \docfi
1978c2ecf20Sopenharmony_ci	.endm
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	.macro	RESTORE_SOME docfi=0
2008c2ecf20Sopenharmony_ci	LONG_L	a0, sp, PT_PRMD
2018c2ecf20Sopenharmony_ci	andi    a0, a0, 0x3	/* extract pplv bit */
2028c2ecf20Sopenharmony_ci	beqz    a0, 8f
2038c2ecf20Sopenharmony_ci	cfi_ld  u0, PT_R21, \docfi
2048c2ecf20Sopenharmony_ci8:
2058c2ecf20Sopenharmony_ci	LONG_L	a0, sp, PT_ERA
2068c2ecf20Sopenharmony_ci	csrwr	a0, LOONGARCH_CSR_ERA
2078c2ecf20Sopenharmony_ci	LONG_L	a0, sp, PT_PRMD
2088c2ecf20Sopenharmony_ci	csrwr	a0, LOONGARCH_CSR_PRMD
2098c2ecf20Sopenharmony_ci	cfi_ld	ra, PT_R1, \docfi
2108c2ecf20Sopenharmony_ci	cfi_ld	a0, PT_R4, \docfi
2118c2ecf20Sopenharmony_ci	cfi_ld	a1, PT_R5, \docfi
2128c2ecf20Sopenharmony_ci	cfi_ld	a2, PT_R6, \docfi
2138c2ecf20Sopenharmony_ci	cfi_ld	a3, PT_R7, \docfi
2148c2ecf20Sopenharmony_ci	cfi_ld	a4, PT_R8, \docfi
2158c2ecf20Sopenharmony_ci	cfi_ld	a5, PT_R9, \docfi
2168c2ecf20Sopenharmony_ci	cfi_ld	a6, PT_R10, \docfi
2178c2ecf20Sopenharmony_ci	cfi_ld	a7, PT_R11, \docfi
2188c2ecf20Sopenharmony_ci	cfi_ld	tp, PT_R2, \docfi
2198c2ecf20Sopenharmony_ci	cfi_ld	fp, PT_R22, \docfi
2208c2ecf20Sopenharmony_ci	.endm
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	.macro	RESTORE_SP_AND_RET docfi=0
2238c2ecf20Sopenharmony_ci	cfi_ld	sp, PT_R3, \docfi
2248c2ecf20Sopenharmony_ci	UNWIND_HINT sp_reg=ORC_REG_SP type=ORC_TYPE_CALL
2258c2ecf20Sopenharmony_ci	ertn
2268c2ecf20Sopenharmony_ci	.endm
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	.macro	RESTORE_ALL_AND_RET docfi=0
2298c2ecf20Sopenharmony_ci	RESTORE_STATIC \docfi
2308c2ecf20Sopenharmony_ci	RESTORE_TEMP \docfi
2318c2ecf20Sopenharmony_ci	RESTORE_SOME \docfi
2328c2ecf20Sopenharmony_ci	RESTORE_SP_AND_RET \docfi
2338c2ecf20Sopenharmony_ci	.endm
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci#endif /* _ASM_STACKFRAME_H */
236