aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/entry.S
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/sh/kernel/entry.S
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/sh/kernel/entry.S')
-rw-r--r--arch/sh/kernel/entry.S1149
1 files changed, 1149 insertions, 0 deletions
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S
new file mode 100644
index 000000000000..6615e4838ee4
--- /dev/null
+++ b/arch/sh/kernel/entry.S
@@ -0,0 +1,1149 @@
1/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
2 *
3 * linux/arch/sh/entry.S
4 *
5 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
6 * Copyright (C) 2003 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 *
12 */
13
14#include <linux/sys.h>
15#include <linux/linkage.h>
16#include <linux/config.h>
17#include <asm/asm-offsets.h>
18#include <asm/thread_info.h>
19#include <asm/unistd.h>
20
21#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
22#define sys_nfsservctl sys_ni_syscall
23#endif
24
25#if !defined(CONFIG_MMU)
26#define sys_madvise sys_ni_syscall
27#define sys_readahead sys_ni_syscall
28#define sys_mprotect sys_ni_syscall
29#define sys_msync sys_ni_syscall
30#define sys_mlock sys_ni_syscall
31#define sys_munlock sys_ni_syscall
32#define sys_mlockall sys_ni_syscall
33#define sys_munlockall sys_ni_syscall
34#define sys_mremap sys_ni_syscall
35#define sys_mincore sys_ni_syscall
36#define sys_remap_file_pages sys_ni_syscall
37#endif
38
39! NOTE:
40! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
41! to be jumped is too far, but it causes illegal slot exception.
42
43/*
44 * entry.S contains the system-call and fault low-level handling routines.
45 * This also contains the timer-interrupt handler, as well as all interrupts
46 * and faults that can result in a task-switch.
47 *
48 * NOTE: This code handles signal-recognition, which happens every time
49 * after a timer-interrupt and after each system call.
50 *
51 * NOTE: This code uses a convention that instructions in the delay slot
52 * of a transfer-control instruction are indented by an extra space, thus:
53 *
54 * jmp @k0 ! control-transfer instruction
55 * ldc k1, ssr ! delay slot
56 *
57 * Stack layout in 'ret_from_syscall':
58 * ptrace needs to have all regs on the stack.
59 * if the order here is changed, it needs to be
60 * updated in ptrace.c and ptrace.h
61 *
62 * r0
63 * ...
64 * r15 = stack pointer
65 * spc
66 * pr
67 * ssr
68 * gbr
69 * mach
70 * macl
71 * syscall #
72 *
73 */
74
75ENOSYS = 38
76EINVAL = 22
77
78#if defined(CONFIG_CPU_SH3)
79TRA = 0xffffffd0
80EXPEVT = 0xffffffd4
81#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
82 defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
83INTEVT = 0xa4000000 ! INTEVTE2(0xa4000000)
84#else
85INTEVT = 0xffffffd8
86#endif
87MMU_TEA = 0xfffffffc ! TLB Exception Address Register
88#elif defined(CONFIG_CPU_SH4)
89TRA = 0xff000020
90EXPEVT = 0xff000024
91INTEVT = 0xff000028
92MMU_TEA = 0xff00000c ! TLB Exception Address Register
93#endif
94
95#if defined(CONFIG_KGDB_NMI)
96NMI_VEC = 0x1c0 ! Must catch early for debounce
97#endif
98
99/* Offsets to the stack */
100OFF_R0 = 0 /* Return value. New ABI also arg4 */
101OFF_R1 = 4 /* New ABI: arg5 */
102OFF_R2 = 8 /* New ABI: arg6 */
103OFF_R3 = 12 /* New ABI: syscall_nr */
104OFF_R4 = 16 /* New ABI: arg0 */
105OFF_R5 = 20 /* New ABI: arg1 */
106OFF_R6 = 24 /* New ABI: arg2 */
107OFF_R7 = 28 /* New ABI: arg3 */
108OFF_SP = (15*4)
109OFF_PC = (16*4)
110OFF_SR = (16*4+8)
111OFF_TRA = (16*4+6*4)
112
113
114#define k0 r0
115#define k1 r1
116#define k2 r2
117#define k3 r3
118#define k4 r4
119
120#define k_ex_code r2_bank /* r2_bank1 */
121#define g_imask r6 /* r6_bank1 */
122#define k_g_imask r6_bank /* r6_bank1 */
123#define current r7 /* r7_bank1 */
124
125/*
126 * Kernel mode register usage:
127 * k0 scratch
128 * k1 scratch
129 * k2 scratch (Exception code)
130 * k3 scratch (Return address)
131 * k4 scratch
132 * k5 reserved
133 * k6 Global Interrupt Mask (0--15 << 4)
134 * k7 CURRENT_THREAD_INFO (pointer to current thread info)
135 */
136
137!
138! TLB Miss / Initial Page write exception handling
139! _and_
140! TLB hits, but the access violate the protection.
141! It can be valid access, such as stack grow and/or C-O-W.
142!
143!
144! Find the pmd/pte entry and loadtlb
145! If it's not found, cause address error (SEGV)
146!
147! Although this could be written in assembly language (and it'd be faster),
148! this first version depends *much* on C implementation.
149!
150
151#define CLI() \
152 stc sr, r0; \
153 or #0xf0, r0; \
154 ldc r0, sr
155
156#define STI() \
157 mov.l __INV_IMASK, r11; \
158 stc sr, r10; \
159 and r11, r10; \
160 stc k_g_imask, r11; \
161 or r11, r10; \
162 ldc r10, sr
163
164#if defined(CONFIG_PREEMPT)
165# define preempt_stop() CLI()
166#else
167# define preempt_stop()
168# define resume_kernel restore_all
169#endif
170
171#if defined(CONFIG_MMU)
172 .align 2
173ENTRY(tlb_miss_load)
174 bra call_dpf
175 mov #0, r5
176
177 .align 2
178ENTRY(tlb_miss_store)
179 bra call_dpf
180 mov #1, r5
181
182 .align 2
183ENTRY(initial_page_write)
184 bra call_dpf
185 mov #1, r5
186
187 .align 2
188ENTRY(tlb_protection_violation_load)
189 bra call_dpf
190 mov #0, r5
191
192 .align 2
193ENTRY(tlb_protection_violation_store)
194 bra call_dpf
195 mov #1, r5
196
197call_dpf:
198 mov.l 1f, r0
199 mov r5, r8
200 mov.l @r0, r6
201 mov r6, r9
202 mov.l 2f, r0
203 sts pr, r10
204 jsr @r0
205 mov r15, r4
206 !
207 tst r0, r0
208 bf/s 0f
209 lds r10, pr
210 rts
211 nop
2120: STI()
213 mov.l 3f, r0
214 mov r9, r6
215 mov r8, r5
216 jmp @r0
217 mov r15, r4
218
219 .align 2
2201: .long MMU_TEA
2212: .long __do_page_fault
2223: .long do_page_fault
223
224 .align 2
225ENTRY(address_error_load)
226 bra call_dae
227 mov #0,r5 ! writeaccess = 0
228
229 .align 2
230ENTRY(address_error_store)
231 bra call_dae
232 mov #1,r5 ! writeaccess = 1
233
234 .align 2
235call_dae:
236 mov.l 1f, r0
237 mov.l @r0, r6 ! address
238 mov.l 2f, r0
239 jmp @r0
240 mov r15, r4 ! regs
241
242 .align 2
2431: .long MMU_TEA
2442: .long do_address_error
245#endif /* CONFIG_MMU */
246
247#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
248! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
249! If both are configured, handle the debug traps (breakpoints) in SW,
250! but still allow BIOS traps to FW.
251
252 .align 2
253debug_kernel:
254#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
255 /* Force BIOS call to FW (debug_trap put TRA in r8) */
256 mov r8,r0
257 shlr2 r0
258 cmp/eq #0x3f,r0
259 bt debug_kernel_fw
260#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
261
262debug_enter:
263#if defined(CONFIG_SH_KGDB)
264 /* Jump to kgdb, pass stacked regs as arg */
265debug_kernel_sw:
266 mov.l 3f, r0
267 jmp @r0
268 mov r15, r4
269 .align 2
2703: .long kgdb_handle_exception
271#endif /* CONFIG_SH_KGDB */
272
273#if defined(CONFIG_SH_STANDARD_BIOS)
274 /* Unwind the stack and jmp to the debug entry */
275debug_kernel_fw:
276 mov.l @r15+, r0
277 mov.l @r15+, r1
278 mov.l @r15+, r2
279 mov.l @r15+, r3
280 mov.l @r15+, r4
281 mov.l @r15+, r5
282 mov.l @r15+, r6
283 mov.l @r15+, r7
284 stc sr, r8
285 mov.l 1f, r9 ! BL =1, RB=1, IMASK=0x0F
286 or r9, r8
287 ldc r8, sr ! here, change the register bank
288 mov.l @r15+, r8
289 mov.l @r15+, r9
290 mov.l @r15+, r10
291 mov.l @r15+, r11
292 mov.l @r15+, r12
293 mov.l @r15+, r13
294 mov.l @r15+, r14
295 mov.l @r15+, k0
296 ldc.l @r15+, spc
297 lds.l @r15+, pr
298 mov.l @r15+, k1
299 ldc.l @r15+, gbr
300 lds.l @r15+, mach
301 lds.l @r15+, macl
302 mov k0, r15
303 !
304 mov.l 2f, k0
305 mov.l @k0, k0
306 jmp @k0
307 ldc k1, ssr
308 .align 2
3091: .long 0x300000f0
3102: .long gdb_vbr_vector
311#endif /* CONFIG_SH_STANDARD_BIOS */
312
313#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
314
315
316 .align 2
317debug_trap:
318#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
319 mov #OFF_SR, r0
320 mov.l @(r0,r15), r0 ! get status register
321 shll r0
322 shll r0 ! kernel space?
323 bt/s debug_kernel
324#endif
325 mov.l @r15, r0 ! Restore R0 value
326 mov.l 1f, r8
327 jmp @r8
328 nop
329
330 .align 2
331ENTRY(exception_error)
332 !
333 STI()
334 mov.l 2f, r0
335 jmp @r0
336 nop
337
338!
339 .align 2
3401: .long break_point_trap_software
3412: .long do_exception_error
342
343 .align 2
344ret_from_exception:
345 preempt_stop()
346ret_from_irq:
347 !
348 mov #OFF_SR, r0
349 mov.l @(r0,r15), r0 ! get status register
350 shll r0
351 shll r0 ! kernel space?
352 bt/s resume_kernel ! Yes, it's from kernel, go back soon
353 GET_THREAD_INFO(r8)
354
355#ifdef CONFIG_PREEMPT
356 bra resume_userspace
357 nop
358ENTRY(resume_kernel)
359 mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
360 tst r0, r0
361 bf noresched
362need_resched:
363 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
364 tst #_TIF_NEED_RESCHED, r0 ! need_resched set?
365 bt noresched
366
367 mov #OFF_SR, r0
368 mov.l @(r0,r15), r0 ! get status register
369 and #0xf0, r0 ! interrupts off (exception path)?
370 cmp/eq #0xf0, r0
371 bt noresched
372
373 mov.l 1f, r0
374 mov.l r0, @(TI_PRE_COUNT,r8)
375
376 STI()
377 mov.l 2f, r0
378 jsr @r0
379 nop
380 mov #0, r0
381 mov.l r0, @(TI_PRE_COUNT,r8)
382 CLI()
383
384 bra need_resched
385 nop
386noresched:
387 bra restore_all
388 nop
389
390 .align 2
3911: .long PREEMPT_ACTIVE
3922: .long schedule
393#endif
394
395ENTRY(resume_userspace)
396 ! r8: current_thread_info
397 CLI()
398 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
399 tst #_TIF_WORK_MASK, r0
400 bt/s restore_all
401 tst #_TIF_NEED_RESCHED, r0
402
403 .align 2
404work_pending:
405 ! r0: current_thread_info->flags
406 ! r8: current_thread_info
407 ! t: result of "tst #_TIF_NEED_RESCHED, r0"
408 bf/s work_resched
409 tst #_TIF_SIGPENDING, r0
410work_notifysig:
411 bt/s restore_all
412 mov r15, r4
413 mov #0, r5
414 mov.l 2f, r1
415 mova restore_all, r0
416 jmp @r1
417 lds r0, pr
418work_resched:
419#ifndef CONFIG_PREEMPT
420 ! gUSA handling
421 mov.l @(OFF_SP,r15), r0 ! get user space stack pointer
422 mov r0, r1
423 shll r0
424 bf/s 1f
425 shll r0
426 bf/s 1f
427 mov #OFF_PC, r0
428 ! SP >= 0xc0000000 : gUSA mark
429 mov.l @(r0,r15), r2 ! get user space PC (program counter)
430 mov.l @(OFF_R0,r15), r3 ! end point
431 cmp/hs r3, r2 ! r2 >= r3?
432 bt 1f
433 add r3, r1 ! rewind point #2
434 mov.l r1, @(r0,r15) ! reset PC to rewind point #2
435 !
4361:
437#endif
438 mov.l 1f, r1
439 jsr @r1 ! schedule
440 nop
441 CLI()
442 !
443 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
444 tst #_TIF_WORK_MASK, r0
445 bt restore_all
446 bra work_pending
447 tst #_TIF_NEED_RESCHED, r0
448
449 .align 2
4501: .long schedule
4512: .long do_signal
452
453 .align 2
454syscall_exit_work:
455 ! r0: current_thread_info->flags
456 ! r8: current_thread_info
457 tst #_TIF_SYSCALL_TRACE, r0
458 bt/s work_pending
459 tst #_TIF_NEED_RESCHED, r0
460 STI()
461 ! XXX setup arguments...
462 mov.l 4f, r0 ! do_syscall_trace
463 jsr @r0
464 nop
465 bra resume_userspace
466 nop
467
468 .align 2
469syscall_trace_entry:
470 ! Yes it is traced.
471 ! XXX setup arguments...
472 mov.l 4f, r11 ! Call do_syscall_trace which notifies
473 jsr @r11 ! superior (will chomp R[0-7])
474 nop
475 ! Reload R0-R4 from kernel stack, where the
476 ! parent may have modified them using
477 ! ptrace(POKEUSR). (Note that R0-R2 are
478 ! used by the system call handler directly
479 ! from the kernel stack anyway, so don't need
480 ! to be reloaded here.) This allows the parent
481 ! to rewrite system calls and args on the fly.
482 mov.l @(OFF_R4,r15), r4 ! arg0
483 mov.l @(OFF_R5,r15), r5
484 mov.l @(OFF_R6,r15), r6
485 mov.l @(OFF_R7,r15), r7 ! arg3
486 mov.l @(OFF_R3,r15), r3 ! syscall_nr
487 ! Arrange for do_syscall_trace to be called
488 ! again as the system call returns.
489 mov.l 2f, r10 ! Number of syscalls
490 cmp/hs r10, r3
491 bf syscall_call
492 mov #-ENOSYS, r0
493 bra syscall_exit
494 mov.l r0, @(OFF_R0,r15) ! Return value
495
496/*
497 * Syscall interface:
498 *
499 * Syscall #: R3
500 * Arguments #0 to #3: R4--R7
501 * Arguments #4 to #6: R0, R1, R2
502 * TRA: (number of arguments + 0x10) x 4
503 *
504 * This code also handles delegating other traps to the BIOS/gdb stub
505 * according to:
506 *
507 * Trap number
508 * (TRA>>2) Purpose
509 * -------- -------
510 * 0x0-0xf old syscall ABI
511 * 0x10-0x1f new syscall ABI
512 * 0x20-0xff delegated through debug_trap to BIOS/gdb stub.
513 *
514 * Note: When we're first called, the TRA value must be shifted
515 * right 2 bits in order to get the value that was used as the "trapa"
516 * argument.
517 */
518
519 .align 2
520 .globl ret_from_fork
521ret_from_fork:
522 mov.l 1f, r8
523 jsr @r8
524 mov r0, r4
525 bra syscall_exit
526 nop
527 .align 2
5281: .long schedule_tail
529 !
530ENTRY(system_call)
531 mov.l 1f, r9
532 mov.l @r9, r8 ! Read from TRA (Trap Address) Register
533 !
534 ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
535 mov #0x7f, r9
536 cmp/hi r9, r8
537 bt/s 0f
538 mov #OFF_TRA, r9
539 add r15, r9
540 !
541 mov.l r8, @r9 ! set TRA value to tra
542 STI()
543 ! Call the system call handler through the table.
544 ! First check for bad syscall number
545 mov r3, r9
546 mov.l 2f, r8 ! Number of syscalls
547 cmp/hs r8, r9
548 bf/s good_system_call
549 GET_THREAD_INFO(r8)
550syscall_badsys: ! Bad syscall number
551 mov #-ENOSYS, r0
552 bra resume_userspace
553 mov.l r0, @(OFF_R0,r15) ! Return value
554 !
5550:
556 bra debug_trap
557 nop
558 !
559good_system_call: ! Good syscall number
560 mov.l @(TI_FLAGS,r8), r8
561 mov #_TIF_SYSCALL_TRACE, r10
562 tst r10, r8
563 bf syscall_trace_entry
564 !
565syscall_call:
566 shll2 r9 ! x4
567 mov.l 3f, r8 ! Load the address of sys_call_table
568 add r8, r9
569 mov.l @r9, r8
570 jsr @r8 ! jump to specific syscall handler
571 nop
572 mov.l r0, @(OFF_R0,r15) ! save the return value
573 !
574syscall_exit:
575 CLI()
576 !
577 GET_THREAD_INFO(r8)
578 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
579 tst #_TIF_ALLWORK_MASK, r0
580 bf syscall_exit_work
581restore_all:
582 mov.l @r15+, r0
583 mov.l @r15+, r1
584 mov.l @r15+, r2
585 mov.l @r15+, r3
586 mov.l @r15+, r4
587 mov.l @r15+, r5
588 mov.l @r15+, r6
589 mov.l @r15+, r7
590 !
591 stc sr, r8
592 mov.l 7f, r9
593 or r9, r8 ! BL =1, RB=1
594 ldc r8, sr ! here, change the register bank
595 !
596 mov.l @r15+, r8
597 mov.l @r15+, r9
598 mov.l @r15+, r10
599 mov.l @r15+, r11
600 mov.l @r15+, r12
601 mov.l @r15+, r13
602 mov.l @r15+, r14
603 mov.l @r15+, k4 ! original stack pointer
604 ldc.l @r15+, spc
605 lds.l @r15+, pr
606 mov.l @r15+, k3 ! original SR
607 ldc.l @r15+, gbr
608 lds.l @r15+, mach
609 lds.l @r15+, macl
610 add #4, r15 ! Skip syscall number
611 !
612#ifdef CONFIG_SH_DSP
613 mov.l @r15+, k0 ! DSP mode marker
614 mov.l 5f, k1
615 cmp/eq k0, k1 ! Do we have a DSP stack frame?
616 bf skip_restore
617
618 stc sr, k0 ! Enable CPU DSP mode
619 or k1, k0 ! (within kernel it may be disabled)
620 ldc k0, sr
621 mov r2, k0 ! Backup r2
622
623 ! Restore DSP registers from stack
624 mov r15, r2
625 movs.l @r2+, a1
626 movs.l @r2+, a0g
627 movs.l @r2+, a1g
628 movs.l @r2+, m0
629 movs.l @r2+, m1
630 mov r2, r15
631
632 lds.l @r15+, a0
633 lds.l @r15+, x0
634 lds.l @r15+, x1
635 lds.l @r15+, y0
636 lds.l @r15+, y1
637 lds.l @r15+, dsr
638 ldc.l @r15+, rs
639 ldc.l @r15+, re
640 ldc.l @r15+, mod
641
642 mov k0, r2 ! Restore r2
643skip_restore:
644#endif
645 !
646 ! Calculate new SR value
647 mov k3, k2 ! original SR value
648 mov.l 9f, k1
649 and k1, k2 ! Mask orignal SR value
650 !
651 mov k3, k0 ! Calculate IMASK-bits
652 shlr2 k0
653 and #0x3c, k0
654 cmp/eq #0x3c, k0
655 bt/s 6f
656 shll2 k0
657 mov g_imask, k0
658 !
6596: or k0, k2 ! Set the IMASK-bits
660 ldc k2, ssr
661 !
662#if defined(CONFIG_KGDB_NMI)
663 ! Clear in_nmi
664 mov.l 4f, k0
665 mov #0, k1
666 mov.b k1, @k0
667#endif
668 mov.l @r15+, k2 ! restore EXPEVT
669 mov k4, r15
670 rte
671 nop
672
673 .align 2
6741: .long TRA
6752: .long NR_syscalls
6763: .long sys_call_table
6774: .long do_syscall_trace
6785: .long 0x00001000 ! DSP
6797: .long 0x30000000
6809:
681__INV_IMASK:
682 .long 0xffffff0f ! ~(IMASK)
683
684! Exception Vector Base
685!
686! Should be aligned page boundary.
687!
688 .balign 4096,0,4096
689ENTRY(vbr_base)
690 .long 0
691!
692 .balign 256,0,256
693general_exception:
694 mov.l 1f, k2
695 mov.l 2f, k3
696 bra handle_exception
697 mov.l @k2, k2
698 .align 2
6991: .long EXPEVT
7002: .long ret_from_exception
701!
702!
703 .balign 1024,0,1024
704tlb_miss:
705 mov.l 1f, k2
706 mov.l 4f, k3
707 bra handle_exception
708 mov.l @k2, k2
709!
710 .balign 512,0,512
711interrupt:
712 mov.l 2f, k2
713 mov.l 3f, k3
714#if defined(CONFIG_KGDB_NMI)
715 ! Debounce (filter nested NMI)
716 mov.l @k2, k0
717 mov.l 5f, k1
718 cmp/eq k1, k0
719 bf 0f
720 mov.l 6f, k1
721 tas.b @k1
722 bt 0f
723 rte
724 nop
725 .align 2
7265: .long NMI_VEC
7276: .long in_nmi
7280:
729#endif /* defined(CONFIG_KGDB_NMI) */
730 bra handle_exception
731 mov.l @k2, k2
732
733 .align 2
7341: .long EXPEVT
7352: .long INTEVT
7363: .long ret_from_irq
7374: .long ret_from_exception
738
739!
740!
741 .align 2
742handle_exception:
743 ! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
744 ! save all registers onto stack.
745 !
746 stc ssr, k0 ! Is it from kernel space?
747 shll k0 ! Check MD bit (bit30) by shifting it into...
748 shll k0 ! ...the T bit
749 bt/s 1f ! It's a kernel to kernel transition.
750 mov r15, k0 ! save original stack to k0
751 /* User space to kernel */
752 mov #0x20, k1
753 shll8 k1 ! k1 := 8192 (== THREAD_SIZE)
754 add current, k1
755 mov k1, r15 ! change to kernel stack
756 !
7571: mov #-1, k4
758 mov.l 2f, k1
759 !
760#ifdef CONFIG_SH_DSP
761 mov.l r2, @-r15 ! Save r2, we need another reg
762 stc sr, k4
763 mov.l 1f, r2
764 tst r2, k4 ! Check if in DSP mode
765 mov.l @r15+, r2 ! Restore r2 now
766 bt/s skip_save
767 mov #0, k4 ! Set marker for no stack frame
768
769 mov r2, k4 ! Backup r2 (in k4) for later
770
771 ! Save DSP registers on stack
772 stc.l mod, @-r15
773 stc.l re, @-r15
774 stc.l rs, @-r15
775 sts.l dsr, @-r15
776 sts.l y1, @-r15
777 sts.l y0, @-r15
778 sts.l x1, @-r15
779 sts.l x0, @-r15
780 sts.l a0, @-r15
781
782 ! GAS is broken, does not generate correct "movs.l Ds,@-As" instr.
783
784 ! FIXME: Make sure that this is still the case with newer toolchains,
785 ! as we're not at all interested in supporting ancient toolchains at
786 ! this point. -- PFM.
787
788 mov r15, r2
789 .word 0xf653 ! movs.l a1, @-r2
790 .word 0xf6f3 ! movs.l a0g, @-r2
791 .word 0xf6d3 ! movs.l a1g, @-r2
792 .word 0xf6c3 ! movs.l m0, @-r2
793 .word 0xf6e3 ! movs.l m1, @-r2
794 mov r2, r15
795
796 mov k4, r2 ! Restore r2
797 mov.l 1f, k4 ! Force DSP stack frame
798skip_save:
799 mov.l k4, @-r15 ! Push DSP mode marker onto stack
800#endif
801 ! Save the user registers on the stack.
802 mov.l k2, @-r15 ! EXPEVT
803 mov.l k4, @-r15 ! set TRA (default: -1)
804 !
805 sts.l macl, @-r15
806 sts.l mach, @-r15
807 stc.l gbr, @-r15
808 stc.l ssr, @-r15
809 sts.l pr, @-r15
810 stc.l spc, @-r15
811 !
812 lds k3, pr ! Set the return address to pr
813 !
814 mov.l k0, @-r15 ! save orignal stack
815 mov.l r14, @-r15
816 mov.l r13, @-r15
817 mov.l r12, @-r15
818 mov.l r11, @-r15
819 mov.l r10, @-r15
820 mov.l r9, @-r15
821 mov.l r8, @-r15
822 !
823 stc sr, r8 ! Back to normal register bank, and
824 or k1, r8 ! Block all interrupts
825 mov.l 3f, k1
826 and k1, r8 ! ...
827 ldc r8, sr ! ...changed here.
828 !
829 mov.l r7, @-r15
830 mov.l r6, @-r15
831 mov.l r5, @-r15
832 mov.l r4, @-r15
833 mov.l r3, @-r15
834 mov.l r2, @-r15
835 mov.l r1, @-r15
836 mov.l r0, @-r15
837 ! Then, dispatch to the handler, according to the exception code.
838 stc k_ex_code, r8
839 shlr2 r8
840 shlr r8
841 mov.l 4f, r9
842 add r8, r9
843 mov.l @r9, r9
844 jmp @r9
845 nop
846
847 .align 2
8481: .long 0x00001000 ! DSP=1
8492: .long 0x000080f0 ! FD=1, IMASK=15
8503: .long 0xcfffffff ! RB=0, BL=0
8514: .long exception_handling_table
852
853 .align 2
854ENTRY(exception_none)
855 rts
856 nop
857
858 .data
859ENTRY(sys_call_table)
860 .long sys_ni_syscall /* 0 - old "setup()" system call*/
861 .long sys_exit
862 .long sys_fork
863 .long sys_read
864 .long sys_write
865 .long sys_open /* 5 */
866 .long sys_close
867 .long sys_waitpid
868 .long sys_creat
869 .long sys_link
870 .long sys_unlink /* 10 */
871 .long sys_execve
872 .long sys_chdir
873 .long sys_time
874 .long sys_mknod
875 .long sys_chmod /* 15 */
876 .long sys_lchown16
877 .long sys_ni_syscall /* old break syscall holder */
878 .long sys_stat
879 .long sys_lseek
880 .long sys_getpid /* 20 */
881 .long sys_mount
882 .long sys_oldumount
883 .long sys_setuid16
884 .long sys_getuid16
885 .long sys_stime /* 25 */
886 .long sys_ptrace
887 .long sys_alarm
888 .long sys_fstat
889 .long sys_pause
890 .long sys_utime /* 30 */
891 .long sys_ni_syscall /* old stty syscall holder */
892 .long sys_ni_syscall /* old gtty syscall holder */
893 .long sys_access
894 .long sys_nice
895 .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
896 .long sys_sync
897 .long sys_kill
898 .long sys_rename
899 .long sys_mkdir
900 .long sys_rmdir /* 40 */
901 .long sys_dup
902 .long sys_pipe
903 .long sys_times
904 .long sys_ni_syscall /* old prof syscall holder */
905 .long sys_brk /* 45 */
906 .long sys_setgid16
907 .long sys_getgid16
908 .long sys_signal
909 .long sys_geteuid16
910 .long sys_getegid16 /* 50 */
911 .long sys_acct
912 .long sys_umount /* recycled never used phys() */
913 .long sys_ni_syscall /* old lock syscall holder */
914 .long sys_ioctl
915 .long sys_fcntl /* 55 */
916 .long sys_ni_syscall /* old mpx syscall holder */
917 .long sys_setpgid
918 .long sys_ni_syscall /* old ulimit syscall holder */
919 .long sys_ni_syscall /* sys_olduname */
920 .long sys_umask /* 60 */
921 .long sys_chroot
922 .long sys_ustat
923 .long sys_dup2
924 .long sys_getppid
925 .long sys_getpgrp /* 65 */
926 .long sys_setsid
927 .long sys_sigaction
928 .long sys_sgetmask
929 .long sys_ssetmask
930 .long sys_setreuid16 /* 70 */
931 .long sys_setregid16
932 .long sys_sigsuspend
933 .long sys_sigpending
934 .long sys_sethostname
935 .long sys_setrlimit /* 75 */
936 .long sys_old_getrlimit
937 .long sys_getrusage
938 .long sys_gettimeofday
939 .long sys_settimeofday
940 .long sys_getgroups16 /* 80 */
941 .long sys_setgroups16
942 .long sys_ni_syscall /* sys_oldselect */
943 .long sys_symlink
944 .long sys_lstat
945 .long sys_readlink /* 85 */
946 .long sys_uselib
947 .long sys_swapon
948 .long sys_reboot
949 .long old_readdir
950 .long old_mmap /* 90 */
951 .long sys_munmap
952 .long sys_truncate
953 .long sys_ftruncate
954 .long sys_fchmod
955 .long sys_fchown16 /* 95 */
956 .long sys_getpriority
957 .long sys_setpriority
958 .long sys_ni_syscall /* old profil syscall holder */
959 .long sys_statfs
960 .long sys_fstatfs /* 100 */
961 .long sys_ni_syscall /* ioperm */
962 .long sys_socketcall
963 .long sys_syslog
964 .long sys_setitimer
965 .long sys_getitimer /* 105 */
966 .long sys_newstat
967 .long sys_newlstat
968 .long sys_newfstat
969 .long sys_uname
970 .long sys_ni_syscall /* 110 */ /* iopl */
971 .long sys_vhangup
972 .long sys_ni_syscall /* idle */
973 .long sys_ni_syscall /* vm86old */
974 .long sys_wait4
975 .long sys_swapoff /* 115 */
976 .long sys_sysinfo
977 .long sys_ipc
978 .long sys_fsync
979 .long sys_sigreturn
980 .long sys_clone /* 120 */
981 .long sys_setdomainname
982 .long sys_newuname
983 .long sys_ni_syscall /* sys_modify_ldt */
984 .long sys_adjtimex
985 .long sys_mprotect /* 125 */
986 .long sys_sigprocmask
987 .long sys_ni_syscall /* old "create_module" */
988 .long sys_init_module
989 .long sys_delete_module
990 .long sys_ni_syscall /* 130: old "get_kernel_syms" */
991 .long sys_quotactl
992 .long sys_getpgid
993 .long sys_fchdir
994 .long sys_bdflush
995 .long sys_sysfs /* 135 */
996 .long sys_personality
997 .long sys_ni_syscall /* for afs_syscall */
998 .long sys_setfsuid16
999 .long sys_setfsgid16
1000 .long sys_llseek /* 140 */
1001 .long sys_getdents
1002 .long sys_select
1003 .long sys_flock
1004 .long sys_msync
1005 .long sys_readv /* 145 */
1006 .long sys_writev
1007 .long sys_getsid
1008 .long sys_fdatasync
1009 .long sys_sysctl
1010 .long sys_mlock /* 150 */
1011 .long sys_munlock
1012 .long sys_mlockall
1013 .long sys_munlockall
1014 .long sys_sched_setparam
1015 .long sys_sched_getparam /* 155 */
1016 .long sys_sched_setscheduler
1017 .long sys_sched_getscheduler
1018 .long sys_sched_yield
1019 .long sys_sched_get_priority_max
1020 .long sys_sched_get_priority_min /* 160 */
1021 .long sys_sched_rr_get_interval
1022 .long sys_nanosleep
1023 .long sys_mremap
1024 .long sys_setresuid16
1025 .long sys_getresuid16 /* 165 */
1026 .long sys_ni_syscall /* vm86 */
1027 .long sys_ni_syscall /* old "query_module" */
1028 .long sys_poll
1029 .long sys_nfsservctl
1030 .long sys_setresgid16 /* 170 */
1031 .long sys_getresgid16
1032 .long sys_prctl
1033 .long sys_rt_sigreturn
1034 .long sys_rt_sigaction
1035 .long sys_rt_sigprocmask /* 175 */
1036 .long sys_rt_sigpending
1037 .long sys_rt_sigtimedwait
1038 .long sys_rt_sigqueueinfo
1039 .long sys_rt_sigsuspend
1040 .long sys_pread_wrapper /* 180 */
1041 .long sys_pwrite_wrapper
1042 .long sys_chown16
1043 .long sys_getcwd
1044 .long sys_capget
1045 .long sys_capset /* 185 */
1046 .long sys_sigaltstack
1047 .long sys_sendfile
1048 .long sys_ni_syscall /* streams1 */
1049 .long sys_ni_syscall /* streams2 */
1050 .long sys_vfork /* 190 */
1051 .long sys_getrlimit
1052 .long sys_mmap2
1053 .long sys_truncate64
1054 .long sys_ftruncate64
1055 .long sys_stat64 /* 195 */
1056 .long sys_lstat64
1057 .long sys_fstat64
1058 .long sys_lchown
1059 .long sys_getuid
1060 .long sys_getgid /* 200 */
1061 .long sys_geteuid
1062 .long sys_getegid
1063 .long sys_setreuid
1064 .long sys_setregid
1065 .long sys_getgroups /* 205 */
1066 .long sys_setgroups
1067 .long sys_fchown
1068 .long sys_setresuid
1069 .long sys_getresuid
1070 .long sys_setresgid /* 210 */
1071 .long sys_getresgid
1072 .long sys_chown
1073 .long sys_setuid
1074 .long sys_setgid
1075 .long sys_setfsuid /* 215 */
1076 .long sys_setfsgid
1077 .long sys_pivot_root
1078 .long sys_mincore
1079 .long sys_madvise
1080 .long sys_getdents64 /* 220 */
1081 .long sys_fcntl64
1082 .long sys_ni_syscall /* reserved for TUX */
1083 .long sys_ni_syscall /* Reserved for Security */
1084 .long sys_gettid
1085 .long sys_readahead /* 225 */
1086 .long sys_setxattr
1087 .long sys_lsetxattr
1088 .long sys_fsetxattr
1089 .long sys_getxattr
1090 .long sys_lgetxattr /* 230 */
1091 .long sys_fgetxattr
1092 .long sys_listxattr
1093 .long sys_llistxattr
1094 .long sys_flistxattr
1095 .long sys_removexattr /* 235 */
1096 .long sys_lremovexattr
1097 .long sys_fremovexattr
1098 .long sys_tkill
1099 .long sys_sendfile64
1100 .long sys_futex /* 240 */
1101 .long sys_sched_setaffinity
1102 .long sys_sched_getaffinity
1103 .long sys_ni_syscall
1104 .long sys_ni_syscall
1105 .long sys_io_setup /* 245 */
1106 .long sys_io_destroy
1107 .long sys_io_getevents
1108 .long sys_io_submit
1109 .long sys_io_cancel
1110 .long sys_fadvise64 /* 250 */
1111 .long sys_ni_syscall
1112 .long sys_exit_group
1113 .long sys_lookup_dcookie
1114 .long sys_epoll_create
1115 .long sys_epoll_ctl /* 255 */
1116 .long sys_epoll_wait
1117 .long sys_remap_file_pages
1118 .long sys_set_tid_address
1119 .long sys_timer_create
1120 .long sys_timer_settime /* 260 */
1121 .long sys_timer_gettime
1122 .long sys_timer_getoverrun
1123 .long sys_timer_delete
1124 .long sys_clock_settime
1125 .long sys_clock_gettime /* 265 */
1126 .long sys_clock_getres
1127 .long sys_clock_nanosleep
1128 .long sys_statfs64
1129 .long sys_fstatfs64
1130 .long sys_tgkill /* 270 */
1131 .long sys_utimes
1132 .long sys_fadvise64_64_wrapper
1133 .long sys_ni_syscall /* Reserved for vserver */
1134 .long sys_ni_syscall /* Reserved for mbind */
1135 .long sys_ni_syscall /* 275 - get_mempolicy */
1136 .long sys_ni_syscall /* set_mempolicy */
1137 .long sys_mq_open
1138 .long sys_mq_unlink
1139 .long sys_mq_timedsend
1140 .long sys_mq_timedreceive /* 280 */
1141 .long sys_mq_notify
1142 .long sys_mq_getsetattr
1143 .long sys_ni_syscall /* Reserved for kexec */
1144 .long sys_waitid
1145 .long sys_add_key /* 285 */
1146 .long sys_request_key
1147 .long sys_keyctl
1148
1149/* End of entry.S */