summaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
commitb9ba7aeb165cffecdffb60aec8c3fa8d590d9ca9 (patch)
tree42d07b0c7246ae2536a702e7c5de9e2732341116 /arch/sh/kernel
parent7406b0a326f2d70ade2671c37d1beef62249db97 (diff)
Merge with 2.3.99-pre6.
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r--arch/sh/kernel/Makefile1
-rw-r--r--arch/sh/kernel/entry.S442
-rw-r--r--arch/sh/kernel/fpu.c49
-rw-r--r--arch/sh/kernel/head.S16
-rw-r--r--arch/sh/kernel/irq.c2
-rw-r--r--arch/sh/kernel/irq_imask.c12
-rw-r--r--arch/sh/kernel/irq_onchip.c4
-rw-r--r--arch/sh/kernel/process.c31
-rw-r--r--arch/sh/kernel/setup.c19
-rw-r--r--arch/sh/kernel/signal.c30
-rw-r--r--arch/sh/kernel/time.c41
-rw-r--r--arch/sh/kernel/traps.c10
12 files changed, 391 insertions, 266 deletions
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 8996a13dc..266aafe1f 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -29,7 +29,6 @@ all: kernel.o head.o init_task.o
entry.o: entry.S
head.o: head.S
- $(CC) $(AFLAGS) -traditional -c $*.S -o $*.o
clean:
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S
index 46ad20f53..00372811c 100644
--- a/arch/sh/kernel/entry.S
+++ b/arch/sh/kernel/entry.S
@@ -14,6 +14,8 @@
#include <linux/linkage.h>
#include <linux/config.h>
+#define COMPAT_OLD_SYSCALL_ABI 1
+
! NOTE:
! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
! to be jumped is too far, but it causes illegal slot exception.
@@ -31,26 +33,24 @@
* if the order here is changed, it needs to be
* updated in ptrace.c and ptrace.h
*
- * syscall #
- * ssr
- * r0
+ * $r0
* ...
- * r15 = stack pointer
- * gbr
- * mach
- * macl
- * pr
- * spc
+ * $r15 = stack pointer
+ * $spc
+ * $pr
+ * $ssr
+ * $gbr
+ * $mach
+ * $macl
+ * syscall #
*
*/
/*
* These are offsets into the task-struct.
*/
-state = 0
flags = 4
sigpending = 8
-addr_limit = 12
need_resched = 20
PF_TRACESYS = 0x00000020
@@ -75,30 +75,35 @@ MMU_TEA = 0xff00000c ! TLB Exception Address Register
#endif
/* Offsets to the stack */
-SYSCALL_NR = 0
-SR = 4
-R0 = 8
-SP = (8+15*4)
+R0 = 0 /* Return value */
+SP = (15*4)
+SR = (16*4+8)
+SYSCALL_NR = (16*4+6*4)
+
#define k0 r0
#define k1 r1
#define k2 r2
#define k3 r3
+#define k4 r4
-#define kernel_sp r4 /* r4_bank1 */
-#define ksp r4_bank /* r4_bank1 */
+#define current r7 /* r7_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 */
-/* Kernel mode register usage:
- k0 scratch
- k1 scratch
- k2 scratch (Exception code)
- k3 scratch (Return address)
- k4 Stack base = current+8192
- k5 Global Interrupt Mask (0--15)
- k6 reserved
- k7 reserved
-*/
+/*
+ * Kernel mode register usage:
+ * k0 scratch
+ * k1 scratch
+ * k2 scratch (Exception code)
+ * k3 scratch (Return address)
+ * k4 scratch
+ * k5 reserved
+ * k6 Global Interrupt Mask (0--15 << 4)
+ * k7 CURRENT (pointer to current task)
+ */
!
! TLB Miss / Initial Page write exception handling
@@ -114,42 +119,60 @@ SP = (8+15*4)
! this first version depends *much* on C implementation.
!
-#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
+#define STI() \
+ mov.l __INV_IMASK, $r11; \
+ stc $sr, $r10; \
+ and $r11, $r10; \
+ stc $k_g_imask, $r11; \
+ or $r11, $r10; \
+ ldc $r10, $sr
.balign 4
-tlb_protection_violation_load:
tlb_miss_load:
- mov #-1, $r0
- mov.l $r0, @$r15 ! syscall nr = -1
mov.l 2f, $r0
mov.l @$r0, $r6
- RESTORE_FLAGS()
-9: mov $r15, $r4
+ STI()
+ mov $r15, $r4
mov.l 1f, $r0
jmp @$r0
mov #0, $r5
.balign 4
-tlb_protection_violation_store:
tlb_miss_store:
+ mov.l 2f, $r0
+ mov.l @$r0, $r6
+ STI()
+ mov $r15, $r4
+ mov.l 1f, $r0
+ jmp @$r0
+ mov #1, $r5
+
+ .balign 4
initial_page_write:
- mov #-1, $r0
- mov.l $r0, @$r15 ! syscall nr = -1
mov.l 2f, $r0
mov.l @$r0, $r6
- RESTORE_FLAGS()
-9: mov $r15, $r4
+ STI()
+ mov $r15, $r4
+ mov.l 1f, $r0
+ jmp @$r0
+ mov #1, $r5
+
+ .balign 4
+tlb_protection_violation_load:
+ mov.l 2f, $r0
+ mov.l @$r0, $r6
+ STI()
+ mov $r15, $r4
+ mov.l 1f, $r0
+ jmp @$r0
+ mov #0, $r5
+
+ .balign 4
+tlb_protection_violation_store:
+ mov.l 2f, $r0
+ mov.l @$r0, $r6
+ STI()
+ mov $r15, $r4
mov.l 1f, $r0
jmp @$r0
mov #1, $r5
@@ -162,8 +185,6 @@ initial_page_write:
.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+, $r0
mov.l @$r15+, $r1
mov.l @$r15+, $r2
@@ -172,11 +193,10 @@ debug:
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
+ stc $sr, $r8
+ mov.l 1f, $r9 ! BL =1, RB=1, IMASK=0x0F
+ or $r9, $r8
+ ldc $r8, $sr ! here, change the register bank
mov.l @$r15+, $r8
mov.l @$r15+, $r9
mov.l @$r15+, $r10
@@ -185,11 +205,12 @@ debug:
mov.l @$r15+, $r13
mov.l @$r15+, $r14
mov.l @$r15+, $k0
+ ldc.l @$r15+, $spc
+ lds.l @$r15+, $pr
+ mov.l @$r15+, $k1
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 2f, $k0
@@ -203,11 +224,10 @@ debug:
.balign 4
error:
!
- RESTORE_FLAGS()
-9: mov.l 1f, $r1
- mov #-1, $r0
- jmp @$r1
- mov.l $r0, @$r15 ! syscall nr = -1
+ STI()
+ mov.l 1f, $r0
+ jmp @$r0
+ nop
.balign 4
1: .long SYMBOL_NAME(do_exception_error)
@@ -222,76 +242,106 @@ ENTRY(ret_from_fork)
bra SYMBOL_NAME(ret_from_syscall)
add #4, $r15 ! pop down bogus r0 (see switch_to MACRO)
-!
-! The immediate value of "trapa" indicates the number of arguments
-! placed on the stack.
-!
-! Note that TRA register contains the value = Imm x 4.
-!
+/*
+ * 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 #: R3
+ * Arguments #0 to #3: R4--R7
+ * Arguments #4 to #6: R0, R1, R2
+ * TRA: (number of arguments + 0x10) x 4
+ *
+ */
+
system_call:
- mov.l 1f, $r2
- mov.l @$r2, $r8
- !
- ! DEBUG DEBUG
- ! mov.l led, $r1
- ! mov $r0, $r2
- ! mov.b $r2, @$r1
+ mov.l 1f, $r9
+ mov.l @$r9, $r8
!
#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
- mov #0x20, $r1
- extu.b $r1, $r1
- shll2 $r1
- cmp/hs $r1, $r8
+ mov #0x20, $r9
+ extu.b $r9, $r9
+ shll2 $r9
+ cmp/hs $r9, $r8
bt debug
#endif
!
- mov $r0, $r2
- RESTORE_FLAGS()
-9: mov.l __n_sys, $r1
- cmp/hs $r1, $r2
+ mov #SYSCALL_NR, $r14
+ add $r15, $r14
+ !
+ mov #0x40, $r9
+#ifdef COMPAT_OLD_SYSCALL_ABI
+ cmp/hs $r9, $r8
+ mov $r0, $r10
+ bf/s 0f
+ mov $r0, $r9
+#endif
+ ! New Syscall ABI
+ sub $r9, $r8
+ shlr2 $r8
+ shll8 $r8
+ shll8 $r8
+ mov $r3, $r10
+ or $r8, $r10 ! Encode syscall # and # of arguments
+ !
+ mov $r3, $r9
+ mov #0, $r8
+0:
+ mov.l $r10, @$r14 ! set syscall_nr
+ STI()
+ mov.l __n_sys, $r10
+ cmp/hs $r10, $r9
bt badsys
!
- stc $ksp, $r1
- mov.l __tsk_flags, $r0
- add $r0, $r1 !
- mov.l @$r1, $r0 ! Is it trace?
- tst #PF_TRACESYS, $r0
+#ifdef COMPAT_OLD_SYSCALL_ABI
+ ! Build the stack frame if TRA > 0
+ mov $r8, $r10
+ cmp/pl $r10
+ bf 0f
+ mov.l @(SP,$r15), $r0 ! get original 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
+#endif
+0: stc $k_current, $r11
+ mov.l @(flags,$r11), $r10 ! Is it trace?
+ mov #PF_TRACESYS, $r11
+ tst $r11, $r10
bt 5f
! Trace system call
- mov #-ENOSYS, $r1
- mov.l $r1, @(R0,$r15)
- mov.l 3f, $r1
- jsr @$r1
+ mov #-ENOSYS, $r11
+ mov.l $r11, @(R0,$r15)
+ mov.l 2f, $r11
+ jsr @$r11
nop
- mova 3f, $r0
+ mov.l __syscall_ret_trace, $r10
bra 6f
- lds $r0, $pr
+ lds $r10, $pr
!
-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
+5: mov.l __syscall_ret, $r10
+ lds $r10, $pr
!
-0: mov $r3, $r0
- shll2 $r0 ! x4
- mov.l __sct, $r1
- add $r1, $r0
- mov.l @$r0, $r1
- jmp @$r1
- mov $r2, $r8
+6: mov $r9, $r10
+ shll2 $r10 ! x4
+ mov.l __sct, $r11
+ add $r11, $r10
+ mov.l @$r10, $r11
+ jmp @$r11
+ nop
+
! In case of trace
.balign 4
-3: add $r8, $r15 ! pop off the arguments
+3:
+#ifdef COMPAT_OLD_SYSCALL_ABI
+ add $r8, $r15 ! pop off the arguments
+#endif
mov.l $r0, @(R0,$r15) ! save the return value
mov.l 2f, $r1
mova SYMBOL_NAME(ret_from_syscall), $r0
@@ -302,9 +352,12 @@ system_call:
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
-led: .long 0xa8000000 ! For my board -- gN
+__syscall_ret_trace:
+ .long 3b
+__syscall_ret:
+ .long SYMBOL_NAME(syscall_ret)
+#ifdef COMPAT_OLD_SYSCALL_ABI
.section .fixup,"ax"
fixup_syscall_argerr:
rts
@@ -316,6 +369,7 @@ fixup_syscall_argerr:
.balign 4
.long 4b,fixup_syscall_argerr
.previous
+#endif
.balign 4
reschedule:
@@ -327,23 +381,25 @@ reschedule:
1: .long SYMBOL_NAME(schedule)
ENTRY(ret_from_irq)
- mov.l @(SR,$r15), $r0 ! get status register
+ mov #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
!
- RESTORE_FLAGS()
-9: bra ret_with_reschedule
+ STI()
+ bra ret_with_reschedule
nop
ENTRY(ret_from_exception)
- mov.l @(SR,$r15), $r0 ! get status register
+ mov #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
!
- RESTORE_FLAGS()
-9: bra ret_from_syscall
+ STI()
+ bra ret_from_syscall
nop
.balign 4
__INV_IMASK:
@@ -351,7 +407,9 @@ __INV_IMASK:
.balign 4
syscall_ret:
+#ifdef COMPAT_OLD_SYSCALL_ABI
add $r8, $r15 ! pop off the arguments
+#endif
mov.l $r0, @(R0,$r15) ! save the return value
/* fall through */
@@ -366,9 +424,7 @@ handle_softirq:
jsr @$r0
nop
ret_with_reschedule:
- stc $ksp, $r1
- mov.l __minus8192, $r0
- add $r0, $r1
+ stc $k_current, $r1
mov.l @(need_resched,$r1), $r0
tst #0xff, $r0
bf reschedule
@@ -389,30 +445,14 @@ __softirq_state:
.long SYMBOL_NAME(softirq_state)
__do_softirq:
.long SYMBOL_NAME(do_softirq)
-__minus8192:
- .long -8192 ! offset from stackbase to tsk
.balign 4
restore_all:
#if defined(__SH4__)
- mov.l __fpu_prepare_fd, $r1
- jsr @$r1
+ mov.l __fpu_prepare_fd, $r0
+ jsr @$r0
stc $sr, $r4
#endif
- 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 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+, $r0
mov.l @$r15+, $r1
@@ -422,14 +462,12 @@ restore_all:
mov.l @$r15+, $r5
mov.l @$r15+, $r6
mov.l @$r15+, $r7
- stc $sr, $r14
+ !
+ stc $sr, $r8
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
+ or $r9, $r8
+ ldc $r8, $sr ! here, change the register bank
+ !
mov.l @$r15+, $r8
mov.l @$r15+, $r9
mov.l @$r15+, $r10
@@ -437,20 +475,33 @@ restore_all:
mov.l @$r15+, $r12
mov.l @$r15+, $r13
mov.l @$r15+, $r14
- mov.l @$r15+, $k0 ! original stack
+ mov.l @$r15+, $k4 ! original stack pointer
+ ldc.l @$r15+, $spc
+ lds.l @$r15+, $pr
+ mov.l @$r15+, $k3 ! original SR
ldc.l @$r15+, $gbr
lds.l @$r15+, $mach
lds.l @$r15+, $macl
- lds.l @$r15+, $pr
- ldc.l @$r15+, $spc
- ldc $k1, $ssr
+ add #4, $r15 ! Skip syscall number
+ !
+ ! Calculate new SR value
+ mov $k3, $k2 ! original SR value
+ mov.l 1f, $k1
+ stc $sr, $k0
+ and $k1, $k0 ! Get current FD-bit
+ mov.l 2f, $k1
+ and $k1, $k2 ! Mask orignal SR value
+ or $k0, $k2 ! Inherit current FD-bit
+ or $g_imask, $k2 ! Inherit the IMASK-bits
+ ldc $k2, $ssr
+ !
#if defined(__SH4__)
- shll $k1
- shll $k1
+ shll $k2
+ shll $k2
bf 9f ! user mode
/* Kernel to kernel transition */
mov.l 1f, $k1
- tst $k1, $k2
+ tst $k1, $k3
bf 9f ! it hadn't FPU
! Kernel to kernel and FPU was used
! There's the case we don't get FPU now
@@ -462,14 +513,15 @@ restore_all:
ldc $k2, $sr ! Grab FPU
mov.l __init_task_flags, $k1
mov.l @$k1, $k2
- mov.l __PF_USEDFPU, $k1
- or $k1, $k2
- mov.l __init_task_flags, $k1
+ mov.l __PF_USEDFPU, $k0
+ or $k0, $k2
mov.l $k2, @$k1 ! Set init_task.flags |= PF_USEDFPU
!
! Restoring FPU...
!
-7: fmov.s @$r15+, $fr0
+7: mov.l 3f, $k1
+ lds $k1, $fpscr
+ fmov.s @$r15+, $fr0
fmov.s @$r15+, $fr1
fmov.s @$r15+, $fr2
fmov.s @$r15+, $fr3
@@ -489,7 +541,7 @@ restore_all:
lds.l @$r15+, $fpul
9:
#endif
- mov $k0, $r15
+ mov $k4, $r15
rte
nop
@@ -505,6 +557,7 @@ __PF_USEDFPU:
#endif
1: .long 0x00008000 ! FD
2: .long 0xffff7f0f ! ~(IMASK+FD)
+3: .long 0x00080000 ! SZ=0, PR=1
! Exception Vector Base
!
@@ -569,6 +622,9 @@ handle_exception:
! /* Currently it's not the case for GCC (only udivsi3_i4, divsi3_i4) */
sts.l $fpul, @-$r15
sts.l $fpscr, @-$r15
+ mov.l 6f, $k1
+ lds $k1, $fpscr
+ mov.l 3f, $k1
fmov.s $fr15, @-$r15
fmov.s $fr14, @-$r15
fmov.s $fr13, @-$r15
@@ -584,40 +640,47 @@ handle_exception:
fmov.s $fr3, @-$r15
fmov.s $fr2, @-$r15
fmov.s $fr1, @-$r15
- fmov.s $fr0, @-$r15
bra 9f
- mov.l 3f, $k1
+ fmov.s $fr0, @-$r15
#else
mov.l 3f, $k1
bt/s 9f ! it's from kernel to kernel transition
mov $r15, $k0 ! save original stack to k0 anyway
#endif
8: /* User space to kernel */
- 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
+ mov #0x20, $k1
+ shll8 $k1 ! $k1 <= 8192
+ add $current, $k1
+ mov $k1, $r15 ! change to kernel stack
!
- lds $k3, $pr ! Set the return address to pr
+ mov.l 4f, $k1 ! let kernel release FPU
+9: mov #-1, $k4
+ mov.l $k4, @-$r15 ! syscall_nr (default: -1)
!
sts.l $macl, @-$r15
sts.l $mach, @-$r15
stc.l $gbr, @-$r15
- mov.l $k0, @-$r15 ! save orignal stack
- mov.l $r14, @-$r15
+ stc.l $ssr, @-$r15
+ sts.l $pr, @-$r15
+ stc.l $spc, @-$r15
!
- 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.
+ lds $k3, $pr ! Set the return address to pr
!
+ mov.l $k0, @-$r15 ! save orignal stack
+ mov.l $r14, @-$r15
mov.l $r13, @-$r15
mov.l $r12, @-$r15
mov.l $r11, @-$r15
mov.l $r10, @-$r15
mov.l $r9, @-$r15
mov.l $r8, @-$r15
+ !
+ stc $sr, $r8 ! Back to normal register bank, and
+ or $k1, $r8 ! Block all interrupts, may release FPU
+ mov.l 5f, $k1
+ and $k1, $r8 ! ...
+ ldc $r8, $sr ! ...changed here.
+ !
mov.l $r7, @-$r15
mov.l $r6, @-$r15
mov.l $r5, @-$r15
@@ -626,23 +689,22 @@ handle_exception:
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..
+ ! Then, dispatch to the handler, according to the exception code.
+ stc $k_ex_code, $r8
+ shlr2 $r8
+ shlr $r8
+ mov.l 1f, $r9
+ add $r8, $r9
+ mov.l @$r9, $r9
+ jmp @$r9
+ nop
.balign 4
1: .long SYMBOL_NAME(exception_handling_table)
2: .long 0x00008000 ! FD=1
3: .long 0x000000f0 ! FD=0, IMASK=15
4: .long 0x000080f0 ! FD=1, IMASK=15
5: .long 0xcfffffff ! RB=0, BL=0
+6: .long 0x00080000 ! SZ=0, PR=1
none:
rts
diff --git a/arch/sh/kernel/fpu.c b/arch/sh/kernel/fpu.c
index 5301a1333..cbeb60d31 100644
--- a/arch/sh/kernel/fpu.c
+++ b/arch/sh/kernel/fpu.c
@@ -23,6 +23,7 @@ save_fpu(struct task_struct *tsk)
{
asm volatile("sts.l $fpul, @-%0\n\t"
"sts.l $fpscr, @-%0\n\t"
+ "lds %1, $fpscr\n\t"
"frchg\n\t"
"fmov.s $fr15, @-%0\n\t"
"fmov.s $fr14, @-%0\n\t"
@@ -58,7 +59,8 @@ save_fpu(struct task_struct *tsk)
"fmov.s $fr1, @-%0\n\t"
"fmov.s $fr0, @-%0"
: /* no output */
- : "r" ((char *)(&tsk->thread.fpu.hard.status))
+ : "r" ((char *)(&tsk->thread.fpu.hard.status)),
+ "r" (FPSCR_INIT)
: "memory");
tsk->flags &= ~PF_USEDFPU;
@@ -68,7 +70,8 @@ save_fpu(struct task_struct *tsk)
static void
restore_fpu(struct task_struct *tsk)
{
- asm volatile("fmov.s @%0+, $fr0\n\t"
+ asm volatile("lds %1, $fpscr\n\t"
+ "fmov.s @%0+, $fr0\n\t"
"fmov.s @%0+, $fr1\n\t"
"fmov.s @%0+, $fr2\n\t"
"fmov.s @%0+, $fr3\n\t"
@@ -105,7 +108,7 @@ restore_fpu(struct task_struct *tsk)
"lds.l @%0+, $fpscr\n\t"
"lds.l @%0+, $fpul\n\t"
: /* no output */
- : "r" (&tsk->thread.fpu)
+ : "r" (&tsk->thread.fpu), "r" (FPSCR_INIT)
: "memory");
}
@@ -163,7 +166,6 @@ do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long
{
struct task_struct *tsk = current;
- regs.syscall_nr = -1;
regs.pc += 2;
grab_fpu();
@@ -179,15 +181,34 @@ do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6,
{
struct task_struct *tsk = current;
- regs.syscall_nr = -1;
-
if (!user_mode(&regs)) {
if (tsk != &init_task) {
unlazy_fpu(tsk);
}
tsk = &init_task;
- if (tsk->flags & PF_USEDFPU)
- BUG();
+ if (tsk->flags & PF_USEDFPU) {
+ /*
+ * This weird situation can be occurred.
+ *
+ * There's race condition in __cli:
+ *
+ * (1) $SR --> register
+ * (2) Set IMASK of register
+ * (3) $SR <-- register
+ *
+ * Between (1) and (2), or (2) and (3) getting
+ * interrupt, and interrupt handler (or
+ * softirq) may use FPU.
+ *
+ * Then, SR.FD is overwritten by (3).
+ *
+ * This results init_task.PF_USEDFPU is on,
+ * with SR.FD == 1.
+ *
+ */
+ release_fpu();
+ return;
+ }
}
grab_fpu();
@@ -216,8 +237,8 @@ fpu_prepare_fd(unsigned long sr, unsigned long r5, unsigned long r6,
grab_fpu();
else {
if (!(sr & SR_FD)) {
- release_fpu();
BUG();
+ release_fpu();
}
}
return;
@@ -228,16 +249,20 @@ fpu_prepare_fd(unsigned long sr, unsigned long r5, unsigned long r6,
grab_fpu();
else {
if (init_task.flags & PF_USEDFPU) {
- init_task.flags &= ~PF_USEDFPU;
- BUG();
+ /*
+ * This weird situation can be occurred.
+ * See the comment in do_fpu_state_restore.
+ */
+ grab_fpu();
+ save_fpu(&init_task);
}
}
} else {
if (init_task.flags & PF_USEDFPU)
save_fpu(&init_task);
else {
- release_fpu();
BUG();
+ release_fpu();
}
}
}
diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S
index ae406d22d..db3e8b0a3 100644
--- a/arch/sh/kernel/head.S
+++ b/arch/sh/kernel/head.S
@@ -41,12 +41,21 @@ ENTRY(_stext)
ldc $r0, $sr
! Initialize global interrupt mask
mov #0, $r0
- ldc $r0, $r5_bank
+ ldc $r0, $r6_bank
!
mov.l 2f, $r0
mov $r0, $r15 ! Set initial r15 (stack pointer)
- ldc $r0, $r4_bank ! and stack base
+ mov #0x20, $r1 !
+ shll8 $r1 ! $r1 = 8192
+ sub $r1, $r0 !
+ ldc $r0, $r7_bank ! ... and init_task
!
+#if defined(__SH4__)
+ ! Initialize fpu
+ mov.l 7f, $r0
+ jsr @$r0
+ nop
+#endif
! Enable cache
mov.l 6f, $r0
jsr @$r0
@@ -71,3 +80,6 @@ ENTRY(_stext)
4: .long SYMBOL_NAME(_end)
5: .long SYMBOL_NAME(start_kernel)
6: .long SYMBOL_NAME(cache_init)
+#if defined(__SH4__)
+7: .long SYMBOL_NAME(fpu_init)
+#endif
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index af03ef46d..c989796d7 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -235,8 +235,6 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
struct irqaction * action;
unsigned int status;
- regs.syscall_nr = -1; /* It's not system call */
-
/* Get IRQ number */
asm volatile("stc $r2_bank, %0\n\t"
"shlr2 %0\n\t"
diff --git a/arch/sh/kernel/irq_imask.c b/arch/sh/kernel/irq_imask.c
index 380acf405..7237ba3b5 100644
--- a/arch/sh/kernel/irq_imask.c
+++ b/arch/sh/kernel/irq_imask.c
@@ -43,7 +43,7 @@ static unsigned int startup_imask_irq(unsigned int irq)
}
static struct hw_interrupt_type imask_irq_type = {
- "Interrupt using IMASK of SR register",
+ "SR.IMASK",
startup_imask_irq,
shutdown_imask_irq,
enable_imask_irq,
@@ -56,13 +56,13 @@ void static inline set_interrupt_registers(int ip)
{
unsigned long __dummy;
- asm volatile("ldc %2, $r5_bank\n\t"
+ asm volatile("ldc %2, $r6_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"
+ "shlr2 %0\n\t"
+ "cmp/eq #0x3c, %0\n\t"
+ "bt/s 1f ! CLI-ed\n\t"
+ " stc $sr, %0\n\t"
"and %1, %0\n\t"
"or %2, %0\n\t"
"ldc %0, $sr\n"
diff --git a/arch/sh/kernel/irq_onchip.c b/arch/sh/kernel/irq_onchip.c
index 10c48fd38..36dce33fb 100644
--- a/arch/sh/kernel/irq_onchip.c
+++ b/arch/sh/kernel/irq_onchip.c
@@ -61,7 +61,7 @@ static unsigned int startup_onChip_irq(unsigned int irq)
}
static struct hw_interrupt_type onChip_irq_type = {
- "On-Chip Supporting Module",
+ "On-Chip-IPR",
startup_onChip_irq,
shutdown_onChip_irq,
enable_onChip_irq,
@@ -193,7 +193,7 @@ static unsigned int startup_onChip2_irq(unsigned int irq)
}
static struct hw_interrupt_type onChip2_irq_type = {
- "SH7709 Extended On-Chip Supporting Module",
+ "Extended-IPR",
startup_onChip2_irq,
shutdown_onChip2_irq,
enable_onChip2_irq,
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 97cd1fe0c..2d0f5e18a 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -136,20 +136,20 @@ void free_task_struct(struct task_struct *p)
*/
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{ /* Don't use this in BL=1(cli). Or else, CPU resets! */
- register unsigned long __sc0 __asm__ ("$r0") = __NR_clone;
+ register unsigned long __sc0 __asm__ ("$r3") = __NR_clone;
register unsigned long __sc4 __asm__ ("$r4") = (long) flags | CLONE_VM;
register unsigned long __sc5 __asm__ ("$r5") = 0;
register unsigned long __sc8 __asm__ ("$r8") = (long) arg;
register unsigned long __sc9 __asm__ ("$r9") = (long) fn;
- __asm__("trapa #0\n\t" /* Linux/SH system call */
+ __asm__("trapa #0x12\n\t" /* Linux/SH system call */
"tst #0xff, $r0\n\t" /* child or parent? */
"bf 1f\n\t" /* parent - jump */
"jsr @$r9\n\t" /* call fn */
" mov $r8, $r4\n\t" /* push argument */
"mov $r0, $r4\n\t" /* return value to arg of exit */
- "mov %2, $r0\n\t" /* exit */
- "trapa #0\n"
+ "mov %2, $r3\n\t" /* exit */
+ "trapa #0x11\n"
"1:"
: "=z" (__sc0)
: "0" (__sc0), "i" (__NR_exit),
@@ -194,7 +194,11 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
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));
}
@@ -214,7 +218,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
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;
}
@@ -263,16 +271,21 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
void __switch_to(struct task_struct *prev, struct task_struct *next)
{
#if defined(__SH4__)
- if (prev != &init_task)
+ if (prev != &init_task) {
+ unsigned long flags;
+
+ save_and_cli(flags);
unlazy_fpu(prev);
+ restore_flags(flags);
+ }
#endif
/*
- * Restore the kernel stack onto kernel mode register
- * k4 (r4_bank1)
+ * Restore the kernel mode register
+ * k7 (r7_bank1)
*/
- asm volatile("ldc %0, $r4_bank"
+ asm volatile("ldc %0, $r7_bank"
: /* no output */
- :"r" ((unsigned long)next+8192));
+ :"r" (next));
}
asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 154283571..49179f08f 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -244,7 +244,7 @@ void __init setup_arch(char **cmdline_p)
/*
* Reserve the kernel text and
- * Reserve the bootmem bitmap.We do this in two steps (first step
+ * Reserve the bootmem bitmap. We do this in two steps (first step
* was init_bootmem()), because this catches the (definitely buggy)
* case of us accidentally initializing the bootmem allocator with
* an invalid RAM area.
@@ -262,17 +262,17 @@ void __init setup_arch(char **cmdline_p)
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
reserve_bootmem(INITRD_START+__MEMORY_START, INITRD_SIZE);
- initrd_start =
- INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0;
+ initrd_start =
+ INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0;
initrd_end = initrd_start + INITRD_SIZE;
} else {
- printk("initrd extends beyond end of memory "
- "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+ printk("initrd extends beyond end of memory "
+ "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
INITRD_START + INITRD_SIZE,
max_low_pfn << PAGE_SHIFT);
- initrd_start = 0;
- }
- }
+ initrd_start = 0;
+ }
+ }
#endif
#if 0
@@ -301,10 +301,9 @@ void __init setup_arch(char **cmdline_p)
#endif
#if defined(__SH4__)
+ /* We already grab/initialized FPU in head.S. Make it consisitent. */
init_task.used_math = 1;
init_task.flags |= PF_USEDFPU;
- grab_fpu();
- fpu_init();
#endif
paging_init();
}
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index 4b11100ae..8751d45f5 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -152,30 +152,36 @@ struct rt_sigframe
#if defined(__SH4__)
static inline int restore_sigcontext_fpu(struct sigcontext *sc)
{
- current->used_math = 1;
+ struct task_struct *tsk = current;
+
+ tsk->used_math = 1;
return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0],
- sizeof(long)*(NUM_FPU_REGS*2+2));
+ sizeof(long)*(16*2+2));
}
static inline int save_sigcontext_fpu(struct sigcontext *sc)
{
struct task_struct *tsk = current;
+ unsigned long flags;
if (!tsk->used_math) {
- sc->owend_fp = 0;
+ sc->sc_ownedfp = 0;
return 0;
}
- sc->owend_fp = 1;
+ sc->sc_ownedfp = 1;
/* 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)*(NUM_FPU_REGS*2+2));
+ sizeof(long)*(16*2+2));
}
#endif
@@ -206,7 +212,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *r0_p)
regs->sr |= SR_FD; /* Release FPU */
clear_fpu(tsk);
current->used_math = 0;
- __get_user (owned_fp, &context->sc_ownedfp);
+ __get_user (owned_fp, &sc->sc_ownedfp);
if (owned_fp)
err |= restore_sigcontext_fpu(sc);
}
@@ -363,11 +369,11 @@ static void setup_frame(int sig, struct k_sigaction *ka,
if (ka->sa.sa_flags & SA_RESTORER) {
regs->pr = (unsigned long) ka->sa.sa_restorer;
} else {
- /* This is : mov #__NR_sigreturn,r0 ; trapa #0 */
+ /* This is : mov #__NR_sigreturn,r3 ; trapa #0x10 */
#ifdef __LITTLE_ENDIAN__
- unsigned long code = 0xc300e000 | (__NR_sigreturn);
+ unsigned long code = 0xc310e300 | (__NR_sigreturn);
#else
- unsigned long code = 0xe000c300 | (__NR_sigreturn << 16);
+ unsigned long code = 0xe300c310 | (__NR_sigreturn << 16);
#endif
regs->pr = (unsigned long) frame->retcode;
@@ -437,11 +443,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (ka->sa.sa_flags & SA_RESTORER) {
regs->pr = (unsigned long) ka->sa.sa_restorer;
} else {
- /* This is : mov #__NR_rt_sigreturn,r0 ; trapa #0 */
+ /* This is : mov #__NR_rt_sigreturn,r3 ; trapa #0x10 */
#ifdef __LITTLE_ENDIAN__
- unsigned long code = 0xc300e000 | (__NR_rt_sigreturn);
+ unsigned long code = 0xc310e300 | (__NR_rt_sigreturn);
#else
- unsigned long code = 0xe000c300 | (__NR_rt_sigreturn << 16);
+ unsigned long code = 0xe300c310 | (__NR_rt_sigreturn << 16);
#endif
regs->pr = (unsigned long) frame->retcode;
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index fad3a8145..3e9cd8d28 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -33,6 +33,23 @@
#define TMU0_TCR_INIT 0x0020
#define TMU_TSTR_INIT 1
+/* RCR1 Bits */
+#define RCR1_CF 0x80 /* Carry Flag */
+#define RCR1_CIE 0x10 /* Carry Interrupt Enable */
+#define RCR1_AIE 0x08 /* Alarm Interrupt Enable */
+#define RCR1_AF 0x01 /* Alarm Flag */
+
+/* RCR2 Bits */
+#define RCR2_PEF 0x80 /* PEriodic interrupt Flag */
+#define RCR2_PESMASK 0x70 /* Periodic interrupt Set */
+#define RCR2_RTCEN 0x08 /* ENable RTC */
+#define RCR2_ADJ 0x04 /* ADJustment (30-second) */
+#define RCR2_RESET 0x02 /* Reset bit */
+#define RCR2_START 0x01 /* Start bit */
+
+#define RTC_IRQ 22
+#define RTC_IPR_OFFSET 0
+
#if defined(__sh3__)
#define TMU_TOCR 0xfffffe90 /* Byte access */
#define TMU_TSTR 0xfffffe92 /* Byte access */
@@ -43,9 +60,6 @@
#define FRQCR 0xffffff80
-#define RTC_IRQ 22
-#define RTC_IPR_OFFSET 0
-
/* SH-3 RTC */
#define R64CNT 0xfffffec0
#define RSECCNT 0xfffffec2
@@ -74,9 +88,6 @@
#define FRQCR 0xffc00000
-#define RTC_IRQ 22
-#define RTC_IPR_OFFSET 0
-
/* SH-4 RTC */
#define R64CNT 0xffc80000
#define RSECCNT 0xffc80004
@@ -149,7 +160,7 @@ static int set_rtc_time(unsigned long nowtime)
int retval = 0;
int real_seconds, real_minutes, cmos_minutes;
- ctrl_outb(0x02, RCR2); /* reset pre-scaler & stop RTC */
+ ctrl_outb(RCR2_RESET, RCR2); /* Reset pre-scaler & stop RTC */
cmos_minutes = ctrl_inb(RMINCNT);
BCD_TO_BIN(cmos_minutes);
@@ -178,7 +189,7 @@ static int set_rtc_time(unsigned long nowtime)
retval = -1;
}
- ctrl_outb(0x01, RCR2); /* start RTC */
+ ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start RTC */
return retval;
}
@@ -283,8 +294,8 @@ static unsigned long get_rtc_time(void)
unsigned int sec, min, hr, wk, day, mon, yr, yr100;
again:
- ctrl_outb(0x01, RCR1); /* clear CF bit */
do {
+ ctrl_outb(0, RCR1); /* Clear CF-bit */
sec = ctrl_inb(RSECCNT);
min = ctrl_inb(RMINCNT);
hr = ctrl_inb(RHRCNT);
@@ -299,7 +310,7 @@ static unsigned long get_rtc_time(void)
yr = ctrl_inb(RYRCNT);
yr100 = (yr == 0x99) ? 0x19 : 0x20;
#endif
- } while ((ctrl_inb(RCR1) & 0x80) != 0);
+ } while ((ctrl_inb(RCR1) & RCR1_CF) != 0);
BCD_TO_BIN(yr100);
BCD_TO_BIN(yr);
@@ -313,7 +324,7 @@ static unsigned long get_rtc_time(void)
hr > 23 || min > 59 || sec > 59) {
printk(KERN_ERR
"SH RTC: invalid value, resetting to 1 Jan 2000\n");
- ctrl_outb(0x02, RCR2); /* reset, stop */
+ ctrl_outb(RCR2_RESET, RCR2); /* Reset & Stop */
ctrl_outb(0, RSECCNT);
ctrl_outb(0, RMINCNT);
ctrl_outb(0, RHRCNT);
@@ -325,7 +336,7 @@ static unsigned long get_rtc_time(void)
#else
ctrl_outb(0, RYRCNT);
#endif
- ctrl_outb(0x01, RCR2); /* start */
+ ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start */
goto again;
}
@@ -339,13 +350,13 @@ static __init unsigned int get_cpu_mhz(void)
sti();
do {} while (ctrl_inb(R64CNT) != 0);
- ctrl_outb(0x11, RCR1);
+ ctrl_outb(RCR1_CIE, RCR1); /* Enable carry interrupt */
asm volatile(
"1:\t"
"tst %1,%1\n\t"
"bt/s 1b\n\t"
" add #1,%0"
- : "=&r"(count), "=&z" (__dummy)
+ : "=r"(count), "=z" (__dummy)
: "0" (0), "1" (0));
cli();
/*
@@ -373,7 +384,7 @@ static __init unsigned int get_cpu_mhz(void)
static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- ctrl_outb(0x01, RCR1);
+ ctrl_outb(0, RCR1); /* Disable Carry Interrupts */
regs->regs[0] = 1;
}
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 98431cb36..a9775f306 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -43,7 +43,6 @@ asmlinkage void do_##name(unsigned long r4, unsigned long r5, \
\
asm volatile("stc $r2_bank, %0": "=r" (error_code)); \
sti(); \
- regs.syscall_nr = -1; \
tsk->thread.error_code = error_code; \
tsk->thread.trap_no = trapnr; \
force_sig(signr, tsk); \
@@ -95,9 +94,9 @@ DO_ERROR( 8, SIGSEGV, "address error (store)", address_error_store, current)
DO_ERROR(12, SIGILL, "reserved instruction", reserved_inst, current)
DO_ERROR(13, SIGILL, "illegal slot instruction", illegal_slot_inst, current)
-asmlinkage void do_exception_error (unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7,
- struct pt_regs regs)
+asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
{
long ex;
asm volatile("stc $r2_bank, %0" : "=r" (ex));
@@ -131,7 +130,8 @@ void dump_stack(void)
unsigned long *p;
asm("mov $r15, %0" : "=r" (start));
- asm("stc $r4_bank, %0" : "=r" (end));
+ asm("stc $r7_bank, %0" : "=r" (end));
+ end += 8192;
printk("%08lx:%08lx\n", (unsigned long)start, (unsigned long)end);
for (p=start; p < end; p++)