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