2 * arch/score/kernel/entry.S
4 * Score Processor version.
6 * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
7 * Chen Liqin <liqin.chen@sunplusct.com>
8 * Lennox Wu <lennox.wu@sunplusct.com>
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.
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.
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
26 #include <linux/err.h>
27 #include <linux/init.h>
28 #include <linux/linkage.h>
30 #include <asm/asmmacro.h>
31 #include <asm/thread_info.h>
32 #include <asm/unistd.h>
64 ENTRY(debug_exception_vector)
74 ENTRY(general_exception_vector) # should move to addr 0x200
83 ENTRY(interrupt_exception_vector) # should move to addr 0x210
92 .section ".text", "ax"
97 la r30, exception_handlers
98 andi r31, 0x1f # get ecr.exc_code
108 lw r16, [r28, TI_REGS]
109 sw r0, [r28, TI_REGS]
111 srli r4, r4, 18 # get ecr.ip[7:2], interrupt No.
115 ENTRY(handle_nmi) # NMI #1
118 la r8, nmi_exception_handler
122 ENTRY(handle_adelinsn) # AdEL-instruction #2
135 ENTRY(handle_ibe) # BusEL-instruction #5
144 ENTRY(handle_pel) # P-EL #6
153 ENTRY(handle_ccu) # CCU #8
162 ENTRY(handle_ri) # RI #9
171 ENTRY(handle_tr) # Trap #10
180 ENTRY(handle_adedata) # AdES-instruction #12
193 ENTRY(handle_cee) # CeE #16
202 ENTRY(handle_cpe) # CpE #17
211 ENTRY(handle_dbe) # BusEL-data #18
220 ENTRY(handle_reserved) # others
229 #ifndef CONFIG_PREEMPT
230 #define resume_kernel restore_all
232 #define __ret_from_irq ret_from_exception
236 #ifndef CONFIG_PREEMPT
237 ENTRY(ret_from_exception)
238 disable_irq # preempt stop
245 sw r16, [r28, TI_REGS]
247 ENTRY(__ret_from_irq)
248 lw r8, [r0, PT_PSR] # returning to kernel mode?
249 andri.c r8, r8, KU_USER
254 lw r6, [r28, TI_FLAGS] # current->work
255 li r8, _TIF_WORK_MASK
256 and.c r8, r8, r6 # ignoring syscall_trace
262 #ifdef CONFIG_PREEMPT
265 lw r8, [r28, TI_PRE_COUNT]
269 lw r8, [r28, TI_FLAGS]
270 andri.c r9, r8, _TIF_NEED_RESCHED
272 lw r8, [r28, PT_PSR] # Interrupts off?
275 bl preempt_schedule_irq
281 ENTRY(ret_from_kernel_thread)
282 bl schedule_tail # r4=struct task_struct *prev
289 bl schedule_tail # r4=struct task_struct *prev
294 lw r6, [r28, TI_FLAGS] # current->work
295 li r8, _TIF_WORK_MASK
297 bne syscall_exit_work
299 ENTRY(restore_all) # restore full frame
303 andri.c r8, r6, _TIF_NEED_RESCHED # r6 is preloaded with TI_FLAGS
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?
314 andri.c r8, r6, _TIF_NEED_RESCHED
320 bl do_notify_resume # r6 already loaded
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?
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]
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]
372 * task_struct *resume(task_struct *prev, task_struct *next,
373 * struct thread_info *next_ti)
379 sw r9, [r4, THREAD_PSR]
381 sw r3, [r4, THREAD_REG3]
386 addi r8, KERNEL_STACK_SIZE
395 lw r6, [r5, THREAD_PSR]
400 nop; nop; nop; nop; nop
405 sw r8, [r0, 16] # argument 5 from user r8
406 sw r9, [r0, 20] # argument 6 from user r9
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
413 lw r9, [r0, PT_EPC] # skip syscall on return
417 cmpi.c r27, __NR_syscalls # check syscall number
420 slli r8, r27, 2 # get syscall routine
421 la r11, sys_call_table
423 lw r10, [r11] # get syscall entry
428 lw r8, [r28, TI_FLAGS]
429 li r9, _TIF_SYSCALL_TRACE
431 bne syscall_trace_entry
433 brl r10 # Do The Real system call
441 cmpi.c r4, -MAX_ERRNO - 1
447 sw r4, [r0, PT_R4] # save result
451 lw r6, [r28, TI_FLAGS] # current->work
452 li r8, _TIF_WORK_MASK
454 bne syscall_return_work
467 lw r4, [r0, PT_R4] # Restore argument registers
473 li r8, -MAX_ERRNO - 1
474 sw r8, [r0, PT_R7] # set error flag
477 sw r4, [r0, PT_R0] # set flag for syscall
479 1: sw r4, [r0, PT_R2] # result
483 ldi r4, -ENOSYS # error
484 sw r4, [r0, PT_ORIG_R4]
486 ldi r9, 1 # set error flag
490 ENTRY(sys_rt_sigreturn)
492 la r8, score_rt_sigreturn
495 ENTRY(sys_sigaltstack)
497 la r8, score_sigaltstack