root/arch/mips/kernel/entry.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 /*
   2  * Low level exception handling
   3  *
   4  * This file is subject to the terms and conditions of the GNU General Public
   5  * License.  See the file "COPYING" in the main directory of this archive
   6  * for more details.
   7  *
   8  * Copyright (C) 1994, 1995 by Ralf Baechle
   9  */
  10 
  11 /*
  12  * entry.S contains the system-call and fault low-level handling routines.
  13  * This also contains the timer-interrupt handler, as well as all interrupts
  14  * and faults that can result in a task-switch. The ISA dependend TLB
  15  * code is in arch/mips/kernel/<cputype>.S
  16  */
  17 #include <linux/sys.h>
  18 
  19 #include <asm/asm.h>
  20 #include <asm/errno.h>
  21 #include <asm/segment.h>
  22 #include <asm/mipsregs.h>
  23 #include <asm/mipsconfig.h>
  24 #include <asm/page.h>
  25 #include <asm/pgtable.h>
  26 #include <asm/stackframe.h>
  27 #include <asm/processor.h>
  28 #include <asm/unistd.h>
  29 
  30 /*
  31  * These are offsets into the task-struct.
  32  */
  33 state           =  0
  34 counter         =  4
  35 priority        =  8
  36 signal          = 12
  37 blocked         = 16
  38 flags           = 20
  39 errno           = 24
  40 exec_domain     = 60
  41 
  42 #ifdef __SMP__
  43 #error "Fix this for SMP"
  44 #else
  45 #define current current_set
  46 #endif
  47 
  48 /*
  49  * Heia ...  The %lo, %hi and %HI stuff is too strong for the ELF assembler
  50  * and the ABI to cope with ...
  51  */
  52                 .text
  53                 .set    noreorder
  54                 .align 4
  55 handle_bottom_half:
  56                 lui     s0,%hi(intr_count)
  57                 lw      s1,%lo(intr_count)(s0)
  58                 mfc0    s3,CP0_STATUS           # Enable IRQs
  59                 addiu   s2,s1,1
  60                 sw      s2,%lo(intr_count)(s0)
  61                 ori     t0,s3,0x1f
  62                 xori    t0,0x1e
  63                 jal     do_bottom_half
  64                 mtc0    t0,CP0_STATUS           # delay slot
  65                 mtc0    s3,CP0_STATUS           # Restore old IRQ state
  66                 b       9f
  67                 sw      s1,%lo(intr_count)(s0)  # delay slot
  68 
  69 reschedule:     jal     schedule 
  70                 nop                             # delay slot
  71 EXPORT(ret_from_sys_call)
  72                 lw      t0,intr_count           # bottom half
  73                 bnez    t0,return
  74 
  75 9:              lw      t0,bh_mask              # delay slot
  76                 lw      t1,bh_active            # unused delay slot
  77                 and     t0,t1
  78                 bnez    t0,handle_bottom_half
  79 
  80                 lw      t0,FR_STATUS(sp)        # returning to kernel mode?
  81                 andi    t1,t0,0x10
  82                 beqz    t1,return               # -> yes
  83 
  84                 mfc0    t0,CP0_STATUS           # delay slot
  85                 lw      t1,need_resched
  86                 ori     t0,0x1f                 # enable irqs
  87                 xori    t0,0x1e
  88                 bnez    t1,reschedule
  89                 mtc0    t0,CP0_STATUS           # delay slot
  90 
  91                 lw      s0,current
  92                 lw      t0,task
  93                 lw      a0,blocked(s0)
  94                 beq     s0,t0,return            # task[0] cannot have signals
  95                                                 # save blocked in a0 for
  96                                                 # signal handling
  97                 lw      t0,signal(s0)
  98                 nor     t1,zero,a0
  99                 and     t1,t0,t1
 100                 beqz    t1,return
 101                 nop
 102 
 103                 jal     do_signal
 104                 move    a1,sp                   # delay slot
 105                 
 106                 .set    noat
 107 EXPORT(return)  RESTORE_ALL
 108                 ERET
 109                 .set    at
 110 
 111 /*
 112  * Beware: interrupt, fast_interrupt and bad_interrupt have unusal
 113  * calling conventions to speedup the mess.
 114  *
 115  * t1 - interrupt number
 116  * s2 - destroyed
 117  * return values:
 118  * v0 - return routine
 119  */
 120                 .text
 121                 .set    at
 122                 .align  5
 123 NESTED(interrupt, FR_SIZE, sp)
 124                 move    s2,ra
 125                 mfc0    t0,CP0_STATUS                   # enable IRQs
 126                 ori     t0,0x1f
 127                 xori    t0,0x1e
 128                 mtc0    t0,CP0_STATUS
 129                 move    a0,t1
 130                 jal     do_IRQ
 131                 move    a1,sp                           # delay slot
 132                 mfc0    t0,CP0_STATUS                   # disable IRQs
 133                 ori     t0,1
 134                 xori    t0,1
 135                 la      v0,ret_from_sys_call
 136                 jr      s2
 137                 mtc0    t0,CP0_STATUS                   # delay slot
 138                 END(interrupt)
 139 
 140                 .align  5
 141 NESTED(fast_interrupt, FR_SIZE, sp)
 142                 move    s2,ra
 143                 move    a0,t1
 144                 jal     do_fast_IRQ
 145                 move    a1,sp                           # delay slot
 146                 lui     v0,%hi(return)
 147                 jr      s2
 148                 addiu   v0,%lo(return)                  # delay slot
 149                 END(fast_interrupt)
 150 
 151 LEAF(bad_interrupt)
 152                 /*
 153                  * Don't return & unblock the pic
 154                  */
 155                 j       return
 156                 nop
 157                 END(bad_interrupt)
 158 
 159 /*
 160  * do_syscall calls the function in a1 with upto 7 arguments.  If over
 161  * four arguments are being requested, the additional arguments will
 162  * be copied from the user stack pointed to by a0->reg29.
 163  * Note that this routine relies on the GNU assemblers weak instruction
 164  * scheduling abilities to generate the best possible code for all MIPS CPUs.
 165  *
 166  * a0 (struct pt_regs *)  pointer to user registers
 167  * a1 (syscall_t)         pointer to syscall to do
 168  * a2 (int)               number of arguments to syscall
 169  */
 170                 .set    noreorder
 171                 .text
 172 NESTED(do_syscalls, 32, sp)
 173                 subu    sp,32
 174                 sw      ra,28(sp)
 175                 sll     a2,a2,PTRLOG
 176                 lw      t0,dst(a2)
 177                 move    t2,a1
 178                 jalr    t0
 179                 lw      t0,FR_REG29(a0)         # get old user stack pointer
 180 
 181                 .set    reorder                 # for sake of R3000
 182 7:              lw      t1,24(t0)               # parameter #7 from usp
 183                 sw      t1,24(t0)
 184 6:              lw      t1,20(t0)               # parameter #6 from usp
 185                 sw      t1,20(t0)
 186 5:              lw      t1,16(t0)               # parameter #5 from usp
 187                 sw      t1,16(t0)
 188                 .set    noreorder
 189 4:              lw      a3,FR_REG7(a0)          # 4 args
 190 3:              lw      a2,FR_REG6(a0)          # 3 args
 191 2:              lw      a1,FR_REG5(a0)          # 2 args
 192 1:              jalr    t2                      # 1 args
 193                 lw      a0,FR_REG4(a0)          # delay slot
 194                 .set    reorder
 195                 lw      ra,28(sp)
 196                 addiu   sp,32
 197                 jr      ra
 198 0:              jalr    t2                      # 0 args, just pass a0
 199                 lw      ra,28(sp)
 200                 addiu   sp,32
 201                 jr      ra
 202                 END(do_syscalls)
 203                 .set    noreorder
 204 
 205                 .rdata
 206                 .align  PTRLOG
 207 dst:            PTR     0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b
 208 
 209 /*
 210  * Build a default exception handler for the exceptions that don't need
 211  * special handlers.  If you didn't know yet - I *like* playing games with
 212  * the C preprocessor ...
 213  */
 214 #define __BUILD_silent(exception)
 215 #define __BUILD_verbose(exception)                                      \
 216                 la      a1,8f;                                          \
 217                 TEXT    (#exception);                                   \
 218                 lw      a2,FR_EPC(sp);                                  \
 219                 PRINT("Got %s at %08x.\n")
 220 #define __BUILD_count(exception)                                        \
 221                 .set    reorder;                                        \
 222                 lw      t0,exception_count_##exception;                 \
 223                 addiu   t0,1;                                           \
 224                 sw      t0,exception_count_##exception;                 \
 225                 .set    noreorder;                                      \
 226                 .data;                                                  \
 227 EXPORT(exception_count_##exception);                                    \
 228                 .word   0;                                              \
 229                 .text;
 230 #define BUILD_HANDLER(exception,verbose)                                \
 231                 .text;                                                  \
 232                 .align  5;                                              \
 233                 NESTED(handle_##exception, FR_SIZE, sp);                \
 234                 .set    noat;                                           \
 235                 SAVE_ALL;                                               \
 236                 STI;                                                    \
 237                 .set    at;                                             \
 238                 __BUILD_##verbose(exception);                           \
 239                 li      t0,-1;                   /* not a sys call */   \
 240                 sw      t0,FR_ORIG_REG2(sp);                            \
 241                 jal     do_##exception;                                 \
 242                 move    a0,sp;                   /* delay slot */       \
 243                 j       ret_from_sys_call;                              \
 244                 nop;                             /* delay slot */       \
 245                 END(handle_##exception)
 246 
 247                 BUILD_HANDLER(adel,verbose)             /* #4  */
 248                 BUILD_HANDLER(ades,verbose)             /* #5  */
 249                 BUILD_HANDLER(ibe,verbose)              /* #6  */
 250                 BUILD_HANDLER(dbe,verbose)              /* #7  */
 251                 BUILD_HANDLER(sys,silent)               /* #8  */
 252                 BUILD_HANDLER(bp,verbose)               /* #9  */
 253                 BUILD_HANDLER(ri,verbose)               /* #10 */
 254                 BUILD_HANDLER(cpu,silent)               /* #11 */
 255                 BUILD_HANDLER(ov,verbose)               /* #12 */
 256                 BUILD_HANDLER(tr,verbose)               /* #13 */
 257                 BUILD_HANDLER(vcei,verbose)             /* #14 */
 258                 BUILD_HANDLER(fpe,verbose)              /* #15 */
 259                 BUILD_HANDLER(watch,verbose)            /* #23 */
 260                 BUILD_HANDLER(vced,verbose)             /* #31 */
 261                 BUILD_HANDLER(reserved,verbose)         /* others */
 262 
 263 /*
 264  * Exception handler table with 32 entries.
 265  * This might be extended to handle software exceptions
 266  */
 267                 .bss
 268                 .align  PTRLOG
 269 EXPORT(exception_handlers)
 270                 .fill   32,PTRSIZE,0
 271 
 272 /*
 273  * Interrupt handler table with 16 entries.
 274  */
 275 EXPORT(IRQ_vectors)
 276                 .fill   16,PTRSIZE,0
 277 
 278 /*
 279  * Table of syscalls
 280  */
 281                 .data
 282                 .align  PTRLOG
 283 EXPORT(sys_call_table)
 284                 /*
 285                  * Reserved space for all the SVR4, SVR, BSD43 and POSIX
 286                  * flavoured syscalls.
 287                  */
 288                 .space  (__NR_Linux)*PTRSIZE
 289 
 290                 /*
 291                  * Linux flavoured syscalls.
 292                  */
 293 #define SYS(call, narg) PTR call
 294 #include "syscalls.h"
 295 
 296 /*
 297  * Number of arguments of each syscall
 298  */
 299 EXPORT(sys_narg_table)
 300                 /*
 301                  * Reserved space for all the SVR4, SVR, BSD43 and POSIX
 302                  * flavoured syscalls.
 303                  */
 304                 .space  (__NR_Linux)
 305 
 306                 /*
 307                  * Linux flavoured syscalls.
 308                  */
 309 #undef SYS
 310 #define SYS(call, narg) .byte narg
 311 #include "syscalls.h"

/* [previous][next][first][last][top][bottom][index][help] */