1/* $Id: entry.S,v 1.1.1.1 2008/10/15 03:26:01 james26_jang Exp $ 2 * 3 * linux/arch/cris/entry.S 4 * 5 * Copyright (C) 2000, 2001, 2002 Axis Communications AB 6 * 7 * Authors: Bjorn Wesen (bjornw@axis.com) 8 * 9 * $Log: entry.S,v $ 10 * Revision 1.1.1.1 2008/10/15 03:26:01 james26_jang 11 * Initial. 12 * 13 * Revision 1.1.1.1 2008/07/21 09:14:23 james26_jang 14 * New UI, New QoS, New wireless driver(4.151.10.29), ipmonitor. 15 * 16 * Revision 1.1.1.1 2008/07/02 14:38:30 james26_jang 17 * 4.100.10.29, New QoS and New UI. 18 * 19 * Revision 1.1.1.1 2007/02/15 12:10:52 jiahao 20 * initial update 21 * 22 * Revision 1.1.1.1 2007/01/25 12:51:48 jiahao_jhou 23 * 24 * 25 * Revision 1.1.1.1 2003/02/03 22:37:20 mhuang 26 * LINUX_2_4 branch snapshot from linux-mips.org CVS 27 * 28 * Revision 1.39 2002/04/24 00:46:45 bjornw 29 * Added sys_tkill 30 * 31 * Revision 1.38 2002/01/16 15:15:30 bjornw 32 * Use a C-code compatible watchdog reset when NICE_DOGGY is enabled 33 * 34 * Revision 1.37 2001/12/07 17:03:55 bjornw 35 * Call a c-hook called watchdog_bite_hook instead of show_registers directly 36 * 37 * Revision 1.36 2001/11/22 13:36:36 bjornw 38 * * In ret_from_intr, check regs->dccr for usermode reentrance instead of 39 * DCCR explicitely (because the latter might not reflect current reality) 40 * * In mmu_bus_fault, set $r9 _after_ calling the C-code instead of before 41 * since $r9 is call-clobbered and is potentially needed afterwards 42 * 43 * Revision 1.35 2001/10/30 17:10:15 bjornw 44 * Add some syscalls 45 * 46 * Revision 1.34 2001/10/01 14:45:03 bjornw 47 * Removed underscores and added register prefixes 48 * 49 * Revision 1.33 2001/08/21 13:48:01 jonashg 50 * Added fix by HP to avoid oops when doing a hard_reset_now. 51 * 52 * Revision 1.32 2001/08/14 04:32:02 hp 53 * In _resume, add comment why R9 is saved; don't sound like it's call-saved. 54 * 55 * Revision 1.31 2001/07/25 16:07:42 bjornw 56 * softirq_active/mask -> softirq_pending only 57 * 58 * Revision 1.30 2001/07/05 01:03:32 hp 59 * - include asm/errno.h to get ENOSYS. 60 * - Use ENOSYS, not local constant LENOSYS; tweak comments. 61 * - Explain why .include, not #include is used. 62 * - Make oops-register-dump if watchdog bits and it's not expected. 63 * - Don't jsr, use jump _hard_reset_now, and skip spurious nop. 64 * - Use correct section attribute for section .rodata. 65 * - Adjust sys_ni_syscall fill number. 66 * 67 * Revision 1.29 2001/06/25 14:07:00 hp 68 * Fix review comment. 69 * * head.S: Use IO_STATE, IO_FIELD and IO_MASK constructs instead of 70 * magic numbers. Add comment that -traditional must not be used. 71 * * entry.S (SYMBOL_NAME): Change redefinition to use ## concatenation. 72 * Correct and update comment. 73 * * Makefile (.S.o): Don't use -traditional. Add comment why the 74 * toplevel rule can't be used (now that there's a reason). 75 * 76 * Revision 1.28 2001/06/21 02:00:40 hp 77 * * entry.S: Include asm/unistd.h. 78 * (_sys_call_table): Use section .rodata, not .data. 79 * (_kernel_thread): Move from... 80 * * process.c: ... here. 81 * * entryoffsets.c (VAL): Break out from... 82 * (OF): Use VAL. 83 * (LCLONE_VM): New asmified value from CLONE_VM. 84 * 85 * Revision 1.27 2001/05/29 11:25:27 markusl 86 * In case of "spurious_interrupt", do hard_reset instead of hanging system in a loop... 87 * 88 * Revision 1.26 2001/05/15 15:46:03 bjornw 89 * Include config.h now that we use some CONFIG_ options 90 * 91 * Revision 1.25 2001/05/15 05:38:47 hp 92 * Tweaked code in _ret_from_sys_call 93 * 94 * Revision 1.24 2001/05/15 05:27:49 hp 95 * Save r9 in r1 over function call rather than on stack. 96 * 97 * Revision 1.23 2001/05/15 05:10:00 hp 98 * Generate entry.S structure offsets from C 99 * 100 * Revision 1.22 2001/04/17 13:58:39 orjanf 101 * * Renamed CONFIG_KGDB to CONFIG_ETRAX_KGDB. 102 * 103 * Revision 1.21 2001/04/17 11:33:29 orjanf 104 * Updated according to review: 105 * * Included asm/sv_addr_ag.h to get macro for internal register. 106 * * Corrected comment regarding system call argument passing. 107 * * Removed comment about instruction being in a delay slot. 108 * * Added comment about SYMBOL_NAME macro. 109 * 110 * Revision 1.20 2001/04/12 08:51:07 hp 111 * - Add entry for sys_fcntl64. In fact copy last piece from i386 including ... 112 * - .rept to fill table to safe state with sys_ni_syscall. 113 * 114 * Revision 1.19 2001/04/04 09:43:32 orjanf 115 * * Moved do_sigtrap from traps.c to entry.S. 116 * * LTASK_PID need not be global anymore. 117 * 118 * Revision 1.18 2001/03/26 09:25:02 markusl 119 * Updated after review, should now handle USB interrupts correctly. 120 * 121 * Revision 1.17 2001/03/21 16:12:55 bjornw 122 * * Always make room for the cpu status record in the frame, in order to 123 * use the same framelength and layout for both mmu busfaults and normal 124 * irqs. No need to check for the explicit CRIS_FRAME_FIXUP type anymore. 125 * * Fixed bug with using addq for popping the stack in the epilogue - it 126 * destroyed the flag register. Use instructions that don't affect the 127 * flag register instead. 128 * * Removed write to R_PORT_PA_DATA during spurious_interrupt 129 * 130 * Revision 1.16 2001/03/20 19:43:02 bjornw 131 * * Get rid of esp0 setting 132 * * Give a 7th argument to a systemcall - the stackframe 133 * 134 * Revision 1.15 2001/03/05 13:14:30 bjornw 135 * Spelling fix 136 * 137 * Revision 1.14 2001/02/23 08:36:36 perf 138 * New ABI; syscallnr=r9, arg5=mof, arg6=srp. 139 * Corrected tracesys call check. 140 * 141 * Revision 1.13 2001/02/15 08:40:55 perf 142 * H-P by way of perf; 143 * - (_system_call): Don't read system call function address into r1. 144 * - (RBFExit): There is no such thing as a null pop. Adjust sp by addq. 145 * - (_system_call): Don't use r10 and don't save and restore it. 146 * - (THREAD_ESP0): New constant. 147 * - (_system_call): Inline set_esp0. 148 * 149 * Revision 1.12 2001/01/31 17:56:25 orjanf 150 * Added definition of LTASK_PID and made it global. 151 * 152 * Revision 1.11 2001/01/10 21:13:29 bjornw 153 * SYMBOL_NAME is defined incorrectly for the compiler options we currently use 154 * 155 * Revision 1.10 2000/12/18 23:47:56 bjornw 156 * * Added syscall trace support (ptrace), completely untested of course 157 * * Removed redundant check for NULL entries in syscall_table 158 * 159 * Revision 1.9 2000/11/21 16:40:51 bjornw 160 * * New frame type used when an SBFS frame needs to be popped without 161 * actually restarting the instruction 162 * * Enable interrupts in signal_return (they did so in x86, I hope it's a good 163 * idea) 164 * 165 * Revision 1.8 2000/11/17 16:53:35 bjornw 166 * Added detection of frame-type in Rexit, so that mmu_bus_fault can 167 * use ret_from_intr in the return-path to check for signals (like SEGV) 168 * and other foul things that might have occurred during the fault. 169 * 170 * Revision 1.7 2000/10/06 15:04:28 bjornw 171 * Include mof in register savings 172 * 173 * Revision 1.6 2000/09/12 16:02:44 bjornw 174 * Linux-2.4.0-test7 derived updates 175 * 176 * Revision 1.5 2000/08/17 15:35:15 bjornw 177 * 2.4.0-test6 changed local_irq_count and friends API 178 * 179 * Revision 1.4 2000/08/02 13:59:30 bjornw 180 * Removed olduname and uname from the syscall list 181 * 182 * Revision 1.3 2000/07/31 13:32:58 bjornw 183 * * Export ret_from_intr 184 * * _resume updated (prev/last tjohejsan) 185 * * timer_interrupt obsolete 186 * * SIGSEGV detection in mmu_bus_fault temporarily disabled 187 * 188 * 189 */ 190 191/* 192 * entry.S contains the system-call and fault low-level handling routines. 193 * 194 * NOTE: This code handles signal-recognition, which happens every time 195 * after a timer-interrupt and after each system call. 196 * 197 * Stack layout in 'ret_from_system_call': 198 * ptrace needs to have all regs on the stack. 199 * if the order here is changed, it needs to be 200 * updated in fork.c:copy_process, signal.c:do_signal, 201 * ptrace.c and ptrace.h 202 * 203 */ 204 205#include <linux/config.h> 206#include <linux/linkage.h> 207#include <linux/sys.h> 208#include <asm/unistd.h> 209#include <asm/sv_addr_ag.h> 210#include <asm/errno.h> 211 212 ;; functions exported from this file 213 214 .globl system_call 215 .globl ret_from_intr 216 .globl ret_from_sys_call 217 .globl resume 218 .globl multiple_interrupt 219 .globl hwbreakpoint 220 .globl IRQ1_interrupt 221 .globl timer_interrupt 222 .globl timer_shortcut 223 .globl spurious_interrupt 224 .globl hw_bp_trigs 225 .globl mmu_bus_fault 226 .globl do_sigtrap 227 .globl gdb_handle_breakpoint 228 229 .globl sys_call_table 230 231 ;; Get values and offsets into various structs. The file isn't 232 ;; suitable for consumption by the preprocessor, so don't use 233 ;; #include. 234 .include "entryoffsets.s" 235 236 ;; process bits for ptrace. FIXME: Should be in a header file. 237 238PT_TRACESYS_BIT = 1 239 240 ;; below are various parts of system_call which are not in the fast-path 241 242 ;; handle software irqs 243 244_handle_softirq: 245 move.d $r9, $r1 246 jsr do_softirq ; call the C routine for softirq handling 247 move.d $r1, $r9 248 249 ;; fall-through 250 251ret_from_intr: 252 ;; check for resched only if we're going back to user-mode 253 ;; this test matches the user_regs(regs) macro 254 ;; we cannot simply test $dccr, because that does not necessarily 255 ;; reflect what mode we'll return into. 256 257 move.d [$sp + LDCCR], $r0; regs->dccr 258 btstq 8, $r0 ; U-flag 259 bpl _Rexit ; go back directly 260 nop 261 ba _ret_with_reschedule ; go back but check schedule and signals first 262 nop 263 264_reschedule: 265 ;; keep r9 intact 266 move.d $r9, $r1 267 jsr schedule 268 ba ret_from_sys_call 269 move.d $r1, $r9 270 271 ;; return but call do_signal first 272_signal_return: 273 ei ; we can get here from an interrupt 274 move.d $r9, $r10 ; do_signals syscall/irq param 275 moveq 0, $r11 ; oldset param - 0 in this case 276 move.d $sp, $r12 ; another argument to do_signal (the regs param) 277 jsr do_signal ; arch/cris/kernel/signal.c 278 ba _Rexit 279 nop 280 281 ;; The system_call is called by a BREAK instruction, which works like 282 ;; an interrupt call but it stores the return PC in BRP instead of IRP. 283 ;; Since we dont really want to have two epilogues (one for system calls 284 ;; and one for interrupts) we push the contents of BRP instead of IRP in the 285 ;; system call prologue, to make it look like an ordinary interrupt on the 286 ;; stackframe. 287 ;; 288 ;; Since we can't have system calls inside interrupts, it should not matter 289 ;; that we don't stack IRP. 290 ;; 291 ;; In r9 we have the wanted syscall number. Arguments come in r10,r11,r12,r13,mof,srp 292 ;; 293 ;; This function looks on the _surface_ like spaghetti programming, but it's 294 ;; really designed so that the fast-path does not force cache-loading of non-used 295 ;; instructions. Only the non-common cases cause the outlined code to run.. 296 297system_call: 298 ;; stack-frame similar to the irq heads, which is reversed in ret_from_sys_call 299 move $brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame 300 push $srp 301 push $dccr 302 push $mof 303 subq 14*4, $sp ; make room for r0-r13 304 movem $r13, [$sp] ; push r0-r13 305 push $r10 ; push orig_r10 306 clear.d [$sp=$sp-4] ; frametype == 0, normal stackframe 307 308 movs.w -ENOSYS, $r0 309 move.d $r0, [$sp+LR10] ; put the default return value in r10 in the frame 310 311 ;; check if this process is syscall-traced 312 313 movs.w -8192, $r0 ; THREAD_SIZE == 8192 314 and.d $sp, $r0 315 316 move.d [$r0+LTASK_PTRACE], $r0 317 btstq PT_TRACESYS_BIT, $r0 318 bmi _tracesys 319 nop 320 321 ;; check for sanity in the requested syscall number 322 323 cmpu.w NR_syscalls, $r9 324 bcc ret_from_sys_call 325 lslq 2, $r9 ; multiply by 4, in the delay slot 326 327 ;; as a bonus 7th parameter, we give the location on the stack 328 ;; of the register structure itself. some syscalls need this. 329 330 push $sp 331 332 ;; the parameter carrying registers r10, r11, r12 and 13 are intact. 333 ;; the fifth and sixth parameters (if any) was in mof and srp 334 ;; respectively, and we need to put them on the stack. 335 336 push $srp 337 push $mof 338 339 jsr [$r9+sys_call_table] ; actually do the system call 340 addq 3*4, $sp ; pop the mof, srp and regs parameters 341 move.d $r10, [$sp+LR10] ; save the return value 342 343 moveq 1, $r9 ; "parameter" to ret_from_sys_call to show it was a sys call 344 345 ;; fall through into ret_from_sys_call to return 346 347ret_from_sys_call: 348 ;; r9 is a parameter - if 1, we came from a syscall, if 0, from an irq 349 350 ;; check if any bottom halves need service 351 352 test.d [irq_stat] ; softirq_pending 353 bne _handle_softirq 354 nop 355 356_ret_with_reschedule: 357 ;; first get the current task-struct pointer (see top for defs) 358 359 move.d $sp, $r0 360 and.d -8192, $r0 ; THREAD_SIZE == 8192 361 362 ;; see if we want to reschedule into another process 363 364 test.d [$r0+LTASK_NEEDRESCHED] 365 bne _reschedule 366 nop 367 368 ;; see if we need to run signal checks (important that r9 is intact here) 369 370 test.d [$r0+LTASK_SIGPENDING] 371 bne _signal_return 372 nop 373 374_Rexit: 375 ;; this epilogue MUST match the prologues in multiple_interrupt, irq.h and ptregs.h 376 pop $r10 ; frametype 377 bne _RBFexit ; was not CRIS_FRAME_NORMAL, handle otherwise 378 addq 4, $sp ; skip orig_r10, in delayslot 379 movem [$sp+], $r13 ; registers r0-r13 380 pop $mof ; multiply overflow register 381 pop $dccr ; condition codes 382 pop $srp ; subroutine return pointer 383 ;; now we have a 4-word SBFS frame which we do not want to restore 384 ;; using RBF since it was not stacked with SBFS. instead we would like to 385 ;; just get the PC value to restart it with, and skip the rest of 386 ;; the frame. 387 ;; Also notice that it's important to use instructions here that 388 ;; keep the interrupts disabled (since we've already popped DCCR) 389 move [$sp=$sp+16], $p8; pop the SBFS frame from the sp 390 jmpu [$sp-16] ; return through the irp field in the sbfs frame 391 392_RBFexit: 393 movem [$sp+], $r13 ; registers r0-r13, in delay slot 394 pop $mof ; multiply overflow register 395 pop $dccr ; condition codes 396 pop $srp ; subroutine return pointer 397 rbf [$sp+] ; return by popping the CPU status 398 399_tracesys: 400 ;; this first invocation of syscall_trace _requires_ that 401 ;; LR10 in the frame contains -ENOSYS (as is set in the beginning 402 ;; of system_call). 403 404 jsr syscall_trace 405 406 ;; now we should more or less do the same things as in the system_call 407 ;; but since our argument regs got clobbered during syscall_trace and 408 ;; because syscall_trace might want to alter them, we need to reload them 409 ;; from the stack-frame as we use them. 410 411 ;; check for sanity in the requested syscall number 412 413 move.d [$sp+LR9], $r9 414 movs.w -ENOSYS, $r10 415 cmpu.w NR_syscalls, $r9 416 bcc 1f 417 lslq 2, $r9 ; multiply by 4, in the delay slot 418 419 ;; read the system call vector entry into r9 420 421 move.d [$r9+sys_call_table], $r9 422 423 ;; restore r10, r11, r12, r13, mof and srp into the needed registers 424 425 move.d [$sp+LORIG_R10], $r10 ; LR10 is already filled with -ENOSYS. 426 move.d [$sp+LR11], $r11 427 move.d [$sp+LR12], $r12 428 move.d [$sp+LR13], $r13 429 move [$sp+LMOF], $mof 430 move [$sp+LSRP], $srp 431 432 ;; as a bonus 7th parameter, we give the location on the stack 433 ;; of the register structure itself. some syscalls need this. 434 435 push $sp 436 437 ;; the fifth and sixth parameters needs to be put on the stack for 438 ;; the system call to find them 439 440 push $srp 441 push $mof 442 443 jsr $r9 ; actually call the system-call 444 addq 3*4, $sp ; pop the srp, mof and regs parameters 445 4461: move.d $r10, [$sp+LR10]; save the return value 447 448 ;; second call of syscall_trace, to let it grab the results 449 450 jsr syscall_trace 451 452 moveq 1, $r9 ; "parameter" to ret_from_sys_call to show it was a sys call 453 ba ret_from_sys_call 454 nop 455 456 ;; resume performs the actual task-switching, by switching stack pointers 457 ;; input arguments: r10 = prev, r11 = next, r12 = thread offset in task struct 458 ;; returns old current in r10 459 ;; 460 ;; TODO: see the i386 version. The switch_to which calls resume in our version 461 ;; could really be an inline asm of this. 462 463resume: 464 push $srp ; we keep the old/new PC on the stack 465 add.d $r12, $r10 ; r10 = current tasks tss 466 move $dccr, [$r10+LTHREAD_DCCR] ; save irq enable state 467 di 468 469 move $usp, [$r10+LTHREAD_USP] ; save user-mode stackpointer 470 471 ;; See copy_thread for the reason why register R9 is saved. 472 subq 10*4, $sp 473 movem $r9, [$sp] ; save non-scratch registers and R9. 474 475 move.d $sp, [$r10+LTHREAD_KSP] ; save the kernel stack pointer for the old task 476 move.d $sp, $r10 ; return last running task in r10 477 and.d -8192, $r10 ; get task ptr from stackpointer 478 add.d $r12, $r11 ; find the new tasks tss 479 move.d [$r11+LTHREAD_KSP], $sp ; switch into the new stackframe by restoring kernel sp 480 481 movem [$sp+], $r9 ; restore non-scratch registers and R9. 482 483 move [$r11+LTHREAD_USP], $usp ; restore user-mode stackpointer 484 485 move [$r11+LTHREAD_DCCR], $dccr ; restore irq enable status 486 jump [$sp+] ; restore PC 487 488 ;; This is the MMU bus fault handler. 489 ;; It needs to stack the CPU status and overall is different 490 ;; from the other interrupt handlers. 491 492mmu_bus_fault: 493 sbfs [$sp=$sp-16] ; push the internal CPU status 494 ;; the first longword in the sbfs frame was the interrupted PC 495 ;; which fits nicely with the "IRP" slot in pt_regs normally used to 496 ;; contain the return address. used by Oops to print kernel errors.. 497 push $srp ; make a stackframe similar to pt_regs 498 push $dccr 499 push $mof 500 di 501 subq 14*4, $sp 502 movem $r13, [$sp] 503 push $r10 ; dummy orig_r10 504 moveq 1, $r10 505 push $r10 ; frametype == 1, BUSFAULT frame type 506 507 move.d $sp, $r10 ; pt_regs argument to handle_mmu_bus_fault 508 509 jsr handle_mmu_bus_fault ; in arch/cris/mm/fault.c 510 511 ;; now we need to return through the normal path, we cannot just 512 ;; do the RBFexit since we might have killed off the running 513 ;; process due to a SEGV, scheduled due to a page blocking or 514 ;; whatever. 515 516 moveq 0, $r9 ; busfault is equivalent to an irq 517 518 ba ret_from_intr 519 nop 520 521 ;; special handlers for breakpoint and NMI 522hwbreakpoint: 523 push $dccr 524 di 525 push $r10 526 push $r11 527 move.d [hw_bp_trig_ptr],$r10 528 move.d [$r10],$r11 529 cmp.d 42,$r11 530 beq 1f 531 nop 532 move $brp,$r11 533 move.d $r11,[$r10+] 534 move.d $r10,[hw_bp_trig_ptr] 5351: pop $r11 536 pop $r10 537 pop $dccr 538 retb 539 nop 540 541IRQ1_interrupt: 542 543#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM) 544;; If we receive a watchdog interrupt while it is not expected, then set 545;; up a canonical frame and dump register contents before dying. 546 547 ;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!! 548 move $brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame 549 push $srp 550 push $dccr 551 push $mof 552 di 553 subq 14*4, $sp 554 movem $r13, [$sp] 555 push $r10 ; push orig_r10 556 clear.d [$sp=$sp-4] ; frametype == 0, normal frame 557 558;; We don't check that we actually were bit by the watchdog as opposed to 559;; an external NMI, since there is currently no handler for external NMI. 560 561;; Check if we're waiting for reset to happen, as signalled by 562;; hard_reset_now setting cause_of_death to a magic value. If so, just 563;; get stuck until reset happens. 564 .comm cause_of_death, 4 ;; Don't declare this anywhere. 565 move.d [cause_of_death], $r10 566 cmp.d 0xbedead, $r10 567_killed_by_death: 568 beq _killed_by_death 569 nop 570 571;; We'll see this in ksymoops dumps. 572Watchdog_bite: 573 574#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY 575 ;; We just restart the watchdog here to be sure we dont get 576 ;; hit while printing the watchdogmsg below 577 ;; This restart is compatible with the rest of the C-code, so 578 ;; the C-code can keep restarting the watchdog after this point. 579 ;; The non-NICE_DOGGY code below though, disables the possibility 580 ;; to restart since it changes the watchdog key, to avoid any 581 ;; buggy loops etc. keeping the watchdog alive after this. 582 jsr reset_watchdog 583#else 584;; We need to extend the 3.3ms after the NMI at watchdog bite, so we have 585;; time for an oops-dump over a 115k2 serial wire. Another 100ms should do. 586 587;; Change the watchdog key to an arbitrary 3-bit value and restart the 588;; watchdog. 589#define WD_INIT 2 590 moveq IO_FIELD (R_WATCHDOG, key, WD_INIT), $r10 591 move.d R_WATCHDOG, $r11 592 593 move.d $r10, [$r11] 594 moveq IO_FIELD (R_WATCHDOG, key, \ 595 IO_EXTRACT (R_WATCHDOG, key, \ 596 IO_MASK (R_WATCHDOG, key)) \ 597 ^ WD_INIT) \ 598 | IO_STATE (R_WATCHDOG, enable, start), $r10 599 move.d $r10, [$r11] 600#endif 601 602;; Note that we don't do "setf m" here (or after two necessary NOPs), 603;; since *not* doing that saves us from re-entrancy checks. We don't want 604;; to get here again due to possible subsequent NMIs; we want the watchdog 605;; to reset us. 606 607 move.d _watchdogmsg,$r10 608 jsr printk 609 610 move.d $sp, $r10 611 jsr watchdog_bite_hook 612 613;; This nop is here so we see the "Watchdog_bite" label in ksymoops dumps 614;; rather than "spurious_interrupt". 615 nop 616;; At this point we drop down into spurious_interrupt, which will do a 617;; hard reset. 618 619 .section .rodata,"a" 620_watchdogmsg: 621 .ascii "Oops: bitten by watchdog\n\0" 622 .previous 623 624#endif /* CONFIG_ETRAX_WATCHDOG and not CONFIG_SVINTO_SIM */ 625 626spurious_interrupt: 627 di 628 jump hard_reset_now 629 630 ;; this handles the case when multiple interrupts arrive at the same time 631 ;; we jump to the first set interrupt bit in a priority fashion 632 ;; the hardware will call the unserved interrupts after the handler finishes 633 634multiple_interrupt: 635 ;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!! 636 move $irp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame 637 push $srp 638 push $dccr 639 push $mof 640 di 641 subq 14*4, $sp 642 movem $r13, [$sp] 643 push $r10 ; push orig_r10 644 clear.d [$sp=$sp-4] ; frametype == 0, normal frame 645 646 move.d irq_shortcuts + 8, $r1 647 moveq 2, $r2 ; first bit we care about is the timer0 irq 648 move.d [R_VECT_MASK_RD], $r0; read the irq bits that triggered the multiple irq 6491: 650 btst $r2, $r0 ; check for the irq given by bit r2 651 bmi _do_shortcut ; actually do the shortcut 652 nop 653 addq 1, $r2 ; next vector bit 654 addq 4, $r1 ; next vector 655 cmp.b 32, $r2 656 bne 1b ; process all irq's up to and including number 31 657 nop 658 659 ;; strange, we didn't get any set vector bits.. oh well, just return 660 661 ba _Rexit 662 nop 663 664_do_shortcut: 665 test.d [$r1] 666 beq _Rexit 667 nop 668 jump [$r1] ; jump to the irq handlers shortcut 669 670do_sigtrap: 671 ;; 672 ;; SIGTRAP the process that executed the break instruction. 673 ;; Make a frame that Rexit in entry.S expects. 674 ;; 675 move $brp, [$sp=$sp-16] ; Push BRP while faking a cpu status record. 676 push $srp ; Push subroutine return pointer. 677 push $dccr ; Push condition codes. 678 push $mof ; Push multiply overflow reg. 679 di ; Need to disable irq's at this point. 680 subq 14*4, $sp ; Make room for r0-r13. 681 movem $r13, [$sp] ; Push the r0-r13 registers. 682 push $r10 ; Push orig_r10. 683 clear.d [$sp=$sp-4] ; Frametype - this is a normal stackframe. 684 685 movs.w -8192,$r9 ; THREAD_SIZE == 8192 686 and.d $sp, $r9 687 move.d [$r9+LTASK_PID], $r10 ; current->pid as arg1. 688 moveq 5, $r11 ; SIGTRAP as arg2. 689 jsr sys_kill 690 jump ret_from_intr ; Use the return routine for interrupts. 691 692gdb_handle_breakpoint: 693 push $dccr 694 push $r0 695#ifdef CONFIG_ETRAX_KGDB 696 move $dccr, $r0 ; U-flag not affected by previous insns. 697 btstq 8, $r0 ; Test the U-flag. 698 bmi _ugdb_handle_breakpoint ; Go to user mode debugging. 699 nop ; Empty delay slot (cannot pop r0 here). 700 pop $r0 ; Restore r0. 701 ba kgdb_handle_breakpoint ; Go to kernel debugging. 702 pop $dccr ; Restore dccr in delay slot. 703#endif 704 705_ugdb_handle_breakpoint: 706 move $brp, $r0 ; Use r0 temporarily for calculation. 707 subq 2, $r0 ; Set to address of previous instruction. 708 move $r0, $brp 709 pop $r0 ; Restore r0. 710 ba do_sigtrap ; SIGTRAP the offending process. 711 pop $dccr ; Restore dccr in delay slot. 712 713 .data 714 715hw_bp_trigs: 716 .space 64*4 717hw_bp_trig_ptr: 718 .dword hw_bp_trigs 719 720/* 721 * This is the mechanism for creating a new kernel thread. 722 * 723 * NOTE! Only a kernel-only process (i.e. the swapper or direct descendants 724 * who haven't done an "execve()") should use this: it will work within 725 * a system call from a "real" process, but the process memory space will 726 * not be free'd until both the parent and the child have exited. 727 * 728 * This *can* be done in C with an single-asm-wrapped-in-a-function, but you 729 * get more or less gross code. The safer you make the asm-constraints, 730 * the grosser the code, at least with the gcc version in cris-dist-1.13. 731 */ 732 733/* int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) */ 734/* r10 r11 r12 */ 735 736 .text 737 .global kernel_thread 738kernel_thread: 739 740 /* Save ARG for later. */ 741 move.d $r11, $r13 742 743 /* r11 is argument 2 to clone, the flags */ 744 move.d $r12, $r11 745 or.w LCLONE_VM, $r11 746 747 /* Save FN for later. */ 748 move.d $r10, $r12 749 750 /* r9 contains syscall number, to sys_clone */ 751 movu.w __NR_clone, $r9 752 753 /* r10 is argument 1 to clone */ 754 clear.d $r10 755 756 /* call sys_clone, this will fork */ 757 break 13 758 759 /* parent or child? child returns 0 here. */ 760 test.d $r10 761 762 /* jump if parent */ 763 bne 1f 764 nop /* delay slot */ 765 766 /* set argument to function to call */ 767 move.d $r13, $r10 768 769 /* call specified function */ 770 jsr $r12 771 /* If we ever return from the function, something bad has happened. */ 772 773 /* r9 is sys_exit syscall number */ 774 movu.w __NR_exit, $r9 775 776 /* Give a really bad exit-value */ 777 moveq -1, $r10 778 779 /* call sys_exit, killing the child */ 780 break 13 7811: 782 ret 783 nop /* delay slot */ 784 785 .section .rodata,"a" 786sys_call_table: 787 .long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/ 788 .long SYMBOL_NAME(sys_exit) 789 .long SYMBOL_NAME(sys_fork) 790 .long SYMBOL_NAME(sys_read) 791 .long SYMBOL_NAME(sys_write) 792 .long SYMBOL_NAME(sys_open) /* 5 */ 793 .long SYMBOL_NAME(sys_close) 794 .long SYMBOL_NAME(sys_waitpid) 795 .long SYMBOL_NAME(sys_creat) 796 .long SYMBOL_NAME(sys_link) 797 .long SYMBOL_NAME(sys_unlink) /* 10 */ 798 .long SYMBOL_NAME(sys_execve) 799 .long SYMBOL_NAME(sys_chdir) 800 .long SYMBOL_NAME(sys_time) 801 .long SYMBOL_NAME(sys_mknod) 802 .long SYMBOL_NAME(sys_chmod) /* 15 */ 803 .long SYMBOL_NAME(sys_lchown16) 804 .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */ 805 .long SYMBOL_NAME(sys_stat) 806 .long SYMBOL_NAME(sys_lseek) 807 .long SYMBOL_NAME(sys_getpid) /* 20 */ 808 .long SYMBOL_NAME(sys_mount) 809 .long SYMBOL_NAME(sys_oldumount) 810 .long SYMBOL_NAME(sys_setuid16) 811 .long SYMBOL_NAME(sys_getuid16) 812 .long SYMBOL_NAME(sys_stime) /* 25 */ 813 .long SYMBOL_NAME(sys_ptrace) 814 .long SYMBOL_NAME(sys_alarm) 815 .long SYMBOL_NAME(sys_fstat) 816 .long SYMBOL_NAME(sys_pause) 817 .long SYMBOL_NAME(sys_utime) /* 30 */ 818 .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */ 819 .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */ 820 .long SYMBOL_NAME(sys_access) 821 .long SYMBOL_NAME(sys_nice) 822 .long SYMBOL_NAME(sys_ni_syscall) /* 35 old ftime syscall holder */ 823 .long SYMBOL_NAME(sys_sync) 824 .long SYMBOL_NAME(sys_kill) 825 .long SYMBOL_NAME(sys_rename) 826 .long SYMBOL_NAME(sys_mkdir) 827 .long SYMBOL_NAME(sys_rmdir) /* 40 */ 828 .long SYMBOL_NAME(sys_dup) 829 .long SYMBOL_NAME(sys_pipe) 830 .long SYMBOL_NAME(sys_times) 831 .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */ 832 .long SYMBOL_NAME(sys_brk) /* 45 */ 833 .long SYMBOL_NAME(sys_setgid16) 834 .long SYMBOL_NAME(sys_getgid16) 835 .long SYMBOL_NAME(sys_signal) 836 .long SYMBOL_NAME(sys_geteuid16) 837 .long SYMBOL_NAME(sys_getegid16) /* 50 */ 838 .long SYMBOL_NAME(sys_acct) 839 .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */ 840 .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */ 841 .long SYMBOL_NAME(sys_ioctl) 842 .long SYMBOL_NAME(sys_fcntl) /* 55 */ 843 .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */ 844 .long SYMBOL_NAME(sys_setpgid) 845 .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */ 846 .long SYMBOL_NAME(sys_ni_syscall) /* old sys_olduname holder */ 847 .long SYMBOL_NAME(sys_umask) /* 60 */ 848 .long SYMBOL_NAME(sys_chroot) 849 .long SYMBOL_NAME(sys_ustat) 850 .long SYMBOL_NAME(sys_dup2) 851 .long SYMBOL_NAME(sys_getppid) 852 .long SYMBOL_NAME(sys_getpgrp) /* 65 */ 853 .long SYMBOL_NAME(sys_setsid) 854 .long SYMBOL_NAME(sys_sigaction) 855 .long SYMBOL_NAME(sys_sgetmask) 856 .long SYMBOL_NAME(sys_ssetmask) 857 .long SYMBOL_NAME(sys_setreuid16) /* 70 */ 858 .long SYMBOL_NAME(sys_setregid16) 859 .long SYMBOL_NAME(sys_sigsuspend) 860 .long SYMBOL_NAME(sys_sigpending) 861 .long SYMBOL_NAME(sys_sethostname) 862 .long SYMBOL_NAME(sys_setrlimit) /* 75 */ 863 .long SYMBOL_NAME(sys_old_getrlimit) 864 .long SYMBOL_NAME(sys_getrusage) 865 .long SYMBOL_NAME(sys_gettimeofday) 866 .long SYMBOL_NAME(sys_settimeofday) 867 .long SYMBOL_NAME(sys_getgroups16) /* 80 */ 868 .long SYMBOL_NAME(sys_setgroups16) 869 .long SYMBOL_NAME(sys_select) /* was old_select in Linux/E100 */ 870 .long SYMBOL_NAME(sys_symlink) 871 .long SYMBOL_NAME(sys_lstat) 872 .long SYMBOL_NAME(sys_readlink) /* 85 */ 873 .long SYMBOL_NAME(sys_uselib) 874 .long SYMBOL_NAME(sys_swapon) 875 .long SYMBOL_NAME(sys_reboot) 876 .long SYMBOL_NAME(old_readdir) 877 .long SYMBOL_NAME(old_mmap) /* 90 */ 878 .long SYMBOL_NAME(sys_munmap) 879 .long SYMBOL_NAME(sys_truncate) 880 .long SYMBOL_NAME(sys_ftruncate) 881 .long SYMBOL_NAME(sys_fchmod) 882 .long SYMBOL_NAME(sys_fchown16) /* 95 */ 883 .long SYMBOL_NAME(sys_getpriority) 884 .long SYMBOL_NAME(sys_setpriority) 885 .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */ 886 .long SYMBOL_NAME(sys_statfs) 887 .long SYMBOL_NAME(sys_fstatfs) /* 100 */ 888 .long SYMBOL_NAME(sys_ni_syscall) /* sys_ioperm in i386 */ 889 .long SYMBOL_NAME(sys_socketcall) 890 .long SYMBOL_NAME(sys_syslog) 891 .long SYMBOL_NAME(sys_setitimer) 892 .long SYMBOL_NAME(sys_getitimer) /* 105 */ 893 .long SYMBOL_NAME(sys_newstat) 894 .long SYMBOL_NAME(sys_newlstat) 895 .long SYMBOL_NAME(sys_newfstat) 896 .long SYMBOL_NAME(sys_ni_syscall) /* old sys_uname holder */ 897 .long SYMBOL_NAME(sys_ni_syscall) /* sys_iopl in i386 */ 898 .long SYMBOL_NAME(sys_vhangup) 899 .long SYMBOL_NAME(sys_ni_syscall) /* old "idle" system call */ 900 .long SYMBOL_NAME(sys_ni_syscall) /* vm86old in i386 */ 901 .long SYMBOL_NAME(sys_wait4) 902 .long SYMBOL_NAME(sys_swapoff) /* 115 */ 903 .long SYMBOL_NAME(sys_sysinfo) 904 .long SYMBOL_NAME(sys_ipc) 905 .long SYMBOL_NAME(sys_fsync) 906 .long SYMBOL_NAME(sys_sigreturn) 907 .long SYMBOL_NAME(sys_clone) /* 120 */ 908 .long SYMBOL_NAME(sys_setdomainname) 909 .long SYMBOL_NAME(sys_newuname) 910 .long SYMBOL_NAME(sys_ni_syscall) /* TODO sys_modify_ldt - do something ?*/ 911 .long SYMBOL_NAME(sys_adjtimex) 912 .long SYMBOL_NAME(sys_mprotect) /* 125 */ 913 .long SYMBOL_NAME(sys_sigprocmask) 914 .long SYMBOL_NAME(sys_create_module) 915 .long SYMBOL_NAME(sys_init_module) 916 .long SYMBOL_NAME(sys_delete_module) 917 .long SYMBOL_NAME(sys_get_kernel_syms) /* 130 */ 918 .long SYMBOL_NAME(sys_quotactl) 919 .long SYMBOL_NAME(sys_getpgid) 920 .long SYMBOL_NAME(sys_fchdir) 921 .long SYMBOL_NAME(sys_bdflush) 922 .long SYMBOL_NAME(sys_sysfs) /* 135 */ 923 .long SYMBOL_NAME(sys_personality) 924 .long SYMBOL_NAME(sys_ni_syscall) /* for afs_syscall */ 925 .long SYMBOL_NAME(sys_setfsuid16) 926 .long SYMBOL_NAME(sys_setfsgid16) 927 .long SYMBOL_NAME(sys_llseek) /* 140 */ 928 .long SYMBOL_NAME(sys_getdents) 929 .long SYMBOL_NAME(sys_select) 930 .long SYMBOL_NAME(sys_flock) 931 .long SYMBOL_NAME(sys_msync) 932 .long SYMBOL_NAME(sys_readv) /* 145 */ 933 .long SYMBOL_NAME(sys_writev) 934 .long SYMBOL_NAME(sys_getsid) 935 .long SYMBOL_NAME(sys_fdatasync) 936 .long SYMBOL_NAME(sys_sysctl) 937 .long SYMBOL_NAME(sys_mlock) /* 150 */ 938 .long SYMBOL_NAME(sys_munlock) 939 .long SYMBOL_NAME(sys_mlockall) 940 .long SYMBOL_NAME(sys_munlockall) 941 .long SYMBOL_NAME(sys_sched_setparam) 942 .long SYMBOL_NAME(sys_sched_getparam) /* 155 */ 943 .long SYMBOL_NAME(sys_sched_setscheduler) 944 .long SYMBOL_NAME(sys_sched_getscheduler) 945 .long SYMBOL_NAME(sys_sched_yield) 946 .long SYMBOL_NAME(sys_sched_get_priority_max) 947 .long SYMBOL_NAME(sys_sched_get_priority_min) /* 160 */ 948 .long SYMBOL_NAME(sys_sched_rr_get_interval) 949 .long SYMBOL_NAME(sys_nanosleep) 950 .long SYMBOL_NAME(sys_mremap) 951 .long SYMBOL_NAME(sys_setresuid16) 952 .long SYMBOL_NAME(sys_getresuid16) /* 165 */ 953 .long SYMBOL_NAME(sys_ni_syscall) /* sys_vm86 */ 954 .long SYMBOL_NAME(sys_query_module) 955 .long SYMBOL_NAME(sys_poll) 956 .long SYMBOL_NAME(sys_nfsservctl) 957 .long SYMBOL_NAME(sys_setresgid16) /* 170 */ 958 .long SYMBOL_NAME(sys_getresgid16) 959 .long SYMBOL_NAME(sys_prctl) 960 .long SYMBOL_NAME(sys_rt_sigreturn) 961 .long SYMBOL_NAME(sys_rt_sigaction) 962 .long SYMBOL_NAME(sys_rt_sigprocmask) /* 175 */ 963 .long SYMBOL_NAME(sys_rt_sigpending) 964 .long SYMBOL_NAME(sys_rt_sigtimedwait) 965 .long SYMBOL_NAME(sys_rt_sigqueueinfo) 966 .long SYMBOL_NAME(sys_rt_sigsuspend) 967 .long SYMBOL_NAME(sys_pread) /* 180 */ 968 .long SYMBOL_NAME(sys_pwrite) 969 .long SYMBOL_NAME(sys_chown16) 970 .long SYMBOL_NAME(sys_getcwd) 971 .long SYMBOL_NAME(sys_capget) 972 .long SYMBOL_NAME(sys_capset) /* 185 */ 973 .long SYMBOL_NAME(sys_sigaltstack) 974 .long SYMBOL_NAME(sys_sendfile) 975 .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ 976 .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ 977 .long SYMBOL_NAME(sys_vfork) /* 190 */ 978 .long SYMBOL_NAME(sys_getrlimit) 979 .long SYMBOL_NAME(sys_mmap2) 980 .long SYMBOL_NAME(sys_truncate64) 981 .long SYMBOL_NAME(sys_ftruncate64) 982 .long SYMBOL_NAME(sys_stat64) /* 195 */ 983 .long SYMBOL_NAME(sys_lstat64) 984 .long SYMBOL_NAME(sys_fstat64) 985 .long SYMBOL_NAME(sys_lchown) 986 .long SYMBOL_NAME(sys_getuid) 987 .long SYMBOL_NAME(sys_getgid) /* 200 */ 988 .long SYMBOL_NAME(sys_geteuid) 989 .long SYMBOL_NAME(sys_getegid) 990 .long SYMBOL_NAME(sys_setreuid) 991 .long SYMBOL_NAME(sys_setregid) 992 .long SYMBOL_NAME(sys_getgroups) /* 205 */ 993 .long SYMBOL_NAME(sys_setgroups) 994 .long SYMBOL_NAME(sys_fchown) 995 .long SYMBOL_NAME(sys_setresuid) 996 .long SYMBOL_NAME(sys_getresuid) 997 .long SYMBOL_NAME(sys_setresgid) /* 210 */ 998 .long SYMBOL_NAME(sys_getresgid) 999 .long SYMBOL_NAME(sys_chown) 1000 .long SYMBOL_NAME(sys_setuid) 1001 .long SYMBOL_NAME(sys_setgid) 1002 .long SYMBOL_NAME(sys_setfsuid) /* 215 */ 1003 .long SYMBOL_NAME(sys_setfsgid) 1004 .long SYMBOL_NAME(sys_pivot_root) 1005 .long SYMBOL_NAME(sys_mincore) 1006 .long SYMBOL_NAME(sys_madvise) 1007 .long SYMBOL_NAME(sys_getdents64) /* 220 */ 1008 .long SYMBOL_NAME(sys_fcntl64) 1009 .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */ 1010 .long SYMBOL_NAME(sys_ni_syscall) /* Reserved for Security */ 1011 .long SYMBOL_NAME(sys_gettid) 1012 .long SYMBOL_NAME(sys_readahead) /* 225 */ 1013 .long SYMBOL_NAME(sys_tkill) 1014 1015 /* 1016 * NOTE!! This doesn't have to be exact - we just have 1017 * to make sure we have _enough_ of the "sys_ni_syscall" 1018 * entries. Don't panic if you notice that this hasn't 1019 * been shrunk every time we add a new system call. 1020 */ 1021 1022 .rept NR_syscalls-(.-sys_call_table)/4 1023 .long SYMBOL_NAME(sys_ni_syscall) 1024 .endr 1025 1026