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_USER
23 mfcr a0, epsr
24 btsti a0, 31
25 bt 1f
26 jbsr user_exit_callable
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 ret_from_exception
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 */
83 jmpi ret_from_exception
84
85csky_syscall_trace:
86 mov a0, sp /* sp = pt_regs pointer */
87 jbsr syscall_trace_enter
88 cmpnei a0, 0
89 bt 1f
90 /* Prepare args before do system call */
91 ldw a0, (sp, LSAVE_A0)
92 ldw a1, (sp, LSAVE_A1)
93 ldw a2, (sp, LSAVE_A2)
94 ldw a3, (sp, LSAVE_A3)
95#if defined(__CSKYABIV2__)
96 subi sp, 8
97 ldw r9, (sp, LSAVE_A4)
98 stw r9, (sp, 0x0)
99 ldw r9, (sp, LSAVE_A5)
100 stw r9, (sp, 0x4)
101 jsr syscallid /* Do system call */
102 addi sp, 8
103#else
104 ldw r6, (sp, LSAVE_A4)
105 ldw r7, (sp, LSAVE_A5)
106 jsr syscallid /* Do system call */
107#endif
108 stw a0, (sp, LSAVE_A0) /* Save return value */
109
1101:
111 mov a0, sp /* right now, sp --> pt_regs */
112 jbsr syscall_trace_exit
113 br ret_from_exception
114
115ENTRY(ret_from_kernel_thread)
116 jbsr schedule_tail
117 mov a0, r10
118 jsr r9
119 jbsr ret_from_exception
120
121ENTRY(ret_from_fork)
122 jbsr schedule_tail
123 mov r9, sp
124 bmaski r10, THREAD_SHIFT
125 andn r9, r10
126 ldw r10, (r9, TINFO_FLAGS)
127 lrw r9, _TIF_SYSCALL_WORK
128 and r10, r9
129 cmpnei r10, 0
130 bf ret_from_exception
131 mov a0, sp /* sp = pt_regs pointer */
132 jbsr syscall_trace_exit
133
134ret_from_exception:
135 psrclr ie
136 ld r9, (sp, LSAVE_PSR)
137 btsti r9, 31
138
139 bt 1f
140 /*
141 * Load address of current->thread_info, Then get address of task_struct
142 * Get task_needreshed in task_struct
143 */
144 mov r9, sp
145 bmaski r10, THREAD_SHIFT
146 andn r9, r10
147
148 ldw r10, (r9, TINFO_FLAGS)
149 lrw r9, _TIF_WORK_MASK
150 and r10, r9
151 cmpnei r10, 0
152 bt exit_work
153#ifdef CONFIG_CONTEXT_TRACKING_USER
154 jbsr user_enter_callable
155#endif
1561:
157#ifdef CONFIG_PREEMPTION
158 mov r9, sp
159 bmaski r10, THREAD_SHIFT
160 andn r9, r10
161
162 ldw r10, (r9, TINFO_PREEMPT)
163 cmpnei r10, 0
164 bt 2f
165 jbsr preempt_schedule_irq /* irq en/disable is done inside */
1662:
167#endif
168
169#ifdef CONFIG_TRACE_IRQFLAGS
170 ld r10, (sp, LSAVE_PSR)
171 btsti r10, 6
172 bf 2f
173 jbsr trace_hardirqs_on
1742:
175#endif
176 RESTORE_ALL
177
178exit_work:
179 lrw r9, ret_from_exception
180 mov lr, r9
181
182 btsti r10, TIF_NEED_RESCHED
183 bt work_resched
184
185 psrset ie
186 mov a0, sp
187 mov a1, r10
188 jmpi do_notify_resume
189
190work_resched:
191 jmpi schedule
192
193ENTRY(csky_trap)
194 SAVE_ALL 0
195 zero_fp
196 context_tracking
197 psrset ee
198 mov a0, sp /* Push Stack pointer arg */
199 jbsr trap_c /* Call C-level trap handler */
200 jmpi ret_from_exception
201
202/*
203 * Prototype from libc for abiv1:
204 * register unsigned int __result asm("a0");
205 * asm( "trap 3" :"=r"(__result)::);
206 */
207ENTRY(csky_get_tls)
208 USPTOKSP
209
210 RD_MEH a0
211 WR_MEH a0
212
213 /* increase epc for continue */
214 mfcr a0, epc
215 addi a0, TRAP0_SIZE
216 mtcr a0, epc
217
218 /* get current task thread_info with kernel 8K stack */
219 bmaski a0, THREAD_SHIFT
220 not a0
221 subi sp, 1
222 and a0, sp
223 addi sp, 1
224
225 /* get tls */
226 ldw a0, (a0, TINFO_TP_VALUE)
227
228 KSPTOUSP
229 rte
230
231ENTRY(csky_irq)
232 SAVE_ALL 0
233 zero_fp
234 context_tracking
235 psrset ee
236
237#ifdef CONFIG_TRACE_IRQFLAGS
238 jbsr trace_hardirqs_off
239#endif
240
241
242 mov a0, sp
243 jbsr generic_handle_arch_irq
244
245 jmpi ret_from_exception
246
247/*
248 * a0 = prev task_struct *
249 * a1 = next task_struct *
250 * a0 = return next
251 */
252ENTRY(__switch_to)
253 lrw a3, TASK_THREAD
254 addu a3, a0
255
256 SAVE_SWITCH_STACK
257
258 stw sp, (a3, THREAD_KSP)
259
260 /* Set up next process to run */
261 lrw a3, TASK_THREAD
262 addu a3, a1
263
264 ldw sp, (a3, THREAD_KSP) /* Set next kernel sp */
265
266#if defined(__CSKYABIV2__)
267 addi a3, a1, TASK_THREAD_INFO
268 ldw tls, (a3, TINFO_TP_VALUE)
269#endif
270
271 RESTORE_SWITCH_STACK
272
273 rts
274ENDPROC(__switch_to)
275

source code of linux/arch/csky/kernel/entry.S