X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;ds=sidebyside;f=arch%2Fsh%2Fkernel%2Fentry-common.S;h=efbb4268875e3a2b1fc43de0789b08b834cf2b3e;hb=7c12d906f4ef690c65e60111375856640f63a545;hp=5bc7fa91d095c0f44914e471f3b9ef12f89d1266;hpb=de39840646a223ae13a346048c280b7c871bf56e;p=safe%2Fjmp%2Flinux-2.6 diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index 5bc7fa9..efbb426 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 @@ -54,65 +51,34 @@ # define resume_kernel __restore_all #endif -#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) -! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present. -! If both are configured, handle the debug traps (breakpoints) in SW, -! but still allow BIOS traps to FW. - - .align 2 -debug_kernel: -#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB) - /* Force BIOS call to FW (debug_trap put TRA in r8) */ - mov r8,r0 - shlr2 r0 - cmp/eq #0x3f,r0 - bt debug_kernel_fw -#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */ - -debug_enter: -#if defined(CONFIG_SH_KGDB) - /* Jump to kgdb, pass stacked regs as arg */ -debug_kernel_sw: - mov.l 3f, r0 - jmp @r0 - mov r15, r4 - .align 2 -3: .long kgdb_handle_exception -#endif /* CONFIG_SH_KGDB */ - -#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ - - - .align 2 -debug_trap: -#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) - mov #OFF_SR, r0 - mov.l @(r0,r15), r0 ! get status register - shll r0 - shll r0 ! kernel space? - bt/s debug_kernel -#endif - mov.l @r15, r0 ! Restore R0 value - mov.l 1f, r8 - jmp @r8 - nop .align 2 ENTRY(exception_error) ! - sti +#ifdef CONFIG_TRACE_IRQFLAGS mov.l 2f, r0 + jsr @r0 + nop +#endif + sti + mov.l 1f, r0 jmp @r0 nop -! .align 2 -1: .long break_point_trap_software -2: .long do_exception_error +1: .long do_exception_error +#ifdef CONFIG_TRACE_IRQFLAGS +2: .long trace_hardirqs_on +#endif .align 2 ret_from_exception: preempt_stop() +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 4f, r0 + jsr @r0 + nop +#endif ENTRY(ret_from_irq) ! mov #OFF_SR, r0 @@ -126,6 +92,7 @@ ENTRY(ret_from_irq) bra resume_userspace nop ENTRY(resume_kernel) + cli mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count tst r0, r0 bf noresched @@ -139,20 +106,12 @@ need_resched: and #0xf0, r0 ! interrupts off (exception path)? cmp/eq #0xf0, r0 bt noresched - - mov.l 1f, r0 - mov.l r0, @(TI_PRE_COUNT,r8) - - sti - mov.l 2f, r0 - jsr @r0 + mov.l 3f, r0 + jsr @r0 ! call preempt_schedule_irq nop - mov #0, r0 - mov.l r0, @(TI_PRE_COUNT,r8) - cli - bra need_resched nop + noresched: bra __restore_all nop @@ -160,11 +119,17 @@ noresched: .align 2 1: .long PREEMPT_ACTIVE 2: .long schedule +3: .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 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags tst #_TIF_WORK_MASK, r0 bt/s __restore_all @@ -187,29 +152,15 @@ work_notifysig: jmp @r1 lds r0, pr work_resched: -#ifndef CONFIG_PREEMPT - ! gUSA handling - mov.l @(OFF_SP,r15), r0 ! get user space stack pointer - mov r0, r1 - shll r0 - bf/s 1f - shll r0 - bf/s 1f - mov #OFF_PC, r0 - ! SP >= 0xc0000000 : gUSA mark - mov.l @(r0,r15), r2 ! get user space PC (program counter) - mov.l @(OFF_R0,r15), r3 ! end point - cmp/hs r3, r2 ! r2 >= r3? - bt 1f - add r3, r1 ! rewind point #2 - mov.l r1, @(r0,r15) ! reset PC to rewind point #2 - ! -1: -#endif mov.l 1f, r1 jsr @r1 ! schedule nop cli +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 5f, r0 + jsr @r0 + nop +#endif ! mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags tst #_TIF_WORK_MASK, r0 @@ -220,18 +171,27 @@ work_resched: .align 2 1: .long schedule 2: .long do_notify_resume -3: .long restore_all +3: .long resume_userspace +#ifdef CONFIG_TRACE_IRQFLAGS +4: .long trace_hardirqs_on +5: .long trace_hardirqs_off +#endif .align 2 syscall_exit_work: ! r0: current_thread_info->flags ! r8: current_thread_info - tst #_TIF_SYSCALL_TRACE, r0 + tst #_TIF_WORK_SYSCALL_MASK, r0 bt/s work_pending tst #_TIF_NEED_RESCHED, r0 +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 5f, r0 + jsr @r0 + nop +#endif sti - ! XXX setup arguments... - mov.l 4f, r0 ! do_syscall_trace + mov r15, r4 + mov.l 8f, r0 ! do_syscall_trace_leave jsr @r0 nop bra resume_userspace @@ -240,10 +200,11 @@ syscall_exit_work: .align 2 syscall_trace_entry: ! Yes it is traced. - ! XXX setup arguments... - mov.l 4f, r11 ! Call do_syscall_trace which notifies + mov r15, r4 + 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 @@ -256,8 +217,7 @@ syscall_trace_entry: mov.l @(OFF_R6,r15), r6 mov.l @(OFF_R7,r15), r7 ! arg3 mov.l @(OFF_R3,r15), r3 ! syscall_nr - ! Arrange for do_syscall_trace to be called - ! again as the system call returns. + ! mov.l 2f, r10 ! Number of syscalls cmp/hs r10, r3 bf syscall_call @@ -266,30 +226,62 @@ syscall_trace_entry: mov.l r0, @(OFF_R0,r15) ! Return value __restore_all: - mov.l 1f,r0 + mov.l 1f, r0 jmp @r0 nop .align 2 1: .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 + +/* + * The main debug trap handler. + * + * r8=TRA (not the trap number!) + * + * Note: This assumes that the trapa value is left in its original + * form (without the shlr2 shift) so the calculation for the jump + * call table offset remains a simple in place mask. + */ +debug_trap: + mov r8, r0 + and #(0xf << 2), r0 + mov.l 1f, r8 + add r0, r8 + mov.l @r8, r8 + jsr @r8 + nop + bra __restore_all + nop + + .align 2 +1: .long debug_trap_table + /* * Syscall interface: * * Syscall #: R3 * Arguments #0 to #3: R4--R7 * Arguments #4 to #6: R0, R1, R2 - * TRA: (number of arguments + 0x10) x 4 + * TRA: (number of arguments + ABI revision) x 4 * * This code also handles delegating other traps to the BIOS/gdb stub * according to: * * Trap number - * (TRA>>2) Purpose - * -------- ------- - * 0x0-0xf old syscall ABI - * 0x10-0x1f new syscall ABI - * 0x20-0xff delegated through debug_trap to BIOS/gdb stub. + * (TRA>>2) Purpose + * -------- ------- + * 0x00-0x0f original SH-3/4 syscall ABI (not in general use). + * 0x10-0x1f general SH-3/4 syscall ABI. + * 0x20-0x2f syscall ABI for SH-2 parts. + * 0x30-0x3f debug traps used by the kernel. + * 0x40-0xff Not supported by all parts, so left unhandled. * * Note: When we're first called, the TRA value must be shifted * right 2 bits in order to get the value that was used as the "trapa" @@ -306,49 +298,48 @@ ret_from_fork: nop .align 2 1: .long schedule_tail - ! + +/* + * The poorly named main trapa decode and dispatch routine, for + * system calls and debug traps through their respective jump tables. + */ ENTRY(system_call) #if !defined(CONFIG_CPU_SH2) mov.l 1f, r9 mov.l @r9, r8 ! Read from TRA (Trap Address) Register #endif - ! - ! Is the trap argument >= 0x20? (TRA will be >= 0x80) - mov #0x7f, r9 + /* + * Check the trap type + */ + mov #((0x20 << 2) - 1), r9 cmp/hi r9, r8 - bt/s 0f + 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 - sti - ! Call the system call handler through the table. - ! First check for bad syscall number - mov r3, r9 - mov.l 2f, r8 ! Number of syscalls - cmp/hs r8, r9 - get_current_thread_info r8, r10 - bf good_system_call -syscall_badsys: ! Bad syscall number - mov #-ENOSYS, r0 - bra resume_userspace - mov.l r0, @(OFF_R0,r15) ! Return value - ! -0: - bra debug_trap +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 5f, r10 + jsr @r10 nop +#endif + sti + ! -good_system_call: ! Good syscall number + get_current_thread_info r8, r10 mov.l @(TI_FLAGS,r8), r8 - mov #_TIF_SYSCALL_TRACE, r10 + mov #_TIF_WORK_SYSCALL_MASK, r10 tst r10, r8 bf syscall_trace_entry ! + mov.l 2f, r8 ! Number of syscalls + cmp/hs r8, r3 + bt syscall_badsys + ! syscall_call: - shll2 r9 ! x4 + shll2 r3 ! x4 mov.l 3f, r8 ! Load the address of sys_call_table - add r8, r9 - mov.l @r9, r8 + add r8, r3 + mov.l @r3, r8 jsr @r8 ! jump to specific syscall handler nop mov.l @(OFF_R0,r15), r12 ! save r0 @@ -356,6 +347,11 @@ syscall_call: ! syscall_exit: cli +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 6f, r0 + jsr @r0 + nop +#endif ! get_current_thread_info r8, r0 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags @@ -369,4 +365,9 @@ 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