powerpc: Fix sysfs pci mmap on 32-bit machines with 64-bit PCI
[safe/jmp/linux-2.6] / arch / sh / kernel / entry-common.S
index 5bc7fa9..efbb426 100644 (file)
@@ -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
 #  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