]>
Commit | Line | Data |
---|---|---|
e94e6682 AJ |
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 | ||
46f15067 MS |
403 | ENTRY(ret_from_kernel_thread) |
404 | #ifdef CONFIG_C6X_BIG_KERNEL | |
405 | MVKL .S1 schedule_tail,A0 | |
406 | MVKH .S1 schedule_tail,A0 | |
407 | B .S2X A0 | |
408 | #else | |
409 | B .S2 schedule_tail | |
410 | #endif | |
411 | LDW .D2T2 *+SP(REGS_A0+8),B10 /* get fn */ | |
412 | ADDKPC .S2 0f,B3,3 | |
413 | 0: | |
414 | B .S2 B10 /* call fn */ | |
415 | LDW .D2T1 *+SP(REGS_A1+8),A4 /* get arg */ | |
416 | MVKL .S2 sys_exit,B11 | |
417 | MVKH .S2 sys_exit,B11 | |
418 | ADDKPC .S2 0f,B3,1 | |
419 | 0: | |
420 | BNOP .S2 B11,5 /* jump to sys_exit */ | |
421 | ENDPROC(ret_from_kernel_thread) | |
422 | ||
e94e6682 AJ |
423 | ;; |
424 | ;; These are the interrupt handlers, responsible for calling __do_IRQ() | |
425 | ;; int6 is used for syscalls (see _system_call entry) | |
426 | ;; | |
427 | .macro SAVE_ALL_INT | |
428 | SAVE_ALL IRP,ITSR | |
429 | .endm | |
430 | ||
431 | .macro CALL_INT int | |
432 | #ifdef CONFIG_C6X_BIG_KERNEL | |
433 | MVKL .S1 c6x_do_IRQ,A0 | |
434 | MVKH .S1 c6x_do_IRQ,A0 | |
435 | BNOP .S2X A0,1 | |
436 | MVK .S1 int,A4 | |
437 | ADDAW .D2 SP,2,B4 | |
438 | MVKL .S2 ret_from_interrupt,B3 | |
439 | MVKH .S2 ret_from_interrupt,B3 | |
440 | #else | |
441 | CALLP .S2 c6x_do_IRQ,B3 | |
442 | || MVK .S1 int,A4 | |
443 | || ADDAW .D2 SP,2,B4 | |
444 | B .S1 ret_from_interrupt | |
445 | NOP 5 | |
446 | #endif | |
447 | .endm | |
448 | ||
449 | ENTRY(_int4_handler) | |
450 | SAVE_ALL_INT | |
451 | CALL_INT 4 | |
452 | ENDPROC(_int4_handler) | |
453 | ||
454 | ENTRY(_int5_handler) | |
455 | SAVE_ALL_INT | |
456 | CALL_INT 5 | |
457 | ENDPROC(_int5_handler) | |
458 | ||
459 | ENTRY(_int6_handler) | |
460 | SAVE_ALL_INT | |
461 | CALL_INT 6 | |
462 | ENDPROC(_int6_handler) | |
463 | ||
464 | ENTRY(_int7_handler) | |
465 | SAVE_ALL_INT | |
466 | CALL_INT 7 | |
467 | ENDPROC(_int7_handler) | |
468 | ||
469 | ENTRY(_int8_handler) | |
470 | SAVE_ALL_INT | |
471 | CALL_INT 8 | |
472 | ENDPROC(_int8_handler) | |
473 | ||
474 | ENTRY(_int9_handler) | |
475 | SAVE_ALL_INT | |
476 | CALL_INT 9 | |
477 | ENDPROC(_int9_handler) | |
478 | ||
479 | ENTRY(_int10_handler) | |
480 | SAVE_ALL_INT | |
481 | CALL_INT 10 | |
482 | ENDPROC(_int10_handler) | |
483 | ||
484 | ENTRY(_int11_handler) | |
485 | SAVE_ALL_INT | |
486 | CALL_INT 11 | |
487 | ENDPROC(_int11_handler) | |
488 | ||
489 | ENTRY(_int12_handler) | |
490 | SAVE_ALL_INT | |
491 | CALL_INT 12 | |
492 | ENDPROC(_int12_handler) | |
493 | ||
494 | ENTRY(_int13_handler) | |
495 | SAVE_ALL_INT | |
496 | CALL_INT 13 | |
497 | ENDPROC(_int13_handler) | |
498 | ||
499 | ENTRY(_int14_handler) | |
500 | SAVE_ALL_INT | |
501 | CALL_INT 14 | |
502 | ENDPROC(_int14_handler) | |
503 | ||
504 | ENTRY(_int15_handler) | |
505 | SAVE_ALL_INT | |
506 | CALL_INT 15 | |
507 | ENDPROC(_int15_handler) | |
508 | ||
509 | ;; | |
510 | ;; Handler for uninitialized and spurious interrupts | |
511 | ;; | |
512 | ENTRY(_bad_interrupt) | |
513 | B .S2 IRP | |
514 | NOP 5 | |
515 | ENDPROC(_bad_interrupt) | |
516 | ||
517 | ;; | |
518 | ;; Entry for NMI/exceptions/syscall | |
519 | ;; | |
520 | ENTRY(_nmi_handler) | |
521 | SAVE_ALL NRP,NTSR | |
522 | ||
523 | MVC .S2 EFR,B2 | |
524 | CMPEQ .L2 1,B2,B2 | |
525 | || MVC .S2 TSR,B1 | |
526 | CLR .S2 B1,10,10,B1 | |
527 | MVC .S2 B1,TSR | |
528 | #ifdef CONFIG_C6X_BIG_KERNEL | |
529 | [!B2] MVKL .S1 process_exception,A0 | |
530 | [!B2] MVKH .S1 process_exception,A0 | |
531 | [!B2] B .S2X A0 | |
532 | #else | |
533 | [!B2] B .S2 process_exception | |
534 | #endif | |
535 | [B2] B .S2 system_call_saved | |
536 | [!B2] ADDAW .D2 SP,2,B1 | |
537 | [!B2] MV .D1X B1,A4 | |
538 | ADDKPC .S2 ret_from_trap,B3,2 | |
539 | ||
540 | ret_from_trap: | |
541 | MV .D2X A4,B0 | |
542 | [!B0] BNOP .S2 ret_from_exception,5 | |
543 | ||
544 | #ifdef CONFIG_C6X_BIG_KERNEL | |
545 | MVKL .S2 system_call_saved_noack,B3 | |
546 | MVKH .S2 system_call_saved_noack,B3 | |
547 | #endif | |
548 | LDW .D2T2 *+SP(REGS_B0+8),B0 | |
549 | LDW .D2T1 *+SP(REGS_A4+8),A4 | |
550 | LDW .D2T2 *+SP(REGS_B4+8),B4 | |
551 | LDW .D2T1 *+SP(REGS_A6+8),A6 | |
552 | LDW .D2T2 *+SP(REGS_B6+8),B6 | |
553 | LDW .D2T1 *+SP(REGS_A8+8),A8 | |
554 | #ifdef CONFIG_C6X_BIG_KERNEL | |
555 | || B .S2 B3 | |
556 | #else | |
557 | || B .S2 system_call_saved_noack | |
558 | #endif | |
559 | LDW .D2T2 *+SP(REGS_B8+8),B8 | |
560 | NOP 4 | |
561 | ENDPROC(_nmi_handler) | |
562 | ||
563 | ;; | |
564 | ;; Jump to schedule() then return to ret_from_isr | |
565 | ;; | |
566 | #ifdef CONFIG_PREEMPT | |
567 | resume_kernel: | |
568 | GET_THREAD_INFO A12 | |
569 | LDW .D1T1 *+A12(THREAD_INFO_PREEMPT_COUNT),A1 | |
570 | NOP 4 | |
571 | [A1] BNOP .S2 restore_all,5 | |
572 | ||
573 | preempt_schedule: | |
574 | GET_THREAD_INFO A2 | |
575 | LDW .D1T1 *+A2(THREAD_INFO_FLAGS),A1 | |
576 | #ifdef CONFIG_C6X_BIG_KERNEL | |
577 | MVKL .S2 preempt_schedule_irq,B0 | |
578 | MVKH .S2 preempt_schedule_irq,B0 | |
579 | NOP 2 | |
580 | #else | |
581 | NOP 4 | |
582 | #endif | |
583 | AND .D1 _TIF_NEED_RESCHED,A1,A1 | |
584 | [!A1] BNOP .S2 restore_all,5 | |
585 | #ifdef CONFIG_C6X_BIG_KERNEL | |
586 | B .S2 B0 | |
587 | #else | |
588 | B .S2 preempt_schedule_irq | |
589 | #endif | |
590 | ADDKPC .S2 preempt_schedule,B3,4 | |
591 | #endif /* CONFIG_PREEMPT */ | |
592 | ||
593 | ENTRY(enable_exception) | |
594 | DINT | |
595 | MVC .S2 TSR,B0 | |
596 | MVC .S2 B3,NRP | |
597 | MVK .L2 0xc,B1 | |
598 | OR .D2 B0,B1,B0 | |
599 | MVC .S2 B0,TSR ; Set GEE and XEN in TSR | |
600 | B .S2 NRP | |
601 | NOP 5 | |
602 | ENDPROC(enable_exception) | |
603 | ||
604 | ENTRY(sys_sigaltstack) | |
605 | #ifdef CONFIG_C6X_BIG_KERNEL | |
606 | MVKL .S1 do_sigaltstack,A0 ; branch to do_sigaltstack | |
607 | MVKH .S1 do_sigaltstack,A0 | |
608 | B .S2X A0 | |
609 | #else | |
610 | B .S2 do_sigaltstack | |
611 | #endif | |
612 | LDW .D2T1 *+SP(REGS_SP+8),A6 | |
613 | NOP 4 | |
614 | ENDPROC(sys_sigaltstack) | |
615 | ||
616 | ;; kernel_execve | |
617 | ENTRY(kernel_execve) | |
618 | MVK .S2 __NR_execve,B0 | |
619 | SWE | |
620 | BNOP .S2 B3,5 | |
621 | ENDPROC(kernel_execve) | |
622 | ||
623 | ;; | |
624 | ;; Special system calls | |
625 | ;; return address is in B3 | |
626 | ;; | |
627 | ENTRY(sys_clone) | |
628 | ADD .D1X SP,8,A4 | |
629 | #ifdef CONFIG_C6X_BIG_KERNEL | |
630 | || MVKL .S1 sys_c6x_clone,A0 | |
631 | MVKH .S1 sys_c6x_clone,A0 | |
632 | BNOP .S2X A0,5 | |
633 | #else | |
634 | || B .S2 sys_c6x_clone | |
635 | NOP 5 | |
636 | #endif | |
637 | ENDPROC(sys_clone) | |
638 | ||
639 | ENTRY(sys_rt_sigreturn) | |
640 | ADD .D1X SP,8,A4 | |
641 | #ifdef CONFIG_C6X_BIG_KERNEL | |
642 | || MVKL .S1 do_rt_sigreturn,A0 | |
643 | MVKH .S1 do_rt_sigreturn,A0 | |
644 | BNOP .S2X A0,5 | |
645 | #else | |
646 | || B .S2 do_rt_sigreturn | |
647 | NOP 5 | |
648 | #endif | |
649 | ENDPROC(sys_rt_sigreturn) | |
650 | ||
651 | ENTRY(sys_execve) | |
652 | ADDAW .D2 SP,2,B6 ; put regs addr in 4th parameter | |
653 | ; & adjust regs stack addr | |
654 | LDW .D2T2 *+SP(REGS_B4+8),B4 | |
655 | ||
656 | ;; c6x_execve(char *name, char **argv, | |
657 | ;; char **envp, struct pt_regs *regs) | |
658 | #ifdef CONFIG_C6X_BIG_KERNEL | |
659 | || MVKL .S1 sys_c6x_execve,A0 | |
660 | MVKH .S1 sys_c6x_execve,A0 | |
661 | B .S2X A0 | |
662 | #else | |
663 | || B .S2 sys_c6x_execve | |
664 | #endif | |
665 | STW .D2T2 B3,*SP--[2] | |
666 | ADDKPC .S2 ret_from_c6x_execve,B3,3 | |
667 | ||
668 | ret_from_c6x_execve: | |
669 | LDW .D2T2 *++SP[2],B3 | |
670 | NOP 4 | |
671 | BNOP .S2 B3,5 | |
672 | ENDPROC(sys_execve) | |
673 | ||
674 | ENTRY(sys_pread_c6x) | |
675 | MV .D2X A8,B7 | |
676 | #ifdef CONFIG_C6X_BIG_KERNEL | |
677 | || MVKL .S1 sys_pread64,A0 | |
678 | MVKH .S1 sys_pread64,A0 | |
679 | BNOP .S2X A0,5 | |
680 | #else | |
681 | || B .S2 sys_pread64 | |
682 | NOP 5 | |
683 | #endif | |
684 | ENDPROC(sys_pread_c6x) | |
685 | ||
686 | ENTRY(sys_pwrite_c6x) | |
687 | MV .D2X A8,B7 | |
688 | #ifdef CONFIG_C6X_BIG_KERNEL | |
689 | || MVKL .S1 sys_pwrite64,A0 | |
690 | MVKH .S1 sys_pwrite64,A0 | |
691 | BNOP .S2X A0,5 | |
692 | #else | |
693 | || B .S2 sys_pwrite64 | |
694 | NOP 5 | |
695 | #endif | |
696 | ENDPROC(sys_pwrite_c6x) | |
697 | ||
698 | ;; On Entry | |
699 | ;; A4 - path | |
700 | ;; B4 - offset_lo (LE), offset_hi (BE) | |
701 | ;; A6 - offset_lo (BE), offset_hi (LE) | |
702 | ENTRY(sys_truncate64_c6x) | |
703 | #ifdef CONFIG_CPU_BIG_ENDIAN | |
704 | MV .S2 B4,B5 | |
705 | MV .D2X A6,B4 | |
706 | #else | |
707 | MV .D2X A6,B5 | |
708 | #endif | |
709 | #ifdef CONFIG_C6X_BIG_KERNEL | |
710 | || MVKL .S1 sys_truncate64,A0 | |
711 | MVKH .S1 sys_truncate64,A0 | |
712 | BNOP .S2X A0,5 | |
713 | #else | |
714 | || B .S2 sys_truncate64 | |
715 | NOP 5 | |
716 | #endif | |
717 | ENDPROC(sys_truncate64_c6x) | |
718 | ||
719 | ;; On Entry | |
720 | ;; A4 - fd | |
721 | ;; B4 - offset_lo (LE), offset_hi (BE) | |
722 | ;; A6 - offset_lo (BE), offset_hi (LE) | |
723 | ENTRY(sys_ftruncate64_c6x) | |
724 | #ifdef CONFIG_CPU_BIG_ENDIAN | |
725 | MV .S2 B4,B5 | |
726 | MV .D2X A6,B4 | |
727 | #else | |
728 | MV .D2X A6,B5 | |
729 | #endif | |
730 | #ifdef CONFIG_C6X_BIG_KERNEL | |
731 | || MVKL .S1 sys_ftruncate64,A0 | |
732 | MVKH .S1 sys_ftruncate64,A0 | |
733 | BNOP .S2X A0,5 | |
734 | #else | |
735 | || B .S2 sys_ftruncate64 | |
736 | NOP 5 | |
737 | #endif | |
738 | ENDPROC(sys_ftruncate64_c6x) | |
739 | ||
e94e6682 AJ |
740 | ;; On Entry |
741 | ;; A4 - fd | |
742 | ;; B4 - offset_lo (LE), offset_hi (BE) | |
743 | ;; A6 - offset_lo (BE), offset_hi (LE) | |
744 | ;; B6 - len_lo (LE), len_hi (BE) | |
745 | ;; A8 - len_lo (BE), len_hi (LE) | |
746 | ;; B8 - advice | |
747 | ENTRY(sys_fadvise64_64_c6x) | |
748 | #ifdef CONFIG_C6X_BIG_KERNEL | |
749 | MVKL .S1 sys_fadvise64_64,A0 | |
750 | MVKH .S1 sys_fadvise64_64,A0 | |
751 | BNOP .S2X A0,2 | |
752 | #else | |
753 | B .S2 sys_fadvise64_64 | |
754 | NOP 2 | |
755 | #endif | |
756 | #ifdef CONFIG_CPU_BIG_ENDIAN | |
757 | MV .L2 B4,B5 | |
758 | || MV .D2X A6,B4 | |
759 | MV .L1 A8,A6 | |
760 | || MV .D1X B6,A7 | |
761 | #else | |
762 | MV .D2X A6,B5 | |
763 | MV .L1 A8,A7 | |
764 | || MV .D1X B6,A6 | |
765 | #endif | |
766 | MV .L2 B8,B6 | |
767 | ENDPROC(sys_fadvise64_64_c6x) | |
768 | ||
769 | ;; On Entry | |
770 | ;; A4 - fd | |
771 | ;; B4 - mode | |
772 | ;; A6 - offset_hi | |
773 | ;; B6 - offset_lo | |
774 | ;; A8 - len_hi | |
775 | ;; B8 - len_lo | |
776 | ENTRY(sys_fallocate_c6x) | |
777 | #ifdef CONFIG_C6X_BIG_KERNEL | |
778 | MVKL .S1 sys_fallocate,A0 | |
779 | MVKH .S1 sys_fallocate,A0 | |
780 | BNOP .S2X A0,1 | |
781 | #else | |
782 | B .S2 sys_fallocate | |
783 | NOP | |
784 | #endif | |
785 | MV .D1 A6,A7 | |
786 | MV .D1X B6,A6 | |
787 | MV .D2X A8,B7 | |
788 | MV .D2 B8,B6 | |
789 | ENDPROC(sys_fallocate_c6x) | |
790 | ||
791 | ;; put this in .neardata for faster access when using DSBT mode | |
792 | .section .neardata,"aw",@progbits | |
793 | .global current_ksp | |
794 | .hidden current_ksp | |
795 | current_ksp: | |
796 | .word init_thread_union + THREAD_START_SP |