Merge branch 'next' into for-linus
[platform/adaptation/renesas_rcar/renesas_kernel.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_kernel_thread)
282         bl      schedule_tail                   # r4=struct task_struct *prev
283         nop
284         mv      r4, r13
285         brl     r12
286         j       syscall_exit
287
288 ENTRY(ret_from_fork)
289         bl      schedule_tail                   # r4=struct task_struct *prev
290
291 ENTRY(syscall_exit)
292         nop
293         disable_irq
294         lw      r6, [r28, TI_FLAGS]             # current->work
295         li      r8, _TIF_WORK_MASK
296         and.c   r8, r6, r8
297         bne     syscall_exit_work
298
299 ENTRY(restore_all)                                      # restore full frame
300         RESTORE_ALL_AND_RET
301
302 work_pending:
303         andri.c r8, r6, _TIF_NEED_RESCHED # r6 is preloaded with TI_FLAGS
304         beq     work_notifysig
305 work_resched:
306         bl      schedule
307         nop
308         disable_irq
309         lw      r6, [r28, TI_FLAGS]
310         li      r8, _TIF_WORK_MASK
311         and.c   r8, r6, r8      # is there any work to be done
312                                 # other than syscall tracing?
313         beq     restore_all
314         andri.c r8, r6, _TIF_NEED_RESCHED
315         bne     work_resched
316
317 work_notifysig:
318         mv      r4, r0
319         li      r5, 0
320         bl      do_notify_resume        # r6 already loaded
321         nop
322         j       resume_userspace
323         nop
324
325 ENTRY(syscall_exit_work)
326         li      r8, _TIF_SYSCALL_TRACE
327         and.c   r8, r8, r6              # r6 is preloaded with TI_FLAGS
328         beq     work_pending            # trace bit set?
329         nop
330         enable_irq
331         mv      r4, r0
332         li      r5, 1
333         bl      do_syscall_trace
334         nop
335         b       resume_userspace
336         nop
337
338 .macro  save_context    reg
339         sw      r12, [\reg, THREAD_REG12];
340         sw      r13, [\reg, THREAD_REG13];
341         sw      r14, [\reg, THREAD_REG14];
342         sw      r15, [\reg, THREAD_REG15];
343         sw      r16, [\reg, THREAD_REG16];
344         sw      r17, [\reg, THREAD_REG17];
345         sw      r18, [\reg, THREAD_REG18];
346         sw      r19, [\reg, THREAD_REG19];
347         sw      r20, [\reg, THREAD_REG20];
348         sw      r21, [\reg, THREAD_REG21];
349         sw      r29, [\reg, THREAD_REG29];
350         sw      r2, [\reg, THREAD_REG2];
351         sw      r0, [\reg, THREAD_REG0]
352 .endm
353
354 .macro  restore_context reg
355         lw      r12, [\reg, THREAD_REG12];
356         lw      r13, [\reg, THREAD_REG13];
357         lw      r14, [\reg, THREAD_REG14];
358         lw      r15, [\reg, THREAD_REG15];
359         lw      r16, [\reg, THREAD_REG16];
360         lw      r17, [\reg, THREAD_REG17];
361         lw      r18, [\reg, THREAD_REG18];
362         lw      r19, [\reg, THREAD_REG19];
363         lw      r20, [\reg, THREAD_REG20];
364         lw      r21, [\reg, THREAD_REG21];
365         lw      r29, [\reg, THREAD_REG29];
366         lw      r0, [\reg, THREAD_REG0];
367         lw      r2, [\reg, THREAD_REG2];
368         lw      r3, [\reg, THREAD_REG3]
369 .endm
370
371 /*
372  * task_struct *resume(task_struct *prev, task_struct *next,
373  *                      struct thread_info *next_ti)
374  */
375 ENTRY(resume)
376         mfcr    r9, cr0
377         nop
378         nop
379         sw      r9, [r4, THREAD_PSR]
380         save_context    r4
381         sw      r3, [r4, THREAD_REG3]
382
383         mv      r28, r6
384         restore_context r5
385         mv      r8, r6
386         addi    r8, KERNEL_STACK_SIZE
387         subi    r8, 32
388         la      r9, kernelsp;
389         sw      r8, [r9];
390
391         mfcr    r9, cr0
392         ldis    r7, 0x00ff
393         nop
394         and     r9, r9, r7
395         lw      r6, [r5, THREAD_PSR]
396         not     r7, r7
397         and     r6, r6, r7
398         or      r6, r6, r9
399         mtcr    r6, cr0
400         nop; nop; nop; nop; nop
401         br      r3
402
403 ENTRY(handle_sys)
404         SAVE_ALL
405         sw      r8, [r0, 16]            # argument 5 from user r8
406         sw      r9, [r0, 20]            # argument 6 from user r9
407         enable_irq
408
409         sw      r4, [r0, PT_ORIG_R4]    #for restart syscall
410         sw      r7, [r0, PT_ORIG_R7]    #for restart syscall
411         sw      r27, [r0, PT_IS_SYSCALL] # it from syscall
412
413         lw      r9, [r0, PT_EPC]        # skip syscall on return
414         addi    r9, 4
415         sw      r9, [r0, PT_EPC]
416
417         cmpi.c  r27, __NR_syscalls      # check syscall number
418         bgeu    illegal_syscall
419
420         slli    r8, r27, 2              # get syscall routine
421         la      r11, sys_call_table
422         add     r11, r11, r8
423         lw      r10, [r11]              # get syscall entry
424
425         cmpz.c  r10
426         beq     illegal_syscall
427
428         lw      r8, [r28, TI_FLAGS]
429         li      r9, _TIF_SYSCALL_TRACE
430         and.c   r8, r8, r9
431         bne     syscall_trace_entry
432
433         brl     r10                     # Do The Real system call
434
435         cmpi.c  r4, 0
436         blt     1f
437         ldi     r8, 0
438         sw      r8, [r0, PT_R7]
439         b 2f
440 1:
441         cmpi.c  r4, -MAX_ERRNO - 1
442         ble     2f
443         ldi     r8, 0x1;
444         sw      r8, [r0, PT_R7]
445         neg     r4, r4
446 2:
447         sw      r4, [r0, PT_R4]         # save result
448
449 syscall_return:
450         disable_irq
451         lw      r6, [r28, TI_FLAGS]     # current->work
452         li      r8, _TIF_WORK_MASK
453         and.c   r8, r6, r8
454         bne     syscall_return_work
455         j       restore_all
456
457 syscall_return_work:
458         j       syscall_exit_work
459
460 syscall_trace_entry:
461         mv      r16, r10
462         mv      r4, r0
463         li      r5, 0
464         bl      do_syscall_trace
465
466         mv      r8, r16
467         lw      r4, [r0, PT_R4]         # Restore argument registers
468         lw      r5, [r0, PT_R5]
469         lw      r6, [r0, PT_R6]
470         lw      r7, [r0, PT_R7]
471         brl     r8
472
473         li      r8, -MAX_ERRNO - 1
474         sw      r8, [r0, PT_R7]         # set error flag
475
476         neg     r4, r4                  # error
477         sw      r4, [r0, PT_R0]         # set flag for syscall
478                                         # restarting
479 1:      sw      r4, [r0, PT_R2]         # result
480         j       syscall_exit
481
482 illegal_syscall:
483         ldi     r4, -ENOSYS             # error
484         sw      r4, [r0, PT_ORIG_R4]
485         sw      r4, [r0, PT_R4]
486         ldi     r9, 1                   # set error flag
487         sw      r9, [r0, PT_R7]
488         j       syscall_return
489
490 ENTRY(sys_rt_sigreturn)
491         mv      r4, r0
492         la      r8, score_rt_sigreturn
493         br      r8