diff options
Diffstat (limited to 'arch/c6x/kernel/entry.S')
-rw-r--r-- | arch/c6x/kernel/entry.S | 803 |
1 files changed, 803 insertions, 0 deletions
diff --git a/arch/c6x/kernel/entry.S b/arch/c6x/kernel/entry.S new file mode 100644 index 000000000000..3e977ccda827 --- /dev/null +++ b/arch/c6x/kernel/entry.S | |||
@@ -0,0 +1,803 @@ | |||
1 | ; | ||
2 | ; Port on Texas Instruments TMS320C6x architecture | ||
3 | ; | ||
4 | ; Copyright (C) 2004-2011 Texas Instruments Incorporated | ||
5 | ; Author: Aurelien Jacquiot (aurelien.jacquiot@virtuallogix.com) | ||
6 | ; Updated for 2.6.34: Mark Salter <msalter@redhat.com> | ||
7 | ; | ||
8 | ; This program is free software; you can redistribute it and/or modify | ||
9 | ; it under the terms of the GNU General Public License version 2 as | ||
10 | ; published by the Free Software Foundation. | ||
11 | ; | ||
12 | |||
13 | #include <linux/sys.h> | ||
14 | #include <linux/linkage.h> | ||
15 | #include <asm/thread_info.h> | ||
16 | #include <asm/asm-offsets.h> | ||
17 | #include <asm/unistd.h> | ||
18 | #include <asm/errno.h> | ||
19 | |||
20 | ; Registers naming | ||
21 | #define DP B14 | ||
22 | #define SP B15 | ||
23 | |||
24 | #ifndef CONFIG_PREEMPT | ||
25 | #define resume_kernel restore_all | ||
26 | #endif | ||
27 | |||
28 | .altmacro | ||
29 | |||
30 | .macro MASK_INT reg | ||
31 | MVC .S2 CSR,reg | ||
32 | CLR .S2 reg,0,0,reg | ||
33 | MVC .S2 reg,CSR | ||
34 | .endm | ||
35 | |||
36 | .macro UNMASK_INT reg | ||
37 | MVC .S2 CSR,reg | ||
38 | SET .S2 reg,0,0,reg | ||
39 | MVC .S2 reg,CSR | ||
40 | .endm | ||
41 | |||
42 | .macro GET_THREAD_INFO reg | ||
43 | SHR .S1X SP,THREAD_SHIFT,reg | ||
44 | SHL .S1 reg,THREAD_SHIFT,reg | ||
45 | .endm | ||
46 | |||
47 | ;; | ||
48 | ;; This defines the normal kernel pt_regs layout. | ||
49 | ;; | ||
50 | .macro SAVE_ALL __rp __tsr | ||
51 | STW .D2T2 B0,*SP--[2] ; save original B0 | ||
52 | MVKL .S2 current_ksp,B0 | ||
53 | MVKH .S2 current_ksp,B0 | ||
54 | LDW .D2T2 *B0,B1 ; KSP | ||
55 | |||
56 | NOP 3 | ||
57 | STW .D2T2 B1,*+SP[1] ; save original B1 | ||
58 | XOR .D2 SP,B1,B0 ; (SP ^ KSP) | ||
59 | LDW .D2T2 *+SP[1],B1 ; restore B0/B1 | ||
60 | LDW .D2T2 *++SP[2],B0 | ||
61 | SHR .S2 B0,THREAD_SHIFT,B0 ; 0 if already using kstack | ||
62 | [B0] STDW .D2T2 SP:DP,*--B1[1] ; user: save user sp/dp kstack | ||
63 | [B0] MV .S2 B1,SP ; and switch to kstack | ||
64 | ||[!B0] STDW .D2T2 SP:DP,*--SP[1] ; kernel: save on current stack | ||
65 | |||
66 | SUBAW .D2 SP,2,SP | ||
67 | |||
68 | ADD .D1X SP,-8,A15 | ||
69 | || STDW .D2T1 A15:A14,*SP--[16] ; save A15:A14 | ||
70 | |||
71 | STDW .D2T2 B13:B12,*SP--[1] | ||
72 | || STDW .D1T1 A13:A12,*A15--[1] | ||
73 | || MVC .S2 __rp,B13 | ||
74 | |||
75 | STDW .D2T2 B11:B10,*SP--[1] | ||
76 | || STDW .D1T1 A11:A10,*A15--[1] | ||
77 | || MVC .S2 CSR,B12 | ||
78 | |||
79 | STDW .D2T2 B9:B8,*SP--[1] | ||
80 | || STDW .D1T1 A9:A8,*A15--[1] | ||
81 | || MVC .S2 RILC,B11 | ||
82 | STDW .D2T2 B7:B6,*SP--[1] | ||
83 | || STDW .D1T1 A7:A6,*A15--[1] | ||
84 | || MVC .S2 ILC,B10 | ||
85 | |||
86 | STDW .D2T2 B5:B4,*SP--[1] | ||
87 | || STDW .D1T1 A5:A4,*A15--[1] | ||
88 | |||
89 | STDW .D2T2 B3:B2,*SP--[1] | ||
90 | || STDW .D1T1 A3:A2,*A15--[1] | ||
91 | || MVC .S2 __tsr,B5 | ||
92 | |||
93 | STDW .D2T2 B1:B0,*SP--[1] | ||
94 | || STDW .D1T1 A1:A0,*A15--[1] | ||
95 | || MV .S1X B5,A5 | ||
96 | |||
97 | STDW .D2T2 B31:B30,*SP--[1] | ||
98 | || STDW .D1T1 A31:A30,*A15--[1] | ||
99 | STDW .D2T2 B29:B28,*SP--[1] | ||
100 | || STDW .D1T1 A29:A28,*A15--[1] | ||
101 | STDW .D2T2 B27:B26,*SP--[1] | ||
102 | || STDW .D1T1 A27:A26,*A15--[1] | ||
103 | STDW .D2T2 B25:B24,*SP--[1] | ||
104 | || STDW .D1T1 A25:A24,*A15--[1] | ||
105 | STDW .D2T2 B23:B22,*SP--[1] | ||
106 | || STDW .D1T1 A23:A22,*A15--[1] | ||
107 | STDW .D2T2 B21:B20,*SP--[1] | ||
108 | || STDW .D1T1 A21:A20,*A15--[1] | ||
109 | STDW .D2T2 B19:B18,*SP--[1] | ||
110 | || STDW .D1T1 A19:A18,*A15--[1] | ||
111 | STDW .D2T2 B17:B16,*SP--[1] | ||
112 | || STDW .D1T1 A17:A16,*A15--[1] | ||
113 | |||
114 | STDW .D2T2 B13:B12,*SP--[1] ; save PC and CSR | ||
115 | |||
116 | STDW .D2T2 B11:B10,*SP--[1] ; save RILC and ILC | ||
117 | STDW .D2T1 A5:A4,*SP--[1] ; save TSR and orig A4 | ||
118 | |||
119 | ;; We left an unused word on the stack just above pt_regs. | ||
120 | ;; It is used to save whether or not this frame is due to | ||
121 | ;; a syscall. It is cleared here, but the syscall handler | ||
122 | ;; sets it to a non-zero value. | ||
123 | MVK .L2 0,B1 | ||
124 | STW .D2T2 B1,*+SP(REGS__END+8) ; clear syscall flag | ||
125 | .endm | ||
126 | |||
127 | .macro RESTORE_ALL __rp __tsr | ||
128 | LDDW .D2T2 *++SP[1],B9:B8 ; get TSR (B9) | ||
129 | LDDW .D2T2 *++SP[1],B11:B10 ; get RILC (B11) and ILC (B10) | ||
130 | LDDW .D2T2 *++SP[1],B13:B12 ; get PC (B13) and CSR (B12) | ||
131 | |||
132 | ADDAW .D1X SP,30,A15 | ||
133 | |||
134 | LDDW .D1T1 *++A15[1],A17:A16 | ||
135 | || LDDW .D2T2 *++SP[1],B17:B16 | ||
136 | LDDW .D1T1 *++A15[1],A19:A18 | ||
137 | || LDDW .D2T2 *++SP[1],B19:B18 | ||
138 | LDDW .D1T1 *++A15[1],A21:A20 | ||
139 | || LDDW .D2T2 *++SP[1],B21:B20 | ||
140 | LDDW .D1T1 *++A15[1],A23:A22 | ||
141 | || LDDW .D2T2 *++SP[1],B23:B22 | ||
142 | LDDW .D1T1 *++A15[1],A25:A24 | ||
143 | || LDDW .D2T2 *++SP[1],B25:B24 | ||
144 | LDDW .D1T1 *++A15[1],A27:A26 | ||
145 | || LDDW .D2T2 *++SP[1],B27:B26 | ||
146 | LDDW .D1T1 *++A15[1],A29:A28 | ||
147 | || LDDW .D2T2 *++SP[1],B29:B28 | ||
148 | LDDW .D1T1 *++A15[1],A31:A30 | ||
149 | || LDDW .D2T2 *++SP[1],B31:B30 | ||
150 | |||
151 | LDDW .D1T1 *++A15[1],A1:A0 | ||
152 | || LDDW .D2T2 *++SP[1],B1:B0 | ||
153 | |||
154 | LDDW .D1T1 *++A15[1],A3:A2 | ||
155 | || LDDW .D2T2 *++SP[1],B3:B2 | ||
156 | || MVC .S2 B9,__tsr | ||
157 | LDDW .D1T1 *++A15[1],A5:A4 | ||
158 | || LDDW .D2T2 *++SP[1],B5:B4 | ||
159 | || MVC .S2 B11,RILC | ||
160 | LDDW .D1T1 *++A15[1],A7:A6 | ||
161 | || LDDW .D2T2 *++SP[1],B7:B6 | ||
162 | || MVC .S2 B10,ILC | ||
163 | |||
164 | LDDW .D1T1 *++A15[1],A9:A8 | ||
165 | || LDDW .D2T2 *++SP[1],B9:B8 | ||
166 | || MVC .S2 B13,__rp | ||
167 | |||
168 | LDDW .D1T1 *++A15[1],A11:A10 | ||
169 | || LDDW .D2T2 *++SP[1],B11:B10 | ||
170 | || MVC .S2 B12,CSR | ||
171 | |||
172 | LDDW .D1T1 *++A15[1],A13:A12 | ||
173 | || LDDW .D2T2 *++SP[1],B13:B12 | ||
174 | |||
175 | MV .D2X A15,SP | ||
176 | || MVKL .S1 current_ksp,A15 | ||
177 | MVKH .S1 current_ksp,A15 | ||
178 | || ADDAW .D1X SP,6,A14 | ||
179 | STW .D1T1 A14,*A15 ; save kernel stack pointer | ||
180 | |||
181 | LDDW .D2T1 *++SP[1],A15:A14 | ||
182 | |||
183 | B .S2 __rp ; return from interruption | ||
184 | LDDW .D2T2 *+SP[1],SP:DP | ||
185 | NOP 4 | ||
186 | .endm | ||
187 | |||
188 | .section .text | ||
189 | |||
190 | ;; | ||
191 | ;; Jump to schedule() then return to ret_from_exception | ||
192 | ;; | ||
193 | _reschedule: | ||
194 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
195 | MVKL .S1 schedule,A0 | ||
196 | MVKH .S1 schedule,A0 | ||
197 | B .S2X A0 | ||
198 | #else | ||
199 | B .S1 schedule | ||
200 | #endif | ||
201 | ADDKPC .S2 ret_from_exception,B3,4 | ||
202 | |||
203 | ;; | ||
204 | ;; Called before syscall handler when process is being debugged | ||
205 | ;; | ||
206 | tracesys_on: | ||
207 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
208 | MVKL .S1 syscall_trace_entry,A0 | ||
209 | MVKH .S1 syscall_trace_entry,A0 | ||
210 | B .S2X A0 | ||
211 | #else | ||
212 | B .S1 syscall_trace_entry | ||
213 | #endif | ||
214 | ADDKPC .S2 ret_from_syscall_trace,B3,3 | ||
215 | ADD .S1X 8,SP,A4 | ||
216 | |||
217 | ret_from_syscall_trace: | ||
218 | ;; tracing returns (possibly new) syscall number | ||
219 | MV .D2X A4,B0 | ||
220 | || MVK .S2 __NR_syscalls,B1 | ||
221 | CMPLTU .L2 B0,B1,B1 | ||
222 | |||
223 | [!B1] BNOP .S2 ret_from_syscall_function,5 | ||
224 | || MVK .S1 -ENOSYS,A4 | ||
225 | |||
226 | ;; reload syscall args from (possibly modified) stack frame | ||
227 | ;; and get syscall handler addr from sys_call_table: | ||
228 | LDW .D2T2 *+SP(REGS_B4+8),B4 | ||
229 | || MVKL .S2 sys_call_table,B1 | ||
230 | LDW .D2T1 *+SP(REGS_A6+8),A6 | ||
231 | || MVKH .S2 sys_call_table,B1 | ||
232 | LDW .D2T2 *+B1[B0],B0 | ||
233 | || MVKL .S2 ret_from_syscall_function,B3 | ||
234 | LDW .D2T2 *+SP(REGS_B6+8),B6 | ||
235 | || MVKH .S2 ret_from_syscall_function,B3 | ||
236 | LDW .D2T1 *+SP(REGS_A8+8),A8 | ||
237 | LDW .D2T2 *+SP(REGS_B8+8),B8 | ||
238 | NOP | ||
239 | ; B0 = sys_call_table[__NR_*] | ||
240 | BNOP .S2 B0,5 ; branch to syscall handler | ||
241 | || LDW .D2T1 *+SP(REGS_ORIG_A4+8),A4 | ||
242 | |||
243 | syscall_exit_work: | ||
244 | AND .D1 _TIF_SYSCALL_TRACE,A2,A0 | ||
245 | [!A0] BNOP .S1 work_pending,5 | ||
246 | [A0] B .S2 syscall_trace_exit | ||
247 | ADDKPC .S2 resume_userspace,B3,1 | ||
248 | MVC .S2 CSR,B1 | ||
249 | SET .S2 B1,0,0,B1 | ||
250 | MVC .S2 B1,CSR ; enable ints | ||
251 | |||
252 | work_pending: | ||
253 | AND .D1 _TIF_NEED_RESCHED,A2,A0 | ||
254 | [!A0] BNOP .S1 work_notifysig,5 | ||
255 | |||
256 | work_resched: | ||
257 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
258 | MVKL .S1 schedule,A1 | ||
259 | MVKH .S1 schedule,A1 | ||
260 | B .S2X A1 | ||
261 | #else | ||
262 | B .S2 schedule | ||
263 | #endif | ||
264 | ADDKPC .S2 work_rescheduled,B3,4 | ||
265 | work_rescheduled: | ||
266 | ;; make sure we don't miss an interrupt setting need_resched or | ||
267 | ;; sigpending between sampling and the rti | ||
268 | MASK_INT B2 | ||
269 | GET_THREAD_INFO A12 | ||
270 | LDW .D1T1 *+A12(THREAD_INFO_FLAGS),A2 | ||
271 | MVK .S1 _TIF_WORK_MASK,A1 | ||
272 | MVK .S1 _TIF_NEED_RESCHED,A3 | ||
273 | NOP 2 | ||
274 | AND .D1 A1,A2,A0 | ||
275 | || AND .S1 A3,A2,A1 | ||
276 | [!A0] BNOP .S1 restore_all,5 | ||
277 | [A1] BNOP .S1 work_resched,5 | ||
278 | |||
279 | work_notifysig: | ||
280 | B .S2 do_notify_resume | ||
281 | LDW .D2T1 *+SP(REGS__END+8),A6 ; syscall flag | ||
282 | ADDKPC .S2 resume_userspace,B3,1 | ||
283 | ADD .S1X 8,SP,A4 ; pt_regs pointer is first arg | ||
284 | MV .D2X A2,B4 ; thread_info flags is second arg | ||
285 | |||
286 | ;; | ||
287 | ;; On C64x+, the return way from exception and interrupt | ||
288 | ;; is a little bit different | ||
289 | ;; | ||
290 | ENTRY(ret_from_exception) | ||
291 | #ifdef CONFIG_PREEMPT | ||
292 | MASK_INT B2 | ||
293 | #endif | ||
294 | |||
295 | ENTRY(ret_from_interrupt) | ||
296 | ;; | ||
297 | ;; Check if we are comming from user mode. | ||
298 | ;; | ||
299 | LDW .D2T2 *+SP(REGS_TSR+8),B0 | ||
300 | MVK .S2 0x40,B1 | ||
301 | NOP 3 | ||
302 | AND .D2 B0,B1,B0 | ||
303 | [!B0] BNOP .S2 resume_kernel,5 | ||
304 | |||
305 | resume_userspace: | ||
306 | ;; make sure we don't miss an interrupt setting need_resched or | ||
307 | ;; sigpending between sampling and the rti | ||
308 | MASK_INT B2 | ||
309 | GET_THREAD_INFO A12 | ||
310 | LDW .D1T1 *+A12(THREAD_INFO_FLAGS),A2 | ||
311 | MVK .S1 _TIF_WORK_MASK,A1 | ||
312 | MVK .S1 _TIF_NEED_RESCHED,A3 | ||
313 | NOP 2 | ||
314 | AND .D1 A1,A2,A0 | ||
315 | [A0] BNOP .S1 work_pending,5 | ||
316 | BNOP .S1 restore_all,5 | ||
317 | |||
318 | ;; | ||
319 | ;; System call handling | ||
320 | ;; B0 = syscall number (in sys_call_table) | ||
321 | ;; A4,B4,A6,B6,A8,B8 = arguments of the syscall function | ||
322 | ;; A4 is the return value register | ||
323 | ;; | ||
324 | system_call_saved: | ||
325 | MVK .L2 1,B2 | ||
326 | STW .D2T2 B2,*+SP(REGS__END+8) ; set syscall flag | ||
327 | MVC .S2 B2,ECR ; ack the software exception | ||
328 | |||
329 | UNMASK_INT B2 ; re-enable global IT | ||
330 | |||
331 | system_call_saved_noack: | ||
332 | ;; Check system call number | ||
333 | MVK .S2 __NR_syscalls,B1 | ||
334 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
335 | || MVKL .S1 sys_ni_syscall,A0 | ||
336 | #endif | ||
337 | CMPLTU .L2 B0,B1,B1 | ||
338 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
339 | || MVKH .S1 sys_ni_syscall,A0 | ||
340 | #endif | ||
341 | |||
342 | ;; Check for ptrace | ||
343 | GET_THREAD_INFO A12 | ||
344 | |||
345 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
346 | [!B1] B .S2X A0 | ||
347 | #else | ||
348 | [!B1] B .S2 sys_ni_syscall | ||
349 | #endif | ||
350 | [!B1] ADDKPC .S2 ret_from_syscall_function,B3,4 | ||
351 | |||
352 | ;; Get syscall handler addr from sys_call_table | ||
353 | ;; call tracesys_on or call syscall handler | ||
354 | LDW .D1T1 *+A12(THREAD_INFO_FLAGS),A2 | ||
355 | || MVKL .S2 sys_call_table,B1 | ||
356 | MVKH .S2 sys_call_table,B1 | ||
357 | LDW .D2T2 *+B1[B0],B0 | ||
358 | NOP 2 | ||
359 | ; A2 = thread_info flags | ||
360 | AND .D1 _TIF_SYSCALL_TRACE,A2,A2 | ||
361 | [A2] BNOP .S1 tracesys_on,5 | ||
362 | ;; B0 = _sys_call_table[__NR_*] | ||
363 | B .S2 B0 | ||
364 | ADDKPC .S2 ret_from_syscall_function,B3,4 | ||
365 | |||
366 | ret_from_syscall_function: | ||
367 | STW .D2T1 A4,*+SP(REGS_A4+8) ; save return value in A4 | ||
368 | ; original A4 is in orig_A4 | ||
369 | syscall_exit: | ||
370 | ;; make sure we don't miss an interrupt setting need_resched or | ||
371 | ;; sigpending between sampling and the rti | ||
372 | MASK_INT B2 | ||
373 | LDW .D1T1 *+A12(THREAD_INFO_FLAGS),A2 | ||
374 | MVK .S1 _TIF_ALLWORK_MASK,A1 | ||
375 | NOP 3 | ||
376 | AND .D1 A1,A2,A2 ; check for work to do | ||
377 | [A2] BNOP .S1 syscall_exit_work,5 | ||
378 | |||
379 | restore_all: | ||
380 | RESTORE_ALL NRP,NTSR | ||
381 | |||
382 | ;; | ||
383 | ;; After a fork we jump here directly from resume, | ||
384 | ;; so that A4 contains the previous task structure. | ||
385 | ;; | ||
386 | ENTRY(ret_from_fork) | ||
387 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
388 | MVKL .S1 schedule_tail,A0 | ||
389 | MVKH .S1 schedule_tail,A0 | ||
390 | B .S2X A0 | ||
391 | #else | ||
392 | B .S2 schedule_tail | ||
393 | #endif | ||
394 | ADDKPC .S2 ret_from_fork_2,B3,4 | ||
395 | ret_from_fork_2: | ||
396 | ;; return 0 in A4 for child process | ||
397 | GET_THREAD_INFO A12 | ||
398 | BNOP .S2 syscall_exit,3 | ||
399 | MVK .L2 0,B0 | ||
400 | STW .D2T2 B0,*+SP(REGS_A4+8) | ||
401 | ENDPROC(ret_from_fork) | ||
402 | |||
403 | ;; | ||
404 | ;; These are the interrupt handlers, responsible for calling __do_IRQ() | ||
405 | ;; int6 is used for syscalls (see _system_call entry) | ||
406 | ;; | ||
407 | .macro SAVE_ALL_INT | ||
408 | SAVE_ALL IRP,ITSR | ||
409 | .endm | ||
410 | |||
411 | .macro CALL_INT int | ||
412 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
413 | MVKL .S1 c6x_do_IRQ,A0 | ||
414 | MVKH .S1 c6x_do_IRQ,A0 | ||
415 | BNOP .S2X A0,1 | ||
416 | MVK .S1 int,A4 | ||
417 | ADDAW .D2 SP,2,B4 | ||
418 | MVKL .S2 ret_from_interrupt,B3 | ||
419 | MVKH .S2 ret_from_interrupt,B3 | ||
420 | #else | ||
421 | CALLP .S2 c6x_do_IRQ,B3 | ||
422 | || MVK .S1 int,A4 | ||
423 | || ADDAW .D2 SP,2,B4 | ||
424 | B .S1 ret_from_interrupt | ||
425 | NOP 5 | ||
426 | #endif | ||
427 | .endm | ||
428 | |||
429 | ENTRY(_int4_handler) | ||
430 | SAVE_ALL_INT | ||
431 | CALL_INT 4 | ||
432 | ENDPROC(_int4_handler) | ||
433 | |||
434 | ENTRY(_int5_handler) | ||
435 | SAVE_ALL_INT | ||
436 | CALL_INT 5 | ||
437 | ENDPROC(_int5_handler) | ||
438 | |||
439 | ENTRY(_int6_handler) | ||
440 | SAVE_ALL_INT | ||
441 | CALL_INT 6 | ||
442 | ENDPROC(_int6_handler) | ||
443 | |||
444 | ENTRY(_int7_handler) | ||
445 | SAVE_ALL_INT | ||
446 | CALL_INT 7 | ||
447 | ENDPROC(_int7_handler) | ||
448 | |||
449 | ENTRY(_int8_handler) | ||
450 | SAVE_ALL_INT | ||
451 | CALL_INT 8 | ||
452 | ENDPROC(_int8_handler) | ||
453 | |||
454 | ENTRY(_int9_handler) | ||
455 | SAVE_ALL_INT | ||
456 | CALL_INT 9 | ||
457 | ENDPROC(_int9_handler) | ||
458 | |||
459 | ENTRY(_int10_handler) | ||
460 | SAVE_ALL_INT | ||
461 | CALL_INT 10 | ||
462 | ENDPROC(_int10_handler) | ||
463 | |||
464 | ENTRY(_int11_handler) | ||
465 | SAVE_ALL_INT | ||
466 | CALL_INT 11 | ||
467 | ENDPROC(_int11_handler) | ||
468 | |||
469 | ENTRY(_int12_handler) | ||
470 | SAVE_ALL_INT | ||
471 | CALL_INT 12 | ||
472 | ENDPROC(_int12_handler) | ||
473 | |||
474 | ENTRY(_int13_handler) | ||
475 | SAVE_ALL_INT | ||
476 | CALL_INT 13 | ||
477 | ENDPROC(_int13_handler) | ||
478 | |||
479 | ENTRY(_int14_handler) | ||
480 | SAVE_ALL_INT | ||
481 | CALL_INT 14 | ||
482 | ENDPROC(_int14_handler) | ||
483 | |||
484 | ENTRY(_int15_handler) | ||
485 | SAVE_ALL_INT | ||
486 | CALL_INT 15 | ||
487 | ENDPROC(_int15_handler) | ||
488 | |||
489 | ;; | ||
490 | ;; Handler for uninitialized and spurious interrupts | ||
491 | ;; | ||
492 | ENTRY(_bad_interrupt) | ||
493 | B .S2 IRP | ||
494 | NOP 5 | ||
495 | ENDPROC(_bad_interrupt) | ||
496 | |||
497 | ;; | ||
498 | ;; Entry for NMI/exceptions/syscall | ||
499 | ;; | ||
500 | ENTRY(_nmi_handler) | ||
501 | SAVE_ALL NRP,NTSR | ||
502 | |||
503 | MVC .S2 EFR,B2 | ||
504 | CMPEQ .L2 1,B2,B2 | ||
505 | || MVC .S2 TSR,B1 | ||
506 | CLR .S2 B1,10,10,B1 | ||
507 | MVC .S2 B1,TSR | ||
508 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
509 | [!B2] MVKL .S1 process_exception,A0 | ||
510 | [!B2] MVKH .S1 process_exception,A0 | ||
511 | [!B2] B .S2X A0 | ||
512 | #else | ||
513 | [!B2] B .S2 process_exception | ||
514 | #endif | ||
515 | [B2] B .S2 system_call_saved | ||
516 | [!B2] ADDAW .D2 SP,2,B1 | ||
517 | [!B2] MV .D1X B1,A4 | ||
518 | ADDKPC .S2 ret_from_trap,B3,2 | ||
519 | |||
520 | ret_from_trap: | ||
521 | MV .D2X A4,B0 | ||
522 | [!B0] BNOP .S2 ret_from_exception,5 | ||
523 | |||
524 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
525 | MVKL .S2 system_call_saved_noack,B3 | ||
526 | MVKH .S2 system_call_saved_noack,B3 | ||
527 | #endif | ||
528 | LDW .D2T2 *+SP(REGS_B0+8),B0 | ||
529 | LDW .D2T1 *+SP(REGS_A4+8),A4 | ||
530 | LDW .D2T2 *+SP(REGS_B4+8),B4 | ||
531 | LDW .D2T1 *+SP(REGS_A6+8),A6 | ||
532 | LDW .D2T2 *+SP(REGS_B6+8),B6 | ||
533 | LDW .D2T1 *+SP(REGS_A8+8),A8 | ||
534 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
535 | || B .S2 B3 | ||
536 | #else | ||
537 | || B .S2 system_call_saved_noack | ||
538 | #endif | ||
539 | LDW .D2T2 *+SP(REGS_B8+8),B8 | ||
540 | NOP 4 | ||
541 | ENDPROC(_nmi_handler) | ||
542 | |||
543 | ;; | ||
544 | ;; Jump to schedule() then return to ret_from_isr | ||
545 | ;; | ||
546 | #ifdef CONFIG_PREEMPT | ||
547 | resume_kernel: | ||
548 | GET_THREAD_INFO A12 | ||
549 | LDW .D1T1 *+A12(THREAD_INFO_PREEMPT_COUNT),A1 | ||
550 | NOP 4 | ||
551 | [A1] BNOP .S2 restore_all,5 | ||
552 | |||
553 | preempt_schedule: | ||
554 | GET_THREAD_INFO A2 | ||
555 | LDW .D1T1 *+A2(THREAD_INFO_FLAGS),A1 | ||
556 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
557 | MVKL .S2 preempt_schedule_irq,B0 | ||
558 | MVKH .S2 preempt_schedule_irq,B0 | ||
559 | NOP 2 | ||
560 | #else | ||
561 | NOP 4 | ||
562 | #endif | ||
563 | AND .D1 _TIF_NEED_RESCHED,A1,A1 | ||
564 | [!A1] BNOP .S2 restore_all,5 | ||
565 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
566 | B .S2 B0 | ||
567 | #else | ||
568 | B .S2 preempt_schedule_irq | ||
569 | #endif | ||
570 | ADDKPC .S2 preempt_schedule,B3,4 | ||
571 | #endif /* CONFIG_PREEMPT */ | ||
572 | |||
573 | ENTRY(enable_exception) | ||
574 | DINT | ||
575 | MVC .S2 TSR,B0 | ||
576 | MVC .S2 B3,NRP | ||
577 | MVK .L2 0xc,B1 | ||
578 | OR .D2 B0,B1,B0 | ||
579 | MVC .S2 B0,TSR ; Set GEE and XEN in TSR | ||
580 | B .S2 NRP | ||
581 | NOP 5 | ||
582 | ENDPROC(enable_exception) | ||
583 | |||
584 | ENTRY(sys_sigaltstack) | ||
585 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
586 | MVKL .S1 do_sigaltstack,A0 ; branch to do_sigaltstack | ||
587 | MVKH .S1 do_sigaltstack,A0 | ||
588 | B .S2X A0 | ||
589 | #else | ||
590 | B .S2 do_sigaltstack | ||
591 | #endif | ||
592 | LDW .D2T1 *+SP(REGS_SP+8),A6 | ||
593 | NOP 4 | ||
594 | ENDPROC(sys_sigaltstack) | ||
595 | |||
596 | ;; kernel_execve | ||
597 | ENTRY(kernel_execve) | ||
598 | MVK .S2 __NR_execve,B0 | ||
599 | SWE | ||
600 | BNOP .S2 B3,5 | ||
601 | ENDPROC(kernel_execve) | ||
602 | |||
603 | ;; | ||
604 | ;; Special system calls | ||
605 | ;; return address is in B3 | ||
606 | ;; | ||
607 | ENTRY(sys_clone) | ||
608 | ADD .D1X SP,8,A4 | ||
609 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
610 | || MVKL .S1 sys_c6x_clone,A0 | ||
611 | MVKH .S1 sys_c6x_clone,A0 | ||
612 | BNOP .S2X A0,5 | ||
613 | #else | ||
614 | || B .S2 sys_c6x_clone | ||
615 | NOP 5 | ||
616 | #endif | ||
617 | ENDPROC(sys_clone) | ||
618 | |||
619 | ENTRY(sys_rt_sigreturn) | ||
620 | ADD .D1X SP,8,A4 | ||
621 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
622 | || MVKL .S1 do_rt_sigreturn,A0 | ||
623 | MVKH .S1 do_rt_sigreturn,A0 | ||
624 | BNOP .S2X A0,5 | ||
625 | #else | ||
626 | || B .S2 do_rt_sigreturn | ||
627 | NOP 5 | ||
628 | #endif | ||
629 | ENDPROC(sys_rt_sigreturn) | ||
630 | |||
631 | ENTRY(sys_execve) | ||
632 | ADDAW .D2 SP,2,B6 ; put regs addr in 4th parameter | ||
633 | ; & adjust regs stack addr | ||
634 | LDW .D2T2 *+SP(REGS_B4+8),B4 | ||
635 | |||
636 | ;; c6x_execve(char *name, char **argv, | ||
637 | ;; char **envp, struct pt_regs *regs) | ||
638 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
639 | || MVKL .S1 sys_c6x_execve,A0 | ||
640 | MVKH .S1 sys_c6x_execve,A0 | ||
641 | B .S2X A0 | ||
642 | #else | ||
643 | || B .S2 sys_c6x_execve | ||
644 | #endif | ||
645 | STW .D2T2 B3,*SP--[2] | ||
646 | ADDKPC .S2 ret_from_c6x_execve,B3,3 | ||
647 | |||
648 | ret_from_c6x_execve: | ||
649 | LDW .D2T2 *++SP[2],B3 | ||
650 | NOP 4 | ||
651 | BNOP .S2 B3,5 | ||
652 | ENDPROC(sys_execve) | ||
653 | |||
654 | ENTRY(sys_pread_c6x) | ||
655 | MV .D2X A8,B7 | ||
656 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
657 | || MVKL .S1 sys_pread64,A0 | ||
658 | MVKH .S1 sys_pread64,A0 | ||
659 | BNOP .S2X A0,5 | ||
660 | #else | ||
661 | || B .S2 sys_pread64 | ||
662 | NOP 5 | ||
663 | #endif | ||
664 | ENDPROC(sys_pread_c6x) | ||
665 | |||
666 | ENTRY(sys_pwrite_c6x) | ||
667 | MV .D2X A8,B7 | ||
668 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
669 | || MVKL .S1 sys_pwrite64,A0 | ||
670 | MVKH .S1 sys_pwrite64,A0 | ||
671 | BNOP .S2X A0,5 | ||
672 | #else | ||
673 | || B .S2 sys_pwrite64 | ||
674 | NOP 5 | ||
675 | #endif | ||
676 | ENDPROC(sys_pwrite_c6x) | ||
677 | |||
678 | ;; On Entry | ||
679 | ;; A4 - path | ||
680 | ;; B4 - offset_lo (LE), offset_hi (BE) | ||
681 | ;; A6 - offset_lo (BE), offset_hi (LE) | ||
682 | ENTRY(sys_truncate64_c6x) | ||
683 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
684 | MV .S2 B4,B5 | ||
685 | MV .D2X A6,B4 | ||
686 | #else | ||
687 | MV .D2X A6,B5 | ||
688 | #endif | ||
689 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
690 | || MVKL .S1 sys_truncate64,A0 | ||
691 | MVKH .S1 sys_truncate64,A0 | ||
692 | BNOP .S2X A0,5 | ||
693 | #else | ||
694 | || B .S2 sys_truncate64 | ||
695 | NOP 5 | ||
696 | #endif | ||
697 | ENDPROC(sys_truncate64_c6x) | ||
698 | |||
699 | ;; On Entry | ||
700 | ;; A4 - fd | ||
701 | ;; B4 - offset_lo (LE), offset_hi (BE) | ||
702 | ;; A6 - offset_lo (BE), offset_hi (LE) | ||
703 | ENTRY(sys_ftruncate64_c6x) | ||
704 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
705 | MV .S2 B4,B5 | ||
706 | MV .D2X A6,B4 | ||
707 | #else | ||
708 | MV .D2X A6,B5 | ||
709 | #endif | ||
710 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
711 | || MVKL .S1 sys_ftruncate64,A0 | ||
712 | MVKH .S1 sys_ftruncate64,A0 | ||
713 | BNOP .S2X A0,5 | ||
714 | #else | ||
715 | || B .S2 sys_ftruncate64 | ||
716 | NOP 5 | ||
717 | #endif | ||
718 | ENDPROC(sys_ftruncate64_c6x) | ||
719 | |||
720 | #ifdef __ARCH_WANT_SYSCALL_OFF_T | ||
721 | ;; On Entry | ||
722 | ;; A4 - fd | ||
723 | ;; B4 - offset_lo (LE), offset_hi (BE) | ||
724 | ;; A6 - offset_lo (BE), offset_hi (LE) | ||
725 | ;; B6 - len | ||
726 | ;; A8 - advice | ||
727 | ENTRY(sys_fadvise64_c6x) | ||
728 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
729 | MVKL .S1 sys_fadvise64,A0 | ||
730 | MVKH .S1 sys_fadvise64,A0 | ||
731 | BNOP .S2X A0,2 | ||
732 | #else | ||
733 | B .S2 sys_fadvise64 | ||
734 | NOP 2 | ||
735 | #endif | ||
736 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
737 | MV .L2 B4,B5 | ||
738 | || MV .D2X A6,B4 | ||
739 | #else | ||
740 | MV .D2X A6,B5 | ||
741 | #endif | ||
742 | MV .D1X B6,A6 | ||
743 | MV .D2X A8,B6 | ||
744 | #endif | ||
745 | ENDPROC(sys_fadvise64_c6x) | ||
746 | |||
747 | ;; On Entry | ||
748 | ;; A4 - fd | ||
749 | ;; B4 - offset_lo (LE), offset_hi (BE) | ||
750 | ;; A6 - offset_lo (BE), offset_hi (LE) | ||
751 | ;; B6 - len_lo (LE), len_hi (BE) | ||
752 | ;; A8 - len_lo (BE), len_hi (LE) | ||
753 | ;; B8 - advice | ||
754 | ENTRY(sys_fadvise64_64_c6x) | ||
755 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
756 | MVKL .S1 sys_fadvise64_64,A0 | ||
757 | MVKH .S1 sys_fadvise64_64,A0 | ||
758 | BNOP .S2X A0,2 | ||
759 | #else | ||
760 | B .S2 sys_fadvise64_64 | ||
761 | NOP 2 | ||
762 | #endif | ||
763 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
764 | MV .L2 B4,B5 | ||
765 | || MV .D2X A6,B4 | ||
766 | MV .L1 A8,A6 | ||
767 | || MV .D1X B6,A7 | ||
768 | #else | ||
769 | MV .D2X A6,B5 | ||
770 | MV .L1 A8,A7 | ||
771 | || MV .D1X B6,A6 | ||
772 | #endif | ||
773 | MV .L2 B8,B6 | ||
774 | ENDPROC(sys_fadvise64_64_c6x) | ||
775 | |||
776 | ;; On Entry | ||
777 | ;; A4 - fd | ||
778 | ;; B4 - mode | ||
779 | ;; A6 - offset_hi | ||
780 | ;; B6 - offset_lo | ||
781 | ;; A8 - len_hi | ||
782 | ;; B8 - len_lo | ||
783 | ENTRY(sys_fallocate_c6x) | ||
784 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
785 | MVKL .S1 sys_fallocate,A0 | ||
786 | MVKH .S1 sys_fallocate,A0 | ||
787 | BNOP .S2X A0,1 | ||
788 | #else | ||
789 | B .S2 sys_fallocate | ||
790 | NOP | ||
791 | #endif | ||
792 | MV .D1 A6,A7 | ||
793 | MV .D1X B6,A6 | ||
794 | MV .D2X A8,B7 | ||
795 | MV .D2 B8,B6 | ||
796 | ENDPROC(sys_fallocate_c6x) | ||
797 | |||
798 | ;; put this in .neardata for faster access when using DSBT mode | ||
799 | .section .neardata,"aw",@progbits | ||
800 | .global current_ksp | ||
801 | .hidden current_ksp | ||
802 | current_ksp: | ||
803 | .word init_thread_union + THREAD_START_SP | ||