linux/arch/score/kernel/entry.S
<<
>>
Prefs
   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
  64ENTRY(debug_exception_vector)
  65        nop!
  66        nop!
  67        nop!
  68        nop!
  69        nop!
  70        nop!
  71        nop!
  72        nop!
  73
  74ENTRY(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
  83ENTRY(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;
  94general_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
 104interrupt_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
 115ENTRY(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
 122ENTRY(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
 135ENTRY(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
 144ENTRY(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
 153ENTRY(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
 162ENTRY(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
 171ENTRY(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
 180ENTRY(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
 193ENTRY(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
 202ENTRY(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
 211ENTRY(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
 220ENTRY(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
 237ENTRY(ret_from_exception)
 238        disable_irq                     # preempt stop
 239        nop
 240        j       __ret_from_irq
 241        nop
 242#endif
 243
 244ENTRY(ret_from_irq)
 245        sw      r16, [r28, TI_REGS]
 246
 247ENTRY(__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
 252resume_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
 263resume_kernel:
 264        disable_irq
 265        lw      r8, [r28, TI_PRE_COUNT]
 266        cmpz.c  r8
 267        bne     restore_all
 268need_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
 281ENTRY(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
 288ENTRY(ret_from_fork)
 289        bl      schedule_tail                   # r4=struct task_struct *prev
 290
 291ENTRY(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
 299ENTRY(restore_all)                                      # restore full frame
 300        RESTORE_ALL_AND_RET
 301
 302work_pending:
 303        andri.c r8, r6, _TIF_NEED_RESCHED # r6 is preloaded with TI_FLAGS
 304        beq     work_notifysig
 305work_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
 317work_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
 325ENTRY(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 */
 375ENTRY(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
 403ENTRY(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        bcs     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
 4401:
 441        cmpi.c  r4, -MAX_ERRNO - 1
 442        ble     2f
 443        ldi     r8, 0x1;
 444        sw      r8, [r0, PT_R7]
 445        neg     r4, r4
 4462:
 447        sw      r4, [r0, PT_R4]         # save result
 448
 449syscall_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
 457syscall_return_work:
 458        j       syscall_exit_work
 459
 460syscall_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
 4791:      sw      r4, [r0, PT_R2]         # result
 480        j       syscall_exit
 481
 482illegal_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
 490ENTRY(sys_rt_sigreturn)
 491        mv      r4, r0
 492        la      r8, score_rt_sigreturn
 493        br      r8
 494