xref: /linux/arch/loongarch/kernel/genex.S (revision c586c97dd84a4d1c8df38171dc715f6241c7e6a3)
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4 *
5 * Derived from MIPS:
6 * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle
7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8 * Copyright (C) 2002, 2007  Maciej W. Rozycki
9 * Copyright (C) 2001, 2012 MIPS Technologies, Inc.  All rights reserved.
10 */
11#include <asm/asm.h>
12#include <asm/asmmacro.h>
13#include <asm/loongarch.h>
14#include <asm/regdef.h>
15#include <asm/fpregdef.h>
16#include <asm/stackframe.h>
17#include <asm/thread_info.h>
18
19	.section .cpuidle.text, "ax"
20	.align	5
21SYM_FUNC_START(__arch_cpu_idle)
22	/* start of idle interrupt region */
23	ori	t0, zero, CSR_CRMD_IE
24	/* idle instruction needs irq enabled */
25	csrxchg	t0, t0, LOONGARCH_CSR_CRMD
26	/*
27	 * If an interrupt lands here; between enabling interrupts above and
28	 * going idle on the next instruction, we must *NOT* go idle since the
29	 * interrupt could have set TIF_NEED_RESCHED or caused an timer to need
30	 * reprogramming. Fall through -- see handle_vint() below -- and have
31	 * the idle loop take care of things.
32	 */
33	idle	0
34	/* end of idle interrupt region */
35idle_exit:
36	jr	ra
37SYM_FUNC_END(__arch_cpu_idle)
38	.previous
39
40SYM_CODE_START(handle_vint)
41	UNWIND_HINT_UNDEFINED
42	BACKUP_T0T1
43	SAVE_ALL
44	la_abs	t1, idle_exit
45	LONG_L	t0, sp, PT_ERA
46	/* 3 instructions idle interrupt region */
47	ori	t0, t0, 0b1100
48	bne	t0, t1, 1f
49	LONG_S	t0, sp, PT_ERA
501:	move	a0, sp
51	move	a1, sp
52	la_abs	t0, do_vint
53	jirl	ra, t0, 0
54	RESTORE_ALL_AND_RET
55SYM_CODE_END(handle_vint)
56
57SYM_CODE_START(except_vec_cex)
58	UNWIND_HINT_UNDEFINED
59	b	cache_parity_error
60SYM_CODE_END(except_vec_cex)
61
62	.macro	build_prep_badv
63	csrrd	t0, LOONGARCH_CSR_BADV
64	PTR_S	t0, sp, PT_BVADDR
65	.endm
66
67	.macro	build_prep_fcsr
68	movfcsr2gr	a1, fcsr0
69	.endm
70
71	.macro	build_prep_none
72	.endm
73
74	.macro	BUILD_HANDLER exception handler prep
75	.align	5
76	SYM_CODE_START(handle_\exception)
77	UNWIND_HINT_UNDEFINED
78	666:
79	BACKUP_T0T1
80	SAVE_ALL
81	build_prep_\prep
82	move	a0, sp
83	la_abs	t0, do_\handler
84	jirl	ra, t0, 0
85	668:
86	RESTORE_ALL_AND_RET
87	SYM_CODE_END(handle_\exception)
88	.pushsection	".data", "aw", %progbits
89	SYM_DATA(unwind_hint_\exception, .word 668b - 666b)
90	.popsection
91	.endm
92
93	BUILD_HANDLER ade ade badv
94	BUILD_HANDLER ale ale badv
95	BUILD_HANDLER bce bce none
96	BUILD_HANDLER bp bp none
97	BUILD_HANDLER fpe fpe fcsr
98	BUILD_HANDLER fpu fpu none
99	BUILD_HANDLER lsx lsx none
100	BUILD_HANDLER lasx lasx none
101	BUILD_HANDLER lbt lbt none
102	BUILD_HANDLER ri ri none
103	BUILD_HANDLER watch watch none
104	BUILD_HANDLER reserved reserved none	/* others */
105
106SYM_CODE_START(handle_sys)
107	UNWIND_HINT_UNDEFINED
108	la_abs	t0, handle_syscall
109	jr	t0
110SYM_CODE_END(handle_sys)
111