patch-2.4.0-test9 linux/arch/sh/kernel/entry.S
Next file: linux/arch/sh/kernel/head.S
Previous file: linux/arch/sh/config.in
Back to the patch index
Back to the overall index
- Lines: 396
- Date:
Mon Oct 2 11:57:34 2000
- Orig file:
v2.4.0-test8/linux/arch/sh/kernel/entry.S
- Orig date:
Fri Aug 11 14:29:05 2000
diff -u --recursive --new-file v2.4.0-test8/linux/arch/sh/kernel/entry.S linux/arch/sh/kernel/entry.S
@@ -14,7 +14,12 @@
#include <linux/linkage.h>
#include <linux/config.h>
-#define COMPAT_OLD_SYSCALL_ABI 1
+
+/*
+ * Define this to turn on compatibility with the previous
+ * system call ABI. This feature is not properly maintained.
+ */
+#undef COMPAT_OLD_SYSCALL_ABI
! NOTE:
! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
@@ -28,6 +33,12 @@
* NOTE: This code handles signal-recognition, which happens every time
* after a timer-interrupt and after each system call.
*
+ * NOTE: This code uses a convention that instructions in the delay slot
+ * of a transfer-control instruction are indented by an extra space, thus:
+ *
+ * jmp @$k0 ! control-transfer instruction
+ * ldc $k1, $ssr ! delay slot
+ *
* Stack layout in 'ret_from_syscall':
* ptrace needs to have all regs on the stack.
* if the order here is changed, it needs to be
@@ -58,6 +69,7 @@
PF_USEDFPU = 0x00100000
ENOSYS = 38
+EINVAL = 22
#if defined(__sh3__)
TRA = 0xffffffd0
@@ -76,7 +88,14 @@
#endif
/* Offsets to the stack */
-R0 = 0 /* Return value */
+R0 = 0 /* Return value. New ABI also arg4 */
+R1 = 4 /* New ABI: arg5 */
+R2 = 8 /* New ABI: arg6 */
+R3 = 12 /* New ABI: syscall_nr */
+R4 = 16 /* New ABI: arg0 */
+R5 = 20 /* New ABI: arg1 */
+R6 = 24 /* New ABI: arg2 */
+R7 = 28 /* New ABI: arg3 */
SP = (15*4)
SR = (16*4+8)
SYSCALL_NR = (16*4+6*4)
@@ -132,7 +151,6 @@
tlb_miss_load:
mov.l 2f, $r0
mov.l @$r0, $r6
- STI()
mov $r15, $r4
mov.l 1f, $r0
jmp @$r0
@@ -142,7 +160,6 @@
tlb_miss_store:
mov.l 2f, $r0
mov.l @$r0, $r6
- STI()
mov $r15, $r4
mov.l 1f, $r0
jmp @$r0
@@ -152,7 +169,6 @@
initial_page_write:
mov.l 2f, $r0
mov.l @$r0, $r6
- STI()
mov $r15, $r4
mov.l 1f, $r0
jmp @$r0
@@ -162,7 +178,6 @@
tlb_protection_violation_load:
mov.l 2f, $r0
mov.l @$r0, $r6
- STI()
mov $r15, $r4
mov.l 1f, $r0
jmp @$r0
@@ -172,14 +187,13 @@
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
.align 2
-1: .long SYMBOL_NAME(do_page_fault)
+1: .long SYMBOL_NAME(__do_page_fault)
2: .long MMU_TEA
#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS)
@@ -249,9 +263,6 @@
.align 2
1: .long SYMBOL_NAME(do_exception_error)
-badsys: mov #-ENOSYS, $r0
- rts ! go to ret_from_syscall..
- mov.l $r0, @(R0,$r15)
!
!
@@ -291,7 +302,7 @@
*/
system_call:
- mov.l 1f, $r9
+ mov.l __TRA, $r9
mov.l @$r9, $r8
!
! Is the trap argument >= 0x20? (TRA will be >= 0x80)
@@ -304,122 +315,160 @@
mov #SYSCALL_NR, $r14
add $r15, $r14
!
- mov #0x40, $r9
#ifdef COMPAT_OLD_SYSCALL_ABI
+ mov #0x40, $r9
cmp/hs $r9, $r8
- mov $r0, $r10
- bf/s 0f
- mov $r0, $r9
+ bf/s old_abi_system_call
+ nop
#endif
! New Syscall ABI
add #-0x40, $r8
shlr2 $r8
shll8 $r8
- shll8 $r8
+ shll8 $r8 ! $r8 = num_args<<16
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
!
-#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 @(tsk_ptrace,$r11), $r10 ! Is it trace?
+ stc $k_current, $r11
+ mov.l @(tsk_ptrace,$r11), $r10 ! Is current PTRACE_SYSCALL'd?
mov #PT_TRACESYS, $r11
tst $r11, $r10
bt 5f
- ! Trace system call
- mov #-ENOSYS, $r11
- mov.l $r11, @(R0,$r15)
- ! Push up $R0--$R2, and $R4--$R7
- mov.l $r0, @-$r15
- mov.l $r1, @-$r15
- mov.l $r2, @-$r15
- mov.l $r4, @-$r15
- mov.l $r5, @-$r15
- mov.l $r6, @-$r15
- mov.l $r7, @-$r15
- !
- mov.l 2f, $r11
- jsr @$r11
+ ! Yes it is traced.
+ mov.l __syscall_trace, $r11 ! Call syscall_trace() which notifies
+ jsr @$r11 ! superior (will chomp $R[0-7])
nop
- ! Pop down $R0--$R2, and $R4--$R7
- mov.l @$r15+, $r7
- mov.l @$r15+, $r6
- mov.l @$r15+, $r5
- mov.l @$r15+, $r4
- mov.l @$r15+, $r2
- mov.l @$r15+, $r1
- mov.l @$r15+, $r0
- !
+ ! 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 @(R4,$r15), $r4 ! arg0
+ mov.l @(R5,$r15), $r5
+ mov.l @(R6,$r15), $r6
+ mov.l @(R7,$r15), $r7 ! arg3
+ mov.l @(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
- !
-6: mov $r9, $r10
- shll2 $r10 ! x4
+ ! 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, $r10
- mov.l @$r10, $r11
- jmp @$r11
+ add $r11, $r9
+ mov.l @$r9, $r11
+ jmp @$r11 ! jump to specific syscall handler
nop
! In case of trace
- .align 2
-3:
-#ifdef COMPAT_OLD_SYSCALL_ABI
- add $r8, $r15 ! pop off the arguments
-#endif
+syscall_ret_trace:
mov.l $r0, @(R0,$r15) ! save the return value
- mov.l 2f, $r1
+ mov.l __syscall_trace, $r1
mova SYMBOL_NAME(ret_from_syscall), $r0
- jmp @$r1
- lds $r0, $pr
- .align 2
-1: .long TRA
-2: .long SYMBOL_NAME(syscall_trace)
-__n_sys: .long NR_syscalls
-__sct: .long SYMBOL_NAME(sys_call_table)
-__syscall_ret_trace:
- .long 3b
-__syscall_ret:
- .long SYMBOL_NAME(syscall_ret)
+ 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 @(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
+ 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.l 1f, $r0
-1: .long -22 ! -EINVAL
-.previous
+ mov #-EINVAL, $r0
+ .previous
.section __ex_table, "a"
.align 2
.long 4b,fixup_syscall_argerr
-.previous
+ .previous
#endif
.align 2
+__TRA: .long TRA
+__syscall_trace:
+ .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 SYMBOL_NAME(syscall_ret)
+
+
+
+ .align 2
reschedule:
mova SYMBOL_NAME(ret_from_syscall), $r0
mov.l 1f, $r1
@@ -454,10 +503,12 @@
.long 0xffffff0f ! ~(IMASK)
.align 2
-syscall_ret:
#ifdef COMPAT_OLD_SYSCALL_ABI
+old_abi_syscall_ret:
add $r8, $r15 ! pop off the arguments
+ /* fall through */
#endif
+syscall_ret:
mov.l $r0, @(R0,$r15) ! save the return value
/* fall through */
@@ -707,7 +758,7 @@
#endif
8: /* User space to kernel */
mov #0x20, $k1
- shll8 $k1 ! $k1 <= 8192
+ shll8 $k1 ! $k1 <= 8192 == THREAD_SIZE
add $current, $k1
mov $k1, $r15 ! change to kernel stack
!
@@ -1107,6 +1158,7 @@
.long SYMBOL_NAME(sys_mincore)
.long SYMBOL_NAME(sys_madvise)
.long SYMBOL_NAME(sys_getdents64) /* 220 */
+ .long SYMBOL_NAME(sys_fcntl64)
/*
* NOTE!! This doesn't have to be exact - we just have
@@ -1114,7 +1166,7 @@
* entries. Don't panic if you notice that this hasn't
* been shrunk every time we add a new system call.
*/
- .rept NR_syscalls-220
+ .rept NR_syscalls-221
.long SYMBOL_NAME(sys_ni_syscall)
.endr
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)