From: NIIBE Y. <gn...@m1...> - 2002-04-12 03:01:54
|
I'll send following patch set to Linus to sync. I'll send only SuperH specific change, leaving drivers changes in our repository. -------------------------- Here's the SuperH update. All changes are SuperH specific. (i.e., under arch/sh/ or include/asm-sh/) Follow up: Introduce thread_info. Implemented (mostly copied from i386 implementation.) Scheduler: sched_find_first_bit, switch_to Macros: SI_DETHREAD, PROT_SEM, VM_DATA_DEFAULT_FLAGS, and PCI_DMA_BUS_IS_PHYS Page handling: pmd_*, pte_* functions/macros change Cache handling function: flush_icache_user_range New system calles: gettid, .., futex, sched_{set,get}affinity, New arch specific headers: cacheflush.h, tlbflush.h Bug fixes: Paul Mundt: arch/sh/kernel/io_7751se.c: Typo fix. Niibe Yutaka: Init task fpu initialization. Signal return. Improvement: Paul Mundt, Niibe Yutaka: arch/sh/mm/cache-sh4.c flush_cache_range implemented (was: flush_cache_all). Paul Mundt: arch/sh/kernel/traps.c show_trace_task implemented. Others: Niibe Yutaka: FPU cleanup Implement kernel profile function (sh_do_profile). diff -ruN3p linux-2.5.8-pre3/arch/sh/Config.help linux/arch/sh/Config.help --- linux-2.5.8-pre3/arch/sh/Config.help Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/Config.help Fri Mar 22 13:49:37 2002 @@ -754,6 +754,13 @@ CONFIG_SH_DREAMCAST <http://www.m17n.org/linux-sh/dreamcast/>. There is a Dreamcast project is at <http://linuxdc.sourceforge.net/>. +CONFIG_SH_SH2000 + SH-2000 is a single-board computer based around SH7709A chip + intended for embedded applications. + It has an Ethernet interface (CS8900A), direct connected + Compact Flash socket, three serial ports and PC-104 bus. + More information at <http://sh2000.sh-linux.org>. + CONFIG_SH_UNKNOWN "Bare CPU" aka "unknown" means an SH-based system which is not one of the specific ones mentioned above, which means you need to enter @@ -790,6 +797,12 @@ CONFIG_CPU_SUBTYPE_SH7709 CONFIG_CPU_SUBTYPE_SH7750 Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. + +CONFIG_CPU_SUBTYPE_SH7751 + Select SH7750 if you have a 166 Mhz SH-4 HD6417751 CPU. + +CONFIG_CPU_SUBTYPE_ST40STB1 + Select ST40STB1 if you have a ST40STB1 CPU. CONFIG_MEMORY_START Computers built with Hitachi SuperH processors always diff -ruN3p linux-2.5.8-pre3/arch/sh/config.in linux/arch/sh/config.in --- linux-2.5.8-pre3/arch/sh/config.in Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/config.in Fri Mar 22 13:49:37 2002 @@ -258,7 +258,7 @@ fi endmenu # -# input before char - char/joystick depends on it. As does USB. +# input - input/joystick depends on it. As does USB. # source drivers/input/Config.in @@ -307,7 +307,7 @@ if [ "$CONFIG_SH_DREAMCAST" = "y" -a "$C endmenu fi -source drivers/char/joystick/Config.in +source drivers/input/joystick/Config.in if [ "$CONFIG_PARPORT" != "n" ]; then dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/entry.S linux/arch/sh/kernel/entry.S --- linux-2.5.8-pre3/arch/sh/kernel/entry.S Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/kernel/entry.S Wed Apr 10 20:54:45 2002 @@ -1,8 +1,8 @@ -/* $Id: entry.S,v 1.71 2001/07/27 11:47:50 gniibe Exp $ +/* $Id: entry.S,v 1.72 2002/03/29 00:02:04 gniibe Exp $ * * linux/arch/sh/entry.S * - * Copyright (C) 1999, 2000 Niibe Yutaka + * Copyright (C) 1999, 2000, 2002 Niibe Yutaka * * 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 @@ -13,13 +13,11 @@ #include <linux/sys.h> #include <linux/linkage.h> #include <linux/config.h> +#include <asm/thread_info.h> - -/* - * Define this to turn on compatibility with the previous - * system call ABI. This feature is not properly maintained. - */ -#undef COMPAT_OLD_SYSCALL_ABI +#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE) +#define sys_nfsservctl sys_ni_syscall +#endif ! NOTE: ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address @@ -57,16 +55,6 @@ * */ -/* - * These are offsets into the task-struct. - */ -flags = 4 -#error sigpending = 8 -#error need_resched = 20 -#error tsk_ptrace = 24 - -#error PT_TRACESYS = 0x00000002 - ENOSYS = 38 EINVAL = 22 @@ -87,17 +75,17 @@ MMU_TEA = 0xff00000c ! TLB Exception Ad #endif /* Offsets to the stack */ -OFF_R0 = 0 /* Return value. New ABI also arg4 */ -OFF_R1 = 4 /* New ABI: arg5 */ -OFF_R2 = 8 /* New ABI: arg6 */ -OFF_R3 = 12 /* New ABI: syscall_nr */ -OFF_R4 = 16 /* New ABI: arg0 */ -OFF_R5 = 20 /* New ABI: arg1 */ -OFF_R6 = 24 /* New ABI: arg2 */ -OFF_R7 = 28 /* New ABI: arg3 */ -OFF_SP = (15*4) -OFF_SR = (16*4+8) -SYSCALL_NR = (16*4+6*4) +OFF_R0 = 0 /* Return value. New ABI also arg4 */ +OFF_R1 = 4 /* New ABI: arg5 */ +OFF_R2 = 8 /* New ABI: arg6 */ +OFF_R3 = 12 /* New ABI: syscall_nr */ +OFF_R4 = 16 /* New ABI: arg0 */ +OFF_R5 = 20 /* New ABI: arg1 */ +OFF_R6 = 24 /* New ABI: arg2 */ +OFF_R7 = 28 /* New ABI: arg3 */ +OFF_SP = (15*4) +OFF_SR = (16*4+8) +OFF_TRA = (16*4+6*4) #define k0 r0 @@ -106,11 +94,10 @@ SYSCALL_NR = (16*4+6*4) #define k3 r3 #define k4 r4 -#define current r7 /* r7_bank1 */ +#define k_ex_code r2_bank /* r2_bank1 */ #define g_imask r6 /* r6_bank1 */ -#define k_current r7_bank /* r7_bank1 */ #define k_g_imask r6_bank /* r6_bank1 */ -#define k_ex_code r2_bank /* r2_bank1 */ +#define current r7 /* r7_bank1 */ /* * Kernel mode register usage: @@ -121,7 +108,7 @@ SYSCALL_NR = (16*4+6*4) * k4 scratch * k5 reserved * k6 Global Interrupt Mask (0--15 << 4) - * k7 CURRENT (pointer to current task) + * k7 CURRENT_THREAD_INFO (pointer to current thread info) */ ! @@ -142,7 +129,7 @@ SYSCALL_NR = (16*4+6*4) mov.l __INV_IMASK, r11; \ stc sr, r10; \ and r11, r10; \ - stc k_g_imask, r11; \ + stc k_g_imask, r11; \ or r11, r10; \ ldc r10, sr @@ -208,6 +195,7 @@ address_error_store: bra call_dae mov #1,r5 ! writeaccess = 1 + .align 2 call_dae: mov.l 1f, r0 mov.l @r0, r6 ! address @@ -269,56 +257,125 @@ debug_trap: shll r0 ! kernel space? bt/s debug_kernel #endif - mov.l @r15, r0 + mov.l @r15, r0 ! Restore R0 value mov.l 1f, r8 jmp @r8 nop .align 2 -1: .long SYMBOL_NAME(break_point_trap_software) - - .align 2 error: ! STI() - mov.l 1f, r0 + mov.l 2f, r0 jmp @r0 nop + +! + .align 2 +1: .long SYMBOL_NAME(break_point_trap_software) +2: .long SYMBOL_NAME(do_exception_error) + .align 2 -1: .long SYMBOL_NAME(do_exception_error) +ret_from_irq: +ret_from_exception: + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + shll r0 + shll r0 ! kernel space? + bt/s restore_all ! Yes, it's from kernel, go back soon + GET_THREAD_INFO(r8) +ENTRY(resume_userspace) + ! r8: current_thread_info + /* CLI */ + stc sr, r0 + or #0xf0, r0 + ldc r0, sr + ! + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_WORK_MASK, r0 + bt/s restore_all + tst #_TIF_NEED_RESCHED, r0 -! -! -! -ENTRY(ret_from_fork) - mov.l @r15+,r0 - ! Call schedule_tail + .align 2 +work_pending: + ! r0: current_thread_info->flags + ! r8: current_thread_info + ! t: result of "tst #_TIF_NEED_RESCHED, r0" + bf/s work_resched + tst #_TIF_SIGPENDING, r0 +work_notifysig: + bt/s restore_all + mov r15, r4 + mov #0, r5 + mov.l 2f, r1 + mova restore_all, r0 + jmp @r1 + lds r0, pr +work_resched: mov.l 1f, r1 - jsr @r1 - mov r0, r4 - ! If we're being traced, return via syscall_ret_trace, otherwise - ! return directly to ret_from_syscall - stc k_current, r0 -#error mov.l @(tsk_ptrace,r0), r0 ! Is current PTRACE_SYSCALL'd? -#error mov #PT_TRACESYS, r1 - tst r1, r0 - bt ret_from_syscall - bra syscall_ret_trace - nop + jsr @r1 ! schedule + nop + /* CLI */ + stc sr, r0 + or #0xf0, r0 + ldc r0, sr + ! + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_WORK_MASK, r0 + bt restore_all + bra work_pending + tst #_TIF_NEED_RESCHED, r0 .align 2 -1: .long SYMBOL_NAME(schedule_tail) +1: .long SYMBOL_NAME(schedule) +2: .long SYMBOL_NAME(do_signal) + + .align 2 +syscall_exit_work: + ! r0: current_thread_info->flags + ! r8: current_thread_info + tst #_TIF_SYSCALL_TRACE, r0 + bt/s work_pending + tst #_TIF_NEED_RESCHED, r0 + STI() + ! XXX setup arguments... + mov.l 4f, r0 ! do_syscall_trace + jsr @r0 + nop + bra resume_userspace + nop + + .align 2 +syscall_trace_entry: + ! Yes it is traced. + ! XXX setup arguments... + mov.l 4f, r11 ! Call do_syscall_trace which notifies + jsr @r11 ! superior (will chomp R[0-7]) + nop + ! 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. + mov.l @(OFF_R4,r15), r4 ! arg0 + mov.l @(OFF_R5,r15), r5 + 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 + mov #-ENOSYS, r0 + bra syscall_exit + mov.l r0, @(OFF_R0,r15) ! Return value /* - * Old syscall interface: - * - * Syscall #: R0 - * Arguments #0 to #3: R4--R7 - * more arguments: On the stack - * TRA: (number of arguments on the stack) x 4 - * - * New syscall interface: + * Syscall interface: * * Syscall #: R3 * Arguments #0 to #3: R4--R7 @@ -340,231 +397,58 @@ ENTRY(ret_from_fork) * argument. */ + .align 2 system_call: - mov.l __TRA, r9 - mov.l @r9, r8 + mov.l 1f, r9 + mov.l @r9, r8 ! Read from TRA (Trap Address) Register ! ! Is the trap argument >= 0x20? (TRA will be >= 0x80) - mov #0x20, r9 - extu.b r9, r9 - shll2 r9 - cmp/hs r9, r8 - bt debug_trap - ! - mov #SYSCALL_NR, r14 - add r15, r14 - ! -#ifdef COMPAT_OLD_SYSCALL_ABI - mov #0x40, r9 - cmp/hs r9, r8 - bf/s old_abi_system_call - nop -#endif - ! New Syscall ABI - add #-0x40, r8 - shlr2 r8 - shll8 r8 - shll8 r8 ! r8 = num_args<<16 - mov r3, r10 - or r8, r10 ! Encode syscall # and # of arguments - mov.l r10, @r14 ! set syscall_nr - STI() + mov #0x7f, r9 + cmp/hi r9, r8 + bt/s debug_trap + mov #OFF_TRA, r9 + add r15, r9 ! - stc k_current, r11 -#error mov.l @(tsk_ptrace,r11), r10 ! Is current PTRACE_SYSCALL'd? -#error mov #PT_TRACESYS, r11 - tst r11, r10 - bt 5f - ! Yes it is traced. - mov.l __syscall_trace, r11 ! Call syscall_trace() which notifies - jsr @r11 ! superior (will chomp R[0-7]) - nop - ! 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. - mov.l @(OFF_R4,r15), r4 ! arg0 - mov.l @(OFF_R5,r15), r5 - mov.l @(OFF_R6,r15), r6 - mov.l @(OFF_R7,r15), r7 ! arg3 - mov.l @(OFF_R3,r15), r3 ! syscall_nr - ! Arrange for syscall_trace() to be called - ! again as the system call returns. - mov.l __syscall_ret_trace, r10 - bra 6f - lds r10, pr - ! No it isn't traced. - ! Arrange for normal system call return. -5: mov.l __syscall_ret, r10 - lds r10, pr - ! Call the system call handler through the table. - ! (both normal and ptrace'd) - ! First check for bad syscall number -6: mov r3, r9 - mov.l __n_sys, r10 - cmp/hs r10, r9 - bf 2f - ! Bad syscall number - rts ! go to syscall_ret or syscall_ret_trace - mov #-ENOSYS, r0 - ! Good syscall number -2: shll2 r9 ! x4 - mov.l __sct, r11 - add r11, r9 - mov.l @r9, r11 - jmp @r11 ! jump to specific syscall handler - nop - - ! In case of trace -syscall_ret_trace: - mov.l r0, @(OFF_R0,r15) ! save the return value - mov.l __syscall_trace, r1 - mova SYMBOL_NAME(ret_from_syscall), r0 - jmp @r1 ! Call syscall_trace() which notifies superior - lds r0, pr ! Then return to ret_from_syscall() - - - -#ifdef COMPAT_OLD_SYSCALL_ABI -! Handle old ABI system call. -! Note that ptrace(SYSCALL) is not supported for the old ABI. -! At this point: -! r0, r4-7 as per ABI -! r8 = value of TRA register (= num_args<<2) -! r14 = points to SYSCALL_NR in stack frame -old_abi_system_call: - mov r0, r9 ! Save system call number in r9 - ! ! arrange for return which pops stack - mov.l __old_abi_syscall_ret, r10 - lds r10, pr - ! Build the stack frame if TRA > 0 - mov r8, r10 - cmp/pl r10 - bf 0f - mov.l @(OFF_SP,r15), r0 ! get original user stack -7: add #-4, r10 -4: mov.l @(r0,r10), r1 ! May cause address error exception.. - mov.l r1, @-r15 - cmp/pl r10 - bt 7b -0: - mov.l r9, @r14 ! set syscall_nr + 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.l __n_sys, r10 - cmp/hs r10, r9 - bf 2f - ! Bad syscall number - rts ! return to old_abi_syscall_ret - mov #-ENOSYS, r0 - ! Good syscall number -2: shll2 r9 ! x4 - mov.l __sct, r11 - add r11, r9 - mov.l @r9, r11 - jmp @r11 ! call specific syscall handler, - nop - - .align 2 -__old_abi_syscall_ret: - .long old_abi_syscall_ret - - ! This code gets called on address error exception when copying - ! syscall arguments from user stack to kernel stack. It is - ! supposed to return -EINVAL through old_abi_syscall_ret, but it - ! appears to have been broken for a long time in that the r0 - ! return value will be saved into the kernel stack relative to r15 - ! but the value of r15 is not correct partway through the loop. - ! So the user prog is returned its old r0 value, not -EINVAL. - ! Greg Banks 28 Aug 2000. - .section .fixup,"ax" -fixup_syscall_argerr: - ! First get r15 back to - rts - mov #-EINVAL, r0 - .previous - - .section __ex_table, "a" - .align 2 - .long 4b,fixup_syscall_argerr - .previous -#endif - - .align 2 -__TRA: .long TRA -__syscall_trace: -#error .long SYMBOL_NAME(syscall_trace) -__n_sys:.long NR_syscalls -__sct: .long SYMBOL_NAME(sys_call_table) -__syscall_ret_trace: - .long syscall_ret_trace -__syscall_ret: - .long syscall_ret -__INV_IMASK: - .long 0xffffff0f ! ~(IMASK) - - - .align 2 -reschedule: - mova SYMBOL_NAME(ret_from_syscall), r0 - mov.l 1f, r1 - jmp @r1 - lds r0, pr - .align 2 -1: .long SYMBOL_NAME(schedule) - -ret_from_irq: -ret_from_exception: - mov #OFF_SR, r0 - mov.l @(r0,r15), r0 ! get status register - shll r0 - shll r0 ! kernel space? - bt restore_all ! Yes, it's from kernel, go back soon - ! - bra ret_from_syscall + mov r3, r9 + mov.l 2f, r8 ! Number of syscalls + cmp/hs r8, r9 + bf/s good_system_call + GET_THREAD_INFO(r8) +syscall_badsys: ! Bad syscall number + mov #-ENOSYS, r0 + bra resume_userspace + mov.l r0, @(OFF_R0,r15) ! Return value + ! +good_system_call: ! Good syscall number + mov.l @(TI_FLAGS,r8), r8 + mov #_TIF_SYSCALL_TRACE, r10 + tst r10, r8 + bf syscall_trace_entry + ! +syscall_call: + shll2 r9 ! x4 + mov.l 3f, r8 ! Load the address of sys_call_table + add r8, r9 + mov.l @r9, r8 + jsr @r8 ! jump to specific syscall handler nop - - .align 2 -#ifdef COMPAT_OLD_SYSCALL_ABI -old_abi_syscall_ret: - add r8, r15 ! pop off the arguments - /* fall through */ -#endif -syscall_ret: - mov.l r0, @(OFF_R0,r15) ! save the return value - /* fall through */ - -ENTRY(ret_from_syscall) + mov.l r0, @(OFF_R0,r15) ! save the return value + .globl ret_from_fork +ret_from_fork: +syscall_exit: /* CLI */ stc sr, r0 or #0xf0, r0 ldc r0, sr ! - stc k_current, r1 -#error mov.l @(need_resched,r1), r0 - tst r0, r0 - bf reschedule -#error mov.l @(sigpending,r1), r0 - tst r0, r0 - bt restore_all -signal_return: - mov r15, r4 - mov #0, r5 - mov.l __do_signal, r1 - mova restore_all, r0 - jmp @r1 - lds r0, pr - .align 2 -__do_signal: -#error .long SYMBOL_NAME(do_signal) -__irq_stat: - .long SYMBOL_NAME(irq_stat) - - .align 2 + GET_THREAD_INFO(r8) + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_ALLWORK_MASK, r0 + bf syscall_exit_work restore_all: mov.l @r15+, r0 mov.l @r15+, r1 @@ -576,8 +460,8 @@ restore_all: mov.l @r15+, r7 ! stc sr, r8 - mov.l __blrb_flags, r9 ! BL =1, RB=1 - or r9, r8 + mov.l 7f, r9 + or r9, r8 ! BL =1, RB=1 ldc r8, sr ! here, change the register bank ! mov.l @r15+, r8 @@ -598,10 +482,10 @@ restore_all: ! ! Calculate new SR value mov k3, k2 ! original SR value - mov.l 1f, k1 + mov.l 8f, k1 stc sr, k0 and k1, k0 ! Get current FD-bit - mov.l 2f, k1 + mov.l 9f, k1 and k1, k2 ! Mask orignal SR value or k0, k2 ! Inherit current FD-bit ! @@ -609,11 +493,11 @@ restore_all: shlr2 k0 and #0x3c, k0 cmp/eq #0x3c, k0 - bt/s 7f + bt/s 6f shll2 k0 mov g_imask, k0 ! -7: or k0, k2 ! Set the IMASK-bits +6: or k0, k2 ! Set the IMASK-bits ldc k2, ssr ! mov k4, r15 @@ -621,10 +505,15 @@ restore_all: nop .align 2 -__blrb_flags: .long 0x30000000 -1: .long 0x00008000 ! FD -2: .long 0xffff7f0f ! ~(IMASK+FD) -3: .long 0x00080000 ! SZ=0, PR=1 +1: .long TRA +2: .long NR_syscalls +3: .long SYMBOL_NAME(sys_call_table) +4: .long SYMBOL_NAME(do_syscall_trace) +7: .long 0x30000000 +8: .long 0x00008000 ! FD +9: .long 0xffff7f0f ! ~(IMASK+FD) +__INV_IMASK: + .long 0xffffff0f ! ~(IMASK) ! Exception Vector Base ! @@ -641,8 +530,8 @@ general_exception: bra handle_exception mov.l @k2, k2 .align 2 -2: .long ret_from_exception 1: .long EXPEVT +2: .long ret_from_exception ! ! .balign 1024,0,1024 @@ -667,6 +556,7 @@ interrupt: ! ! + .align 2 handle_exception: ! Using k0, k1 for scratch registers (r0_bank1, r1_bank), ! save all registers onto stack. @@ -674,18 +564,18 @@ handle_exception: stc ssr, k0 ! Is it from kernel space? shll k0 ! Check MD bit (bit30) by shifting it into... shll k0 ! ...the T bit - bt/s 9f ! It's a kernel to kernel transition. + bt/s 1f ! It's a kernel to kernel transition. mov r15, k0 ! save original stack to k0 /* User space to kernel */ mov #0x20, k1 - shll8 k1 ! k1 <= 8192 == THREAD_SIZE + shll8 k1 ! k1 := 8192 (== THREAD_SIZE) add current, k1 mov k1, r15 ! change to kernel stack ! -9: mov #-1, k4 - mov.l 3f, k1 +1: mov #-1, k4 + mov.l 2f, k1 ! Save the user registers on the stack. - mov.l k4, @-r15 ! syscall_nr (default: -1) + mov.l k4, @-r15 ! set TRA (default: -1) ! sts.l macl, @-r15 sts.l mach, @-r15 @@ -707,7 +597,7 @@ handle_exception: ! stc sr, r8 ! Back to normal register bank, and or k1, r8 ! Block all interrupts - mov.l 5f, k1 + mov.l 3f, k1 and k1, r8 ! ... ldc r8, sr ! ...changed here. ! @@ -723,17 +613,18 @@ handle_exception: stc k_ex_code, r8 shlr2 r8 shlr r8 - mov.l 1f, r9 + mov.l 4f, r9 add r8, r9 mov.l @r9, r9 jmp @r9 nop + .align 2 -1: .long SYMBOL_NAME(exception_handling_table) -3: .long 0x000000f0 ! FD=0, IMASK=15 -5: .long 0xcfffffff ! RB=0, BL=0 -6: .long 0x00080000 ! SZ=0, PR=1 +2: .long 0x000000f0 ! FD=0, IMASK=15 +3: .long 0xcfffffff ! RB=0, BL=0 +4: .long SYMBOL_NAME(exception_handling_table) + .align 2 none: rts nop @@ -1195,16 +1086,29 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_madvise) .long SYMBOL_NAME(sys_getdents64) /* 220 */ .long SYMBOL_NAME(sys_fcntl64) + .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */ + .long SYMBOL_NAME(sys_ni_syscall) /* Reserved for Security */ .long SYMBOL_NAME(sys_gettid) + .long SYMBOL_NAME(sys_readahead) /* 225 */ + .long SYMBOL_NAME(sys_setxattr) + .long SYMBOL_NAME(sys_lsetxattr) + .long SYMBOL_NAME(sys_fsetxattr) + .long SYMBOL_NAME(sys_getxattr) + .long SYMBOL_NAME(sys_lgetxattr) /* 230 */ + .long SYMBOL_NAME(sys_fgetxattr) + .long SYMBOL_NAME(sys_listxattr) + .long SYMBOL_NAME(sys_llistxattr) + .long SYMBOL_NAME(sys_flistxattr) + .long SYMBOL_NAME(sys_removexattr) /* 235 */ + .long SYMBOL_NAME(sys_lremovexattr) + .long SYMBOL_NAME(sys_fremovexattr) .long SYMBOL_NAME(sys_tkill) + .long SYMBOL_NAME(sys_sendfile64) + .long SYMBOL_NAME(sys_futex) /* 240 */ + .long SYMBOL_NAME(sys_sched_setaffinity) + .long SYMBOL_NAME(sys_sched_getaffinity) - /* - * NOTE!! This doesn't have to be exact - we just have - * to make sure we have _enough_ of the "sys_ni_syscall" - * entries. Don't panic if you notice that this hasn't - * been shrunk every time we add a new system call. - */ - .rept NR_syscalls-221 + .rept NR_syscalls-(.-sys_call_table)/4 .long SYMBOL_NAME(sys_ni_syscall) .endr diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/fpu.c linux/arch/sh/kernel/fpu.c --- linux-2.5.8-pre3/arch/sh/kernel/fpu.c Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/kernel/fpu.c Fri Mar 22 21:35:26 2002 @@ -67,7 +67,7 @@ save_fpu(struct task_struct *tsk) "r" (FPSCR_INIT) : "memory"); - tsk->flags &= ~PF_USEDFPU; + clear_tsk_thread_flag(tsk, TIF_USEDFPU); release_fpu(); } @@ -260,7 +260,7 @@ ieee_fpe_handler (struct pt_regs *regs) ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); grab_fpu(); restore_fpu(tsk); - tsk->flags |= PF_USEDFPU; + set_tsk_thread_flag(tsk, TIF_USEDFPU); } else { tsk->thread.trap_no = 11; tsk->thread.error_code = 0; @@ -310,5 +310,5 @@ do_fpu_state_restore(unsigned long r4, u fpu_init(); tsk->used_math = 1; } - tsk->flags |= PF_USEDFPU; + set_tsk_thread_flag(tsk, TIF_USEDFPU); } diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/head.S linux/arch/sh/kernel/head.S --- linux-2.5.8-pre3/arch/sh/kernel/head.S Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/kernel/head.S Fri Mar 22 21:57:10 2002 @@ -48,7 +48,7 @@ ENTRY(_stext) mov #0x20, r1 ! shll8 r1 ! r1 = 8192 sub r1, r0 ! - ldc r0, r7_bank ! ... and init_task + ldc r0, r7_bank ! ... and initial thread_info ! ! Enable cache mov.l 6f, r0 diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/init_task.c linux/arch/sh/kernel/init_task.c --- linux-2.5.8-pre3/arch/sh/kernel/init_task.c Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/kernel/init_task.c Tue Feb 26 19:08:42 2002 @@ -12,12 +12,19 @@ static struct signal_struct init_signals struct mm_struct init_mm = INIT_MM(init_mm); /* - * Initial task structure. + * Initial thread structure. * * We need to make sure that this is 8192-byte aligned due to the * way process stacks are handled. This is done by having a special * "init_task" linker map entry.. */ -union task_union init_task_union +union thread_union init_thread_union __attribute__((__section__(".data.init_task"))) = - { INIT_TASK(init_task_union.task) }; + { INIT_THREAD_INFO(init_task) }; + +/* + * Initial task structure. + * + * All other task structs will be allocated on slabs in fork.c + */ +struct task_struct init_task = INIT_TASK(init_task); diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/io_7751se.c linux/arch/sh/kernel/io_7751se.c --- linux-2.5.8-pre3/arch/sh/kernel/io_7751se.c Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/kernel/io_7751se.c Mon Jan 21 08:48:19 2002 @@ -97,7 +97,7 @@ shifted_port(unsigned long port) #define CHECK_SH7751_PCIIO(port) \ ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE))) #else -#define CHECK_SH_7751_PCIIO(port) (0) +#define CHECK_SH7751_PCIIO(port) (0) #endif /* diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/io_se.c linux/arch/sh/kernel/io_se.c --- linux-2.5.8-pre3/arch/sh/kernel/io_se.c Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/kernel/io_se.c Tue Feb 26 18:15:15 2002 @@ -22,6 +22,7 @@ int sh_pcic_io_dummy; static inline void delay(void) { + ctrl_inw(0xa0000000); ctrl_inw(0xa0000000); } diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/pci-dma.c linux/arch/sh/kernel/pci-dma.c --- linux-2.5.8-pre3/arch/sh/kernel/pci-dma.c Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/kernel/pci-dma.c Tue Feb 26 19:10:20 2002 @@ -26,7 +26,7 @@ void *pci_alloc_consistent(struct pci_de if (ret != NULL) { /* Is it neccessary to do the memset? */ memset(ret, 0, size); - *dma_handle = virt_to_bus(ret); + *dma_handle = virt_to_phys(ret); } /* We must flush the cache before we pass it on to the device */ dma_cache_wback_inv(ret, size); diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/process.c linux/arch/sh/kernel/process.c --- linux-2.5.8-pre3/arch/sh/kernel/process.c Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/kernel/process.c Wed Apr 10 20:51:54 2002 @@ -15,6 +15,7 @@ #include <linux/mm.h> #include <linux/slab.h> #include <linux/a.out.h> +#include <linux/platform.h> #include <asm/io.h> #include <asm/uaccess.h> @@ -35,16 +36,14 @@ void enable_hlt(void) hlt_counter--; } -/* - * The idle loop on a uniprocessor i386.. - */ -void cpu_idle(void *unused) +void default_idle(void) { /* endless idle loop with no priority at all */ while (1) { if (hlt_counter) { - if (need_resched()) - break; + while (1) + if (need_resched()) + break; } else { __cli(); while (!need_resched()) { @@ -55,10 +54,17 @@ void cpu_idle(void *unused) __sti(); } schedule(); - check_pgt_cache(); } } +/* + * The idle loop on a uniprocessor i386.. + */ +void cpu_idle(void *unused) +{ + default_idle(); +} + void machine_restart(char * __unused) { /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ @@ -97,17 +103,6 @@ void show_regs(struct pt_regs * regs) regs->mach, regs->macl, regs->gbr, regs->pr); } -struct task_struct * alloc_task_struct(void) -{ - /* Get two pages */ - return (struct task_struct *) __get_free_pages(GFP_KERNEL,1); -} - -void free_task_struct(struct task_struct *p) -{ - free_pages((unsigned long) p, 1); -} - /* * Create a kernel thread */ @@ -177,11 +172,7 @@ int dump_fpu(struct pt_regs *regs, elf_f fpvalid = tsk->used_math; if (fpvalid) { - unsigned long flags; - - save_and_cli(flags); unlazy_fpu(tsk); - restore_flags(flags); memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); } @@ -198,26 +189,14 @@ int copy_thread(int nr, unsigned long cl struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs; -#if defined(__SH4__) - struct task_struct *tsk = current; - - if (tsk != &init_task) { - unsigned long flags; - save_and_cli(flags); - unlazy_fpu(tsk); - restore_flags(flags); - p->thread.fpu = current->thread.fpu; - p->used_math = tsk->used_math; - } -#endif - childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p)) - 1; + childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p->thread_info)) - 1; *childregs = *regs; if (user_mode(regs)) { childregs->regs[15] = usp; } else { - childregs->regs[15] = (unsigned long)p+2*PAGE_SIZE; + childregs->regs[15] = (unsigned long)p->thread_info+THREAD_SIZE; } childregs->regs[0] = 0; /* Set return value for child */ childregs->sr |= SR_FD; /* Invalidate FPU flag */ @@ -225,6 +204,16 @@ int copy_thread(int nr, unsigned long cl p->thread.sp = (unsigned long) childregs; p->thread.pc = (unsigned long) ret_from_fork; +#if defined(__SH4__) + { + struct task_struct *tsk = current; + + unlazy_fpu(tsk); + p->thread.fpu = tsk->thread.fpu; + p->used_math = tsk->used_math; + clear_ti_thread_flag(p->thread_info, TIF_USEDFPU); + } +#endif return 0; } @@ -255,13 +244,7 @@ void dump_thread(struct pt_regs * regs, void __switch_to(struct task_struct *prev, struct task_struct *next) { #if defined(__SH4__) - if (prev != &init_task) { - unsigned long flags; - - save_and_cli(flags); - unlazy_fpu(prev); - restore_flags(flags); - } + unlazy_fpu(prev); #endif /* * Restore the kernel mode register @@ -269,7 +252,7 @@ void __switch_to(struct task_struct *pre */ asm volatile("ldc %0, r7_bank" : /* no output */ - :"r" (next)); + : "r" (next->thread_info)); } asmlinkage int sys_fork(unsigned long r4, unsigned long r5, @@ -347,23 +330,12 @@ unsigned long get_wchan(struct task_stru /* * The same comment as on the Alpha applies here, too ... */ - pc = thread_saved_pc(&p->thread); + pc = thread_saved_pc(p); if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) { schedule_frame = ((unsigned long *)(long)p->thread.sp)[1]; return (unsigned long)((unsigned long *)schedule_frame)[1]; } return pc; -} - -asmlinkage void print_syscall(int x) -{ - unsigned long flags, sr; - asm("stc sr, %0": "=r" (sr)); - save_and_cli(flags); - printk("%c: %c %c, %c: SYSCALL\n", (x&63)+32, - (current->flags&PF_USEDFPU)?'C':' ', - (init_task.flags&PF_USEDFPU)?'K':' ', (sr&SR_FD)?' ':'F'); - restore_flags(flags); } asmlinkage void break_point_trap(unsigned long r4, unsigned long r5, diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/ptrace.c linux/arch/sh/kernel/ptrace.c --- linux-2.5.8-pre3/arch/sh/kernel/ptrace.c Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/kernel/ptrace.c Fri Apr 5 18:15:40 2002 @@ -39,7 +39,7 @@ static inline int get_stack_long(struct { unsigned char *stack; - stack = (unsigned char *)task + THREAD_SIZE - sizeof(struct pt_regs); + stack = (unsigned char *)task->thread_info + THREAD_SIZE - sizeof(struct pt_regs); stack += offset; return (*((int *)stack)); } @@ -52,7 +52,7 @@ static inline int put_stack_long(struct { unsigned char *stack; - stack = (unsigned char *)task + THREAD_SIZE - sizeof(struct pt_regs); + stack = (unsigned char *)task->thread_info + THREAD_SIZE - sizeof(struct pt_regs); stack += offset; *(unsigned long *) stack = data; return 0; @@ -159,7 +159,7 @@ void ptrace_disable(struct task_struct * asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { - struct task_struct *child, *tsk = current; + struct task_struct *child; struct user * dummy = NULL; int ret; @@ -191,15 +191,11 @@ asmlinkage int sys_ptrace(long request, ret = ptrace_attach(child); goto out_tsk; } - ret = -ESRCH; - if (!(child->ptrace & PT_PTRACED)) - goto out_tsk; - if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL) - goto out_tsk; - } - if (child->p_pptr != tsk) + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) goto out_tsk; + switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -279,9 +275,9 @@ asmlinkage int sys_ptrace(long request, if ((unsigned long) data > _NSIG) break; if (request == PTRACE_SYSCALL) - child->ptrace |= PT_TRACESYS; + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); else - child->ptrace &= ~PT_TRACESYS; + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->exit_code = data; wake_up_process(child); ret = 0; @@ -312,7 +308,7 @@ asmlinkage int sys_ptrace(long request, ret = -EIO; if ((unsigned long) data > _NSIG) break; - child->ptrace &= ~PT_TRACESYS; + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); if ((child->ptrace & PT_DTRACE) == 0) { /* Spurious delayed TF traps may occur */ child->ptrace |= PT_DTRACE; @@ -320,7 +316,7 @@ asmlinkage int sys_ptrace(long request, /* Compute next pc. */ pc = get_stack_long(child, (long)&dummy->pc); - regs = (struct pt_regs *)((unsigned long)child + THREAD_SIZE - sizeof(struct pt_regs)); + regs = (struct pt_regs *)(THREAD_SIZE + (unsigned long)child->thread_info) - 1; if (access_process_vm(child, pc&~3, &tmp, sizeof(tmp), 0) != sizeof(tmp)) break; @@ -335,7 +331,7 @@ asmlinkage int sys_ptrace(long request, else insn = tmp >> 16; #endif - compute_next_pc (regs, insn, &nextpc1, &nextpc2); + compute_next_pc(regs, insn, &nextpc1, &nextpc2); if (nextpc1 & 0x80000000) break; @@ -370,22 +366,23 @@ asmlinkage int sys_ptrace(long request, break; } out_tsk: - free_task_struct(child); + put_task_struct(child); out: unlock_kernel(); return ret; } -asmlinkage void syscall_trace(void) +asmlinkage void do_syscall_trace(void) { struct task_struct *tsk = current; - if ((tsk->ptrace & (PT_PTRACED|PT_TRACESYS)) - != (PT_PTRACED|PT_TRACESYS)) + if (!test_thread_flag(TIF_SYSCALL_TRACE)) + return; + if (!(tsk->ptrace & PT_PTRACED)) return; /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ - tsk->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + tsk->exit_code = SIGTRAP | ((tsk->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0); tsk->state = TASK_STOPPED; notify_parent(tsk, SIGCHLD); diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/semaphore.c linux/arch/sh/kernel/semaphore.c --- linux-2.5.8-pre3/arch/sh/kernel/semaphore.c Mon Feb 11 10:50:12 2002 +++ linux/arch/sh/kernel/semaphore.c Fri Apr 5 21:24:59 2002 @@ -7,6 +7,7 @@ * specific changes in <asm/semaphore-helper.h> */ +#include <linux/errno.h> #include <linux/sched.h> #include <linux/wait.h> #include <asm/semaphore.h> diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/setup.c linux/arch/sh/kernel/setup.c --- linux-2.5.8-pre3/arch/sh/kernel/setup.c Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/kernel/setup.c Fri Mar 22 21:57:10 2002 @@ -474,9 +474,9 @@ void __init setup_arch(char **cmdline_p) } #if defined(__SH4__) - /* We already grab/initialized FPU in head.S. Make it consisitent. */ - init_task.used_math = 1; - init_task.flags |= PF_USEDFPU; + /* FPU initialization */ + clear_thread_flag(TIF_USEDFPU); + current->used_math = 0; #endif paging_init(); } diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/sh_ksyms.c linux/arch/sh/kernel/sh_ksyms.c --- linux-2.5.8-pre3/arch/sh/kernel/sh_ksyms.c Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/kernel/sh_ksyms.c Wed Apr 10 20:10:51 2002 @@ -10,6 +10,7 @@ #include <linux/smp_lock.h> #include <linux/vmalloc.h> #include <linux/pci.h> +#include <linux/irq.h> #include <asm/semaphore.h> #include <asm/processor.h> @@ -19,7 +20,8 @@ #include <asm/hardirq.h> #include <asm/delay.h> #include <asm/pgalloc.h> -#include <linux/irq.h> +#include <asm/tlbflush.h> +#include <asm/cacheflush.h> extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(elf_fpregset_t *); @@ -36,9 +38,6 @@ EXPORT_SYMBOL(disable_irq_nosync); EXPORT_SYMBOL(irq_desc); EXPORT_SYMBOL(no_irq_type); -/* Networking helper routines. */ -EXPORT_SYMBOL(csum_partial_copy); - EXPORT_SYMBOL(strpbrk); EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(strlen); @@ -81,7 +80,7 @@ EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__const_udelay); #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL_NOVERS(name) - + /* These symbols are generated by the compiler itself */ DECLARE_EXPORT(__udivsi3); DECLARE_EXPORT(__sdivsi3); diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/signal.c linux/arch/sh/kernel/signal.c --- linux-2.5.8-pre3/arch/sh/kernel/signal.c Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/kernel/signal.c Wed Apr 10 20:47:01 2002 @@ -23,10 +23,12 @@ #include <linux/stddef.h> #include <linux/personality.h> #include <linux/tty.h> +#include <linux/binfmts.h> #include <asm/ucontext.h> #include <asm/uaccess.h> #include <asm/pgtable.h> +#include <asm/cacheflush.h> #define DEBUG_SIG 0 @@ -198,27 +200,20 @@ static inline int restore_sigcontext_fpu static inline int save_sigcontext_fpu(struct sigcontext *sc) { struct task_struct *tsk = current; - unsigned long flags; - int val; if (!tsk->used_math) { - val = 0; - __copy_to_user(&sc->sc_ownedfp, &val, sizeof(int)); + __put_user(0, &sc->sc_ownedfp); return 0; } - val = 1; - __copy_to_user(&sc->sc_ownedfp, &val, sizeof(int)); + __put_user(1, &sc->sc_ownedfp); /* This will cause a "finit" to be triggered by the next attempted FPU operation by the 'current' process. */ tsk->used_math = 0; - save_and_cli(flags); unlazy_fpu(tsk); - restore_flags(flags); - return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard, sizeof(long)*(16*2+2)); } @@ -250,14 +245,14 @@ restore_sigcontext(struct pt_regs *regs, regs->sr |= SR_FD; /* Release FPU */ clear_fpu(tsk); - current->used_math = 0; + tsk->used_math = 0; __get_user (owned_fp, &sc->sc_ownedfp); if (owned_fp) err |= restore_sigcontext_fpu(sc); } #endif - regs->syscall_nr = -1; /* disable syscall checks */ + regs->tra = -1; /* disable syscall checks */ err |= __get_user(*r0_p, &sc->sc_regs[0]); return err; } @@ -390,10 +385,10 @@ static void setup_frame(int sig, struct if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; - signal = current->exec_domain - && current->exec_domain->signal_invmap + signal = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap && sig < 32 - ? current->exec_domain->signal_invmap[sig] + ? current_thread_info()->exec_domain->signal_invmap[sig] : sig; err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); @@ -455,10 +450,10 @@ static void setup_rt_frame(int sig, stru if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; - signal = current->exec_domain - && current->exec_domain->signal_invmap + signal = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap && sig < 32 - ? current->exec_domain->signal_invmap[sig] + ? current_thread_info()->exec_domain->signal_invmap[sig] : sig; err |= __put_user(&frame->info, &frame->pinfo); @@ -526,7 +521,7 @@ handle_signal(unsigned long sig, struct siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) { /* Are we from a system call? */ - if (regs->syscall_nr >= 0) { + if (regs->tra >= 0) { /* If so, check system call restarting.. */ switch (regs->regs[0]) { case -ERESTARTNOHAND: @@ -540,7 +535,6 @@ handle_signal(unsigned long sig, struct } /* fallthrough */ case -ERESTARTNOINTR: - regs->regs[0] = regs->syscall_nr; regs->pc -= 2; } } @@ -620,8 +614,8 @@ int do_signal(struct pt_regs *regs, sigs info.si_signo = signr; info.si_errno = 0; info.si_code = SI_USER; - info.si_pid = current->p_pptr->pid; - info.si_uid = current->p_pptr->uid; + info.si_pid = current->parent->pid; + info.si_uid = current->parent->uid; } /* If the (new) signal is now blocked, requeue it. */ @@ -660,7 +654,7 @@ int do_signal(struct pt_regs *regs, sigs case SIGSTOP: current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) + if (!(current->parent->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; @@ -684,12 +678,11 @@ int do_signal(struct pt_regs *regs, sigs } /* Did we come from a system call? */ - if (regs->syscall_nr >= 0) { + if (regs->tra >= 0) { /* Restart the system call - no handlers present */ if (regs->regs[0] == -ERESTARTNOHAND || regs->regs[0] == -ERESTARTSYS || regs->regs[0] == -ERESTARTNOINTR) { - regs->regs[0] = regs->syscall_nr; regs->pc -= 2; } } diff -ruN3p linux-2.5.8-pre3/arch/sh/kernel/time.c linux/arch/sh/kernel/time.c --- linux-2.5.8-pre3/arch/sh/kernel/time.c Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/kernel/time.c Thu Mar 28 10:39:32 2002 @@ -175,6 +175,25 @@ void do_settimeofday(struct timeval *tv) /* last time the RTC clock got updated */ static long last_rtc_update; + +static __inline__ void sh_do_profile (unsigned long pc) +{ + extern int _stext; + + if (!prof_buffer) + return; + + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Don't ignore out-of-bounds EIP values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len-1) + pc = prof_len-1; + atomic_inc((atomic_t *)&prof_buffer[pc]); +} /* * timer_interrupt() needs to keep up the real-time clock, diff -ruN3p linux-2.5.8-pre3/arch/sh/mm/Makefile linux/arch/sh/mm/Makefile --- linux-2.5.8-pre3/arch/sh/mm/Makefile Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/mm/Makefile Wed Mar 27 14:08:50 2002 @@ -11,7 +11,7 @@ O_TARGET := mm.o obj-y := init.o fault.o extable.o clear_page.o copy_page.o obj-$(CONFIG_CPU_SH3) += cache-sh3.o -obj-$(CONFIG_CPU_SH4) += cache-sh4.o __clear_user_page-sh4.o __copy_user_page-sh4.o ioremap.o +obj-$(CONFIG_CPU_SH4) += cache-sh4.o ioremap.o USE_STANDARD_AS_RULE := true diff -ruN3p linux-2.5.8-pre3/arch/sh/mm/__clear_user_page-sh4.S linux/arch/sh/mm/__clear_user_page-sh4.S --- linux-2.5.8-pre3/arch/sh/mm/__clear_user_page-sh4.S Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/mm/__clear_user_page-sh4.S Thu Jan 1 09:00:00 1970 @@ -1,49 +0,0 @@ -/* $Id$ - * - * __clear_user_page implementation of SuperH - * - * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima - * - */ - -/* - * __clear_user_page - * @to: P1 address (with same color) - * @orig_to: P1 address - * - * void __clear_user_page(void *to, void *orig_to) - */ - -/* - * r0 --- scratch - * r4 --- to - * r5 --- orig_to - * r6 --- to + 4096 - */ -#include <linux/linkage.h> -ENTRY(__clear_user_page) - mov r4,r6 - mov.w .L4096,r0 - add r0,r6 - mov #0,r0 - ! -1: ocbi @r5 - add #32,r5 - movca.l r0,@r4 - mov r4,r1 - add #32,r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - add #28,r4 - cmp/eq r6,r4 - bf/s 1b - ocbwb @r1 - ! - rts - nop -.L4096: .word 4096 diff -ruN3p linux-2.5.8-pre3/arch/sh/mm/__copy_user_page-sh4.S linux/arch/sh/mm/__copy_user_page-sh4.S --- linux-2.5.8-pre3/arch/sh/mm/__copy_user_page-sh4.S Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/mm/__copy_user_page-sh4.S Thu Jan 1 09:00:00 1970 @@ -1,69 +0,0 @@ -/* $Id: __copy_user_page-sh4.S,v 1.1 2001/07/23 09:02:17 gniibe Exp $ - * - * __copy_user_page implementation of SuperH - * - * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima - * - */ - -/* - * __copy_user_page - * @to: P1 address (with same color) - * @from: P1 address - * @orig_to: P1 address - * - * void __copy_user_page(void *to, void *from, void *orig_to) - */ - -/* - * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch - * r8 --- from + 4096 - * r9 --- orig_to - * r10 --- to - * r11 --- from - */ -#include <linux/linkage.h> -ENTRY(__copy_user_page) - mov.l r8,@-r15 - mov.l r9,@-r15 - mov.l r10,@-r15 - mov.l r11,@-r15 - mov r4,r10 - mov r5,r11 - mov r6,r9 - mov r5,r8 - mov.w .L4096,r0 - add r0,r8 - ! -1: ocbi @r9 - add #32,r9 - mov.l @r11+,r0 - mov.l @r11+,r1 - mov.l @r11+,r2 - mov.l @r11+,r3 - mov.l @r11+,r4 - mov.l @r11+,r5 - mov.l @r11+,r6 - mov.l @r11+,r7 - movca.l r0,@r10 - mov r10,r0 - add #32,r10 - mov.l r7,@-r10 - mov.l r6,@-r10 - mov.l r5,@-r10 - mov.l r4,@-r10 - mov.l r3,@-r10 - mov.l r2,@-r10 - mov.l r1,@-r10 - ocbwb @r0 - cmp/eq r11,r8 - bf/s 1b - add #28,r10 - ! - mov.l @r15+,r11 - mov.l @r15+,r10 - mov.l @r15+,r9 - mov.l @r15+,r8 - rts - nop -.L4096: .word 4096 diff -ruN3p linux-2.5.8-pre3/arch/sh/mm/cache-sh3.c linux/arch/sh/mm/cache-sh3.c --- linux-2.5.8-pre3/arch/sh/mm/cache-sh3.c Mon Feb 11 10:50:08 2002 +++ linux/arch/sh/mm/cache-sh3.c Wed Apr 10 20:27:26 2002 @@ -19,6 +19,7 @@ #include <asm/uaccess.h> #include <asm/pgalloc.h> #include <asm/mmu_context.h> +#include <asm/cacheflush.h> #define CCR 0xffffffec /* Address of Cache Control Register */ diff -ruN3p linux-2.5.8-pre3/arch/sh/mm/cache-sh4.c linux/arch/sh/mm/cache-sh4.c --- linux-2.5.8-pre3/arch/sh/mm/cache-sh4.c Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/mm/cache-sh4.c Wed Apr 10 20:27:33 2002 @@ -20,6 +20,7 @@ #include <asm/uaccess.h> #include <asm/pgalloc.h> #include <asm/mmu_context.h> +#include <asm/cacheflush.h> #define CCR 0xff00001c /* Address of Cache Control Register */ @@ -109,7 +110,7 @@ void __init p3_cache_init(void) unsigned long size, unsigned long flags); if (remap_area_pages(P3SEG, 0, PAGE_SIZE*4, _PAGE_CACHABLE)) - panic("p3_cachie_init failed."); + panic("%s failed.", __FUNCTION__); sema_init (&p3map_sem[0], 1); sema_init (&p3map_sem[1], 1); sema_init (&p3map_sem[2], 1); @@ -208,44 +209,64 @@ void flush_cache_sigtramp(unsigned long restore_flags(flags); } -/* - * Writeback&Invalidate the D-cache of the page - */ -static void __flush_dcache_page(unsigned long phys) +static void flush_cache_4096_all(unsigned long start) { - unsigned long addr, data; - unsigned long flags; - - phys |= CACHE_VALID; - - save_and_cli(flags); - jump_to_P2(); - - /* Loop all the D-cache */ - for (addr = CACHE_OC_ADDRESS_ARRAY; - addr < (CACHE_OC_ADDRESS_ARRAY - +(CACHE_OC_NUM_ENTRIES<< CACHE_OC_ENTRY_SHIFT)); - addr += (1<<CACHE_OC_ENTRY_SHIFT)) { - data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); - if (data == phys) - ctrl_outl(0, addr); - } +#if defined(CONFIG_CPU_SUBTYPE_SH7751) || defined(CONFIG_CPU_SUBTYPE_ST40STB1) + /* + * SH7751 and ST40 have no restriction to handle cache. + * (While SH7750 must do that at P2 area.) + */ + unsigned long addr; + for (addr = start; addr < start + 4096; addr += 32) + ctrl_outl(0, addr); +#else + register unsigned long __r0 __asm__ ("r0") = 0; + register unsigned long __r1 __asm__ ("r1") = 128; + register unsigned long __r4 __asm__ ("r4"); + register unsigned long __r5 __asm__ ("r5"); + register unsigned long __r6 __asm__ ("r6"); + register unsigned long __r7 __asm__ ("r7"); + extern void __flush_cache_4096_all(unsigned long); + + asm volatile("jsr @%7; nop" + : "=&r" (__r4), "=&r" (__r5), "=&r" (__r6), "=&r" (__r7) + : "0" (start), "r" (__r0), "r" (__r1), + "r" (__flush_cache_4096_all + 0x20000000) + : "pr"); +#endif +} -#if 0 /* DEBUG DEBUG */ - /* Loop all the I-cache */ - for (addr = CACHE_IC_ADDRESS_ARRAY; - addr < (CACHE_IC_ADDRESS_ARRAY - +(CACHE_IC_NUM_ENTRIES<< CACHE_IC_ENTRY_SHIFT)); - addr += (1<<CACHE_IC_ENTRY_SHIFT)) { - data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); - if (data == phys) { - printk(KERN_INFO "__flush_cache_page: I-cache entry found\n"); - ctrl_outl(0, addr); +static inline void flush_cache_4096(unsigned long start, + unsigned long phys) +{ +#if defined(CONFIG_CPU_SUBTYPE_SH7751) || defined(CONFIG_CPU_SUBTYPE_ST40STB1) + if (start >= CACHE_OC_ADDRESS_ARRAY) { + /* + * SH7751 and ST40 have no restriction to handle cache. + * (While SH7750 must do that at P2 area.) + */ + unsigned long addr, data; + for (addr = start; addr < start + 4096; addr += 32) { + data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); + if (data == phys) + ctrl_outl(0, addr); } - } + } else #endif - back_to_P1(); - restore_flags(flags); + { + register unsigned long addr __asm__ ("r4"); + register unsigned long data __asm__ ("r0"); + register unsigned long __r5 __asm__ ("r5") = phys; + register unsigned long __r6 __asm__ ("r6") = (0x1ffff000|CACHE_VALID); + register unsigned long __r7 __asm__ ("r7") = 0; + extern void __flush_cache_4096(unsigned long, unsigned long); + + asm volatile("jsr @%1; nop" + : "=r" (addr), "=r" (data) + : "0" (start), "1" (__flush_cache_4096 + 0x20000000), + "r" (__r5), "r" (__r6), "r" (__r7) + : "pr"); + } } /* @@ -254,38 +275,122 @@ static void __flush_dcache_page(unsigned */ void flush_dcache_page(struct page *page) { - if (test_bit(PG_mapped, &page->flags)) - __flush_dcache_page(PHYSADDR(page_address(page))); + if (test_bit(PG_mapped, &page->flags)) { + unsigned long phys = PHYSADDR(page_address(page)); + unsigned long flags; + + phys |= CACHE_VALID; + + save_and_cli(flags); + + /* Loop all the D-cache */ + flush_cache_4096(CACHE_OC_ADDRESS_ARRAY, phys); + flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x1000, phys); + flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x2000, phys); + flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x3000, phys); + + restore_flags(flags); + } } -void flush_cache_all(void) +static inline void flush_icache_all(void) { - extern unsigned long empty_zero_page[1024]; unsigned long flags; - unsigned long addr; save_and_cli(flags); + jump_to_P2(); + /* Flush I-cache */ + ctrl_outl(CCR_CACHE_VAL|CCR_CACHE_ICI, CCR); + back_to_P1(); + restore_flags(flags); +} + +#undef C_IMPLEMENTATION_OF_CACHE_ALL + +void flush_cache_all(void) +{ + extern unsigned long empty_zero_page[1024]; /* Prefetch the data to write back D-cache */ + +#ifdef C_IMPLEMENTATION_OF_CACHE_ALL + unsigned long addr; + for (addr = (unsigned long)empty_zero_page; addr < (unsigned long)empty_zero_page + 1024*16; addr += L1_CACHE_BYTES) asm volatile("pref @%0"::"r" (addr)); - - jump_to_P2(); - /* Flush D-cache/I-cache */ - ctrl_outl(CCR_CACHE_INIT, CCR); - back_to_P1(); - restore_flags(flags); +#else + unsigned long a0, a1, a2, a3, cnt; + asm volatile( + "mov %0, %1; add #32, %1\n\t" + "mov %0, %2; add #64, %2\n\t" + "mov %1, %3; add #64, %3\n\t" + "1:\n\t" + "pref @%0\n\t" + "dt %4\n\t" + "pref @%1\n\t" + "add %5, %0\n\t" + "pref @%2\n\t" + "add %5, %1\n\t" + "pref @%3\n\t" + "add %5, %2\n\t" + "bf/s 1b\n\t" + " add %5, %3" + : "=&r" (a0), "=&r" (a1), "=&r" (a2), "=&r" (a3), "=&r" (cnt) + : "r" (32*4), "0" (empty_zero_page), "4" (1024*16/32/4) + : "t"); +#endif + flush_icache_all(); } void flush_cache_mm(struct mm_struct *mm) { /* Is there any good way? */ /* XXX: possibly call flush_cache_range for each vm area */ + /* + * FIXME: Really, the optimal solution here would be able to flush out + * individual lines created by the specified context, but this isn't + * feasible for a number of architectures (such as MIPS, and some + * SPARC) .. is this possible for SuperH? + * + * In the meantime, we'll just flush all of the caches.. this + * seems to be the simplest way to avoid at least a few wasted + * cache flushes. -Lethal + */ flush_cache_all(); } +static void __flush_cache_page(struct vm_area_struct *vma, + unsigned long address, + unsigned long phys) +{ + unsigned long flags; + + phys |= CACHE_VALID; + save_and_cli(flags); + + /* We only need to flush D-cache when we have alias */ + if ((address^phys) & CACHE_ALIAS) { + /* Loop 4K of the D-cache */ + flush_cache_4096( + CACHE_OC_ADDRESS_ARRAY | (address & CACHE_ALIAS), + phys); + /* Loop another 4K of the D-cache */ + flush_cache_4096( + CACHE_OC_ADDRESS_ARRAY | (phys & CACHE_ALIAS), + phys); + } + + if (vma->vm_flags & VM_EXEC) + /* Loop 4K (half) of the I-cache */ + flush_cache_4096( + CACHE_IC_ADDRESS_ARRAY | (address & 0x1000), + phys); + + restore_flags(flags); +} + /* * Write back and invalidate D-caches. * @@ -298,14 +403,52 @@ void flush_cache_mm(struct mm_struct *mm void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - /* - * We could call flush_cache_page for the pages of these range, - * but it's not efficient (scan the caches all the time...). - * - * We can't use A-bit magic, as there's the case we don't have - * valid entry on TLB. - */ - flush_cache_all(); + unsigned long p = start & PAGE_MASK; + pgd_t *dir; + pmd_t *pmd; + pte_t *pte; + pte_t entry; + unsigned long phys; + unsigned long d = 0; + + dir = pgd_offset(vma->vm_mm, p); + pmd = pmd_offset(dir, p); + + do { + if (pmd_none(*pmd) || pmd_bad(*pmd)) { + p &= ~((1 << PMD_SHIFT) -1); + p += (1 << PMD_SHIFT); + pmd++; + continue; + } + pte = pte_offset_kernel(pmd, p); + do { + entry = *pte; + if ((pte_val(entry) & _PAGE_PRESENT)) { + phys = pte_val(entry)&PTE_PHYS_MASK; + if ((p^phys) & CACHE_ALIAS) { + d |= 1 << ((p & CACHE_ALIAS)>>12); + d |= 1 << ((phys & CACHE_ALIAS)>>12); + if (d == 0x0f) + goto loop_exit; + } + } + pte++; + p += PAGE_SIZE; + } while (p < end && (unsigned long)pte & PAGE_MASK); + pmd++; + } while (p < end); + loop_exit: + if (d & 1) + flush_cache_4096_all(CACHE_OC_ADDRESS_ARRAY); + if (d & 2) + flush_cache_4096_all(CACHE_OC_ADDRESS_ARRAY | 0x1000); + if (d & 4) + flush_cache_4096_all(CACHE_OC_ADDRESS_ARRAY | 0x2000); + if (d & 8) + flush_cache_4096_all(CACHE_OC_ADDRESS_ARRAY | 0x3000); + if (vma->vm_flags & VM_EXEC) + flush_icache_all(); } /* @@ -319,58 +462,32 @@ void flush_cache_page(struct vm_area_str pmd_t *pmd; pte_t *pte; pte_t entry; - unsigned long phys, addr, data; - unsigned long flags; + unsigned long phys; dir = pgd_offset(vma->vm_mm, address); pmd = pmd_offset(dir, address); if (pmd_none(*pmd) || pmd_bad(*pmd)) return; - pte = pte_offset(pmd, address); + pte = pte_offset_kernel(pmd, address); entry = *pte; - if (pte_none(entry) || !pte_present(entry)) + if (!(pte_val(entry) & _PAGE_PRESENT)) return; phys = pte_val(entry)&PTE_PHYS_MASK; + __flush_cache_page(vma, address, phys); +} - phys |= CACHE_VALID; - save_and_cli(flags); - jump_to_P2(); - - /* We only need to flush D-cache when we have alias */ - if ((address^phys) & CACHE_ALIAS) { - /* Loop 4K of the D-cache */ - for (addr = CACHE_OC_ADDRESS_ARRAY | (address & CACHE_ALIAS); - addr < (CACHE_OC_ADDRESS_ARRAY + (address & CACHE_ALIAS) - +(CACHE_OC_NUM_ENTRIES/4<<CACHE_OC_ENTRY_SHIFT)); - addr += (1<<CACHE_OC_ENTRY_SHIFT)) { - data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); - if (data == phys) - ctrl_outl(0, addr); - } - /* Loop another 4K of the D-cache */ - for (addr = CACHE_OC_ADDRESS_ARRAY | (phys & CACHE_ALIAS); - addr < (CACHE_OC_ADDRESS_ARRAY + (phys & CACHE_ALIAS) - +(CACHE_OC_NUM_ENTRIES/4<<CACHE_OC_ENTRY_SHIFT)); - addr += (1<<CACHE_OC_ENTRY_SHIFT)) { - data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); - if (data == phys) - ctrl_outl(0, addr); - } - } - - if (vma->vm_flags & VM_EXEC) - /* Loop 4K of the I-cache */ - for (addr = CACHE_IC_ADDRESS_ARRAY|(address&0x1000); - addr < ((CACHE_IC_ADDRESS_ARRAY|(address&0x1000)) - +(CACHE_IC_NUM_ENTRIES/2<<CACHE_IC_ENTRY_SHIFT)); - addr += (1<<CACHE_IC_ENTRY_SHIFT)) { - data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); - if (data == phys) - ctrl_outl(0, addr); - } - back_to_P1(); - restore_flags(flags); +/* + * flush_icache_user_range + * @vma: VMA of the process + * @page: page + * @addr: U0 address + * @len: length of the range (< page size) + */ +void flush_icache_user_range(struct vm_area_struct *vma, + struct page *page, unsigned long addr, int len) +{ + __flush_cache_page(vma, addr, PHYSADDR(page_address(page))); } /* @@ -394,7 +511,7 @@ void clear_user_page(void *to, unsigned unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); pgd_t *dir = pgd_offset_k(p3_addr); pmd_t *pmd = pmd_offset(dir, p3_addr); - pte_t *pte = pte_offset(pmd, p3_addr); + pte_t *pte = pte_offset_kernel(pmd, p3_addr); pte_t entry; unsigned long flags; @@ -433,7 +550,7 @@ void copy_user_page(void *to, void *from unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); pgd_t *dir = pgd_offset_k(p3_addr); pmd_t *pmd = pmd_offset(dir, p3_addr); - pte_t *pte = pte_offset(pmd, p3_addr); + pte_t *pte = pte_offset_kernel(pmd, p3_addr); pte_t entry; unsigned long flags; diff -ruN3p linux-2.5.8-pre3/arch/sh/mm/clear_page.S linux/arch/sh/mm/clear_page.S --- linux-2.5.8-pre3/arch/sh/mm/clear_page.S Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/mm/clear_page.S Wed Apr 3 11:38:34 2002 @@ -1,10 +1,13 @@ -/* $Id: clear_page.S,v 1.1 2001/07/23 10:08:50 gniibe Exp $ +/* $Id: clear_page.S,v 1.5 2002/04/03 02:38:34 gniibe Exp $ * - * clear_page implementation of SuperH + * __clear_user_page, __clear_user, clear_page implementation of SuperH * - * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima + * Copyright (C) 2001 Kaz Kojima + * Copyright (C) 2001, 2002 Niibe Yutaka * */ +#include <linux/config.h> +#include <linux/linkage.h> /* * clear_page @@ -18,7 +21,6 @@ * r4 --- to * r5 --- to + 4096 */ -#include <linux/linkage.h> ENTRY(clear_page) mov r4,r5 mov.w .Llimit,r0 @@ -50,3 +52,181 @@ ENTRY(clear_page) rts nop .Llimit: .word (4096-28) + +ENTRY(__clear_user) + ! + mov #0, r0 + mov #0xe0, r1 ! 0xffffffe0 + ! + ! r4..r4&~32 -------- not aligned [ Area 0 ] + ! r4&~32..(r4+r5)&~32 -------- aligned [ Area 1 ] + ! (r4+r5)&~32..r4+r5 -------- not aligned [ Area 2 ] + ! + ! Clear area 0 + mov r4, r2 + and r1, r2 + cmp/eq r4, r2 + bt/s area1 + mov r4, r3 + sub r2, r3 + mov r4, r2 + ! +l0: dt r3 +0: mov.b r0, @r2 + bf/s l0 + add #1, r2 + ! + mov r4, r3 + add r5, r3 + and r1, r3 + ! + ! Clear area 1 +area1: +#if defined(__SH4__) +1: movca.l r0, @r2 +#else +1: mov.l r0, @r2 +#endif + add #4, r2 +2: mov.l r0, @r2 + add #4, r2 +3: mov.l r0, @r2 + add #4, r2 +4: mov.l r0, @r2 + add #4, r2 +5: mov.l r0, @r2 + add #4, r2 +6: mov.l r0, @r2 + add #4, r2 +7: mov.l r0, @r2 + add #4, r2 +8: mov.l r0, @r2 + add #4, r2 + cmp/hi r2, r3 + bt/s 1b + nop + ! + ! Clear area 2 + add r5, r4 + cmp/eq r4, r2 + bt/s done + sub r2, r4 +l2: dt r4 +9: mov.b r0, @r2 + bf/s l2 + add #1, r2 + ! +done: rts + nop ! return 0 as normal return + + ! return the number of bytes remained +bad_clear_user: + mov r4, r0 + mov r5, r0 + rts + sub r2, r0 + +.section __ex_table,"a" + .align 2 + .long 0b, bad_clear_user + .long 1b, bad_clear_user + .long 2b, bad_clear_user + .long 3b, bad_clear_user + .long 4b, bad_clear_user + .long 5b, bad_clear_user + .long 6b, bad_clear_user + .long 7b, bad_clear_user + .long 8b, bad_clear_user + .long 9b, bad_clear_user +.previous + +#if defined(__SH4__) +/* + * __clear_user_page + * @to: P1 address (with same color) + * @orig_to: P1 address + * + * void __clear_user_page(void *to, void *orig_to) + */ + +/* + * r0 --- scratch + * r4 --- to + * r5 --- orig_to + * r6 --- to + 4096 + */ +ENTRY(__clear_user_page) + mov.w .L4096,r0 + mov r4,r6 + add r0,r6 + mov #0,r0 + ! +1: ocbi @r5 + add #32,r5 + movca.l r0,@r4 + mov r4,r1 + add #32,r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + add #28,r4 + cmp/eq r6,r4 + bf/s 1b + ocbwb @r1 + ! + rts + nop +.L4096: .word 4096 + +ENTRY(__flush_cache_4096) + .rept 128 + mov.l @r4,r0 + and r6,r0 + cmp/eq r5,r0 + bf 1f + mov.l r7,@r4 +1: add #32,r4 + .endr + nop + nop + nop + nop + nop + nop + nop + rts + nop + +#if defined(CONFIG_CPU_SUBTYPE_SH7750) +ENTRY(__flush_cache_4096_all) + mov r4,r5 + mov r4,r6 + mov r4,r7 + add #32,r5 + add #-64,r6 + add #-32,r7 + .rept 32 + mov.l r0,@r4 + add r1,r6 + mov.l r0,@r5 + add r1,r7 + mov.l r0,@r6 + add r1,r4 + mov.l r0,@r7 + add r1,r5 + .endr + nop + nop + nop + nop + nop + nop + nop + rts + nop +#endif +#endif diff -ruN3p linux-2.5.8-pre3/arch/sh/mm/copy_page.S linux/arch/sh/mm/copy_page.S --- linux-2.5.8-pre3/arch/sh/mm/copy_page.S Thu Apr 4 18:41:39 2002 +++ linux/arch/sh/mm/copy_page.S Wed Apr 3 11:38:34 2002 @@ -1,10 +1,11 @@ -/* $Id: copy_page.S,v 1.2 2001/07/23 10:27:25 gniibe Exp $ +/* $Id: copy_page.S,v 1.3 2002/04/03 02:38:34 gniibe Exp $ * - * copy_page implementation of SuperH + * copy_page, __copy_user_page implementation of SuperH * * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima * */ +#include <linux/linkage.h> /* * copy_page @@ -21,7 +22,6 @@ * r10 --- to * r11 --- from */ -#include <linux/linkage.h> ENTRY(copy_page) mov.l r8,@-r15 mov.l r10,@-r15 @@ -66,4 +66,66 @@ ENTRY(copy_page) mov.l @r15+,r8 rts nop + +#if defined(__SH4__) +/* + * __copy_user_page + * @to: P1 address (with same color) + * @from: P1 address + * @orig_to: P1 address + * + * void __copy_user_page(void *to, void *from, void *orig_to) + */ + +/* + * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch + * r8 --- from + 4096 + * r9 --- orig_to + * r10 --- to + * r11 --- from + */ +ENTRY(__copy_user_page) + mov.l r8,@-r15 + mov.l r9,@-r15 + mov.l r10,@-r15 + mov.l r11,@-r15 + mov r4,r10 + mov r5,r11 + mov r6,r9 + mov r5,r8 + mov.w .L4096,r0 + add r0,r8 + ! +1: ocbi @r9 + add #32,r9 + mov.l @r11+,r0 + mov.l @r11+,r1 + mov.l @r11+,r2 + mov.l @r11+,r3 + mov.l @r11+,r4 + mov.l @r11+,r5 + mov.l @r11+,r6 + mov.l @r11+,r7 + movca.l r0,@r10 + mov r10,r0 + add #32,r10 + mov.l r7,@-r10 + mov.l r6,@-r10 + mov.l r5,@-r10 + mov.l r4,@-r10 + mov.l r3,@-r10 + mov.l r2,@-r10 + mov.l r1,@-r10 + ocbwb @r0 + cmp/eq r11,r8 + bf/s 1b + add #28,r10 + ! + mov.l @r15+,r11 + mov.l @r15+,r10 + mov.l @r15+,r9 + mov.l @r15... [truncated message content] |