]>
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: | |
9d34340e MS |
280 | ;; enable interrupts for do_notify_resume() |
281 | UNMASK_INT B2 | |
e94e6682 AJ |
282 | B .S2 do_notify_resume |
283 | LDW .D2T1 *+SP(REGS__END+8),A6 ; syscall flag | |
284 | ADDKPC .S2 resume_userspace,B3,1 | |
285 | ADD .S1X 8,SP,A4 ; pt_regs pointer is first arg | |
286 | MV .D2X A2,B4 ; thread_info flags is second arg | |
287 | ||
288 | ;; | |
289 | ;; On C64x+, the return way from exception and interrupt | |
290 | ;; is a little bit different | |
291 | ;; | |
292 | ENTRY(ret_from_exception) | |
293 | #ifdef CONFIG_PREEMPT | |
294 | MASK_INT B2 | |
295 | #endif | |
296 | ||
297 | ENTRY(ret_from_interrupt) | |
298 | ;; | |
299 | ;; Check if we are comming from user mode. | |
300 | ;; | |
301 | LDW .D2T2 *+SP(REGS_TSR+8),B0 | |
302 | MVK .S2 0x40,B1 | |
303 | NOP 3 | |
304 | AND .D2 B0,B1,B0 | |
305 | [!B0] BNOP .S2 resume_kernel,5 | |
306 | ||
307 | resume_userspace: | |
308 | ;; make sure we don't miss an interrupt setting need_resched or | |
309 | ;; sigpending between sampling and the rti | |
310 | MASK_INT B2 | |
311 | GET_THREAD_INFO A12 | |
312 | LDW .D1T1 *+A12(THREAD_INFO_FLAGS),A2 | |
313 | MVK .S1 _TIF_WORK_MASK,A1 | |
314 | MVK .S1 _TIF_NEED_RESCHED,A3 | |
315 | NOP 2 | |
316 | AND .D1 A1,A2,A0 | |
317 | [A0] BNOP .S1 work_pending,5 | |
318 | BNOP .S1 restore_all,5 | |
319 | ||
320 | ;; | |
321 | ;; System call handling | |
322 | ;; B0 = syscall number (in sys_call_table) | |
323 | ;; A4,B4,A6,B6,A8,B8 = arguments of the syscall function | |
324 | ;; A4 is the return value register | |
325 | ;; | |
326 | system_call_saved: | |
327 | MVK .L2 1,B2 | |
328 | STW .D2T2 B2,*+SP(REGS__END+8) ; set syscall flag | |
329 | MVC .S2 B2,ECR ; ack the software exception | |
330 | ||
331 | UNMASK_INT B2 ; re-enable global IT | |
332 | ||
333 | system_call_saved_noack: | |
334 | ;; Check system call number | |
335 | MVK .S2 __NR_syscalls,B1 | |
336 | #ifdef CONFIG_C6X_BIG_KERNEL | |
337 | || MVKL .S1 sys_ni_syscall,A0 | |
338 | #endif | |
339 | CMPLTU .L2 B0,B1,B1 | |
340 | #ifdef CONFIG_C6X_BIG_KERNEL | |
341 | || MVKH .S1 sys_ni_syscall,A0 | |
342 | #endif | |
343 | ||
344 | ;; Check for ptrace | |
345 | GET_THREAD_INFO A12 | |
346 | ||
347 | #ifdef CONFIG_C6X_BIG_KERNEL | |
348 | [!B1] B .S2X A0 | |
349 | #else | |
350 | [!B1] B .S2 sys_ni_syscall | |
351 | #endif | |
352 | [!B1] ADDKPC .S2 ret_from_syscall_function,B3,4 | |
353 | ||
354 | ;; Get syscall handler addr from sys_call_table | |
355 | ;; call tracesys_on or call syscall handler | |
356 | LDW .D1T1 *+A12(THREAD_INFO_FLAGS),A2 | |
357 | || MVKL .S2 sys_call_table,B1 | |
358 | MVKH .S2 sys_call_table,B1 | |
359 | LDW .D2T2 *+B1[B0],B0 | |
360 | NOP 2 | |
361 | ; A2 = thread_info flags | |
362 | AND .D1 _TIF_SYSCALL_TRACE,A2,A2 | |
363 | [A2] BNOP .S1 tracesys_on,5 | |
364 | ;; B0 = _sys_call_table[__NR_*] | |
365 | B .S2 B0 | |
366 | ADDKPC .S2 ret_from_syscall_function,B3,4 | |
367 | ||
368 | ret_from_syscall_function: | |
369 | STW .D2T1 A4,*+SP(REGS_A4+8) ; save return value in A4 | |
370 | ; original A4 is in orig_A4 | |
371 | syscall_exit: | |
372 | ;; make sure we don't miss an interrupt setting need_resched or | |
373 | ;; sigpending between sampling and the rti | |
374 | MASK_INT B2 | |
375 | LDW .D1T1 *+A12(THREAD_INFO_FLAGS),A2 | |
376 | MVK .S1 _TIF_ALLWORK_MASK,A1 | |
377 | NOP 3 | |
378 | AND .D1 A1,A2,A2 ; check for work to do | |
379 | [A2] BNOP .S1 syscall_exit_work,5 | |
380 | ||
381 | restore_all: | |
382 | RESTORE_ALL NRP,NTSR | |
383 | ||
384 | ;; | |
385 | ;; After a fork we jump here directly from resume, | |
386 | ;; so that A4 contains the previous task structure. | |
387 | ;; | |
388 | ENTRY(ret_from_fork) | |
389 | #ifdef CONFIG_C6X_BIG_KERNEL | |
390 | MVKL .S1 schedule_tail,A0 | |
391 | MVKH .S1 schedule_tail,A0 | |
392 | B .S2X A0 | |
393 | #else | |
394 | B .S2 schedule_tail | |
395 | #endif | |
396 | ADDKPC .S2 ret_from_fork_2,B3,4 | |
397 | ret_from_fork_2: | |
398 | ;; return 0 in A4 for child process | |
399 | GET_THREAD_INFO A12 | |
400 | BNOP .S2 syscall_exit,3 | |
401 | MVK .L2 0,B0 | |
402 | STW .D2T2 B0,*+SP(REGS_A4+8) | |
403 | ENDPROC(ret_from_fork) | |
404 | ||
46f15067 MS |
405 | ENTRY(ret_from_kernel_thread) |
406 | #ifdef CONFIG_C6X_BIG_KERNEL | |
407 | MVKL .S1 schedule_tail,A0 | |
408 | MVKH .S1 schedule_tail,A0 | |
409 | B .S2X A0 | |
410 | #else | |
411 | B .S2 schedule_tail | |
412 | #endif | |
413 | LDW .D2T2 *+SP(REGS_A0+8),B10 /* get fn */ | |
414 | ADDKPC .S2 0f,B3,3 | |
415 | 0: | |
416 | B .S2 B10 /* call fn */ | |
417 | LDW .D2T1 *+SP(REGS_A1+8),A4 /* get arg */ | |
5e7d7333 | 418 | ADDKPC .S2 ret_from_fork_2,B3,3 |
46f15067 MS |
419 | ENDPROC(ret_from_kernel_thread) |
420 | ||
e94e6682 | 421 | ;; |
9c0603f4 | 422 | ;; These are the interrupt handlers, responsible for calling c6x_do_IRQ() |
e94e6682 AJ |
423 | ;; |
424 | .macro SAVE_ALL_INT | |
425 | SAVE_ALL IRP,ITSR | |
426 | .endm | |
427 | ||
428 | .macro CALL_INT int | |
429 | #ifdef CONFIG_C6X_BIG_KERNEL | |
430 | MVKL .S1 c6x_do_IRQ,A0 | |
431 | MVKH .S1 c6x_do_IRQ,A0 | |
432 | BNOP .S2X A0,1 | |
433 | MVK .S1 int,A4 | |
434 | ADDAW .D2 SP,2,B4 | |
435 | MVKL .S2 ret_from_interrupt,B3 | |
436 | MVKH .S2 ret_from_interrupt,B3 | |
437 | #else | |
438 | CALLP .S2 c6x_do_IRQ,B3 | |
439 | || MVK .S1 int,A4 | |
440 | || ADDAW .D2 SP,2,B4 | |
441 | B .S1 ret_from_interrupt | |
442 | NOP 5 | |
443 | #endif | |
444 | .endm | |
445 | ||
446 | ENTRY(_int4_handler) | |
447 | SAVE_ALL_INT | |
448 | CALL_INT 4 | |
449 | ENDPROC(_int4_handler) | |
450 | ||
451 | ENTRY(_int5_handler) | |
452 | SAVE_ALL_INT | |
453 | CALL_INT 5 | |
454 | ENDPROC(_int5_handler) | |
455 | ||
456 | ENTRY(_int6_handler) | |
457 | SAVE_ALL_INT | |
458 | CALL_INT 6 | |
459 | ENDPROC(_int6_handler) | |
460 | ||
461 | ENTRY(_int7_handler) | |
462 | SAVE_ALL_INT | |
463 | CALL_INT 7 | |
464 | ENDPROC(_int7_handler) | |
465 | ||
466 | ENTRY(_int8_handler) | |
467 | SAVE_ALL_INT | |
468 | CALL_INT 8 | |
469 | ENDPROC(_int8_handler) | |
470 | ||
471 | ENTRY(_int9_handler) | |
472 | SAVE_ALL_INT | |
473 | CALL_INT 9 | |
474 | ENDPROC(_int9_handler) | |
475 | ||
476 | ENTRY(_int10_handler) | |
477 | SAVE_ALL_INT | |
478 | CALL_INT 10 | |
479 | ENDPROC(_int10_handler) | |
480 | ||
481 | ENTRY(_int11_handler) | |
482 | SAVE_ALL_INT | |
483 | CALL_INT 11 | |
484 | ENDPROC(_int11_handler) | |
485 | ||
486 | ENTRY(_int12_handler) | |
487 | SAVE_ALL_INT | |
488 | CALL_INT 12 | |
489 | ENDPROC(_int12_handler) | |
490 | ||
491 | ENTRY(_int13_handler) | |
492 | SAVE_ALL_INT | |
493 | CALL_INT 13 | |
494 | ENDPROC(_int13_handler) | |
495 | ||
496 | ENTRY(_int14_handler) | |
497 | SAVE_ALL_INT | |
498 | CALL_INT 14 | |
499 | ENDPROC(_int14_handler) | |
500 | ||
501 | ENTRY(_int15_handler) | |
502 | SAVE_ALL_INT | |
503 | CALL_INT 15 | |
504 | ENDPROC(_int15_handler) | |
505 | ||
506 | ;; | |
507 | ;; Handler for uninitialized and spurious interrupts | |
508 | ;; | |
509 | ENTRY(_bad_interrupt) | |
510 | B .S2 IRP | |
511 | NOP 5 | |
512 | ENDPROC(_bad_interrupt) | |
513 | ||
514 | ;; | |
515 | ;; Entry for NMI/exceptions/syscall | |
516 | ;; | |
517 | ENTRY(_nmi_handler) | |
518 | SAVE_ALL NRP,NTSR | |
519 | ||
520 | MVC .S2 EFR,B2 | |
521 | CMPEQ .L2 1,B2,B2 | |
522 | || MVC .S2 TSR,B1 | |
523 | CLR .S2 B1,10,10,B1 | |
524 | MVC .S2 B1,TSR | |
525 | #ifdef CONFIG_C6X_BIG_KERNEL | |
526 | [!B2] MVKL .S1 process_exception,A0 | |
527 | [!B2] MVKH .S1 process_exception,A0 | |
528 | [!B2] B .S2X A0 | |
529 | #else | |
530 | [!B2] B .S2 process_exception | |
531 | #endif | |
532 | [B2] B .S2 system_call_saved | |
533 | [!B2] ADDAW .D2 SP,2,B1 | |
534 | [!B2] MV .D1X B1,A4 | |
535 | ADDKPC .S2 ret_from_trap,B3,2 | |
536 | ||
537 | ret_from_trap: | |
538 | MV .D2X A4,B0 | |
539 | [!B0] BNOP .S2 ret_from_exception,5 | |
540 | ||
541 | #ifdef CONFIG_C6X_BIG_KERNEL | |
542 | MVKL .S2 system_call_saved_noack,B3 | |
543 | MVKH .S2 system_call_saved_noack,B3 | |
544 | #endif | |
545 | LDW .D2T2 *+SP(REGS_B0+8),B0 | |
546 | LDW .D2T1 *+SP(REGS_A4+8),A4 | |
547 | LDW .D2T2 *+SP(REGS_B4+8),B4 | |
548 | LDW .D2T1 *+SP(REGS_A6+8),A6 | |
549 | LDW .D2T2 *+SP(REGS_B6+8),B6 | |
550 | LDW .D2T1 *+SP(REGS_A8+8),A8 | |
551 | #ifdef CONFIG_C6X_BIG_KERNEL | |
552 | || B .S2 B3 | |
553 | #else | |
554 | || B .S2 system_call_saved_noack | |
555 | #endif | |
556 | LDW .D2T2 *+SP(REGS_B8+8),B8 | |
557 | NOP 4 | |
558 | ENDPROC(_nmi_handler) | |
559 | ||
560 | ;; | |
561 | ;; Jump to schedule() then return to ret_from_isr | |
562 | ;; | |
563 | #ifdef CONFIG_PREEMPT | |
564 | resume_kernel: | |
565 | GET_THREAD_INFO A12 | |
566 | LDW .D1T1 *+A12(THREAD_INFO_PREEMPT_COUNT),A1 | |
567 | NOP 4 | |
568 | [A1] BNOP .S2 restore_all,5 | |
569 | ||
570 | preempt_schedule: | |
571 | GET_THREAD_INFO A2 | |
572 | LDW .D1T1 *+A2(THREAD_INFO_FLAGS),A1 | |
573 | #ifdef CONFIG_C6X_BIG_KERNEL | |
574 | MVKL .S2 preempt_schedule_irq,B0 | |
575 | MVKH .S2 preempt_schedule_irq,B0 | |
576 | NOP 2 | |
577 | #else | |
578 | NOP 4 | |
579 | #endif | |
580 | AND .D1 _TIF_NEED_RESCHED,A1,A1 | |
581 | [!A1] BNOP .S2 restore_all,5 | |
582 | #ifdef CONFIG_C6X_BIG_KERNEL | |
583 | B .S2 B0 | |
584 | #else | |
585 | B .S2 preempt_schedule_irq | |
586 | #endif | |
587 | ADDKPC .S2 preempt_schedule,B3,4 | |
588 | #endif /* CONFIG_PREEMPT */ | |
589 | ||
590 | ENTRY(enable_exception) | |
591 | DINT | |
592 | MVC .S2 TSR,B0 | |
593 | MVC .S2 B3,NRP | |
594 | MVK .L2 0xc,B1 | |
595 | OR .D2 B0,B1,B0 | |
596 | MVC .S2 B0,TSR ; Set GEE and XEN in TSR | |
597 | B .S2 NRP | |
598 | NOP 5 | |
599 | ENDPROC(enable_exception) | |
600 | ||
e94e6682 AJ |
601 | ;; |
602 | ;; Special system calls | |
603 | ;; return address is in B3 | |
604 | ;; | |
e94e6682 AJ |
605 | ENTRY(sys_rt_sigreturn) |
606 | ADD .D1X SP,8,A4 | |
607 | #ifdef CONFIG_C6X_BIG_KERNEL | |
608 | || MVKL .S1 do_rt_sigreturn,A0 | |
609 | MVKH .S1 do_rt_sigreturn,A0 | |
610 | BNOP .S2X A0,5 | |
611 | #else | |
612 | || B .S2 do_rt_sigreturn | |
613 | NOP 5 | |
614 | #endif | |
615 | ENDPROC(sys_rt_sigreturn) | |
616 | ||
e94e6682 AJ |
617 | ENTRY(sys_pread_c6x) |
618 | MV .D2X A8,B7 | |
619 | #ifdef CONFIG_C6X_BIG_KERNEL | |
620 | || MVKL .S1 sys_pread64,A0 | |
621 | MVKH .S1 sys_pread64,A0 | |
622 | BNOP .S2X A0,5 | |
623 | #else | |
624 | || B .S2 sys_pread64 | |
625 | NOP 5 | |
626 | #endif | |
627 | ENDPROC(sys_pread_c6x) | |
628 | ||
629 | ENTRY(sys_pwrite_c6x) | |
630 | MV .D2X A8,B7 | |
631 | #ifdef CONFIG_C6X_BIG_KERNEL | |
632 | || MVKL .S1 sys_pwrite64,A0 | |
633 | MVKH .S1 sys_pwrite64,A0 | |
634 | BNOP .S2X A0,5 | |
635 | #else | |
636 | || B .S2 sys_pwrite64 | |
637 | NOP 5 | |
638 | #endif | |
639 | ENDPROC(sys_pwrite_c6x) | |
640 | ||
641 | ;; On Entry | |
642 | ;; A4 - path | |
643 | ;; B4 - offset_lo (LE), offset_hi (BE) | |
644 | ;; A6 - offset_lo (BE), offset_hi (LE) | |
645 | ENTRY(sys_truncate64_c6x) | |
646 | #ifdef CONFIG_CPU_BIG_ENDIAN | |
647 | MV .S2 B4,B5 | |
648 | MV .D2X A6,B4 | |
649 | #else | |
650 | MV .D2X A6,B5 | |
651 | #endif | |
652 | #ifdef CONFIG_C6X_BIG_KERNEL | |
653 | || MVKL .S1 sys_truncate64,A0 | |
654 | MVKH .S1 sys_truncate64,A0 | |
655 | BNOP .S2X A0,5 | |
656 | #else | |
657 | || B .S2 sys_truncate64 | |
658 | NOP 5 | |
659 | #endif | |
660 | ENDPROC(sys_truncate64_c6x) | |
661 | ||
662 | ;; On Entry | |
663 | ;; A4 - fd | |
664 | ;; B4 - offset_lo (LE), offset_hi (BE) | |
665 | ;; A6 - offset_lo (BE), offset_hi (LE) | |
666 | ENTRY(sys_ftruncate64_c6x) | |
667 | #ifdef CONFIG_CPU_BIG_ENDIAN | |
668 | MV .S2 B4,B5 | |
669 | MV .D2X A6,B4 | |
670 | #else | |
671 | MV .D2X A6,B5 | |
672 | #endif | |
673 | #ifdef CONFIG_C6X_BIG_KERNEL | |
674 | || MVKL .S1 sys_ftruncate64,A0 | |
675 | MVKH .S1 sys_ftruncate64,A0 | |
676 | BNOP .S2X A0,5 | |
677 | #else | |
678 | || B .S2 sys_ftruncate64 | |
679 | NOP 5 | |
680 | #endif | |
681 | ENDPROC(sys_ftruncate64_c6x) | |
682 | ||
e94e6682 AJ |
683 | ;; On Entry |
684 | ;; A4 - fd | |
685 | ;; B4 - offset_lo (LE), offset_hi (BE) | |
686 | ;; A6 - offset_lo (BE), offset_hi (LE) | |
687 | ;; B6 - len_lo (LE), len_hi (BE) | |
688 | ;; A8 - len_lo (BE), len_hi (LE) | |
689 | ;; B8 - advice | |
690 | ENTRY(sys_fadvise64_64_c6x) | |
691 | #ifdef CONFIG_C6X_BIG_KERNEL | |
692 | MVKL .S1 sys_fadvise64_64,A0 | |
693 | MVKH .S1 sys_fadvise64_64,A0 | |
694 | BNOP .S2X A0,2 | |
695 | #else | |
696 | B .S2 sys_fadvise64_64 | |
697 | NOP 2 | |
698 | #endif | |
699 | #ifdef CONFIG_CPU_BIG_ENDIAN | |
700 | MV .L2 B4,B5 | |
701 | || MV .D2X A6,B4 | |
702 | MV .L1 A8,A6 | |
703 | || MV .D1X B6,A7 | |
704 | #else | |
705 | MV .D2X A6,B5 | |
706 | MV .L1 A8,A7 | |
707 | || MV .D1X B6,A6 | |
708 | #endif | |
709 | MV .L2 B8,B6 | |
710 | ENDPROC(sys_fadvise64_64_c6x) | |
711 | ||
712 | ;; On Entry | |
713 | ;; A4 - fd | |
714 | ;; B4 - mode | |
715 | ;; A6 - offset_hi | |
716 | ;; B6 - offset_lo | |
717 | ;; A8 - len_hi | |
718 | ;; B8 - len_lo | |
719 | ENTRY(sys_fallocate_c6x) | |
720 | #ifdef CONFIG_C6X_BIG_KERNEL | |
721 | MVKL .S1 sys_fallocate,A0 | |
722 | MVKH .S1 sys_fallocate,A0 | |
723 | BNOP .S2X A0,1 | |
724 | #else | |
725 | B .S2 sys_fallocate | |
726 | NOP | |
727 | #endif | |
728 | MV .D1 A6,A7 | |
729 | MV .D1X B6,A6 | |
730 | MV .D2X A8,B7 | |
731 | MV .D2 B8,B6 | |
732 | ENDPROC(sys_fallocate_c6x) | |
733 | ||
734 | ;; put this in .neardata for faster access when using DSBT mode | |
735 | .section .neardata,"aw",@progbits | |
736 | .global current_ksp | |
737 | .hidden current_ksp | |
738 | current_ksp: | |
739 | .word init_thread_union + THREAD_START_SP |