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