Back to home page

LXR

 
 

    


0001 /*
0002  * arch/score/kernel/entry.S
0003  *
0004  * Score Processor version.
0005  *
0006  * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
0007  *  Chen Liqin <liqin.chen@sunplusct.com>
0008  *  Lennox Wu <lennox.wu@sunplusct.com>
0009  *
0010  * This program is free software; you can redistribute it and/or modify
0011  * it under the terms of the GNU General Public License as published by
0012  * the Free Software Foundation; either version 2 of the License, or
0013  * (at your option) any later version.
0014  *
0015  * This program is distributed in the hope that it will be useful,
0016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0018  * GNU General Public License for more details.
0019  *
0020  * You should have received a copy of the GNU General Public License
0021  * along with this program; if not, see the file COPYING, or write
0022  * to the Free Software Foundation, Inc.,
0023  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
0024  */
0025 
0026 #include <linux/err.h>
0027 #include <linux/init.h>
0028 #include <linux/linkage.h>
0029 
0030 #include <asm/asmmacro.h>
0031 #include <asm/thread_info.h>
0032 #include <asm/unistd.h>
0033 
0034 /*
0035  * disable interrupts.
0036  */
0037 .macro  disable_irq
0038     mfcr    r8, cr0
0039     srli    r8, r8, 1
0040     slli    r8, r8, 1
0041     mtcr    r8, cr0
0042     nop
0043     nop
0044     nop
0045     nop
0046     nop
0047 .endm
0048 
0049 /*
0050  * enable interrupts.
0051  */
0052 .macro  enable_irq
0053     mfcr    r8, cr0
0054     ori r8, 1
0055     mtcr    r8, cr0
0056     nop
0057     nop
0058     nop
0059     nop
0060     nop
0061 .endm
0062 
0063 __INIT
0064 ENTRY(debug_exception_vector)
0065     nop!
0066     nop!
0067     nop!
0068     nop!
0069     nop!
0070     nop!
0071     nop!
0072     nop!
0073 
0074 ENTRY(general_exception_vector)         # should move to addr 0x200
0075     j   general_exception
0076     nop!
0077     nop!
0078     nop!
0079     nop!
0080     nop!
0081     nop!
0082 
0083 ENTRY(interrupt_exception_vector)       # should move to addr 0x210
0084     j   interrupt_exception
0085     nop!
0086     nop!
0087     nop!
0088     nop!
0089     nop!
0090     nop!
0091 
0092     .section ".text", "ax"
0093     .align  2;
0094 general_exception:
0095     mfcr    r31, cr2
0096     nop
0097     la  r30, exception_handlers
0098     andi    r31, 0x1f           # get ecr.exc_code
0099     slli    r31, r31, 2
0100     add r30, r30, r31
0101     lw  r30, [r30]
0102     br  r30
0103 
0104 interrupt_exception:
0105     SAVE_ALL
0106     mfcr    r4, cr2
0107     nop
0108     lw  r16, [r28, TI_REGS]
0109     sw  r0, [r28, TI_REGS]
0110     la  r3, ret_from_irq
0111     srli    r4, r4, 18          # get ecr.ip[7:2], interrupt No.
0112     mv  r5, r0
0113     j   do_IRQ
0114 
0115 ENTRY(handle_nmi)               # NMI #1
0116     SAVE_ALL
0117     mv  r4, r0
0118     la  r8, nmi_exception_handler
0119     brl r8
0120     j   restore_all
0121 
0122 ENTRY(handle_adelinsn)              # AdEL-instruction #2
0123     SAVE_ALL
0124     mfcr    r8, cr6
0125     nop
0126     nop
0127     sw  r8, [r0, PT_EMA]
0128     mv  r4, r0
0129     la  r8, do_adelinsn
0130     brl r8
0131     mv  r4, r0
0132     j   ret_from_exception
0133     nop
0134 
0135 ENTRY(handle_ibe)               # BusEL-instruction #5
0136     SAVE_ALL
0137     mv  r4, r0
0138     la  r8, do_be
0139     brl r8
0140     mv  r4, r0
0141     j   ret_from_exception
0142     nop
0143 
0144 ENTRY(handle_pel)               # P-EL #6
0145     SAVE_ALL
0146     mv  r4, r0
0147     la  r8, do_pel
0148     brl r8
0149     mv  r4, r0
0150     j   ret_from_exception
0151     nop
0152 
0153 ENTRY(handle_ccu)               # CCU #8
0154     SAVE_ALL
0155     mv  r4, r0
0156     la  r8, do_ccu
0157     brl r8
0158     mv  r4, r0
0159     j   ret_from_exception
0160     nop
0161 
0162 ENTRY(handle_ri)                # RI #9
0163     SAVE_ALL
0164     mv  r4, r0
0165     la  r8, do_ri
0166     brl r8
0167     mv  r4, r0
0168     j   ret_from_exception
0169     nop
0170 
0171 ENTRY(handle_tr)                # Trap #10
0172     SAVE_ALL
0173     mv  r4, r0
0174     la  r8, do_tr
0175     brl r8
0176     mv  r4, r0
0177     j   ret_from_exception
0178     nop
0179 
0180 ENTRY(handle_adedata)               # AdES-instruction #12
0181     SAVE_ALL
0182     mfcr    r8, cr6
0183     nop
0184     nop
0185     sw  r8, [r0, PT_EMA]
0186     mv  r4, r0
0187     la  r8, do_adedata
0188     brl r8
0189     mv  r4, r0
0190     j   ret_from_exception
0191     nop
0192 
0193 ENTRY(handle_cee)               # CeE #16
0194     SAVE_ALL
0195     mv  r4, r0
0196     la  r8, do_cee
0197     brl r8
0198     mv  r4, r0
0199     j   ret_from_exception
0200     nop
0201 
0202 ENTRY(handle_cpe)               # CpE #17
0203     SAVE_ALL
0204     mv  r4, r0
0205     la  r8, do_cpe
0206     brl r8
0207     mv  r4, r0
0208     j   ret_from_exception
0209     nop
0210 
0211 ENTRY(handle_dbe)               # BusEL-data #18
0212     SAVE_ALL
0213     mv  r4, r0
0214     la  r8, do_be
0215     brl r8
0216     mv  r4, r0
0217     j   ret_from_exception
0218     nop
0219 
0220 ENTRY(handle_reserved)              # others
0221     SAVE_ALL
0222     mv  r4, r0
0223     la  r8, do_reserved
0224     brl r8
0225     mv  r4, r0
0226     j   ret_from_exception
0227     nop
0228 
0229 #ifndef CONFIG_PREEMPT
0230 #define resume_kernel   restore_all
0231 #else
0232 #define __ret_from_irq  ret_from_exception
0233 #endif
0234 
0235     .align  2
0236 #ifndef CONFIG_PREEMPT
0237 ENTRY(ret_from_exception)
0238     disable_irq         # preempt stop
0239     nop
0240     j   __ret_from_irq
0241     nop
0242 #endif
0243 
0244 ENTRY(ret_from_irq)
0245     sw  r16, [r28, TI_REGS]
0246 
0247 ENTRY(__ret_from_irq)
0248     lw  r8, [r0, PT_PSR]    # returning to kernel mode?
0249     andri.c r8, r8, KU_USER
0250     beq resume_kernel
0251 
0252 resume_userspace:
0253     disable_irq
0254     lw  r6, [r28, TI_FLAGS] # current->work
0255     li  r8, _TIF_WORK_MASK
0256     and.c   r8, r8, r6      # ignoring syscall_trace
0257     bne work_pending
0258     nop
0259     j   restore_all
0260     nop
0261 
0262 #ifdef CONFIG_PREEMPT
0263 resume_kernel:
0264     disable_irq
0265     lw  r8, [r28, TI_PRE_COUNT]
0266     cmpz.c  r8
0267     bne restore_all
0268 need_resched:
0269     lw  r8, [r28, TI_FLAGS]
0270     andri.c r9, r8, _TIF_NEED_RESCHED
0271     beq restore_all
0272     lw  r8, [r28, PT_PSR]       # Interrupts off?
0273     andri.c r8, r8, 1
0274     beq restore_all
0275     bl  preempt_schedule_irq
0276     nop
0277     j   need_resched
0278     nop
0279 #endif
0280 
0281 ENTRY(ret_from_kernel_thread)
0282     bl  schedule_tail           # r4=struct task_struct *prev
0283     nop
0284     mv  r4, r13
0285     brl r12
0286     j   syscall_exit
0287 
0288 ENTRY(ret_from_fork)
0289     bl  schedule_tail           # r4=struct task_struct *prev
0290 
0291 ENTRY(syscall_exit)
0292     nop
0293     disable_irq
0294     lw  r6, [r28, TI_FLAGS]     # current->work
0295     li  r8, _TIF_WORK_MASK
0296     and.c   r8, r6, r8
0297     bne syscall_exit_work
0298 
0299 ENTRY(restore_all)                  # restore full frame
0300     RESTORE_ALL_AND_RET
0301 
0302 work_pending:
0303     andri.c r8, r6, _TIF_NEED_RESCHED # r6 is preloaded with TI_FLAGS
0304     beq work_notifysig
0305 work_resched:
0306     bl  schedule
0307     nop
0308     disable_irq
0309     lw  r6, [r28, TI_FLAGS]
0310     li  r8, _TIF_WORK_MASK
0311     and.c   r8, r6, r8  # is there any work to be done
0312                 # other than syscall tracing?
0313     beq restore_all
0314     andri.c r8, r6, _TIF_NEED_RESCHED
0315     bne work_resched
0316 
0317 work_notifysig:
0318     mv  r4, r0
0319     li  r5, 0
0320     bl  do_notify_resume    # r6 already loaded
0321     nop
0322     j   resume_userspace
0323     nop
0324 
0325 ENTRY(syscall_exit_work)
0326     li  r8, _TIF_SYSCALL_TRACE
0327     and.c   r8, r8, r6      # r6 is preloaded with TI_FLAGS
0328     beq work_pending        # trace bit set?
0329     nop
0330     enable_irq
0331     mv  r4, r0
0332     li  r5, 1
0333     bl  do_syscall_trace
0334     nop
0335     b   resume_userspace
0336     nop
0337 
0338 .macro  save_context    reg
0339     sw  r12, [\reg, THREAD_REG12];
0340     sw  r13, [\reg, THREAD_REG13];
0341     sw  r14, [\reg, THREAD_REG14];
0342     sw  r15, [\reg, THREAD_REG15];
0343     sw  r16, [\reg, THREAD_REG16];
0344     sw  r17, [\reg, THREAD_REG17];
0345     sw  r18, [\reg, THREAD_REG18];
0346     sw  r19, [\reg, THREAD_REG19];
0347     sw  r20, [\reg, THREAD_REG20];
0348     sw  r21, [\reg, THREAD_REG21];
0349     sw  r29, [\reg, THREAD_REG29];
0350     sw  r2, [\reg, THREAD_REG2];
0351     sw  r0, [\reg, THREAD_REG0]
0352 .endm
0353 
0354 .macro  restore_context reg
0355     lw  r12, [\reg, THREAD_REG12];
0356     lw  r13, [\reg, THREAD_REG13];
0357     lw  r14, [\reg, THREAD_REG14];
0358     lw  r15, [\reg, THREAD_REG15];
0359     lw  r16, [\reg, THREAD_REG16];
0360     lw  r17, [\reg, THREAD_REG17];
0361     lw  r18, [\reg, THREAD_REG18];
0362     lw  r19, [\reg, THREAD_REG19];
0363     lw  r20, [\reg, THREAD_REG20];
0364     lw  r21, [\reg, THREAD_REG21];
0365     lw  r29, [\reg, THREAD_REG29];
0366     lw  r0, [\reg, THREAD_REG0];
0367     lw  r2, [\reg, THREAD_REG2];
0368     lw  r3, [\reg, THREAD_REG3]
0369 .endm
0370 
0371 /*
0372  * task_struct *resume(task_struct *prev, task_struct *next,
0373  *          struct thread_info *next_ti)
0374  */
0375 ENTRY(resume)
0376     mfcr    r9, cr0
0377     nop
0378     nop
0379     sw  r9, [r4, THREAD_PSR]
0380     save_context    r4
0381     sw  r3, [r4, THREAD_REG3]
0382 
0383     mv  r28, r6
0384     restore_context r5
0385     mv  r8, r6
0386     addi    r8, KERNEL_STACK_SIZE
0387     subi    r8, 32
0388     la  r9, kernelsp;
0389     sw  r8, [r9];
0390 
0391     mfcr    r9, cr0
0392     ldis    r7, 0x00ff
0393     nop
0394     and r9, r9, r7
0395     lw  r6, [r5, THREAD_PSR]
0396     not r7, r7
0397     and r6, r6, r7
0398     or  r6, r6, r9
0399     mtcr    r6, cr0
0400     nop; nop; nop; nop; nop
0401     br  r3
0402 
0403 ENTRY(handle_sys)
0404     SAVE_ALL
0405     sw  r8, [r0, 16]        # argument 5 from user r8
0406     sw  r9, [r0, 20]        # argument 6 from user r9
0407     enable_irq
0408 
0409     sw  r4, [r0, PT_ORIG_R4]    #for restart syscall
0410     sw  r7, [r0, PT_ORIG_R7]    #for restart syscall
0411     sw  r27, [r0, PT_IS_SYSCALL] # it from syscall
0412 
0413     lw  r9, [r0, PT_EPC]    # skip syscall on return
0414     addi    r9, 4
0415     sw  r9, [r0, PT_EPC]
0416 
0417     cmpi.c  r27, __NR_syscalls  # check syscall number
0418     bcs illegal_syscall
0419 
0420     slli    r8, r27, 2      # get syscall routine
0421     la  r11, sys_call_table
0422     add r11, r11, r8
0423     lw  r10, [r11]      # get syscall entry
0424 
0425     cmpz.c  r10
0426     beq illegal_syscall
0427 
0428     lw  r8, [r28, TI_FLAGS]
0429     li  r9, _TIF_SYSCALL_TRACE
0430     and.c   r8, r8, r9
0431     bne syscall_trace_entry
0432 
0433     brl r10         # Do The Real system call
0434 
0435     cmpi.c  r4, 0
0436     blt 1f
0437     ldi r8, 0
0438     sw  r8, [r0, PT_R7]
0439     b 2f
0440 1:
0441     cmpi.c  r4, -MAX_ERRNO - 1
0442     ble 2f
0443     ldi r8, 0x1;
0444     sw  r8, [r0, PT_R7]
0445     neg r4, r4
0446 2:
0447     sw  r4, [r0, PT_R4]     # save result
0448 
0449 syscall_return:
0450     disable_irq
0451     lw  r6, [r28, TI_FLAGS] # current->work
0452     li  r8, _TIF_WORK_MASK
0453     and.c   r8, r6, r8
0454     bne syscall_return_work
0455     j   restore_all
0456 
0457 syscall_return_work:
0458     j   syscall_exit_work
0459 
0460 syscall_trace_entry:
0461     mv  r16, r10
0462     mv  r4, r0
0463     li  r5, 0
0464     bl  do_syscall_trace
0465 
0466     mv  r8, r16
0467     lw  r4, [r0, PT_R4]     # Restore argument registers
0468     lw  r5, [r0, PT_R5]
0469     lw  r6, [r0, PT_R6]
0470     lw  r7, [r0, PT_R7]
0471     brl r8
0472 
0473     li  r8, -MAX_ERRNO - 1
0474     sw  r8, [r0, PT_R7]     # set error flag
0475 
0476     neg r4, r4          # error
0477     sw  r4, [r0, PT_R0]     # set flag for syscall
0478                     # restarting
0479 1:  sw  r4, [r0, PT_R2]     # result
0480     j   syscall_exit
0481 
0482 illegal_syscall:
0483     ldi r4, -ENOSYS     # error
0484     sw  r4, [r0, PT_ORIG_R4]
0485     sw  r4, [r0, PT_R4]
0486     ldi r9, 1           # set error flag
0487     sw  r9, [r0, PT_R7]
0488     j   syscall_return
0489 
0490 ENTRY(sys_rt_sigreturn)
0491     mv  r4, r0
0492     la  r8, score_rt_sigreturn
0493     br  r8