Merge branch 'for-3.0' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/asoc...
[deliverable/linux.git] / arch / score / kernel / entry.S
1 /*
2 * arch/score/kernel/entry.S
3 *
4 * Score Processor version.
5 *
6 * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
7 * Chen Liqin <liqin.chen@sunplusct.com>
8 * Lennox Wu <lennox.wu@sunplusct.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see the file COPYING, or write
22 * to the Free Software Foundation, Inc.,
23 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #include <linux/err.h>
27 #include <linux/init.h>
28 #include <linux/linkage.h>
29
30 #include <asm/asmmacro.h>
31 #include <asm/thread_info.h>
32 #include <asm/unistd.h>
33
34 /*
35 * disable interrupts.
36 */
37 .macro disable_irq
38 mfcr r8, cr0
39 srli r8, r8, 1
40 slli r8, r8, 1
41 mtcr r8, cr0
42 nop
43 nop
44 nop
45 nop
46 nop
47 .endm
48
49 /*
50 * enable interrupts.
51 */
52 .macro enable_irq
53 mfcr r8, cr0
54 ori r8, 1
55 mtcr r8, cr0
56 nop
57 nop
58 nop
59 nop
60 nop
61 .endm
62
63 __INIT
64 ENTRY(debug_exception_vector)
65 nop!
66 nop!
67 nop!
68 nop!
69 nop!
70 nop!
71 nop!
72 nop!
73
74 ENTRY(general_exception_vector) # should move to addr 0x200
75 j general_exception
76 nop!
77 nop!
78 nop!
79 nop!
80 nop!
81 nop!
82
83 ENTRY(interrupt_exception_vector) # should move to addr 0x210
84 j interrupt_exception
85 nop!
86 nop!
87 nop!
88 nop!
89 nop!
90 nop!
91
92 .section ".text", "ax"
93 .align 2;
94 general_exception:
95 mfcr r31, cr2
96 nop
97 la r30, exception_handlers
98 andi r31, 0x1f # get ecr.exc_code
99 slli r31, r31, 2
100 add r30, r30, r31
101 lw r30, [r30]
102 br r30
103
104 interrupt_exception:
105 SAVE_ALL
106 mfcr r4, cr2
107 nop
108 lw r16, [r28, TI_REGS]
109 sw r0, [r28, TI_REGS]
110 la r3, ret_from_irq
111 srli r4, r4, 18 # get ecr.ip[7:2], interrupt No.
112 mv r5, r0
113 j do_IRQ
114
115 ENTRY(handle_nmi) # NMI #1
116 SAVE_ALL
117 mv r4, r0
118 la r8, nmi_exception_handler
119 brl r8
120 j restore_all
121
122 ENTRY(handle_adelinsn) # AdEL-instruction #2
123 SAVE_ALL
124 mfcr r8, cr6
125 nop
126 nop
127 sw r8, [r0, PT_EMA]
128 mv r4, r0
129 la r8, do_adelinsn
130 brl r8
131 mv r4, r0
132 j ret_from_exception
133 nop
134
135 ENTRY(handle_ibe) # BusEL-instruction #5
136 SAVE_ALL
137 mv r4, r0
138 la r8, do_be
139 brl r8
140 mv r4, r0
141 j ret_from_exception
142 nop
143
144 ENTRY(handle_pel) # P-EL #6
145 SAVE_ALL
146 mv r4, r0
147 la r8, do_pel
148 brl r8
149 mv r4, r0
150 j ret_from_exception
151 nop
152
153 ENTRY(handle_ccu) # CCU #8
154 SAVE_ALL
155 mv r4, r0
156 la r8, do_ccu
157 brl r8
158 mv r4, r0
159 j ret_from_exception
160 nop
161
162 ENTRY(handle_ri) # RI #9
163 SAVE_ALL
164 mv r4, r0
165 la r8, do_ri
166 brl r8
167 mv r4, r0
168 j ret_from_exception
169 nop
170
171 ENTRY(handle_tr) # Trap #10
172 SAVE_ALL
173 mv r4, r0
174 la r8, do_tr
175 brl r8
176 mv r4, r0
177 j ret_from_exception
178 nop
179
180 ENTRY(handle_adedata) # AdES-instruction #12
181 SAVE_ALL
182 mfcr r8, cr6
183 nop
184 nop
185 sw r8, [r0, PT_EMA]
186 mv r4, r0
187 la r8, do_adedata
188 brl r8
189 mv r4, r0
190 j ret_from_exception
191 nop
192
193 ENTRY(handle_cee) # CeE #16
194 SAVE_ALL
195 mv r4, r0
196 la r8, do_cee
197 brl r8
198 mv r4, r0
199 j ret_from_exception
200 nop
201
202 ENTRY(handle_cpe) # CpE #17
203 SAVE_ALL
204 mv r4, r0
205 la r8, do_cpe
206 brl r8
207 mv r4, r0
208 j ret_from_exception
209 nop
210
211 ENTRY(handle_dbe) # BusEL-data #18
212 SAVE_ALL
213 mv r4, r0
214 la r8, do_be
215 brl r8
216 mv r4, r0
217 j ret_from_exception
218 nop
219
220 ENTRY(handle_reserved) # others
221 SAVE_ALL
222 mv r4, r0
223 la r8, do_reserved
224 brl r8
225 mv r4, r0
226 j ret_from_exception
227 nop
228
229 #ifndef CONFIG_PREEMPT
230 #define resume_kernel restore_all
231 #else
232 #define __ret_from_irq ret_from_exception
233 #endif
234
235 .align 2
236 #ifndef CONFIG_PREEMPT
237 ENTRY(ret_from_exception)
238 disable_irq # preempt stop
239 nop
240 j __ret_from_irq
241 nop
242 #endif
243
244 ENTRY(ret_from_irq)
245 sw r16, [r28, TI_REGS]
246
247 ENTRY(__ret_from_irq)
248 lw r8, [r0, PT_PSR] # returning to kernel mode?
249 andri.c r8, r8, KU_USER
250 beq resume_kernel
251
252 resume_userspace:
253 disable_irq
254 lw r6, [r28, TI_FLAGS] # current->work
255 li r8, _TIF_WORK_MASK
256 and.c r8, r8, r6 # ignoring syscall_trace
257 bne work_pending
258 nop
259 j restore_all
260 nop
261
262 #ifdef CONFIG_PREEMPT
263 resume_kernel:
264 disable_irq
265 lw r8, [r28, TI_PRE_COUNT]
266 cmpz.c r8
267 bne r8, restore_all
268 need_resched:
269 lw r8, [r28, TI_FLAGS]
270 andri.c r9, r8, _TIF_NEED_RESCHED
271 beq restore_all
272 lw r8, [r28, PT_PSR] # Interrupts off?
273 andri.c r8, r8, 1
274 beq restore_all
275 bl preempt_schedule_irq
276 nop
277 j need_resched
278 nop
279 #endif
280
281 ENTRY(ret_from_fork)
282 bl schedule_tail # r4=struct task_struct *prev
283
284 ENTRY(syscall_exit)
285 nop
286 disable_irq
287 lw r6, [r28, TI_FLAGS] # current->work
288 li r8, _TIF_WORK_MASK
289 and.c r8, r6, r8
290 bne syscall_exit_work
291
292 ENTRY(restore_all) # restore full frame
293 RESTORE_ALL_AND_RET
294
295 work_pending:
296 andri.c r8, r6, _TIF_NEED_RESCHED # r6 is preloaded with TI_FLAGS
297 beq work_notifysig
298 work_resched:
299 bl schedule
300 nop
301 disable_irq
302 lw r6, [r28, TI_FLAGS]
303 li r8, _TIF_WORK_MASK
304 and.c r8, r6, r8 # is there any work to be done
305 # other than syscall tracing?
306 beq restore_all
307 andri.c r8, r6, _TIF_NEED_RESCHED
308 bne work_resched
309
310 work_notifysig:
311 mv r4, r0
312 li r5, 0
313 bl do_notify_resume # r6 already loaded
314 nop
315 j resume_userspace
316 nop
317
318 ENTRY(syscall_exit_work)
319 li r8, _TIF_SYSCALL_TRACE
320 and.c r8, r8, r6 # r6 is preloaded with TI_FLAGS
321 beq work_pending # trace bit set?
322 nop
323 enable_irq
324 mv r4, r0
325 li r5, 1
326 bl do_syscall_trace
327 nop
328 b resume_userspace
329 nop
330
331 .macro save_context reg
332 sw r12, [\reg, THREAD_REG12];
333 sw r13, [\reg, THREAD_REG13];
334 sw r14, [\reg, THREAD_REG14];
335 sw r15, [\reg, THREAD_REG15];
336 sw r16, [\reg, THREAD_REG16];
337 sw r17, [\reg, THREAD_REG17];
338 sw r18, [\reg, THREAD_REG18];
339 sw r19, [\reg, THREAD_REG19];
340 sw r20, [\reg, THREAD_REG20];
341 sw r21, [\reg, THREAD_REG21];
342 sw r29, [\reg, THREAD_REG29];
343 sw r2, [\reg, THREAD_REG2];
344 sw r0, [\reg, THREAD_REG0]
345 .endm
346
347 .macro restore_context reg
348 lw r12, [\reg, THREAD_REG12];
349 lw r13, [\reg, THREAD_REG13];
350 lw r14, [\reg, THREAD_REG14];
351 lw r15, [\reg, THREAD_REG15];
352 lw r16, [\reg, THREAD_REG16];
353 lw r17, [\reg, THREAD_REG17];
354 lw r18, [\reg, THREAD_REG18];
355 lw r19, [\reg, THREAD_REG19];
356 lw r20, [\reg, THREAD_REG20];
357 lw r21, [\reg, THREAD_REG21];
358 lw r29, [\reg, THREAD_REG29];
359 lw r0, [\reg, THREAD_REG0];
360 lw r2, [\reg, THREAD_REG2];
361 lw r3, [\reg, THREAD_REG3]
362 .endm
363
364 /*
365 * task_struct *resume(task_struct *prev, task_struct *next,
366 * struct thread_info *next_ti)
367 */
368 ENTRY(resume)
369 mfcr r9, cr0
370 nop
371 nop
372 sw r9, [r4, THREAD_PSR]
373 save_context r4
374 sw r3, [r4, THREAD_REG3]
375
376 mv r28, r6
377 restore_context r5
378 mv r8, r6
379 addi r8, KERNEL_STACK_SIZE
380 subi r8, 32
381 la r9, kernelsp;
382 sw r8, [r9];
383
384 mfcr r9, cr0
385 ldis r7, 0x00ff
386 nop
387 and r9, r9, r7
388 lw r6, [r5, THREAD_PSR]
389 not r7, r7
390 and r6, r6, r7
391 or r6, r6, r9
392 mtcr r6, cr0
393 nop; nop; nop; nop; nop
394 br r3
395
396 ENTRY(handle_sys)
397 SAVE_ALL
398 sw r8, [r0, 16] # argument 5 from user r8
399 sw r9, [r0, 20] # argument 6 from user r9
400 enable_irq
401
402 sw r4, [r0, PT_ORIG_R4] #for restart syscall
403 sw r7, [r0, PT_ORIG_R7] #for restart syscall
404 sw r27, [r0, PT_IS_SYSCALL] # it from syscall
405
406 lw r9, [r0, PT_EPC] # skip syscall on return
407 addi r9, 4
408 sw r9, [r0, PT_EPC]
409
410 cmpi.c r27, __NR_syscalls # check syscall number
411 bgtu illegal_syscall
412
413 slli r8, r27, 2 # get syscall routine
414 la r11, sys_call_table
415 add r11, r11, r8
416 lw r10, [r11] # get syscall entry
417
418 cmpz.c r10
419 beq illegal_syscall
420
421 lw r8, [r28, TI_FLAGS]
422 li r9, _TIF_SYSCALL_TRACE
423 and.c r8, r8, r9
424 bne syscall_trace_entry
425
426 brl r10 # Do The Real system call
427
428 cmpi.c r4, 0
429 blt 1f
430 ldi r8, 0
431 sw r8, [r0, PT_R7]
432 b 2f
433 1:
434 cmpi.c r4, -MAX_ERRNO - 1
435 ble 2f
436 ldi r8, 0x1;
437 sw r8, [r0, PT_R7]
438 neg r4, r4
439 2:
440 sw r4, [r0, PT_R4] # save result
441
442 syscall_return:
443 disable_irq
444 lw r6, [r28, TI_FLAGS] # current->work
445 li r8, _TIF_WORK_MASK
446 and.c r8, r6, r8
447 bne syscall_return_work
448 j restore_all
449
450 syscall_return_work:
451 j syscall_exit_work
452
453 syscall_trace_entry:
454 mv r16, r10
455 mv r4, r0
456 li r5, 0
457 bl do_syscall_trace
458
459 mv r8, r16
460 lw r4, [r0, PT_R4] # Restore argument registers
461 lw r5, [r0, PT_R5]
462 lw r6, [r0, PT_R6]
463 lw r7, [r0, PT_R7]
464 brl r8
465
466 li r8, -MAX_ERRNO - 1
467 sw r8, [r0, PT_R7] # set error flag
468
469 neg r4, r4 # error
470 sw r4, [r0, PT_R0] # set flag for syscall
471 # restarting
472 1: sw r4, [r0, PT_R2] # result
473 j syscall_exit
474
475 illegal_syscall:
476 ldi r4, -ENOSYS # error
477 sw r4, [r0, PT_ORIG_R4]
478 sw r4, [r0, PT_R4]
479 ldi r9, 1 # set error flag
480 sw r9, [r0, PT_R7]
481 j syscall_return
482
483 ENTRY(sys_execve)
484 mv r4, r0
485 la r8, score_execve
486 br r8
487
488 ENTRY(sys_clone)
489 mv r4, r0
490 la r8, score_clone
491 br r8
492
493 ENTRY(sys_rt_sigreturn)
494 mv r4, r0
495 la r8, score_rt_sigreturn
496 br r8
497
498 ENTRY(sys_sigaltstack)
499 mv r4, r0
500 la r8, score_sigaltstack
501 br r8
502
503 #ifdef __ARCH_WANT_SYSCALL_DEPRECATED
504 ENTRY(sys_fork)
505 mv r4, r0
506 la r8, score_fork
507 br r8
508
509 ENTRY(sys_vfork)
510 mv r4, r0
511 la r8, score_vfork
512 br r8
513 #endif /* __ARCH_WANT_SYSCALL_DEPRECATED */
514
This page took 0.048053 seconds and 5 git commands to generate.