162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#ifndef _ASM_STACKFRAME_H
662306a36Sopenharmony_ci#define _ASM_STACKFRAME_H
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/threads.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <asm/addrspace.h>
1162306a36Sopenharmony_ci#include <asm/asm.h>
1262306a36Sopenharmony_ci#include <asm/asmmacro.h>
1362306a36Sopenharmony_ci#include <asm/asm-offsets.h>
1462306a36Sopenharmony_ci#include <asm/loongarch.h>
1562306a36Sopenharmony_ci#include <asm/thread_info.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/* Make the addition of cfi info a little easier. */
1862306a36Sopenharmony_ci	.macro cfi_rel_offset reg offset=0 docfi=0
1962306a36Sopenharmony_ci	.if \docfi
2062306a36Sopenharmony_ci	.cfi_rel_offset \reg, \offset
2162306a36Sopenharmony_ci	.endif
2262306a36Sopenharmony_ci	.endm
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	.macro cfi_st reg offset=0 docfi=0
2562306a36Sopenharmony_ci	cfi_rel_offset \reg, \offset, \docfi
2662306a36Sopenharmony_ci	LONG_S	\reg, sp, \offset
2762306a36Sopenharmony_ci	.endm
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	.macro cfi_restore reg offset=0 docfi=0
3062306a36Sopenharmony_ci	.if \docfi
3162306a36Sopenharmony_ci	.cfi_restore \reg
3262306a36Sopenharmony_ci	.endif
3362306a36Sopenharmony_ci	.endm
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	.macro cfi_ld reg offset=0 docfi=0
3662306a36Sopenharmony_ci	LONG_L	\reg, sp, \offset
3762306a36Sopenharmony_ci	cfi_restore \reg \offset \docfi
3862306a36Sopenharmony_ci	.endm
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci/* Jump to the runtime virtual address. */
4162306a36Sopenharmony_ci	.macro JUMP_VIRT_ADDR temp1 temp2
4262306a36Sopenharmony_ci	li.d	\temp1, CACHE_BASE
4362306a36Sopenharmony_ci	pcaddi	\temp2, 0
4462306a36Sopenharmony_ci	or	\temp1, \temp1, \temp2
4562306a36Sopenharmony_ci	jirl	zero, \temp1, 0xc
4662306a36Sopenharmony_ci	.endm
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	.macro BACKUP_T0T1
4962306a36Sopenharmony_ci	csrwr	t0, EXCEPTION_KS0
5062306a36Sopenharmony_ci	csrwr	t1, EXCEPTION_KS1
5162306a36Sopenharmony_ci	.endm
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	.macro RELOAD_T0T1
5462306a36Sopenharmony_ci	csrrd   t0, EXCEPTION_KS0
5562306a36Sopenharmony_ci	csrrd   t1, EXCEPTION_KS1
5662306a36Sopenharmony_ci	.endm
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	.macro	SAVE_TEMP docfi=0
5962306a36Sopenharmony_ci	RELOAD_T0T1
6062306a36Sopenharmony_ci	cfi_st	t0, PT_R12, \docfi
6162306a36Sopenharmony_ci	cfi_st	t1, PT_R13, \docfi
6262306a36Sopenharmony_ci	cfi_st	t2, PT_R14, \docfi
6362306a36Sopenharmony_ci	cfi_st	t3, PT_R15, \docfi
6462306a36Sopenharmony_ci	cfi_st	t4, PT_R16, \docfi
6562306a36Sopenharmony_ci	cfi_st	t5, PT_R17, \docfi
6662306a36Sopenharmony_ci	cfi_st	t6, PT_R18, \docfi
6762306a36Sopenharmony_ci	cfi_st	t7, PT_R19, \docfi
6862306a36Sopenharmony_ci	cfi_st	t8, PT_R20, \docfi
6962306a36Sopenharmony_ci	.endm
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	.macro	SAVE_STATIC docfi=0
7262306a36Sopenharmony_ci	cfi_st	s0, PT_R23, \docfi
7362306a36Sopenharmony_ci	cfi_st	s1, PT_R24, \docfi
7462306a36Sopenharmony_ci	cfi_st	s2, PT_R25, \docfi
7562306a36Sopenharmony_ci	cfi_st	s3, PT_R26, \docfi
7662306a36Sopenharmony_ci	cfi_st	s4, PT_R27, \docfi
7762306a36Sopenharmony_ci	cfi_st	s5, PT_R28, \docfi
7862306a36Sopenharmony_ci	cfi_st	s6, PT_R29, \docfi
7962306a36Sopenharmony_ci	cfi_st	s7, PT_R30, \docfi
8062306a36Sopenharmony_ci	cfi_st	s8, PT_R31, \docfi
8162306a36Sopenharmony_ci	.endm
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/*
8462306a36Sopenharmony_ci * get_saved_sp returns the SP for the current CPU by looking in the
8562306a36Sopenharmony_ci * kernelsp array for it. It stores the current sp in t0 and loads the
8662306a36Sopenharmony_ci * new value in sp.
8762306a36Sopenharmony_ci */
8862306a36Sopenharmony_ci	.macro	get_saved_sp docfi=0
8962306a36Sopenharmony_ci	la_abs	  t1, kernelsp
9062306a36Sopenharmony_ci#ifdef CONFIG_SMP
9162306a36Sopenharmony_ci	csrrd	  t0, PERCPU_BASE_KS
9262306a36Sopenharmony_ci	LONG_ADD  t1, t1, t0
9362306a36Sopenharmony_ci#endif
9462306a36Sopenharmony_ci	move	  t0, sp
9562306a36Sopenharmony_ci	.if \docfi
9662306a36Sopenharmony_ci	.cfi_register sp, t0
9762306a36Sopenharmony_ci	.endif
9862306a36Sopenharmony_ci	LONG_L	  sp, t1, 0
9962306a36Sopenharmony_ci	.endm
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	.macro	set_saved_sp stackp temp temp2
10262306a36Sopenharmony_ci	la.pcrel  \temp, kernelsp
10362306a36Sopenharmony_ci#ifdef CONFIG_SMP
10462306a36Sopenharmony_ci	LONG_ADD  \temp, \temp, u0
10562306a36Sopenharmony_ci#endif
10662306a36Sopenharmony_ci	LONG_S	  \stackp, \temp, 0
10762306a36Sopenharmony_ci	.endm
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	.macro	SAVE_SOME docfi=0
11062306a36Sopenharmony_ci	csrrd	t1, LOONGARCH_CSR_PRMD
11162306a36Sopenharmony_ci	andi	t1, t1, 0x3	/* extract pplv bit */
11262306a36Sopenharmony_ci	move	t0, sp
11362306a36Sopenharmony_ci	beqz	t1, 8f
11462306a36Sopenharmony_ci	/* Called from user mode, new stack. */
11562306a36Sopenharmony_ci	get_saved_sp docfi=\docfi
11662306a36Sopenharmony_ci8:
11762306a36Sopenharmony_ci	PTR_ADDI sp, sp, -PT_SIZE
11862306a36Sopenharmony_ci	.if \docfi
11962306a36Sopenharmony_ci	.cfi_def_cfa sp, 0
12062306a36Sopenharmony_ci	.endif
12162306a36Sopenharmony_ci	cfi_st	t0, PT_R3, \docfi
12262306a36Sopenharmony_ci	cfi_rel_offset  sp, PT_R3, \docfi
12362306a36Sopenharmony_ci	LONG_S	zero, sp, PT_R0
12462306a36Sopenharmony_ci	csrrd	t0, LOONGARCH_CSR_PRMD
12562306a36Sopenharmony_ci	LONG_S	t0, sp, PT_PRMD
12662306a36Sopenharmony_ci	csrrd	t0, LOONGARCH_CSR_CRMD
12762306a36Sopenharmony_ci	LONG_S	t0, sp, PT_CRMD
12862306a36Sopenharmony_ci	csrrd	t0, LOONGARCH_CSR_EUEN
12962306a36Sopenharmony_ci	LONG_S  t0, sp, PT_EUEN
13062306a36Sopenharmony_ci	csrrd	t0, LOONGARCH_CSR_ECFG
13162306a36Sopenharmony_ci	LONG_S	t0, sp, PT_ECFG
13262306a36Sopenharmony_ci	csrrd	t0, LOONGARCH_CSR_ESTAT
13362306a36Sopenharmony_ci	PTR_S	t0, sp, PT_ESTAT
13462306a36Sopenharmony_ci	cfi_st	ra, PT_R1, \docfi
13562306a36Sopenharmony_ci	cfi_st	a0, PT_R4, \docfi
13662306a36Sopenharmony_ci	cfi_st	a1, PT_R5, \docfi
13762306a36Sopenharmony_ci	cfi_st	a2, PT_R6, \docfi
13862306a36Sopenharmony_ci	cfi_st	a3, PT_R7, \docfi
13962306a36Sopenharmony_ci	cfi_st	a4, PT_R8, \docfi
14062306a36Sopenharmony_ci	cfi_st	a5, PT_R9, \docfi
14162306a36Sopenharmony_ci	cfi_st	a6, PT_R10, \docfi
14262306a36Sopenharmony_ci	cfi_st	a7, PT_R11, \docfi
14362306a36Sopenharmony_ci	csrrd	ra, LOONGARCH_CSR_ERA
14462306a36Sopenharmony_ci	LONG_S	ra, sp, PT_ERA
14562306a36Sopenharmony_ci	.if \docfi
14662306a36Sopenharmony_ci	.cfi_rel_offset ra, PT_ERA
14762306a36Sopenharmony_ci	.endif
14862306a36Sopenharmony_ci	cfi_st	tp, PT_R2, \docfi
14962306a36Sopenharmony_ci	cfi_st	fp, PT_R22, \docfi
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	/* Set thread_info if we're coming from user mode */
15262306a36Sopenharmony_ci	csrrd	t0, LOONGARCH_CSR_PRMD
15362306a36Sopenharmony_ci	andi	t0, t0, 0x3	/* extract pplv bit */
15462306a36Sopenharmony_ci	beqz	t0, 9f
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	li.d	tp, ~_THREAD_MASK
15762306a36Sopenharmony_ci	and	tp, tp, sp
15862306a36Sopenharmony_ci	cfi_st  u0, PT_R21, \docfi
15962306a36Sopenharmony_ci	csrrd	u0, PERCPU_BASE_KS
16062306a36Sopenharmony_ci9:
16162306a36Sopenharmony_ci#ifdef CONFIG_KGDB
16262306a36Sopenharmony_ci	li.w	t0, CSR_CRMD_WE
16362306a36Sopenharmony_ci	csrxchg	t0, t0, LOONGARCH_CSR_CRMD
16462306a36Sopenharmony_ci#endif
16562306a36Sopenharmony_ci	.endm
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	.macro	SAVE_ALL docfi=0
16862306a36Sopenharmony_ci	SAVE_SOME \docfi
16962306a36Sopenharmony_ci	SAVE_TEMP \docfi
17062306a36Sopenharmony_ci	SAVE_STATIC \docfi
17162306a36Sopenharmony_ci	.endm
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	.macro	RESTORE_TEMP docfi=0
17462306a36Sopenharmony_ci	cfi_ld	t0, PT_R12, \docfi
17562306a36Sopenharmony_ci	cfi_ld	t1, PT_R13, \docfi
17662306a36Sopenharmony_ci	cfi_ld	t2, PT_R14, \docfi
17762306a36Sopenharmony_ci	cfi_ld	t3, PT_R15, \docfi
17862306a36Sopenharmony_ci	cfi_ld	t4, PT_R16, \docfi
17962306a36Sopenharmony_ci	cfi_ld	t5, PT_R17, \docfi
18062306a36Sopenharmony_ci	cfi_ld	t6, PT_R18, \docfi
18162306a36Sopenharmony_ci	cfi_ld	t7, PT_R19, \docfi
18262306a36Sopenharmony_ci	cfi_ld	t8, PT_R20, \docfi
18362306a36Sopenharmony_ci	.endm
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	.macro	RESTORE_STATIC docfi=0
18662306a36Sopenharmony_ci	cfi_ld	s0, PT_R23, \docfi
18762306a36Sopenharmony_ci	cfi_ld	s1, PT_R24, \docfi
18862306a36Sopenharmony_ci	cfi_ld	s2, PT_R25, \docfi
18962306a36Sopenharmony_ci	cfi_ld	s3, PT_R26, \docfi
19062306a36Sopenharmony_ci	cfi_ld	s4, PT_R27, \docfi
19162306a36Sopenharmony_ci	cfi_ld	s5, PT_R28, \docfi
19262306a36Sopenharmony_ci	cfi_ld	s6, PT_R29, \docfi
19362306a36Sopenharmony_ci	cfi_ld	s7, PT_R30, \docfi
19462306a36Sopenharmony_ci	cfi_ld	s8, PT_R31, \docfi
19562306a36Sopenharmony_ci	.endm
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	.macro	RESTORE_SOME docfi=0
19862306a36Sopenharmony_ci	LONG_L	a0, sp, PT_PRMD
19962306a36Sopenharmony_ci	andi    a0, a0, 0x3	/* extract pplv bit */
20062306a36Sopenharmony_ci	beqz    a0, 8f
20162306a36Sopenharmony_ci	cfi_ld  u0, PT_R21, \docfi
20262306a36Sopenharmony_ci8:
20362306a36Sopenharmony_ci	LONG_L	a0, sp, PT_ERA
20462306a36Sopenharmony_ci	csrwr	a0, LOONGARCH_CSR_ERA
20562306a36Sopenharmony_ci	LONG_L	a0, sp, PT_PRMD
20662306a36Sopenharmony_ci	csrwr	a0, LOONGARCH_CSR_PRMD
20762306a36Sopenharmony_ci	cfi_ld	ra, PT_R1, \docfi
20862306a36Sopenharmony_ci	cfi_ld	a0, PT_R4, \docfi
20962306a36Sopenharmony_ci	cfi_ld	a1, PT_R5, \docfi
21062306a36Sopenharmony_ci	cfi_ld	a2, PT_R6, \docfi
21162306a36Sopenharmony_ci	cfi_ld	a3, PT_R7, \docfi
21262306a36Sopenharmony_ci	cfi_ld	a4, PT_R8, \docfi
21362306a36Sopenharmony_ci	cfi_ld	a5, PT_R9, \docfi
21462306a36Sopenharmony_ci	cfi_ld	a6, PT_R10, \docfi
21562306a36Sopenharmony_ci	cfi_ld	a7, PT_R11, \docfi
21662306a36Sopenharmony_ci	cfi_ld	tp, PT_R2, \docfi
21762306a36Sopenharmony_ci	cfi_ld	fp, PT_R22, \docfi
21862306a36Sopenharmony_ci	.endm
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	.macro	RESTORE_SP_AND_RET docfi=0
22162306a36Sopenharmony_ci	cfi_ld	sp, PT_R3, \docfi
22262306a36Sopenharmony_ci	ertn
22362306a36Sopenharmony_ci	.endm
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	.macro	RESTORE_ALL_AND_RET docfi=0
22662306a36Sopenharmony_ci	RESTORE_STATIC \docfi
22762306a36Sopenharmony_ci	RESTORE_TEMP \docfi
22862306a36Sopenharmony_ci	RESTORE_SOME \docfi
22962306a36Sopenharmony_ci	RESTORE_SP_AND_RET \docfi
23062306a36Sopenharmony_ci	.endm
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci#endif /* _ASM_STACKFRAME_H */
233