276 lines · 6.1 KB · C
RawDownload
/* SPDX-License-Identifier: GPL-2.0 *//* * Copyright (C) 2020-2022 Loongson Technology Corporation Limited */#ifndef _ASM_STACKFRAME_H#define _ASM_STACKFRAME_H #include <linux/threads.h> #include <asm/addrspace.h>#include <asm/asm.h>#include <asm/asmmacro.h>#include <asm/asm-offsets.h>#include <asm/loongarch.h>#include <asm/thread_info.h>#include <asm/unwind_hints.h> /* Make the addition of cfi info a little easier. */	.macro cfi_rel_offset reg offset=0 docfi=0	.if \docfi	.cfi_rel_offset \reg, \offset	.endif	.endm 	.macro cfi_st reg offset=0 docfi=0	cfi_rel_offset \reg, \offset, \docfi	LONG_S	\reg, sp, \offset	.endm 	.macro cfi_restore reg offset=0 docfi=0	.if \docfi	.cfi_restore \reg	.endif	.endm 	.macro cfi_ld reg offset=0 docfi=0	LONG_L	\reg, sp, \offset	cfi_restore \reg \offset \docfi	.endm 	.macro SETUP_TWINS temp	pcaddi	t0, 0	PTR_LI	t1, ~TO_PHYS_MASK	and	t0, t0, t1	ori	t0, t0, (1 << 4 | 1)	csrwr	t0, LOONGARCH_CSR_DMWIN0	PTR_LI	t0, CSR_DMW1_INIT	csrwr	t0, LOONGARCH_CSR_DMWIN1	.endm 	.macro SETUP_MODES temp	/* Enable PG */	li.w	\temp, 0xb0		# PLV=0, IE=0, PG=1	csrwr	\temp, LOONGARCH_CSR_CRMD	li.w	\temp, 0x04		# PLV=0, PIE=1, PWE=0	csrwr	\temp, LOONGARCH_CSR_PRMD	li.w	\temp, 0x00		# FPE=0, SXE=0, ASXE=0, BTE=0	csrwr	\temp, LOONGARCH_CSR_EUEN	.endm 	.macro SETUP_DMWINS temp	PTR_LI	\temp, CSR_DMW0_INIT	# SUC, PLV0, LA32: 0x8xxx xxxx, LA64: 0x8000 xxxx xxxx xxxx	csrwr	\temp, LOONGARCH_CSR_DMWIN0	PTR_LI	\temp, CSR_DMW1_INIT	# CAC, PLV0, LA32: 0xaxxx xxxx, LA64: 0x9000 xxxx xxxx xxxx	csrwr	\temp, LOONGARCH_CSR_DMWIN1	PTR_LI	\temp, CSR_DMW2_INIT	# WUC, PLV0, LA32: unavailable, LA64: 0xa000 xxxx xxxx xxxx	csrwr	\temp, LOONGARCH_CSR_DMWIN2	PTR_LI	\temp, CSR_DMW3_INIT	# 0x0, unused	csrwr	\temp, LOONGARCH_CSR_DMWIN3	.endm /* Jump to the runtime virtual address. */	.macro JUMP_VIRT_ADDR temp1 temp2	PTR_LI	\temp1, CACHE_BASE	pcaddi	\temp2, 0	PTR_BSTRINS  \temp1, \temp2, (DMW_PABITS - 1), 0	jirl	zero, \temp1, 0xc	.endm 	.macro STACKLEAK_ERASE#ifdef CONFIG_KSTACK_ERASE	bl	stackleak_erase_on_task_stack#endif	.endm 	.macro BACKUP_T0T1	csrwr	t0, EXCEPTION_KS0	csrwr	t1, EXCEPTION_KS1	.endm 	.macro RELOAD_T0T1	csrrd   t0, EXCEPTION_KS0	csrrd   t1, EXCEPTION_KS1	.endm 	.macro	SAVE_TEMP docfi=0	RELOAD_T0T1	cfi_st	t0, PT_R12, \docfi	cfi_st	t1, PT_R13, \docfi	cfi_st	t2, PT_R14, \docfi	cfi_st	t3, PT_R15, \docfi	cfi_st	t4, PT_R16, \docfi	cfi_st	t5, PT_R17, \docfi	cfi_st	t6, PT_R18, \docfi	cfi_st	t7, PT_R19, \docfi	cfi_st	t8, PT_R20, \docfi	.endm 	.macro	SAVE_STATIC docfi=0	cfi_st	s0, PT_R23, \docfi	cfi_st	s1, PT_R24, \docfi	cfi_st	s2, PT_R25, \docfi	cfi_st	s3, PT_R26, \docfi	cfi_st	s4, PT_R27, \docfi	cfi_st	s5, PT_R28, \docfi	cfi_st	s6, PT_R29, \docfi	cfi_st	s7, PT_R30, \docfi	cfi_st	s8, PT_R31, \docfi	.endm /* * get_saved_sp returns the SP for the current CPU by looking in the * kernelsp array for it. It stores the current sp in t0 and loads the * new value in sp. */	.macro	get_saved_sp docfi=0	la_abs	  t1, kernelsp#ifdef CONFIG_SMP	csrrd	  t0, PERCPU_BASE_KS	LONG_ADD  t1, t1, t0#endif	move	  t0, sp	.if \docfi	.cfi_register sp, t0	.endif	LONG_L	  sp, t1, 0	.endm 	.macro	set_saved_sp stackp temp temp2	la.pcrel  \temp, kernelsp#ifdef CONFIG_SMP	LONG_ADD  \temp, \temp, u0#endif	LONG_S	  \stackp, \temp, 0	.endm 	.macro	SAVE_SOME docfi=0	csrrd	t1, LOONGARCH_CSR_PRMD	andi	t1, t1, 0x3	/* extract pplv bit */	move	t0, sp	beqz	t1, 8f	/* Called from user mode, new stack. */	get_saved_sp docfi=\docfi8:	PTR_ADDI sp, sp, -PT_SIZE	.if \docfi	.cfi_def_cfa sp, 0	.endif	cfi_st	t0, PT_R3, \docfi	cfi_rel_offset  sp, PT_R3, \docfi	LONG_S	zero, sp, PT_R0	csrrd	t0, LOONGARCH_CSR_PRMD	LONG_S	t0, sp, PT_PRMD	csrrd	t0, LOONGARCH_CSR_CRMD	LONG_S	t0, sp, PT_CRMD	csrrd	t0, LOONGARCH_CSR_EUEN	LONG_S  t0, sp, PT_EUEN	csrrd	t0, LOONGARCH_CSR_ECFG	LONG_S	t0, sp, PT_ECFG	csrrd	t0, LOONGARCH_CSR_ESTAT	PTR_S	t0, sp, PT_ESTAT	cfi_st	ra, PT_R1, \docfi	cfi_st	a0, PT_R4, \docfi	cfi_st	a1, PT_R5, \docfi	cfi_st	a2, PT_R6, \docfi	cfi_st	a3, PT_R7, \docfi	cfi_st	a4, PT_R8, \docfi	cfi_st	a5, PT_R9, \docfi	cfi_st	a6, PT_R10, \docfi	cfi_st	a7, PT_R11, \docfi	csrrd	ra, LOONGARCH_CSR_ERA	LONG_S	ra, sp, PT_ERA	.if \docfi	.cfi_rel_offset ra, PT_ERA	.endif	cfi_st	tp, PT_R2, \docfi	cfi_st  u0, PT_R21, \docfi	cfi_st	fp, PT_R22, \docfi 	/* Set thread_info if we're coming from user mode */	csrrd	t0, LOONGARCH_CSR_PRMD	andi	t0, t0, 0x3	/* extract pplv bit */	beqz	t0, 9f 	csrrd	u0, PERCPU_BASE_KS 	la_abs	t1, cpu_tasks#ifdef CONFIG_SMP	LONG_ADD t1, t1, u0#endif	LONG_L	tp, t1, 09:#ifdef CONFIG_KGDB	li.w	t0, CSR_CRMD_WE	csrxchg	t0, t0, LOONGARCH_CSR_CRMD#endif	UNWIND_HINT_REGS	.endm 	.macro	SAVE_ALL docfi=0	SAVE_SOME \docfi	SAVE_TEMP \docfi	SAVE_STATIC \docfi	.endm 	.macro	RESTORE_TEMP docfi=0	cfi_ld	t0, PT_R12, \docfi	cfi_ld	t1, PT_R13, \docfi	cfi_ld	t2, PT_R14, \docfi	cfi_ld	t3, PT_R15, \docfi	cfi_ld	t4, PT_R16, \docfi	cfi_ld	t5, PT_R17, \docfi	cfi_ld	t6, PT_R18, \docfi	cfi_ld	t7, PT_R19, \docfi	cfi_ld	t8, PT_R20, \docfi	.endm 	.macro	RESTORE_STATIC docfi=0	cfi_ld	s0, PT_R23, \docfi	cfi_ld	s1, PT_R24, \docfi	cfi_ld	s2, PT_R25, \docfi	cfi_ld	s3, PT_R26, \docfi	cfi_ld	s4, PT_R27, \docfi	cfi_ld	s5, PT_R28, \docfi	cfi_ld	s6, PT_R29, \docfi	cfi_ld	s7, PT_R30, \docfi	cfi_ld	s8, PT_R31, \docfi	.endm 	.macro	RESTORE_SOME docfi=0	LONG_L	a0, sp, PT_PRMD	andi    a0, a0, 0x3	/* extract pplv bit */	beqz    a0, 8f	cfi_ld  u0, PT_R21, \docfi8:	LONG_L	a0, sp, PT_ERA	csrwr	a0, LOONGARCH_CSR_ERA	LONG_L	a0, sp, PT_PRMD	csrwr	a0, LOONGARCH_CSR_PRMD	cfi_ld	ra, PT_R1, \docfi	cfi_ld	a0, PT_R4, \docfi	cfi_ld	a1, PT_R5, \docfi	cfi_ld	a2, PT_R6, \docfi	cfi_ld	a3, PT_R7, \docfi	cfi_ld	a4, PT_R8, \docfi	cfi_ld	a5, PT_R9, \docfi	cfi_ld	a6, PT_R10, \docfi	cfi_ld	a7, PT_R11, \docfi	cfi_ld	tp, PT_R2, \docfi	cfi_ld	fp, PT_R22, \docfi	.endm 	.macro	RESTORE_SP_AND_RET docfi=0	cfi_ld	sp, PT_R3, \docfi	UNWIND_HINT_FUNC	ertn	.endm 	.macro	RESTORE_ALL_AND_RET docfi=0	RESTORE_STATIC \docfi	RESTORE_TEMP \docfi	RESTORE_SOME \docfi	RESTORE_SP_AND_RET \docfi	.endm #endif /* _ASM_STACKFRAME_H */