summaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-04-19 04:00:00 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-04-19 04:00:00 +0000
commit46e045034336a2cc90c1798cd7cc07af744ddfd6 (patch)
tree3b9b51fc482e729f663d25333e77fbed9aaa939a /arch/sh
parent31dc59d503a02e84c4de98826452acaeb56dc15a (diff)
Merge with Linux 2.3.99-pre4.
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/Makefile2
-rw-r--r--arch/sh/config.in5
-rw-r--r--arch/sh/defconfig2
-rw-r--r--arch/sh/kernel/Makefile4
-rw-r--r--arch/sh/kernel/entry.S556
-rw-r--r--arch/sh/kernel/fpu.c6
-rw-r--r--arch/sh/kernel/head.S9
-rw-r--r--arch/sh/kernel/irq.c6
-rw-r--r--arch/sh/kernel/irq_imask.c39
-rw-r--r--arch/sh/kernel/process.c35
-rw-r--r--arch/sh/kernel/ptrace.c595
-rw-r--r--arch/sh/kernel/signal.c77
-rw-r--r--arch/sh/lib/Makefile2
-rw-r--r--arch/sh/mm/cache.c83
-rw-r--r--arch/sh/mm/fault.c27
-rw-r--r--arch/sh/mm/init.c2
16 files changed, 706 insertions, 744 deletions
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 83591c86c..1857ef33b 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.2 1999/12/23 12:13:53 gniibe Exp gniibe $
+# $Id: Makefile,v 1.4 2000/03/08 15:14:14 gniibe Exp $
#
# 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
diff --git a/arch/sh/config.in b/arch/sh/config.in
index e3bfd113c..2ee913c3c 100644
--- a/arch/sh/config.in
+++ b/arch/sh/config.in
@@ -48,6 +48,7 @@ mainmenu_option next_comment
comment 'General setup'
define_bool CONFIG_ISA n
+define_bool CONFIG_SBUS n
bool 'Networking support' CONFIG_NET
@@ -73,6 +74,8 @@ bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
if [ "$CONFIG_HOTPLUG" = "y" ] ; then
source drivers/pcmcia/Config.in
+else
+ define_bool CONFIG_PCMCIA n
fi
bool 'System V IPC' CONFIG_SYSVIPC
@@ -170,8 +173,6 @@ if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then
source drivers/char/pcmcia/Config.in
fi
-#source drivers/misc/Config.in
-
source fs/Config.in
if [ "$CONFIG_VT" = "y" ]; then
diff --git a/arch/sh/defconfig b/arch/sh/defconfig
index fad2ab8b1..337e46956 100644
--- a/arch/sh/defconfig
+++ b/arch/sh/defconfig
@@ -29,10 +29,12 @@ CONFIG_MEMORY_START=0c000000
# General setup
#
# CONFIG_ISA is not set
+# CONFIG_SBUS is not set
# CONFIG_NET is not set
CONFIG_CF_ENABLER=y
# CONFIG_PCI is not set
# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
# CONFIG_SYSVIPC is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_SYSCTL is not set
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index efa2fb109..8996a13dc 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -7,7 +7,7 @@
#
.S.o:
- $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+ $(CC) $(AFLAGS) -traditional -c $< -o $*.o
O_TARGET := kernel.o
O_OBJS := process.o signal.o entry.o traps.o irq.o irq_onchip.o \
@@ -29,7 +29,7 @@ all: kernel.o head.o init_task.o
entry.o: entry.S
head.o: head.S
- $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o
+ $(CC) $(AFLAGS) -traditional -c $*.S -o $*.o
clean:
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S
index 77bb7938b..46ad20f53 100644
--- a/arch/sh/kernel/entry.S
+++ b/arch/sh/kernel/entry.S
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.55 2000/03/05 01:48:58 gniibe Exp $
+/* $Id: entry.S,v 1.71 2000/03/22 13:29:33 gniibe Exp $
*
* linux/arch/sh/entry.S
*
@@ -33,10 +33,9 @@
*
* syscall #
* ssr
- * r15 = stack pointer
* r0
* ...
- * r14
+ * r15 = stack pointer
* gbr
* mach
* macl
@@ -46,7 +45,7 @@
*/
/*
- * these are offsets into the task-struct.
+ * These are offsets into the task-struct.
*/
state = 0
flags = 4
@@ -78,8 +77,8 @@ MMU_TEA = 0xff00000c ! TLB Exception Address Register
/* Offsets to the stack */
SYSCALL_NR = 0
SR = 4
-SP = 8
-R0 = 12
+R0 = 8
+SP = (8+15*4)
#define k0 r0
#define k1 r1
@@ -96,7 +95,7 @@ R0 = 12
k2 scratch (Exception code)
k3 scratch (Return address)
k4 Stack base = current+8192
- k5 reserved
+ k5 Global Interrupt Mask (0--15)
k6 reserved
k7 reserved
*/
@@ -115,109 +114,113 @@ R0 = 12
! this first version depends *much* on C implementation.
!
-#define DO_FAULT(write) \
- mov.l 4f,r0; \
- mov.l @r0,r6; \
- /* STI */ \
- mov.l 3f,r1; \
- stc sr,r0; \
- and r1,r0; \
- ldc r0,sr; \
- /* */ \
- mov r15,r4; \
- mov.l 2f,r0; \
- jmp @r0; \
- mov #write,r5;
+#define RESTORE_FLAGS() \
+ mov.l @(SR,$r15), $r0; \
+ and #0xf0, $r0; \
+ shlr8 $r0; \
+ cmp/eq #0x0f, $r0; \
+ bt 9f; \
+ mov.l __INV_IMASK, $r1; \
+ stc $sr, $r0; \
+ and $r1, $r0; \
+ stc $r5_bank, $r1; \
+ or $r1, $r0; \
+ ldc $r0, $sr
.balign 4
tlb_protection_violation_load:
tlb_miss_load:
- mov #-1,r0
- mov.l r0,@r15 ! syscall nr = -1
- DO_FAULT(0)
+ mov #-1, $r0
+ mov.l $r0, @$r15 ! syscall nr = -1
+ mov.l 2f, $r0
+ mov.l @$r0, $r6
+ RESTORE_FLAGS()
+9: mov $r15, $r4
+ mov.l 1f, $r0
+ jmp @$r0
+ mov #0, $r5
.balign 4
tlb_protection_violation_store:
tlb_miss_store:
initial_page_write:
- mov #-1,r0
- mov.l r0,@r15 ! syscall nr = -1
- DO_FAULT(1)
+ mov #-1, $r0
+ mov.l $r0, @$r15 ! syscall nr = -1
+ mov.l 2f, $r0
+ mov.l @$r0, $r6
+ RESTORE_FLAGS()
+9: mov $r15, $r4
+ mov.l 1f, $r0
+ jmp @$r0
+ mov #1, $r5
.balign 4
-2: .long SYMBOL_NAME(do_page_fault)
-3: .long 0xefffffff ! BL=0
-4: .long MMU_TEA
+1: .long SYMBOL_NAME(do_page_fault)
+2: .long MMU_TEA
#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
.balign 4
/* Unwind the stack and jmp to the debug entry */
debug:
- add #4,r15 ! skip syscall number
- mov.l @r15+,r11 ! SSR
- mov.l @r15+,r10 ! original stack
- mov.l @r15+,r0
- mov.l @r15+,r1
- mov.l @r15+,r2
- mov.l @r15+,r3
- mov.l @r15+,r4
- mov.l @r15+,r5
- mov.l @r15+,r6
- mov.l @r15+,r7
- stc sr,r14
- mov.l 8f,r9 ! BL =1, RB=1
- or r9,r14
- ldc r14,sr ! here, change the register bank
- mov r10,k0
- mov r11,k1
- mov.l @r15+,r8
- mov.l @r15+,r9
- mov.l @r15+,r10
- mov.l @r15+,r11
- mov.l @r15+,r12
- mov.l @r15+,r13
- mov.l @r15+,r14
- ldc.l @r15+,gbr
- lds.l @r15+,mach
- lds.l @r15+,macl
- lds.l @r15+,pr
- ldc.l @r15+,spc
- mov k0,r15
+ add #4, $r15 ! skip syscall number
+ mov.l @$r15+, $r11 ! SSR
+ mov.l @$r15+, $r0
+ mov.l @$r15+, $r1
+ mov.l @$r15+, $r2
+ mov.l @$r15+, $r3
+ mov.l @$r15+, $r4
+ mov.l @$r15+, $r5
+ mov.l @$r15+, $r6
+ mov.l @$r15+, $r7
+ stc $sr, $r14
+ mov.l 1f, $r9 ! BL =1, RB=1
+ or $r9, $r14
+ ldc $r14, $sr ! here, change the register bank
+ mov $r11, $k1
+ mov.l @$r15+, $r8
+ mov.l @$r15+, $r9
+ mov.l @$r15+, $r10
+ mov.l @$r15+, $r11
+ mov.l @$r15+, $r12
+ mov.l @$r15+, $r13
+ mov.l @$r15+, $r14
+ mov.l @$r15+, $k0
+ ldc.l @$r15+, $gbr
+ lds.l @$r15+, $mach
+ lds.l @$r15+, $macl
+ lds.l @$r15+, $pr
+ ldc.l @$r15+, $spc
+ mov $k0, $r15
!
- mov.l 9f,k0
- jmp @k0
- ldc k1,ssr
+ mov.l 2f, $k0
+ jmp @$k0
+ ldc $k1, $ssr
.balign 4
-8: .long 0x300000f0
-9: .long 0xa0000100
+1: .long 0x300000f0
+2: .long 0xa0000100
#endif
.balign 4
error:
- ! STI
- mov.l 2f,r1
- stc sr,r0
- and r1,r0
- ldc r0,sr
!
- mov.l 1f,r1
- mov #-1,r0
- jmp @r1
- mov.l r0,@r15 ! syscall nr = -1
+ RESTORE_FLAGS()
+9: mov.l 1f, $r1
+ mov #-1, $r0
+ jmp @$r1
+ mov.l $r0, @$r15 ! syscall nr = -1
.balign 4
1: .long SYMBOL_NAME(do_exception_error)
-2: .long 0xefffffff ! BL=0
-badsys: mov #-ENOSYS,r0
+badsys: mov #-ENOSYS, $r0
rts ! go to ret_from_syscall..
- mov.l r0,@(R0,r15)
+ mov.l $r0, @(R0,$r15)
!
!
!
ENTRY(ret_from_fork)
bra SYMBOL_NAME(ret_from_syscall)
- add #4,r15 ! pop down bogus r0 (see switch_to MACRO)
+ add #4, $r15 ! pop down bogus r0 (see switch_to MACRO)
!
! The immediate value of "trapa" indicates the number of arguments
@@ -226,83 +229,77 @@ ENTRY(ret_from_fork)
! Note that TRA register contains the value = Imm x 4.
!
system_call:
- mov.l 1f,r2
- mov.l @r2,r8
+ mov.l 1f, $r2
+ mov.l @$r2, $r8
!
! DEBUG DEBUG
- ! mov.l led,r1
- ! mov r0,r2
- ! mov.b r2,@r1
+ ! mov.l led, $r1
+ ! mov $r0, $r2
+ ! mov.b $r2, @$r1
!
#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
- mov #0x20,r1
- extu.b r1,r1
- shll2 r1
- cmp/hs r1,r8
+ mov #0x20, $r1
+ extu.b $r1, $r1
+ shll2 $r1
+ cmp/hs $r1, $r8
bt debug
#endif
- ! STI
- mov.l 2f,r1
- stc sr,r2
- and r1,r2
- ldc r2,sr
!
- mov.l __n_sys,r1
- cmp/hs r1,r0
- bt/s badsys
- mov r0,r2
+ mov $r0, $r2
+ RESTORE_FLAGS()
+9: mov.l __n_sys, $r1
+ cmp/hs $r1, $r2
+ bt badsys
!
- stc ksp,r1 !
- mov.l __tsk_flags,r0 !
- add r0,r1 !
- mov.l @r1,r0 ! Is it trace?
- tst #PF_TRACESYS,r0
+ stc $ksp, $r1
+ mov.l __tsk_flags, $r0
+ add $r0, $r1 !
+ mov.l @$r1, $r0 ! Is it trace?
+ tst #PF_TRACESYS, $r0
bt 5f
! Trace system call
- mov #-ENOSYS,r1
- mov.l r1,@(R0,r15)
- mov.l 3f,r1
- jsr @r1
+ mov #-ENOSYS, $r1
+ mov.l $r1, @(R0,$r15)
+ mov.l 3f, $r1
+ jsr @$r1
nop
- mova 4f,r0
+ mova 3f, $r0
bra 6f
- lds r0,pr
- !
-5: mova ret,r0 ! normal case
- lds r0,pr
- ! Build the stack frame if TRA > 0
+ lds $r0, $pr
!
-6: mov r2,r3
- mov r8,r2
- cmp/pl r8
- bf 9f
- mov.l @(SP,r15),r0 ! get original stack
-7: add #-4,r8
-8: mov.l @(r0,r8),r1 ! May cause address error exception..
- mov.l r1,@-r15
- cmp/pl r8
+5: mova syscall_ret, $r0
+ lds $r0, $pr
+ ! Build the stack frame if TRA > 0
+6: mov $r2, $r3
+ mov $r8, $r2
+ cmp/pl $r8
+ bf 0f
+ mov #SP, $r0
+ mov.l @($r0,$r15), $r0 ! get original stack
+7: add #-4, $r8
+4: mov.l @($r0,$r8), $r1 ! May cause address error exception..
+ mov.l $r1, @-$r15
+ cmp/pl $r8
bt 7b
!
-9: mov r3,r0
- shll2 r0 ! x4
- mov.l __sct,r1
- add r1,r0
- mov.l @r0,r1
- jmp @r1
- mov r2,r8
-
+0: mov $r3, $r0
+ shll2 $r0 ! x4
+ mov.l __sct, $r1
+ add $r1, $r0
+ mov.l @$r0, $r1
+ jmp @$r1
+ mov $r2, $r8
! In case of trace
.balign 4
-4: add r8,r15 ! pop off the arguments
- mov.l r0,@(R0,r15) ! save the return value
- mov.l 3f,r1
- mova SYMBOL_NAME(ret_from_syscall),r0
- jmp @r1
- lds r0,pr
+3: add $r8, $r15 ! pop off the arguments
+ mov.l $r0, @(R0,$r15) ! save the return value
+ mov.l 2f, $r1
+ mova SYMBOL_NAME(ret_from_syscall), $r0
+ jmp @$r1
+ lds $r0, $pr
.balign 4
-3: .long SYMBOL_NAME(syscall_trace)
-2: .long 0xefffffff ! BL=0
1: .long TRA
+2: .long SYMBOL_NAME(syscall_trace)
__n_sys: .long NR_syscalls
__sct: .long SYMBOL_NAME(sys_call_table)
__tsk_flags: .long flags-8192 ! offset from stackbase to tsk->flags
@@ -311,85 +308,80 @@ led: .long 0xa8000000 ! For my board -- gN
.section .fixup,"ax"
fixup_syscall_argerr:
rts
- mov.l 1f,r0
+ mov.l 1f, $r0
1: .long -22 ! -EINVAL
.previous
.section __ex_table, "a"
.balign 4
- .long 8b,fixup_syscall_argerr
+ .long 4b,fixup_syscall_argerr
.previous
+ .balign 4
reschedule:
- mova SYMBOL_NAME(ret_from_syscall),r0
- mov.l 1f,r1
- jmp @r1
- lds r0,pr
+ mova SYMBOL_NAME(ret_from_syscall), $r0
+ mov.l 1f, $r1
+ jmp @$r1
+ lds $r0, $pr
.balign 4
1: .long SYMBOL_NAME(schedule)
ENTRY(ret_from_irq)
- mov.l @(SR,r15),r0 ! get status register
- shll r0
- shll r0 ! kernel space?
+ mov.l @(SR,$r15), $r0 ! get status register
+ shll $r0
+ shll $r0 ! kernel space?
bt restore_all ! Yes, it's from kernel, go back soon
- ! STI
- mov.l 1f, $r1
- stc $sr, $r2
- and $r1, $r2
- ldc $r2, $sr
!
- bra ret_with_reschedule
+ RESTORE_FLAGS()
+9: bra ret_with_reschedule
nop
ENTRY(ret_from_exception)
- mov.l @(SR,r15),r0 ! get status register
- shll r0
- shll r0 ! kernel space?
+ mov.l @(SR,$r15), $r0 ! get status register
+ shll $r0
+ shll $r0 ! kernel space?
bt restore_all ! Yes, it's from kernel, go back soon
- ! STI
- mov.l 1f, $r1
- stc $sr, $r2
- and $r1, $r2
- ldc $r2, $sr
!
- bra ret_from_syscall
+ RESTORE_FLAGS()
+9: bra ret_from_syscall
nop
.balign 4
-1: .long 0xefffffff ! BL=0
+__INV_IMASK:
+ .long 0xffffff0f ! ~(IMASK)
.balign 4
-ret: add r8,r15 ! pop off the arguments
- mov.l r0,@(R0,r15) ! save the return value
+syscall_ret:
+ add $r8, $r15 ! pop off the arguments
+ mov.l $r0, @(R0,$r15) ! save the return value
/* fall through */
ENTRY(ret_from_syscall)
- mov.l __softirq_state,r0
- mov.l @r0,r1
- mov.l @(4,r0),r2
- tst r2,r1
+ mov.l __softirq_state, $r0
+ mov.l @$r0, $r1
+ mov.l @(4,$r0), $r2
+ tst $r2, $r1
bt ret_with_reschedule
handle_softirq:
- mov.l __do_softirq,r0
- jsr @r0
+ mov.l __do_softirq, $r0
+ jsr @$r0
nop
ret_with_reschedule:
- stc ksp,r1
- mov.l __minus8192,r0
- add r0,r1
- mov.l @(need_resched,r1),r0
- tst #0xff,r0
+ stc $ksp, $r1
+ mov.l __minus8192, $r0
+ add $r0, $r1
+ mov.l @(need_resched,$r1), $r0
+ tst #0xff, $r0
bf reschedule
- mov.l @(sigpending,r1),r0
- tst #0xff,r0
+ mov.l @(sigpending,$r1), $r0
+ tst #0xff, $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
+ mov $r15, $r4
+ mov #0, $r5
+ mov.l __do_signal, $r1
+ mova restore_all, $r0
+ jmp @$r1
+ lds $r0, $pr
.balign 4
__do_signal:
.long SYMBOL_NAME(do_signal)
@@ -407,56 +399,57 @@ restore_all:
jsr @$r1
stc $sr, $r4
#endif
- add #4,r15 ! Skip syscall number
- mov.l @r15+,r11 ! Got SSR into R11
+ add #4, $r15 ! Skip syscall number
+ mov.l @$r15+, $r11 ! Got SSR into R11
#if defined(__SH4__)
mov $r11, $r12
#endif
!
- mov.l 1f,r1
- stc sr,r0
- and r1,r0 ! Get IMASK+FD
- mov.l 2f,r1
- and r1,r11
- or r0,r11 ! Inherit the IMASK+FD value of SR
+ mov.l 1f, $r1
+ stc $sr, $r0
+ and $r1, $r0 ! Get FD
+ mov.l 2f, $r1
+ and $r1, $r11
+ or $r0, $r11 ! Inherit the FD value of SR
+ stc $r5_bank, $r0
+ or $r0, $r11 ! Inherit the IMASK value
!
- mov.l @r15+,r10 ! original stack
- mov.l @r15+,r0
- mov.l @r15+,r1
- mov.l @r15+,r2
- mov.l @r15+,r3
- mov.l @r15+,r4
- mov.l @r15+,r5
- mov.l @r15+,r6
- mov.l @r15+,r7
- stc sr,r14
- mov.l __blrb_flags,r9 ! BL =1, RB=1
- or r9,r14
- ldc r14,sr ! here, change the register bank
- mov r10,k0
- mov r11,k1
+ mov.l @$r15+, $r0
+ mov.l @$r15+, $r1
+ mov.l @$r15+, $r2
+ mov.l @$r15+, $r3
+ mov.l @$r15+, $r4
+ mov.l @$r15+, $r5
+ mov.l @$r15+, $r6
+ mov.l @$r15+, $r7
+ stc $sr, $r14
+ mov.l __blrb_flags, $r9 ! BL =1, RB=1
+ or $r9, $r14
+ ldc $r14, $sr ! here, change the register bank
+ mov $r11, $k1
#if defined(__SH4__)
mov $r12, $k2
#endif
- mov.l @r15+,r8
- mov.l @r15+,r9
- mov.l @r15+,r10
- mov.l @r15+,r11
- mov.l @r15+,r12
- mov.l @r15+,r13
- mov.l @r15+,r14
- ldc.l @r15+,gbr
- lds.l @r15+,mach
- lds.l @r15+,macl
- lds.l @r15+,pr
- ldc.l @r15+,spc
- ldc k1,ssr
+ mov.l @$r15+, $r8
+ mov.l @$r15+, $r9
+ mov.l @$r15+, $r10
+ mov.l @$r15+, $r11
+ mov.l @$r15+, $r12
+ mov.l @$r15+, $r13
+ mov.l @$r15+, $r14
+ mov.l @$r15+, $k0 ! original stack
+ ldc.l @$r15+, $gbr
+ lds.l @$r15+, $mach
+ lds.l @$r15+, $macl
+ lds.l @$r15+, $pr
+ ldc.l @$r15+, $spc
+ ldc $k1, $ssr
#if defined(__SH4__)
shll $k1
shll $k1
bf 9f ! user mode
/* Kernel to kernel transition */
- mov.l 3f, $k1
+ mov.l 1f, $k1
tst $k1, $k2
bf 9f ! it hadn't FPU
! Kernel to kernel and FPU was used
@@ -496,7 +489,7 @@ restore_all:
lds.l @$r15+, $fpul
9:
#endif
- mov k0,r15
+ mov $k0, $r15
rte
nop
@@ -510,9 +503,8 @@ __init_task_flags:
__PF_USEDFPU:
.long PF_USEDFPU
#endif
-1: .long 0x000080f0 ! IMASK+FD
+1: .long 0x00008000 ! FD
2: .long 0xffff7f0f ! ~(IMASK+FD)
-3: .long 0x00008000 ! FD=1
! Exception Vector Base
!
@@ -524,10 +516,10 @@ ENTRY(vbr_base)
!
.balign 256,0,256
general_exception:
- mov.l 1f,k2
- mov.l 2f,k3
+ mov.l 1f, $k2
+ mov.l 2f, $k3
bra handle_exception
- mov.l @k2,k2
+ mov.l @$k2, $k2
.balign 4
2: .long SYMBOL_NAME(ret_from_exception)
1: .long EXPEVT
@@ -535,17 +527,17 @@ general_exception:
!
.balign 1024,0,1024
tlb_miss:
- mov.l 1f,k2
- mov.l 4f,k3
+ mov.l 1f, $k2
+ mov.l 4f, $k3
bra handle_exception
- mov.l @k2,k2
+ mov.l @$k2, $k2
!
.balign 512,0,512
interrupt:
- mov.l 2f,k2
- mov.l 3f,k3
+ mov.l 2f, $k2
+ mov.l 3f, $k3
bra handle_exception
- mov.l @k2,k2
+ mov.l @$k2, $k2
.balign 4
1: .long EXPEVT
@@ -559,9 +551,9 @@ handle_exception:
! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
! save all registers onto stack.
!
- stc ssr,k0 ! from kernel space?
- shll k0 ! Check MD bit (bit30)
- shll k0
+ stc $ssr, $k0 ! from kernel space?
+ shll $k0 ! Check MD bit (bit30)
+ shll $k0
#if defined(__SH4__)
bf/s 8f ! it's from user to kernel transition
mov $r15, $k0 ! save original stack to k0
@@ -569,6 +561,7 @@ handle_exception:
mov.l 2f, $k1
stc $ssr, $k0
tst $k1, $k0
+ mov.l 4f, $k1
bf/s 9f ! FPU is not used
mov $r15, $k0 ! save original stack to k0
! FPU is used, save FPU
@@ -593,64 +586,63 @@ handle_exception:
fmov.s $fr1, @-$r15
fmov.s $fr0, @-$r15
bra 9f
- mov #0, $k1
+ mov.l 3f, $k1
#else
+ mov.l 3f, $k1
bt/s 9f ! it's from kernel to kernel transition
- mov r15,k0 ! save original stack to k0 anyway
+ mov $r15, $k0 ! save original stack to k0 anyway
#endif
8: /* User space to kernel */
- mov kernel_sp, $r15 ! change to kernel stack
-#if defined(__SH4__)
- mov.l 2f, $k1 ! let kernel release FPU
-#endif
-9: stc.l spc,@-r15
- sts.l pr,@-r15
+ mov $kernel_sp, $r15 ! change to kernel stack
+ mov.l 4f, $k1 ! let kernel release FPU
+9: stc.l $spc, @-$r15
+ sts.l $pr, @-$r15
!
- lds k3,pr ! Set the return address to pr
+ lds $k3, $pr ! Set the return address to pr
!
- sts.l macl,@-r15
- sts.l mach,@-r15
- stc.l gbr,@-r15
- mov.l r14,@-r15
+ sts.l $macl, @-$r15
+ sts.l $mach, @-$r15
+ stc.l $gbr, @-$r15
+ mov.l $k0, @-$r15 ! save orignal stack
+ mov.l $r14, @-$r15
!
- stc sr,r14 ! Back to normal register bank, and
-#if defined(__SH4__)
- or $k1, $r14 ! may release FPU
-#endif
- mov.l 3f,k1
- and k1,r14 ! ...
- ldc r14,sr ! ...changed here.
+ stc $sr, $r14 ! Back to normal register bank, and
+ or $k1, $r14 ! Block all interrupts, may release FPU
+ mov.l 5f, $k1
+ and $k1, $r14 ! ...
+ ldc $r14, $sr ! ...changed here.
!
- mov.l r13,@-r15
- mov.l r12,@-r15
- mov.l r11,@-r15
- mov.l r10,@-r15
- mov.l r9,@-r15
- mov.l r8,@-r15
- mov.l r7,@-r15
- mov.l r6,@-r15
- mov.l r5,@-r15
- mov.l r4,@-r15
- mov.l r3,@-r15
- mov.l r2,@-r15
- mov.l r1,@-r15
- mov.l r0,@-r15
- stc.l r0_bank,@-r15 ! save orignal stack
- stc.l ssr,@-r15
- mov.l r0,@-r15 ! push r0 again (for syscall number)
+ mov.l $r13, @-$r15
+ mov.l $r12, @-$r15
+ mov.l $r11, @-$r15
+ mov.l $r10, @-$r15
+ mov.l $r9, @-$r15
+ mov.l $r8, @-$r15
+ mov.l $r7, @-$r15
+ mov.l $r6, @-$r15
+ mov.l $r5, @-$r15
+ mov.l $r4, @-$r15
+ mov.l $r3, @-$r15
+ mov.l $r2, @-$r15
+ mov.l $r1, @-$r15
+ mov.l $r0, @-$r15
+ stc.l $ssr, @-$r15
+ mov.l $r0, @-$r15 ! push $r0 again (for syscall number)
! Then, dispatch to the handler, according to the excepiton code.
- stc k_ex_code,r1
- shlr2 r1
- shlr r1
- mov.l 1f,r0
- add r1,r0
- mov.l @r0,r0
- jmp @r0
- mov.l @r15,r0 ! recovering r0..
+ stc $k_ex_code, $r1
+ shlr2 $r1
+ shlr $r1
+ mov.l 1f, $r0
+ add $r1, $r0
+ mov.l @$r0, $r0
+ jmp @$r0
+ mov.l @$r15, $r0 ! recovering $r0..
.balign 4
1: .long SYMBOL_NAME(exception_handling_table)
2: .long 0x00008000 ! FD=1
-3: .long 0xdfffffff ! RB=0, leave BL=1
+3: .long 0x000000f0 ! FD=0, IMASK=15
+4: .long 0x000080f0 ! FD=1, IMASK=15
+5: .long 0xcfffffff ! RB=0, BL=0
none:
rts
@@ -679,7 +671,7 @@ ENTRY(exception_handling_table)
ENTRY(nmi_slot)
.long none ! Not implemented yet
ENTRY(user_break_point_trap)
- .long error ! Not implemented yet
+ .long break_point_trap
ENTRY(interrupt_table)
! external hardware
.long SYMBOL_NAME(do_IRQ) ! 0000
@@ -985,6 +977,8 @@ ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_setfsuid) /* 215 */
.long SYMBOL_NAME(sys_setfsgid)
.long SYMBOL_NAME(sys_pivot_root)
+ .long SYMBOL_NAME(sys_mincore)
+ .long SYMBOL_NAME(sys_madvise)
/*
* NOTE!! This doesn't have to be exact - we just have
@@ -992,7 +986,7 @@ ENTRY(sys_call_table)
* entries. Don't panic if you notice that this hasn't
* been shrunk every time we add a new system call.
*/
- .rept NR_syscalls-217
+ .rept NR_syscalls-219
.long SYMBOL_NAME(sys_ni_syscall)
.endr
diff --git a/arch/sh/kernel/fpu.c b/arch/sh/kernel/fpu.c
index 335902c1d..5301a1333 100644
--- a/arch/sh/kernel/fpu.c
+++ b/arch/sh/kernel/fpu.c
@@ -1,4 +1,4 @@
-/* $Id: fpu.c,v 1.27 2000/03/05 01:48:34 gniibe Exp $
+/* $Id: fpu.c,v 1.29 2000/03/22 13:42:10 gniibe Exp $
*
* linux/arch/sh/kernel/fpu.c
*
@@ -114,8 +114,6 @@ restore_fpu(struct task_struct *tsk)
* has the property that no matter wether considered as single or as
* double precission represents signaling NANS.
*/
-/* Double presision, NANS as NANS, rounding to nearest, no exceptions */
-#define FPU_DEFAULT 0x00080000
void fpu_init(void)
{
@@ -156,7 +154,7 @@ void fpu_init(void)
"fsts $fpul, $fr15\n\t"
"frchg"
: /* no output */
- : "r" (0), "r" (FPU_DEFAULT));
+ : "r" (0), "r" (FPSCR_INIT));
}
asmlinkage void
diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S
index 3f938557a..ae406d22d 100644
--- a/arch/sh/kernel/head.S
+++ b/arch/sh/kernel/head.S
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.16 2000/03/02 00:01:15 gniibe Exp $
+/* $Id: head.S,v 1.17 2000/03/06 12:44:24 gniibe Exp $
*
* arch/sh/kernel/head.S
*
@@ -37,8 +37,11 @@ ENTRY(empty_zero_page)
*/
ENTRY(_stext)
! Initialize Status Register
- mov.l 1f, $r0 ! MD=1, RB=0, BL=1
+ mov.l 1f, $r0 ! MD=1, RB=0, BL=0, IMASK=0xF
ldc $r0, $sr
+ ! Initialize global interrupt mask
+ mov #0, $r0
+ ldc $r0, $r5_bank
!
mov.l 2f, $r0
mov $r0, $r15 ! Set initial r15 (stack pointer)
@@ -62,7 +65,7 @@ ENTRY(_stext)
nop
.balign 4
-1: .long 0x50000000 ! MD=1, RB=0, BL=1, FD=0
+1: .long 0x400000F0 ! MD=1, RB=0, BL=0, FD=0, IMASK=0xF
2: .long SYMBOL_NAME(stack)
3: .long SYMBOL_NAME(__bss_start)
4: .long SYMBOL_NAME(_end)
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index a15352389..af03ef46d 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.11 2000/02/29 11:03:40 gniibe Exp $
+/* $Id: irq.c,v 1.12 2000/03/06 14:07:50 gniibe Exp $
*
* linux/arch/sh/kernel/irq.c
*
@@ -238,11 +238,11 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
regs.syscall_nr = -1; /* It's not system call */
/* Get IRQ number */
- asm volatile("stc r2_bank,%0\n\t"
+ asm volatile("stc $r2_bank, %0\n\t"
"shlr2 %0\n\t"
"shlr2 %0\n\t"
"shlr %0\n\t"
- "add #-16,%0\n\t"
+ "add #-16, %0\n\t"
:"=z" (irq));
kstat.irqs[cpu][irq]++;
diff --git a/arch/sh/kernel/irq_imask.c b/arch/sh/kernel/irq_imask.c
index a3cf78b5f..380acf405 100644
--- a/arch/sh/kernel/irq_imask.c
+++ b/arch/sh/kernel/irq_imask.c
@@ -1,8 +1,8 @@
-/* $Id: irq_imask.c,v 1.2 2000/02/11 04:57:40 gniibe Exp $
+/* $Id: irq_imask.c,v 1.6 2000/03/06 14:11:32 gniibe Exp $
*
* linux/arch/sh/kernel/irq_imask.c
*
- * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 1999, 2000 Niibe Yutaka
*
* Simple interrupt handling using IMASK of SR register.
*
@@ -52,35 +52,40 @@ static struct hw_interrupt_type imask_irq_type = {
end_imask_irq
};
-void disable_imask_irq(unsigned int irq)
+void static inline set_interrupt_registers(int ip)
{
unsigned long __dummy;
+ asm volatile("ldc %2, $r5_bank\n\t"
+ "stc $sr, %0\n\t"
+ "and #0xf0, %0\n\t"
+ "shlr8 %0\n\t"
+ "cmp/eq #0x0f, %0\n\t"
+ "bt 1f ! CLI-ed\n\t"
+ "stc $sr, %0\n\t"
+ "and %1, %0\n\t"
+ "or %2, %0\n\t"
+ "ldc %0, $sr\n"
+ "1:"
+ : "=&z" (__dummy)
+ : "r" (~0xf0), "r" (ip << 4));
+}
+
+void disable_imask_irq(unsigned int irq)
+{
clear_bit(irq, &imask_mask);
if (interrupt_priority < IMASK_PRIORITY - irq)
interrupt_priority = IMASK_PRIORITY - irq;
- asm volatile("stc sr,%0\n\t"
- "and %1,%0\n\t"
- "or %2,%0\n\t"
- "ldc %0,sr"
- : "=&r" (__dummy)
- : "r" (0xffffff0f), "r" (interrupt_priority << 4));
+ set_interrupt_registers(interrupt_priority);
}
static void enable_imask_irq(unsigned int irq)
{
- unsigned long __dummy;
-
set_bit(irq, &imask_mask);
interrupt_priority = IMASK_PRIORITY - ffz(imask_mask);
- asm volatile("stc sr,%0\n\t"
- "and %1,%0\n\t"
- "or %2,%0\n\t"
- "ldc %0,sr"
- : "=&r" (__dummy)
- : "r" (0xffffff0f), "r" (interrupt_priority << 4));
+ set_interrupt_registers(interrupt_priority);
}
static void mask_and_ack_imask(unsigned int irq)
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 2ca91cb40..97cd1fe0c 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.28 2000/03/05 02:16:15 gniibe Exp $
+/* $Id: process.c,v 1.33 2000/03/25 00:06:15 gniibe Exp $
*
* linux/arch/sh/kernel/process.c
*
@@ -94,7 +94,7 @@ void show_regs(struct pt_regs * regs)
{
printk("\n");
printk("PC : %08lx SP : %08lx SR : %08lx TEA : %08lx\n",
- regs->pc, regs->sp, regs->sr, ctrl_inl(MMU_TEA));
+ regs->pc, regs->regs[15], regs->sr, ctrl_inl(MMU_TEA));
printk("R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n",
regs->regs[0],regs->regs[1],
regs->regs[2],regs->regs[3]);
@@ -210,22 +210,22 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct task_struct *p, struct pt_regs *regs)
{
struct pt_regs *childregs;
+#if defined(__SH4__)
struct task_struct *tsk = current;
- childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p)) - 1;
- struct_cpy(childregs, regs);
-
-#if defined(__SH4__)
if (tsk != &init_task) {
unlazy_fpu(tsk);
- struct_cpy(&p->thread.fpu, &current->thread.fpu);
+ p->thread.fpu = current->thread.fpu;
p->used_math = tsk->used_math;
}
#endif
+ childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p)) - 1;
+ *childregs = *regs;
+
if (user_mode(regs)) {
- childregs->sp = usp;
+ childregs->regs[15] = usp;
} else {
- childregs->sp = (unsigned long)p+2*PAGE_SIZE;
+ childregs->regs[15] = (unsigned long)p+2*PAGE_SIZE;
}
childregs->regs[0] = 0; /* Set return value for child */
childregs->sr |= SR_FD; /* Invalidate FPU flag */
@@ -244,7 +244,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
dump->magic = CMAGIC;
dump->start_code = current->mm->start_code;
dump->start_data = current->mm->start_data;
- dump->start_stack = regs->sp & ~(PAGE_SIZE - 1);
+ dump->start_stack = regs->regs[15] & ~(PAGE_SIZE - 1);
dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT;
dump->u_dsize = (current->mm->brk + (PAGE_SIZE-1) - dump->start_data) >> PAGE_SHIFT;
dump->u_ssize = (current->mm->start_stack - dump->start_stack +
@@ -279,7 +279,7 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
- return do_fork(SIGCHLD, regs.sp, &regs);
+ return do_fork(SIGCHLD, regs.regs[15], &regs);
}
asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
@@ -287,7 +287,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
struct pt_regs regs)
{
if (!newsp)
- newsp = regs.sp;
+ newsp = regs.regs[15];
return do_fork(clone_flags, newsp, &regs);
}
@@ -305,7 +305,7 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.sp, &regs);
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], &regs);
}
/*
@@ -370,3 +370,12 @@ asmlinkage void print_syscall(int x)
(init_task.flags&PF_USEDFPU)?'K':' ', (sr&SR_FD)?' ':'F');
restore_flags(flags);
}
+
+asmlinkage void break_point_trap(void)
+{
+ /* Clear traicng. */
+ ctrl_outw(0, UBC_BBRA);
+ ctrl_outw(0, UBC_BBRB);
+
+ force_sig(SIGTRAP, current);
+}
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
index 2d69b5b7c..d4a1556b9 100644
--- a/arch/sh/kernel/ptrace.c
+++ b/arch/sh/kernel/ptrace.c
@@ -1,6 +1,13 @@
-/*
- * Surely this doesn't work... (we need to design ptrace for SupreH)
+/* $Id: ptrace.c,v 1.4 2000/03/22 13:59:01 gniibe Exp $
+ *
* linux/arch/sh/kernel/ptrace.c
+ *
+ * Original x86 implementation:
+ * By Ross Biro 1/23/92
+ * edited by Linus Torvalds
+ *
+ * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka
+ *
*/
#include <linux/kernel.h>
@@ -12,135 +19,126 @@
#include <linux/ptrace.h>
#include <linux/user.h>
+#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/processor.h>
+#include <asm/mmu_context.h>
/*
* does not yet catch signals sent when the child dies.
* in exit.c or in signal.c.
*/
-/* determines which flags the user has access to. */
-/* 1 = access 0 = no access */
-#define FLAG_MASK 0x00044dd5
-
-/* set's the trap flag. */
-#define TRAP_FLAG 0x100
-
/*
- * Offset of eflags on child stack..
+ * This routine will get a word off of the process kernel stack.
*/
-#define EFL_OFFSET ((EFL-2)*4-sizeof(struct pt_regs))
-
-/*
- * this routine will get a word off of the processes privileged stack.
- * the offset is how far from the base addr as stored in the TSS.
- * this routine assumes that all the privileged stacks are in our
- * data space.
- */
static inline int get_stack_long(struct task_struct *task, int offset)
{
unsigned char *stack;
- stack = (unsigned char *)task->thread.sp;
+ stack = (unsigned char *)task + THREAD_SIZE - sizeof(struct pt_regs);
stack += offset;
return (*((int *)stack));
}
/*
- * this routine will put a word on the processes privileged stack.
- * the offset is how far from the base addr as stored in the TSS.
- * this routine assumes that all the privileged stacks are in our
- * data space.
+ * This routine will put a word on the process kernel stack.
*/
static inline int put_stack_long(struct task_struct *task, int offset,
- unsigned long data)
+ unsigned long data)
{
- unsigned char * stack;
+ unsigned char *stack;
- stack = (unsigned char *) task->thread.sp;
+ stack = (unsigned char *)task + THREAD_SIZE - sizeof(struct pt_regs);
stack += offset;
*(unsigned long *) stack = data;
return 0;
}
-static int putreg(struct task_struct *child,
- unsigned long regno, unsigned long value)
+static void
+compute_next_pc(struct pt_regs *regs, unsigned short inst,
+ unsigned long *pc1, unsigned long *pc2)
{
-#if 0
- switch (regno >> 2) {
- case ORIG_EAX:
- return -EIO;
- case FS:
- if (value && (value & 3) != 3)
- return -EIO;
- child->thread.fs = value;
- return 0;
- case GS:
- if (value && (value & 3) != 3)
- return -EIO;
- child->thread.gs = value;
- return 0;
- case DS:
- case ES:
- if (value && (value & 3) != 3)
- return -EIO;
- value &= 0xffff;
- break;
- case SS:
- case CS:
- if ((value & 3) != 3)
- return -EIO;
- value &= 0xffff;
- break;
- case EFL:
- value &= FLAG_MASK;
- value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;
+ int nib[4]
+ = { (inst >> 12) & 0xf,
+ (inst >> 8) & 0xf,
+ (inst >> 4) & 0xf,
+ inst & 0xf};
+
+ /* bra & bsr */
+ if (nib[0] == 0xa || nib[0] == 0xb) {
+ *pc1 = regs->pc + 4 + ((short) ((inst & 0xfff) << 4) >> 3);
+ *pc2 = (unsigned long) -1;
+ return;
}
- if (regno > GS*4)
- regno -= 2*4;
- put_stack_long(child, regno - sizeof(struct pt_regs), value);
-#endif
- return 0;
+
+ /* bt & bf */
+ if (nib[0] == 0x8 && (nib[1] == 0x9 || nib[1] == 0xb)) {
+ *pc1 = regs->pc + 4 + ((char) (inst & 0xff) << 1);
+ *pc2 = regs->pc + 2;
+ return;
+ }
+
+ /* bt/s & bf/s */
+ if (nib[0] == 0x8 && (nib[1] == 0xd || nib[1] == 0xf)) {
+ *pc1 = regs->pc + 4 + ((char) (inst & 0xff) << 1);
+ *pc2 = regs->pc + 4;
+ return;
+ }
+
+ /* jmp & jsr */
+ if (nib[0] == 0x4 && nib[3] == 0xb
+ && (nib[2] == 0x0 || nib[2] == 0x2)) {
+ *pc1 = regs->regs[nib[1]];
+ *pc2 = (unsigned long) -1;
+ return;
+ }
+
+ /* braf & bsrf */
+ if (nib[0] == 0x0 && nib[3] == 0x3
+ && (nib[2] == 0x0 || nib[2] == 0x2)) {
+ *pc1 = regs->pc + 4 + regs->regs[nib[1]];
+ *pc2 = (unsigned long) -1;
+ return;
+ }
+
+ if (inst == 0x000b) {
+ *pc1 = regs->pr;
+ *pc2 = (unsigned long) -1;
+ return;
+ }
+
+ *pc1 = regs->pc + 2;
+ *pc2 = (unsigned long) -1;
+ return;
}
-static unsigned long getreg(struct task_struct *child,
- unsigned long regno)
+/* Tracing by user break controller. */
+static void
+ubc_set_tracing(int asid, unsigned long nextpc1, unsigned nextpc2)
{
- unsigned long retval = ~0UL;
-
-#if 0
- switch (regno >> 2) {
- case FS:
- retval = child->thread.fs;
- break;
- case GS:
- retval = child->thread.gs;
- break;
- case DS:
- case ES:
- case SS:
- case CS:
- retval = 0xffff;
- /* fall through */
- default:
- if (regno > GS*4)
- regno -= 2*4;
- regno = regno - sizeof(struct pt_regs);
- retval &= get_stack_long(child, regno);
+ ctrl_outl(nextpc1, UBC_BARA);
+ ctrl_outb(asid, UBC_BASRA);
+ ctrl_outb(BAMR_12, UBC_BAMRA);
+ ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA);
+
+ if (nextpc2 != (unsigned long) -1) {
+ ctrl_outl(nextpc2, UBC_BARB);
+ ctrl_outb(asid, UBC_BASRB);
+ ctrl_outb(BAMR_12, UBC_BAMRB);
+ ctrl_outw(BBR_INST | BBR_READ, UBC_BBRB);
}
-#endif
- return retval;
+ ctrl_outw(BRCR_PCBA | BRCR_PCBB, UBC_BRCR);
}
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
- struct task_struct *child;
+ struct task_struct *child, *tsk = current;
struct user * dummy = NULL;
unsigned long flags;
- int i, ret;
+ int ret;
lock_kernel();
ret = -EPERM;
@@ -163,16 +161,16 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if (pid == 1) /* you may not mess with init */
goto out;
if (request == PTRACE_ATTACH) {
- if (child == current)
+ if (child == tsk)
goto out;
if ((!child->dumpable ||
- (current->uid != child->euid) ||
- (current->uid != child->suid) ||
- (current->uid != child->uid) ||
- (current->gid != child->egid) ||
- (current->gid != child->sgid) ||
- (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
- (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+ (tsk->uid != child->euid) ||
+ (tsk->uid != child->suid) ||
+ (tsk->uid != child->uid) ||
+ (tsk->gid != child->egid) ||
+ (tsk->gid != child->sgid) ||
+ (!cap_issubset(child->cap_permitted, tsk->cap_permitted)) ||
+ (tsk->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
@@ -180,9 +178,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
child->flags |= PF_PTRACED;
write_lock_irqsave(&tasklist_lock, flags);
- if (child->p_pptr != current) {
+ if (child->p_pptr != tsk) {
REMOVE_LINKS(child);
- child->p_pptr = current;
+ child->p_pptr = tsk;
SET_LINKS(child);
}
write_unlock_irqrestore(&tasklist_lock, flags);
@@ -198,257 +196,180 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if (request != PTRACE_KILL)
goto out;
}
- if (child->p_pptr != current)
+ if (child->p_pptr != tsk)
goto out;
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
- case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- goto out;
- ret = put_user(tmp,(unsigned long *) data);
- goto out;
- }
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKDATA: {
+ unsigned long tmp;
+ int copied;
+
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
+ break;
+ ret = put_user(tmp,(unsigned long *) data);
+ break;
+ }
/* read the word at location addr in the USER area. */
- case PTRACE_PEEKUSR: {
- unsigned long tmp;
-
- ret = -EIO;
- if ((addr & 3) || addr < 0 ||
- addr > sizeof(struct user) - 3)
- goto out;
-
- tmp = 0; /* Default return condition */
- if(addr < 17*sizeof(long))
- tmp = getreg(child, addr);
-#if 0
- if(addr >= (long) &dummy->u_debugreg[0] &&
- addr <= (long) &dummy->u_debugreg[7]){
- addr -= (long) &dummy->u_debugreg[0];
- addr = addr >> 2;
- tmp = child->thread.debugreg[addr];
- };
-#endif
- ret = put_user(tmp,(unsigned long *) data);
- goto out;
- }
+ case PTRACE_PEEKUSR: {
+ unsigned long tmp;
- /* when I and D space are separate, this will have to be fixed. */
- case PTRACE_POKETEXT: /* write the word at location addr. */
- case PTRACE_POKEDATA:
- ret = 0;
- if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
- goto out;
- ret = -EIO;
- goto out;
+ ret = -EIO;
+ if ((addr & 3) || addr < 0 ||
+ addr > sizeof(struct user) - 3)
+ break;
- case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
- ret = -EIO;
- if ((addr & 3) || addr < 0 ||
- addr > sizeof(struct user) - 3)
- goto out;
-
- if (addr < 17*sizeof(long)) {
- ret = putreg(child, addr, data);
- goto out;
- }
-
- /* We need to be very careful here. We implicitly
- want to modify a portion of the task_struct, and we
- have to be selective about what portions we allow someone
- to modify. */
-#if 0
- if(addr >= (long) &dummy->u_debugreg[0] &&
- addr <= (long) &dummy->u_debugreg[7]){
-
- if(addr == (long) &dummy->u_debugreg[4]) return -EIO;
- if(addr == (long) &dummy->u_debugreg[5]) return -EIO;
- if(addr < (long) &dummy->u_debugreg[4] &&
- ((unsigned long) data) >= TASK_SIZE-3) return -EIO;
-
- ret = -EIO;
- if(addr == (long) &dummy->u_debugreg[7]) {
- data &= ~DR_CONTROL_RESERVED;
- for(i=0; i<4; i++)
- if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
- goto out;
- };
-
- addr -= (long) &dummy->u_debugreg;
- addr = addr >> 2;
- child->thread.debugreg[addr] = data;
- ret = 0;
- goto out;
- };
-#endif
- ret = -EIO;
- goto out;
-
- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
- case PTRACE_CONT: { /* restart after signal. */
- long tmp;
-
- ret = -EIO;
- if ((unsigned long) data > _NSIG)
- goto out;
- if (request == PTRACE_SYSCALL)
- child->flags |= PF_TRACESYS;
- else
- child->flags &= ~PF_TRACESYS;
- child->exit_code = data;
- /* make sure the single step bit is not set. */
-#if 0
- tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
- put_stack_long(child, EFL_OFFSET,tmp);
-#endif
- wake_up_process(child);
+ if (addr < sizeof(struct pt_regs))
+ tmp = get_stack_long(child, addr);
+ else if (addr >= (long) &dummy->fpu &&
+ addr < (long) &dummy->u_fpvalid) {
+ if (!child->used_math) {
+ if (addr == (long)&dummy->fpu.fpscr)
+ tmp = FPSCR_INIT;
+ else
+ tmp = 0;
+ } else
+ tmp = ((long *)&child->thread.fpu)
+ [(addr - (long)&dummy->fpu) >> 2];
+ } else if (addr == (long) &dummy->u_fpvalid)
+ tmp = child->used_math;
+ else
+ tmp = 0;
+ ret = put_user(tmp, (unsigned long *)data);
+ break;
+ }
+
+ /* when I and D space are separate, this will have to be fixed. */
+ case PTRACE_POKETEXT: /* write the word at location addr. */
+ case PTRACE_POKEDATA:
+ ret = 0;
+ if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+ break;
+ ret = -EIO;
+ break;
+
+ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+ ret = -EIO;
+ if ((addr & 3) || addr < 0 ||
+ addr > sizeof(struct user) - 3)
+ break;
+
+ if (addr < sizeof(struct pt_regs))
+ ret = put_stack_long(child, addr, data);
+ else if (addr >= (long) &dummy->fpu &&
+ addr < (long) &dummy->u_fpvalid) {
+ child->used_math = 1;
+ ((long *)&child->thread.fpu)
+ [(addr - (long)&dummy->fpu) >> 2] = data;
+ ret = 0;
+ } else if (addr == (long) &dummy->u_fpvalid) {
+ child->used_math = data?1:0;
ret = 0;
- goto out;
}
+ break;
+
+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+ case PTRACE_CONT: { /* restart after signal. */
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ if (request == PTRACE_SYSCALL)
+ child->flags |= PF_TRACESYS;
+ else
+ child->flags &= ~PF_TRACESYS;
+ child->exit_code = data;
+ wake_up_process(child);
+ ret = 0;
+ break;
+ }
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
- case PTRACE_KILL: {
- long tmp;
+ case PTRACE_KILL: {
+ ret = 0;
+ if (child->state == TASK_ZOMBIE) /* already dead */
+ break;
+ child->exit_code = SIGKILL;
+ wake_up_process(child);
+ break;
+ }
- ret = 0;
- if (child->state == TASK_ZOMBIE) /* already dead */
- goto out;
- child->exit_code = SIGKILL;
- /* make sure the single step bit is not set. */
-#if 0
- tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
- put_stack_long(child, EFL_OFFSET, tmp);
-#endif
- wake_up_process(child);
- goto out;
- }
+ case PTRACE_SINGLESTEP: { /* set the trap flag. */
+ long tmp, pc;
+ struct pt_regs *dummy = NULL;
+ struct pt_regs *regs;
+ unsigned long nextpc1, nextpc2;
+ unsigned short insn;
- case PTRACE_SINGLESTEP: { /* set the trap flag. */
- long tmp;
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ child->flags &= ~PF_TRACESYS;
+ if ((child->flags & PF_DTRACE) == 0) {
+ /* Spurious delayed TF traps may occur */
+ child->flags |= PF_DTRACE;
+ }
- ret = -EIO;
- if ((unsigned long) data > _NSIG)
- goto out;
- child->flags &= ~PF_TRACESYS;
- if ((child->flags & PF_DTRACE) == 0) {
- /* Spurious delayed TF traps may occur */
- child->flags |= PF_DTRACE;
- }
-#if 0
- tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
- put_stack_long(child, EFL_OFFSET, tmp);
+ /* Compute next pc. */
+ pc = get_stack_long(child, (long)&dummy->pc);
+ regs = (struct pt_regs *)((unsigned long)child + THREAD_SIZE - sizeof(struct pt_regs));
+ if (access_process_vm(child, pc&~3, &tmp, sizeof(tmp), 1) != sizeof(data))
+ break;
+
+#ifdef __LITTLE_ENDIAN__
+ if (pc & 3)
+ insn = tmp >> 16;
+ else
+ insn = tmp & 0xffff;
+#else
+ if (pc & 3)
+ insn = tmp & 0xffff;
+ else
+ insn = tmp >> 16;
#endif
- child->exit_code = data;
- /* give it a chance to run. */
- wake_up_process(child);
- ret = 0;
- goto out;
- }
+ compute_next_pc (regs, insn, &nextpc1, &nextpc2);
- case PTRACE_DETACH: { /* detach a process that was attached. */
- long tmp;
+ if (nextpc1 & 0x80000000)
+ break;
+ if (nextpc2 != (unsigned long) -1 && (nextpc2 & 0x80000000))
+ break;
- ret = -EIO;
- if ((unsigned long) data > _NSIG)
- goto out;
- child->flags &= ~(PF_PTRACED|PF_TRACESYS);
- child->exit_code = data;
- write_lock_irqsave(&tasklist_lock, flags);
- REMOVE_LINKS(child);
- child->p_pptr = child->p_opptr;
- SET_LINKS(child);
- write_unlock_irqrestore(&tasklist_lock, flags);
- /* make sure the single step bit is not set. */
-#if 0
- tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
- put_stack_long(child, EFL_OFFSET, tmp);
-#endif
- wake_up_process(child);
- ret = 0;
- goto out;
- }
-#if 0
- case PTRACE_GETREGS: { /* Get all gp regs from the child. */
- if (!access_ok(VERIFY_WRITE, (unsigned *)data,
- 17*sizeof(long)))
- {
- ret = -EIO;
- goto out;
- }
- for ( i = 0; i < 17*sizeof(long); i += sizeof(long) )
- {
- __put_user(getreg(child, i),(unsigned long *) data);
- data += sizeof(long);
- }
- ret = 0;
- goto out;
- };
-
- case PTRACE_SETREGS: { /* Set all gp regs in the child. */
- unsigned long tmp;
- if (!access_ok(VERIFY_READ, (unsigned *)data,
- 17*sizeof(long)))
- {
- ret = -EIO;
- goto out;
- }
- for ( i = 0; i < 17*sizeof(long); i += sizeof(long) )
- {
- __get_user(tmp, (unsigned long *) data);
- putreg(child, i, tmp);
- data += sizeof(long);
- }
- ret = 0;
- goto out;
- };
-
- case PTRACE_GETFPREGS: { /* Get the child FPU state. */
- if (!access_ok(VERIFY_WRITE, (unsigned *)data,
- sizeof(struct user_i387_struct)))
- {
- ret = -EIO;
- goto out;
- }
- ret = 0;
- if ( !child->used_math ) {
- /* Simulate an empty FPU. */
- child->thread.i387.hard.cwd = 0xffff037f;
- child->thread.i387.hard.swd = 0xffff0000;
- child->thread.i387.hard.twd = 0xffffffff;
- }
- __copy_to_user((void *)data, &child->thread.i387.hard,
- sizeof(struct user_i387_struct));
- goto out;
- };
-
- case PTRACE_SETFPREGS: { /* Set the child FPU state. */
- if (!access_ok(VERIFY_READ, (unsigned *)data,
- sizeof(struct user_i387_struct)))
- {
- ret = -EIO;
- goto out;
- }
- child->used_math = 1;
- __copy_from_user(&child->thread.i387.hard, (void *)data,
- sizeof(struct user_i387_struct));
- ret = 0;
- goto out;
- };
-#endif
- default:
- ret = -EIO;
- goto out;
+ ubc_set_tracing(child->mm->context & MMU_CONTEXT_ASID_MASK,
+ nextpc1, nextpc2);
+
+ child->exit_code = data;
+ /* give it a chance to run. */
+ wake_up_process(child);
+ ret = 0;
+ break;
+ }
+
+ case PTRACE_DETACH: { /* detach a process that was attached. */
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+ child->exit_code = data;
+ write_lock_irqsave(&tasklist_lock, flags);
+ REMOVE_LINKS(child);
+ child->p_pptr = child->p_opptr;
+ SET_LINKS(child);
+ write_unlock_irqrestore(&tasklist_lock, flags);
+ wake_up_process(child);
+ ret = 0;
+ break;
+ }
+
+ default:
+ ret = -EIO;
+ break;
}
out:
unlock_kernel();
@@ -457,20 +378,22 @@ out:
asmlinkage void syscall_trace(void)
{
- if ((current->flags & (PF_PTRACED|PF_TRACESYS))
- != (PF_PTRACED|PF_TRACESYS))
+ struct task_struct *tsk = current;
+
+ if ((tsk->flags & (PF_PTRACED|PF_TRACESYS))
+ != (PF_PTRACED|PF_TRACESYS))
return;
- current->exit_code = SIGTRAP;
- current->state = TASK_STOPPED;
- notify_parent(current, SIGCHLD);
+ tsk->exit_code = SIGTRAP;
+ tsk->state = TASK_STOPPED;
+ notify_parent(tsk, SIGCHLD);
schedule();
/*
* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
- if (current->exit_code) {
- send_sig(current->exit_code, current, 1);
- current->exit_code = 0;
+ if (tsk->exit_code) {
+ send_sig(tsk->exit_code, tsk, 1);
+ tsk->exit_code = 0;
}
}
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index 0c24acf73..4b11100ae 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.16 2000/01/29 11:31:31 gniibe Exp gniibe $
+/* $Id: signal.c,v 1.21 2000/03/11 14:06:21 gniibe Exp $
*
* linux/arch/sh/kernel/signal.c
*
@@ -6,7 +6,7 @@
*
* 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
*
- * SuperH version: Copyright (C) 1999 Niibe Yutaka
+ * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
*
*/
@@ -125,7 +125,7 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
- return do_sigaltstack(uss, uoss, regs.sp);
+ return do_sigaltstack(uss, uoss, regs.regs[15]);
}
@@ -136,7 +136,6 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss,
struct sigframe
{
struct sigcontext sc;
- /* FPU data should come here: SH-3 has no FPU */
unsigned long extramask[_NSIG_WORDS-1];
char retcode[4];
};
@@ -147,10 +146,38 @@ struct rt_sigframe
void *puc;
struct siginfo info;
struct ucontext uc;
- /* FPU should come here: SH-3 has no FPU */
char retcode[4];
};
+#if defined(__SH4__)
+static inline int restore_sigcontext_fpu(struct sigcontext *sc)
+{
+ current->used_math = 1;
+ return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0],
+ sizeof(long)*(NUM_FPU_REGS*2+2));
+}
+
+static inline int save_sigcontext_fpu(struct sigcontext *sc)
+{
+ struct task_struct *tsk = current;
+
+ if (!tsk->used_math) {
+ sc->owend_fp = 0;
+ return 0;
+ }
+
+ sc->owend_fp = 1;
+
+ /* This will cause a "finit" to be triggered by the next
+ attempted FPU operation by the 'current' process.
+ */
+ tsk->used_math = 0;
+
+ unlazy_fpu(tsk);
+ return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard,
+ sizeof(long)*(NUM_FPU_REGS*2+2));
+}
+#endif
static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *r0_p)
@@ -165,15 +192,28 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *r0_p)
COPY(regs[8]); COPY(regs[9]);
COPY(regs[10]); COPY(regs[11]);
COPY(regs[12]); COPY(regs[13]);
- COPY(regs[14]); COPY(sp);
+ COPY(regs[14]); COPY(regs[15]);
COPY(gbr); COPY(mach);
COPY(macl); COPY(pr);
COPY(sr); COPY(pc);
#undef COPY
+#if defined(__SH4__)
+ {
+ int owned_fp;
+ struct task_struct *tsk = current;
+
+ regs->sr |= SR_FD; /* Release FPU */
+ clear_fpu(tsk);
+ current->used_math = 0;
+ __get_user (owned_fp, &context->sc_ownedfp);
+ if (owned_fp)
+ err |= restore_sigcontext_fpu(sc);
+ }
+#endif
+
regs->syscall_nr = -1; /* disable syscall checks */
err |= __get_user(*r0_p, &sc->sc_regs[0]);
-
return err;
}
@@ -181,7 +221,7 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
- struct sigframe *frame = (struct sigframe *)regs.sp;
+ struct sigframe *frame = (struct sigframe *)regs.regs[15];
sigset_t set;
int r0;
@@ -214,7 +254,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
- struct rt_sigframe *frame = (struct rt_sigframe *)regs.sp;
+ struct rt_sigframe *frame = (struct rt_sigframe *)regs.regs[15];
sigset_t set;
stack_t st;
int r0;
@@ -238,7 +278,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
goto badframe;
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
- do_sigaltstack(&st, NULL, regs.sp);
+ do_sigaltstack(&st, NULL, regs.regs[15]);
return r0;
@@ -265,12 +305,16 @@ setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
COPY(regs[8]); COPY(regs[9]);
COPY(regs[10]); COPY(regs[11]);
COPY(regs[12]); COPY(regs[13]);
- COPY(regs[14]); COPY(sp);
+ COPY(regs[14]); COPY(regs[15]);
COPY(gbr); COPY(mach);
COPY(macl); COPY(pr);
COPY(sr); COPY(pc);
#undef COPY
+#if defined(__SH4__)
+ err |= save_sigcontext_fpu(sc);
+#endif
+
/* non-iBCS2 extensions.. */
err |= __put_user(mask, &sc->oldmask);
@@ -296,7 +340,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
int err = 0;
int signal;
- frame = get_sigframe(ka, regs->sp, sizeof(*frame));
+ frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
@@ -334,7 +378,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
goto give_sigsegv;
/* Set up registers for signal handler */
- regs->sp = (unsigned long) frame;
+ regs->regs[15] = (unsigned long) frame;
regs->regs[4] = signal; /* Arg for signal handler */
regs->pc = (unsigned long) ka->sa.sa_handler;
@@ -361,7 +405,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
int err = 0;
int signal;
- frame = get_sigframe(ka, regs->sp, sizeof(*frame));
+ frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
@@ -381,7 +425,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user((void *)current->sas_ss_sp,
&frame->uc.uc_stack.ss_sp);
- err |= __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(sas_ss_flags(regs->regs[15]),
+ &frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
err |= setup_sigcontext(&frame->uc.uc_mcontext,
regs, set->sig[0]);
@@ -407,7 +452,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
goto give_sigsegv;
/* Set up registers for signal handler */
- regs->sp = (unsigned long) frame;
+ regs->regs[15] = (unsigned long) frame;
regs->regs[4] = signal; /* Arg for signal handler */
regs->pc = (unsigned long) ka->sa.sa_handler;
diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile
index 5f7d68755..7af24f1c3 100644
--- a/arch/sh/lib/Makefile
+++ b/arch/sh/lib/Makefile
@@ -3,7 +3,7 @@
#
.S.o:
- $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+ $(CC) $(AFLAGS) -traditional -c $< -o $*.o
L_TARGET = lib.a
L_OBJS = delay.o memcpy.o memset.o memmove.o memchr.o old-checksum.o \
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
index f5c5200be..33bdf2114 100644
--- a/arch/sh/mm/cache.c
+++ b/arch/sh/mm/cache.c
@@ -1,4 +1,4 @@
-/* $Id: cache.c,v 1.9 2000/02/14 12:45:26 gniibe Exp $
+/* $Id: cache.c,v 1.10 2000/03/07 11:58:34 gniibe Exp $
*
* linux/arch/sh/mm/cache.c
*
@@ -67,36 +67,15 @@ static struct _cache_system_info cache_system_info;
#define CACHE_IC_NUM_WAYS 1
#endif
-#define jump_to_p2(__dummy) \
- asm volatile("mova 1f,%0\n\t" \
- "add %1,%0\n\t" \
- "jmp @r0 ! Jump to P2 area\n\t" \
- " nop\n\t" \
- ".balign 4\n" \
- "1:" \
- : "=&z" (__dummy) \
- : "r" (0x20000000))
-
-#define back_to_p1(__dummy) \
- asm volatile("nop;nop;nop;nop;nop;nop\n\t" \
- "mova 9f,%0\n\t" \
- "sub %1,%0\n\t" \
- "jmp @r0 ! Back to P1 area\n\t" \
- " nop\n\t" \
- ".balign 4\n" \
- "9:" \
- : "=&z" (__dummy) \
- : "r" (0x20000000), "0" (__dummy))
-
/* Write back caches to memory (if needed) and invalidates the caches */
void cache_flush_area(unsigned long start, unsigned long end)
{
- unsigned long flags, __dummy;
+ unsigned long flags;
unsigned long addr, data, v, p;
start &= ~(L1_CACHE_BYTES-1);
save_and_cli(flags);
- jump_to_p2(__dummy);
+ jump_to_P2();
for (v = start; v < end; v+=L1_CACHE_BYTES) {
p = __pa(v);
@@ -110,7 +89,7 @@ void cache_flush_area(unsigned long start, unsigned long end)
: "m" (__m(v)));
#endif
}
- back_to_p1(__dummy);
+ back_to_P1();
restore_flags(flags);
}
@@ -124,12 +103,12 @@ void cache_flush_area(unsigned long start, unsigned long end)
the cache line. */
void cache_purge_area(unsigned long start, unsigned long end)
{
- unsigned long flags, __dummy;
+ unsigned long flags;
unsigned long addr, data, v, p, j;
start &= ~(L1_CACHE_BYTES-1);
save_and_cli(flags);
- jump_to_p2(__dummy);
+ jump_to_P2();
for (v = start; v < end; v+=L1_CACHE_BYTES) {
p = __pa(v);
@@ -150,19 +129,19 @@ void cache_purge_area(unsigned long start, unsigned long end)
: "m" (__m(v)));
#endif
}
- back_to_p1(__dummy);
+ back_to_P1();
restore_flags(flags);
}
/* write back the dirty cache, but not invalidate the cache */
void cache_wback_area(unsigned long start, unsigned long end)
{
- unsigned long flags, __dummy;
+ unsigned long flags;
unsigned long v;
start &= ~(L1_CACHE_BYTES-1);
save_and_cli(flags);
- jump_to_p2(__dummy);
+ jump_to_P2();
for (v = start; v < end; v+=L1_CACHE_BYTES) {
#if CACHE_IC_ADDRESS_ARRAY == CACHE_OC_ADDRESS_ARRAY
@@ -187,7 +166,7 @@ void cache_wback_area(unsigned long start, unsigned long end)
: "m" (__m(v)));
#endif
}
- back_to_p1(__dummy);
+ back_to_P1();
restore_flags(flags);
}
@@ -199,11 +178,11 @@ void cache_wback_area(unsigned long start, unsigned long end)
*/
static void cache_wback_all(void)
{
- unsigned long flags, __dummy;
+ unsigned long flags;
unsigned long addr, data, i, j;
save_and_cli(flags);
- jump_to_p2(__dummy);
+ jump_to_P2();
for (i=0; i<CACHE_OC_NUM_ENTRIES; i++) {
for (j=0; j<CACHE_OC_NUM_WAYS; j++) {
@@ -217,7 +196,7 @@ static void cache_wback_all(void)
}
}
- back_to_p1(__dummy);
+ back_to_P1();
restore_flags(flags);
}
@@ -225,9 +204,9 @@ static void
detect_cpu_and_cache_system(void)
{
#if defined(__sh3__)
- unsigned long __dummy, addr0, addr1, data0, data1, data2, data3;
+ unsigned long addr0, addr1, data0, data1, data2, data3;
- jump_to_p2(__dummy);
+ jump_to_P2();
/* Check if the entry shadows or not.
* When shadowed, it's 128-entry system.
* Otherwise, it's 256-entry system.
@@ -245,7 +224,7 @@ detect_cpu_and_cache_system(void)
/* Invaliate them, in case the cache has been enabled already. */
ctrl_outl(data0&~0x00000001,addr0);
ctrl_outl(data2&~0x00000001,addr1);
- back_to_p1(__dummy);
+ back_to_P1();
if (data0 == data1 && data2 == data3) { /* Shadow */
cache_system_info.way_shift = 11;
@@ -265,7 +244,7 @@ detect_cpu_and_cache_system(void)
void __init cache_init(void)
{
- unsigned long __dummy, ccr;
+ unsigned long ccr;
detect_cpu_and_cache_system();
@@ -277,19 +256,19 @@ void __init cache_init(void)
we only need to flush the half of the caches. */
cache_wback_all();
- jump_to_p2(__dummy);
+ jump_to_P2();
ctrl_outl(CCR_CACHE_INIT, CCR);
- back_to_p1(__dummy);
+ back_to_P1();
}
#if defined(__SH4__)
void flush_icache_page(struct vm_area_struct *vma, struct page *pg)
{
- unsigned long flags, __dummy;
+ unsigned long flags;
unsigned long addr, data, v;
save_and_cli(flags);
- jump_to_p2(__dummy);
+ jump_to_P2();
v = page_address(pg);
@@ -303,18 +282,18 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *pg)
data = (v&0xfffffc00); /* Valid=0 */
ctrl_outl(data,addr);
- back_to_p1(__dummy);
+ back_to_P1();
restore_flags(flags);
}
void flush_icache_range(unsigned long start, unsigned long end)
{
- unsigned long flags, __dummy;
+ unsigned long flags;
unsigned long addr, data, v;
start &= ~(L1_CACHE_BYTES-1);
save_and_cli(flags);
- jump_to_p2(__dummy);
+ jump_to_P2();
for (v = start; v < end; v+=L1_CACHE_BYTES) {
/* Write back O Cache */
@@ -327,22 +306,22 @@ void flush_icache_range(unsigned long start, unsigned long end)
data = (v&0xfffffc00); /* Valid=0 */
ctrl_outl(data,addr);
}
- back_to_p1(__dummy);
+ back_to_P1();
restore_flags(flags);
}
void flush_cache_all(void)
{
- unsigned long flags,__dummy;
+ unsigned long flags;
/* Write back Operand Cache */
cache_wback_all ();
/* Then, invalidate Instruction Cache and Operand Cache */
save_and_cli(flags);
- jump_to_p2(__dummy);
+ jump_to_P2();
ctrl_outl(CCR_CACHE_INIT, CCR);
- back_to_p1(__dummy);
+ back_to_P1();
restore_flags(flags);
}
@@ -356,12 +335,12 @@ void flush_cache_mm(struct mm_struct *mm)
void flush_cache_range(struct mm_struct *mm, unsigned long start,
unsigned long end)
{
- unsigned long flags, __dummy;
+ unsigned long flags;
unsigned long addr, data, v;
start &= ~(L1_CACHE_BYTES-1);
save_and_cli(flags);
- jump_to_p2(__dummy);
+ jump_to_P2();
for (v = start; v < end; v+=L1_CACHE_BYTES) {
addr = CACHE_IC_ADDRESS_ARRAY |
@@ -372,7 +351,7 @@ void flush_cache_range(struct mm_struct *mm, unsigned long start,
(v&CACHE_OC_ENTRY_MASK) | 0x8 /* A-bit */;
ctrl_outl(data,addr);
}
- back_to_p1(__dummy);
+ back_to_P1();
restore_flags(flags);
}
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 3b8e86e36..bf448bf8b 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.12 2000/03/01 11:15:27 gniibe Exp $
+/* $Id: fault.c,v 1.13 2000/03/07 12:05:24 gniibe Exp $
*
* linux/arch/sh/mm/fault.c
* Copyright (C) 1999 Niibe Yutaka
@@ -283,9 +283,6 @@ static void __flush_tlb_page(struct mm_struct *mm, unsigned long page)
{
unsigned long addr, data, asid;
unsigned long saved_asid = MMU_NO_ASID;
-#if defined(__SH4__)
- int i;
-#endif
if (mm->context == NO_CONTEXT)
return;
@@ -305,20 +302,26 @@ static void __flush_tlb_page(struct mm_struct *mm, unsigned long page)
data = (page & 0xfffe0000) | asid; /* VALID bit is off */
ctrl_outl(data, addr);
#elif defined(__SH4__)
+ jump_to_P2();
addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT;
data = page | asid; /* VALID bit is off */
ctrl_outl(data, addr);
-
- for (i=0; i<4; i++) {
- addr = MMU_ITLB_ADDRESS_ARRAY | (i<<8);
- data = ctrl_inl(addr);
- data &= ~0x300;
- if (data == (page | asid)) {
- ctrl_outl(data, addr);
- break;
+#if 0 /* Not need when using ASSOC. ??? */
+ {
+ int i;
+ for (i=0; i<4; i++) {
+ addr = MMU_ITLB_ADDRESS_ARRAY | (i<<8);
+ data = ctrl_inl(addr);
+ data &= ~0x300;
+ if (data == (page | asid)) {
+ ctrl_outl(data, addr);
+ break;
+ }
}
}
#endif
+ back_to_P1();
+#endif
if (saved_asid != MMU_NO_ASID)
set_asid(saved_asid);
}
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 776389cac..931564cac 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -224,7 +224,7 @@ void __init paging_init(void)
zones_size[ZONE_DMA] = max_dma - start_pfn;
zones_size[ZONE_NORMAL] = low - max_dma;
}
- free_area_init_node(0, 0, zones_size, __MEMORY_START);
+ free_area_init_node(0, 0, zones_size, __MEMORY_START, 0);
}
}