summaryrefslogtreecommitdiff
path: root/arch/loongarch/kernel/genex.S
blob: 4f09121417818d2ed1a064ab3e95b4ab3c3a2fd7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
 *
 * Derived from MIPS:
 * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle
 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
 * Copyright (C) 2002, 2007  Maciej W. Rozycki
 * Copyright (C) 2001, 2012 MIPS Technologies, Inc.  All rights reserved.
 */
#include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/loongarch.h>
#include <asm/regdef.h>
#include <asm/fpregdef.h>
#include <asm/stackframe.h>
#include <asm/thread_info.h>

	.align	5
SYM_FUNC_START(__arch_cpu_idle)
	/* start of idle interrupt region */
	ori	t0, zero, CSR_CRMD_IE
	/* idle instruction needs irq enabled */
	csrxchg	t0, t0, LOONGARCH_CSR_CRMD
	/*
	 * If an interrupt lands here; between enabling interrupts above and
	 * going idle on the next instruction, we must *NOT* go idle since the
	 * interrupt could have set TIF_NEED_RESCHED or caused an timer to need
	 * reprogramming. Fall through -- see handle_vint() below -- and have
	 * the idle loop take care of things.
	 */
	idle	0
	/* end of idle interrupt region */
1:	jr	ra
SYM_FUNC_END(__arch_cpu_idle)

SYM_CODE_START(handle_vint)
	UNWIND_HINT_UNDEFINED
	BACKUP_T0T1
	SAVE_ALL
	la_abs	t1, 1b
	LONG_L	t0, sp, PT_ERA
	/* 3 instructions idle interrupt region */
	ori	t0, t0, 0b1100
	bne	t0, t1, 1f
	LONG_S	t0, sp, PT_ERA
1:	move	a0, sp
	move	a1, sp
	la_abs	t0, do_vint
	jirl	ra, t0, 0
	RESTORE_ALL_AND_RET
SYM_CODE_END(handle_vint)

SYM_CODE_START(except_vec_cex)
	UNWIND_HINT_UNDEFINED
	b	cache_parity_error
SYM_CODE_END(except_vec_cex)

	.macro	build_prep_badv
	csrrd	t0, LOONGARCH_CSR_BADV
	PTR_S	t0, sp, PT_BVADDR
	.endm

	.macro	build_prep_fcsr
	movfcsr2gr	a1, fcsr0
	.endm

	.macro	build_prep_none
	.endm

	.macro	BUILD_HANDLER exception handler prep
	.align	5
	SYM_CODE_START(handle_\exception)
	UNWIND_HINT_UNDEFINED
	666:
	BACKUP_T0T1
	SAVE_ALL
	build_prep_\prep
	move	a0, sp
	la_abs	t0, do_\handler
	jirl	ra, t0, 0
	668:
	RESTORE_ALL_AND_RET
	SYM_CODE_END(handle_\exception)
	.pushsection	".data", "aw", %progbits
	SYM_DATA(unwind_hint_\exception, .word 668b - 666b)
	.popsection
	.endm

	BUILD_HANDLER ade ade badv
	BUILD_HANDLER ale ale badv
	BUILD_HANDLER bce bce none
	BUILD_HANDLER bp bp none
	BUILD_HANDLER fpe fpe fcsr
	BUILD_HANDLER fpu fpu none
	BUILD_HANDLER lsx lsx none
	BUILD_HANDLER lasx lasx none
	BUILD_HANDLER lbt lbt none
	BUILD_HANDLER ri ri none
	BUILD_HANDLER watch watch none
	BUILD_HANDLER reserved reserved none	/* others */

SYM_CODE_START(handle_sys)
	UNWIND_HINT_UNDEFINED
	la_abs	t0, handle_syscall
	jr	t0
SYM_CODE_END(handle_sys)