xref: /openbmc/linux/arch/csky/kernel/entry.S (revision a531b0c2)
1/* SPDX-License-Identifier: GPL-2.0 */
2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3
4#include <linux/linkage.h>
5#include <abi/entry.h>
6#include <abi/pgtable-bits.h>
7#include <asm/errno.h>
8#include <asm/setup.h>
9#include <asm/unistd.h>
10#include <asm/asm-offsets.h>
11#include <linux/threads.h>
12#include <asm/page.h>
13#include <asm/thread_info.h>
14
15.macro	zero_fp
16#ifdef CONFIG_STACKTRACE
17	movi	r8, 0
18#endif
19.endm
20
21.macro	context_tracking
22#ifdef CONFIG_CONTEXT_TRACKING
23	mfcr	a0, epsr
24	btsti	a0, 31
25	bt	1f
26	jbsr	context_tracking_user_exit
27	ldw	a0, (sp, LSAVE_A0)
28	ldw	a1, (sp, LSAVE_A1)
29	ldw	a2, (sp, LSAVE_A2)
30	ldw	a3, (sp, LSAVE_A3)
31#if defined(__CSKYABIV1__)
32	ldw	r6, (sp, LSAVE_A4)
33	ldw	r7, (sp, LSAVE_A5)
34#endif
351:
36#endif
37.endm
38
39.text
40ENTRY(csky_pagefault)
41	SAVE_ALL 0
42	zero_fp
43	context_tracking
44	psrset  ee
45	mov     a0, sp
46	jbsr    do_page_fault
47	jmpi    ret_from_exception
48
49ENTRY(csky_systemcall)
50	SAVE_ALL TRAP0_SIZE
51	zero_fp
52	context_tracking
53	psrset  ee, ie
54
55	lrw     r9, __NR_syscalls
56	cmphs   syscallid, r9		/* Check nr of syscall */
57	bt      1f
58
59	lrw     r9, sys_call_table
60	ixw     r9, syscallid
61	ldw     syscallid, (r9)
62	cmpnei  syscallid, 0
63	bf      ret_from_exception
64
65	mov     r9, sp
66	bmaski  r10, THREAD_SHIFT
67	andn    r9, r10
68	ldw     r10, (r9, TINFO_FLAGS)
69	lrw	r9, _TIF_SYSCALL_WORK
70	and	r10, r9
71	cmpnei	r10, 0
72	bt      csky_syscall_trace
73#if defined(__CSKYABIV2__)
74	subi    sp, 8
75	stw  	r5, (sp, 0x4)
76	stw  	r4, (sp, 0x0)
77	jsr     syscallid                      /* Do system call */
78	addi 	sp, 8
79#else
80	jsr     syscallid
81#endif
82	stw     a0, (sp, LSAVE_A0)      /* Save return value */
831:
84#ifdef CONFIG_DEBUG_RSEQ
85	mov	a0, sp
86	jbsr	rseq_syscall
87#endif
88	jmpi    ret_from_exception
89
90csky_syscall_trace:
91	mov	a0, sp                  /* sp = pt_regs pointer */
92	jbsr	syscall_trace_enter
93	cmpnei	a0, 0
94	bt	1f
95	/* Prepare args before do system call */
96	ldw	a0, (sp, LSAVE_A0)
97	ldw	a1, (sp, LSAVE_A1)
98	ldw	a2, (sp, LSAVE_A2)
99	ldw	a3, (sp, LSAVE_A3)
100#if defined(__CSKYABIV2__)
101	subi	sp, 8
102	ldw	r9, (sp, LSAVE_A4)
103	stw	r9, (sp, 0x0)
104	ldw	r9, (sp, LSAVE_A5)
105	stw	r9, (sp, 0x4)
106	jsr	syscallid                     /* Do system call */
107	addi	sp, 8
108#else
109	ldw	r6, (sp, LSAVE_A4)
110	ldw	r7, (sp, LSAVE_A5)
111	jsr	syscallid                     /* Do system call */
112#endif
113	stw	a0, (sp, LSAVE_A0)	/* Save return value */
114
1151:
116#ifdef CONFIG_DEBUG_RSEQ
117	mov	a0, sp
118	jbsr	rseq_syscall
119#endif
120	mov     a0, sp                  /* right now, sp --> pt_regs */
121	jbsr    syscall_trace_exit
122	br	ret_from_exception
123
124ENTRY(ret_from_kernel_thread)
125	jbsr	schedule_tail
126	mov	a0, r10
127	jsr	r9
128	jbsr	ret_from_exception
129
130ENTRY(ret_from_fork)
131	jbsr	schedule_tail
132	mov	r9, sp
133	bmaski	r10, THREAD_SHIFT
134	andn	r9, r10
135	ldw	r10, (r9, TINFO_FLAGS)
136	lrw	r9, _TIF_SYSCALL_WORK
137	and	r10, r9
138	cmpnei	r10, 0
139	bf	ret_from_exception
140	mov	a0, sp			/* sp = pt_regs pointer */
141	jbsr	syscall_trace_exit
142
143ret_from_exception:
144	psrclr	ie
145	ld	r9, (sp, LSAVE_PSR)
146	btsti	r9, 31
147
148	bt	1f
149	/*
150	 * Load address of current->thread_info, Then get address of task_struct
151	 * Get task_needreshed in task_struct
152	 */
153	mov	r9, sp
154	bmaski	r10, THREAD_SHIFT
155	andn	r9, r10
156
157	ldw	r10, (r9, TINFO_FLAGS)
158	lrw	r9, _TIF_WORK_MASK
159	and	r10, r9
160	cmpnei	r10, 0
161	bt	exit_work
162#ifdef CONFIG_CONTEXT_TRACKING
163	jbsr	context_tracking_user_enter
164#endif
1651:
166#ifdef CONFIG_PREEMPTION
167	mov	r9, sp
168	bmaski	r10, THREAD_SHIFT
169	andn	r9, r10
170
171	ldw	r10, (r9, TINFO_PREEMPT)
172	cmpnei	r10, 0
173	bt	2f
174	jbsr	preempt_schedule_irq	/* irq en/disable is done inside */
1752:
176#endif
177
178#ifdef CONFIG_TRACE_IRQFLAGS
179	ld	r10, (sp, LSAVE_PSR)
180	btsti	r10, 6
181	bf	2f
182	jbsr	trace_hardirqs_on
1832:
184#endif
185	RESTORE_ALL
186
187exit_work:
188	lrw	r9, ret_from_exception
189	mov	lr, r9
190
191	btsti	r10, TIF_NEED_RESCHED
192	bt	work_resched
193
194	psrset	ie
195	mov	a0, sp
196	mov	a1, r10
197	jmpi	do_notify_resume
198
199work_resched:
200	jmpi	schedule
201
202ENTRY(csky_trap)
203	SAVE_ALL 0
204	zero_fp
205	context_tracking
206	psrset	ee
207	mov	a0, sp                 /* Push Stack pointer arg */
208	jbsr	trap_c                 /* Call C-level trap handler */
209	jmpi	ret_from_exception
210
211/*
212 * Prototype from libc for abiv1:
213 * register unsigned int __result asm("a0");
214 * asm( "trap 3" :"=r"(__result)::);
215 */
216ENTRY(csky_get_tls)
217	USPTOKSP
218
219	RD_MEH	a0
220	WR_MEH	a0
221
222	/* increase epc for continue */
223	mfcr	a0, epc
224	addi	a0, TRAP0_SIZE
225	mtcr	a0, epc
226
227	/* get current task thread_info with kernel 8K stack */
228	bmaski	a0, THREAD_SHIFT
229	not	a0
230	subi	sp, 1
231	and	a0, sp
232	addi	sp, 1
233
234	/* get tls */
235	ldw	a0, (a0, TINFO_TP_VALUE)
236
237	KSPTOUSP
238	rte
239
240ENTRY(csky_irq)
241	SAVE_ALL 0
242	zero_fp
243	context_tracking
244	psrset	ee
245
246#ifdef CONFIG_TRACE_IRQFLAGS
247	jbsr	trace_hardirqs_off
248#endif
249
250
251	mov	a0, sp
252	jbsr	generic_handle_arch_irq
253
254	jmpi	ret_from_exception
255
256/*
257 * a0 =  prev task_struct *
258 * a1 =  next task_struct *
259 * a0 =  return next
260 */
261ENTRY(__switch_to)
262	lrw	a3, TASK_THREAD
263	addu	a3, a0
264
265	SAVE_SWITCH_STACK
266
267	stw	sp, (a3, THREAD_KSP)
268
269	/* Set up next process to run */
270	lrw	a3, TASK_THREAD
271	addu	a3, a1
272
273	ldw	sp, (a3, THREAD_KSP)	/* Set next kernel sp */
274
275#if  defined(__CSKYABIV2__)
276	addi	a3, a1, TASK_THREAD_INFO
277	ldw	tls, (a3, TINFO_TP_VALUE)
278#endif
279
280	RESTORE_SWITCH_STACK
281
282	rts
283ENDPROC(__switch_to)
284