aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/kernel/entry-common.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/entry-common.S')
-rw-r--r--arch/sh/kernel/entry-common.S203
1 files changed, 100 insertions, 103 deletions
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index 926b2e7b11c..13047a4facd 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -1,9 +1,6 @@
-/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
- *
- * linux/arch/sh/entry.S
- *
+/*
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
- * Copyright (C) 2003 Paul Mundt
+ * Copyright (C) 2003 - 2008 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -46,9 +43,10 @@
* syscall #
*
*/
+#include <asm/dwarf.h>
#if defined(CONFIG_PREEMPT)
-# define preempt_stop() cli
+# define preempt_stop() cli ; TRACE_IRQS_OFF
#else
# define preempt_stop()
# define resume_kernel __restore_all
@@ -58,11 +56,7 @@
.align 2
ENTRY(exception_error)
!
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 2f, r0
- jsr @r0
- nop
-#endif
+ TRACE_IRQS_ON
sti
mov.l 1f, r0
jmp @r0
@@ -70,18 +64,21 @@ ENTRY(exception_error)
.align 2
1: .long do_exception_error
-#ifdef CONFIG_TRACE_IRQFLAGS
-2: .long trace_hardirqs_on
-#endif
.align 2
ret_from_exception:
+ CFI_STARTPROC simple
+ CFI_DEF_CFA r14, 0
+ CFI_REL_OFFSET 17, 64
+ CFI_REL_OFFSET 15, 60
+ CFI_REL_OFFSET 14, 56
+ CFI_REL_OFFSET 13, 52
+ CFI_REL_OFFSET 12, 48
+ CFI_REL_OFFSET 11, 44
+ CFI_REL_OFFSET 10, 40
+ CFI_REL_OFFSET 9, 36
+ CFI_REL_OFFSET 8, 32
preempt_stop()
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 4f, r0
- jsr @r0
- nop
-#endif
ENTRY(ret_from_irq)
!
mov #OFF_SR, r0
@@ -95,6 +92,8 @@ ENTRY(ret_from_irq)
bra resume_userspace
nop
ENTRY(resume_kernel)
+ cli
+ TRACE_IRQS_OFF
mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
tst r0, r0
bf noresched
@@ -105,31 +104,13 @@ need_resched:
mov #OFF_SR, r0
mov.l @(r0,r15), r0 ! get status register
- and #0xf0, r0 ! interrupts off (exception path)?
- cmp/eq #0xf0, r0
+ shlr r0
+ and #(0xf0>>1), r0 ! interrupts off (exception path)?
+ cmp/eq #(0xf0>>1), r0
bt noresched
-
mov.l 1f, r0
- mov.l r0, @(TI_PRE_COUNT,r8)
-
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 3f, r0
- jsr @r0
+ jsr @r0 ! call preempt_schedule_irq
nop
-#endif
- sti
- mov.l 2f, r0
- jsr @r0
- nop
- mov #0, r0
- mov.l r0, @(TI_PRE_COUNT,r8)
- cli
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 4f, r0
- jsr @r0
- nop
-#endif
-
bra need_resched
nop
@@ -138,24 +119,15 @@ noresched:
nop
.align 2
-1: .long PREEMPT_ACTIVE
-2: .long schedule
-#ifdef CONFIG_TRACE_IRQFLAGS
-3: .long trace_hardirqs_on
-4: .long trace_hardirqs_off
-#endif
+1: .long preempt_schedule_irq
#endif
ENTRY(resume_userspace)
! r8: current_thread_info
cli
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 5f, r0
- jsr @r0
- nop
-#endif
+ TRACE_IRQS_OFF
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
- tst #_TIF_WORK_MASK, r0
+ tst #(_TIF_WORK_MASK & 0xff), r0
bt/s __restore_all
tst #_TIF_NEED_RESCHED, r0
@@ -165,12 +137,13 @@ work_pending:
! r8: current_thread_info
! t: result of "tst #_TIF_NEED_RESCHED, r0"
bf/s work_resched
- tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
+ tst #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME), r0
work_notifysig:
bt/s __restore_all
mov r15, r4
mov r12, r5 ! set arg1(save_r0)
mov r0, r6
+ sti
mov.l 2f, r1
mov.l 3f, r0
jmp @r1
@@ -180,14 +153,10 @@ work_resched:
jsr @r1 ! schedule
nop
cli
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 5f, r0
- jsr @r0
- nop
-#endif
+ TRACE_IRQS_OFF
!
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
- tst #_TIF_WORK_MASK, r0
+ tst #(_TIF_WORK_MASK & 0xff), r0
bt __restore_all
bra work_pending
tst #_TIF_NEED_RESCHED, r0
@@ -195,29 +164,19 @@ work_resched:
.align 2
1: .long schedule
2: .long do_notify_resume
-3: .long restore_all
-#ifdef CONFIG_TRACE_IRQFLAGS
-4: .long trace_hardirqs_on
-5: .long trace_hardirqs_off
-#endif
+3: .long resume_userspace
.align 2
syscall_exit_work:
! r0: current_thread_info->flags
! r8: current_thread_info
- tst #_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | _TIF_SYSCALL_AUDIT, r0
+ tst #(_TIF_WORK_SYSCALL_MASK & 0xff), r0
bt/s work_pending
tst #_TIF_NEED_RESCHED, r0
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 5f, r0
- jsr @r0
- nop
-#endif
+ TRACE_IRQS_ON
sti
- ! XXX setup arguments...
mov r15, r4
- mov #1, r5
- mov.l 4f, r0 ! do_syscall_trace
+ mov.l 8f, r0 ! do_syscall_trace_leave
jsr @r0
nop
bra resume_userspace
@@ -226,19 +185,18 @@ syscall_exit_work:
.align 2
syscall_trace_entry:
! Yes it is traced.
- ! XXX setup arguments...
mov r15, r4
- mov #0, r5
- mov.l 4f, r11 ! Call do_syscall_trace which notifies
+ mov.l 7f, r11 ! Call do_syscall_trace_enter which notifies
jsr @r11 ! superior (will chomp R[0-7])
nop
+ mov.l r0, @(OFF_R0,r15) ! Save return value
! Reload R0-R4 from kernel stack, where the
! parent may have modified them using
! ptrace(POKEUSR). (Note that R0-R2 are
- ! used by the system call handler directly
- ! from the kernel stack anyway, so don't need
- ! to be reloaded here.) This allows the parent
- ! to rewrite system calls and args on the fly.
+ ! reloaded from the kernel stack by syscall_call
+ ! below, so don't need to be reloaded here.)
+ ! This allows the parent to rewrite system calls
+ ! and args on the fly.
mov.l @(OFF_R4,r15), r4 ! arg0
mov.l @(OFF_R5,r15), r5
mov.l @(OFF_R6,r15), r6
@@ -253,15 +211,29 @@ syscall_trace_entry:
mov.l r0, @(OFF_R0,r15) ! Return value
__restore_all:
- mov.l 1f, r0
+ mov #OFF_SR, r0
+ mov.l @(r0,r15), r0 ! get status register
+
+ shlr2 r0
+ and #0x3c, r0
+ cmp/eq #0x3c, r0
+ bt 1f
+ TRACE_IRQS_ON
+ bra 2f
+ nop
+1:
+ TRACE_IRQS_OFF
+2:
+ mov.l 3f, r0
jmp @r0
nop
.align 2
-1: .long restore_all
+3: .long restore_all
.align 2
syscall_badsys: ! Bad syscall number
+ get_current_thread_info r8, r0
mov #-ENOSYS, r0
bra resume_userspace
mov.l r0, @(OFF_R0,r15) ! Return value
@@ -281,8 +253,11 @@ debug_trap:
mov.l 1f, r8
add r0, r8
mov.l @r8, r8
- jmp @r8
+ jsr @r8
nop
+ bra __restore_all
+ nop
+ CFI_ENDPROC
.align 2
1: .long debug_trap_table
@@ -320,6 +295,19 @@ ret_from_fork:
mov r0, r4
bra syscall_exit
nop
+
+ .align 2
+ .globl ret_from_kernel_thread
+ret_from_kernel_thread:
+ mov.l 1f, r8
+ jsr @r8
+ mov r0, r4
+ mov.l @(OFF_R5,r15), r5 ! fn
+ jsr @r5
+ mov.l @(OFF_R4,r15), r4 ! arg
+ bra syscall_exit
+ nop
+
.align 2
1: .long schedule_tail
@@ -328,31 +316,36 @@ ret_from_fork:
* system calls and debug traps through their respective jump tables.
*/
ENTRY(system_call)
+ setup_frame_reg
#if !defined(CONFIG_CPU_SH2)
mov.l 1f, r9
mov.l @r9, r8 ! Read from TRA (Trap Address) Register
#endif
+
+ mov #OFF_TRA, r10
+ add r15, r10
+ mov.l r8, @r10 ! set TRA value to tra
+
/*
* Check the trap type
*/
mov #((0x20 << 2) - 1), r9
cmp/hi r9, r8
bt/s debug_trap ! it's a debug trap..
- mov #OFF_TRA, r9
- add r15, r9
- mov.l r8, @r9 ! set TRA value to tra
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 5f, r10
- jsr @r10
nop
-#endif
+
+ TRACE_IRQS_ON
sti
!
get_current_thread_info r8, r10
mov.l @(TI_FLAGS,r8), r8
- mov #(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT), r10
+ mov #(_TIF_WORK_SYSCALL_MASK & 0xff), r10
+ mov #(_TIF_WORK_SYSCALL_MASK >> 8), r9
tst r10, r8
+ shll8 r9
+ bf syscall_trace_entry
+ tst r9, r8
bf syscall_trace_entry
!
mov.l 2f, r8 ! Number of syscalls
@@ -364,22 +357,29 @@ syscall_call:
mov.l 3f, r8 ! Load the address of sys_call_table
add r8, r3
mov.l @r3, r8
+ mov.l @(OFF_R2,r15), r2
+ mov.l @(OFF_R1,r15), r1
+ mov.l @(OFF_R0,r15), r0
+ mov.l r2, @-r15
+ mov.l r1, @-r15
+ mov.l r0, @-r15
jsr @r8 ! jump to specific syscall handler
nop
+ add #12, r15
mov.l @(OFF_R0,r15), r12 ! save r0
mov.l r0, @(OFF_R0,r15) ! save the return value
!
syscall_exit:
cli
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 6f, r0
- jsr @r0
- nop
-#endif
+ TRACE_IRQS_OFF
!
get_current_thread_info r8, r0
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
- tst #_TIF_ALLWORK_MASK, r0
+ tst #(_TIF_ALLWORK_MASK & 0xff), r0
+ mov #(_TIF_ALLWORK_MASK >> 8), r1
+ bf syscall_exit_work
+ shlr8 r0
+ tst r0, r1
bf syscall_exit_work
bra __restore_all
nop
@@ -389,8 +389,5 @@ syscall_exit:
#endif
2: .long NR_syscalls
3: .long sys_call_table
-4: .long do_syscall_trace
-#ifdef CONFIG_TRACE_IRQFLAGS
-5: .long trace_hardirqs_on
-6: .long trace_hardirqs_off
-#endif
+7: .long do_syscall_trace_enter
+8: .long do_syscall_trace_leave