aboutsummaryrefslogtreecommitdiff
path: root/arch/s390/kernel/entry.S
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-07-03 10:25:08 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2006-07-03 10:25:08 -0400
commit0a1340c185734a57fbf4775927966ad4a1347b02 (patch)
treed9ed8f0dd809a7c542a3356601125ea5b5aaa804 /arch/s390/kernel/entry.S
parentaf18ddb8864b096e3ed4732e2d4b21c956dcfe3a (diff)
parent29454dde27d8e340bb1987bad9aa504af7081eba (diff)
Merge rsync://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: include/linux/kernel.h
Diffstat (limited to 'arch/s390/kernel/entry.S')
-rw-r--r--arch/s390/kernel/entry.S90
1 files changed, 65 insertions, 25 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index b2448487854..d8948c342ca 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -11,7 +11,6 @@
#include <linux/sys.h>
#include <linux/linkage.h>
-#include <linux/config.h>
#include <asm/cache.h>
#include <asm/lowcore.h>
#include <asm/errno.h>
@@ -93,13 +92,22 @@ STACK_SIZE = 1 << STACK_SHIFT
l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13
.endm
- .macro SAVE_ALL psworg,savearea,sync
+ .macro SAVE_ALL_SYNC psworg,savearea
la %r12,\psworg
- .if \sync
tm \psworg+1,0x01 # test problem state bit
bz BASED(2f) # skip stack setup save
l %r15,__LC_KERNEL_STACK # problem state -> load ksp
- .else
+#ifdef CONFIG_CHECK_STACK
+ b BASED(3f)
+2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD
+ bz BASED(stack_overflow)
+3:
+#endif
+2:
+ .endm
+
+ .macro SAVE_ALL_ASYNC psworg,savearea
+ la %r12,\psworg
tm \psworg+1,0x01 # test problem state bit
bnz BASED(1f) # from user -> load async stack
clc \psworg+4(4),BASED(.Lcritical_end)
@@ -115,7 +123,6 @@ STACK_SIZE = 1 << STACK_SHIFT
sra %r14,STACK_SHIFT
be BASED(2f)
1: l %r15,__LC_ASYNC_STACK
- .endif
#ifdef CONFIG_CHECK_STACK
b BASED(3f)
2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD
@@ -196,7 +203,7 @@ system_call:
STORE_TIMER __LC_SYNC_ENTER_TIMER
sysc_saveall:
SAVE_ALL_BASE __LC_SAVE_AREA
- SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+ SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
lh %r7,0x8a # get svc number from lowcore
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -221,8 +228,9 @@ sysc_do_svc:
sysc_nr_ok:
mvc SP_ARGS(4,%r15),SP_R7(%r15)
sysc_do_restart:
+ l %r8,BASED(.Lsysc_table)
tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
- l %r8,sys_call_table-system_call(%r7,%r13) # get system call addr.
+ l %r8,0(%r7,%r8) # get system call addr.
bnz BASED(sysc_tracesys)
basr %r14,%r8 # call sys_xxxx
st %r2,SP_R2(%r15) # store return value (change R2 on stack)
@@ -323,9 +331,10 @@ sysc_tracesys:
basr %r14,%r1
clc SP_R2(4,%r15),BASED(.Lnr_syscalls)
bnl BASED(sysc_tracenogo)
+ l %r8,BASED(.Lsysc_table)
l %r7,SP_R2(%r15) # strace might have changed the
sll %r7,2 # system call
- l %r8,sys_call_table-system_call(%r7,%r13)
+ l %r8,0(%r7,%r8)
sysc_tracego:
lm %r3,%r6,SP_R3(%r15)
l %r2,SP_ORIG_R2(%r15)
@@ -425,7 +434,7 @@ pgm_check_handler:
SAVE_ALL_BASE __LC_SAVE_AREA
tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
bnz BASED(pgm_per) # got per exception -> special case
- SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+ SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -464,7 +473,7 @@ pgm_per:
# Normal per exception
#
pgm_per_std:
- SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+ SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -490,7 +499,7 @@ pgm_no_vtime2:
# it was a single stepped SVC that is causing all the trouble
#
pgm_svcper:
- SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+ SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -519,7 +528,7 @@ io_int_handler:
STORE_TIMER __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
SAVE_ALL_BASE __LC_SAVE_AREA+16
- SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+16,0
+ SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -631,7 +640,7 @@ ext_int_handler:
STORE_TIMER __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
SAVE_ALL_BASE __LC_SAVE_AREA+16
- SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16,0
+ SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -657,21 +666,31 @@ __critical_end:
.globl mcck_int_handler
mcck_int_handler:
spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer
- mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA
lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs
SAVE_ALL_BASE __LC_SAVE_AREA+32
la %r12,__LC_MCK_OLD_PSW
tm __LC_MCCK_CODE,0x80 # system damage?
bo BASED(mcck_int_main) # yes -> rest of mcck code invalid
- tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid?
- bo BASED(0f)
- spt __LC_LAST_UPDATE_TIMER # revalidate cpu timer
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER
- mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER
- mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER
+ mvc __LC_SAVE_AREA+52(8),__LC_ASYNC_ENTER_TIMER
+ mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA
+ tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid?
+ bo BASED(1f)
+ la %r14,__LC_SYNC_ENTER_TIMER
+ clc 0(8,%r14),__LC_ASYNC_ENTER_TIMER
+ bl BASED(0f)
+ la %r14,__LC_ASYNC_ENTER_TIMER
+0: clc 0(8,%r14),__LC_EXIT_TIMER
+ bl BASED(0f)
+ la %r14,__LC_EXIT_TIMER
+0: clc 0(8,%r14),__LC_LAST_UPDATE_TIMER
+ bl BASED(0f)
+ la %r14,__LC_LAST_UPDATE_TIMER
+0: spt 0(%r14)
+ mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14)
+1:
#endif
-0: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
+ tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
bno BASED(mcck_int_main) # no -> skip cleanup critical
tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
bnz BASED(mcck_int_main) # from user -> load async stack
@@ -691,7 +710,7 @@ mcck_int_main:
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
bno BASED(mcck_no_vtime) # no -> skip cleanup critical
- tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ?
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
bz BASED(mcck_no_vtime)
UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
@@ -715,6 +734,20 @@ mcck_no_vtime:
l %r1,BASED(.Ls390_handle_mcck)
basr %r14,%r1 # call machine check handler
mcck_return:
+ mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW
+ ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+52
+ tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
+ bno BASED(0f)
+ lm %r0,%r15,SP_R0(%r15) # load gprs 0-15
+ stpt __LC_EXIT_TIMER
+ lpsw __LC_RETURN_MCCK_PSW # back to caller
+0:
+#endif
+ lm %r0,%r15,SP_R0(%r15) # load gprs 0-15
+ lpsw __LC_RETURN_MCCK_PSW # back to caller
+
RESTORE_ALL __LC_RETURN_MCCK_PSW,0
#ifdef CONFIG_SMP
@@ -781,6 +814,8 @@ cleanup_table_sysc_leave:
.long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000
cleanup_table_sysc_work_loop:
.long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000
+cleanup_table_io_return:
+ .long io_return + 0x80000000, io_leave + 0x80000000
cleanup_table_io_leave:
.long io_leave + 0x80000000, io_done + 0x80000000
cleanup_table_io_work_loop:
@@ -807,6 +842,11 @@ cleanup_critical:
clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4)
bl BASED(cleanup_sysc_return)
0:
+ clc 4(4,%r12),BASED(cleanup_table_io_return)
+ bl BASED(0f)
+ clc 4(4,%r12),BASED(cleanup_table_io_return+4)
+ bl BASED(cleanup_io_return)
+0:
clc 4(4,%r12),BASED(cleanup_table_io_leave)
bl BASED(0f)
clc 4(4,%r12),BASED(cleanup_table_io_leave+4)
@@ -839,7 +879,7 @@ cleanup_system_call:
mvc __LC_SAVE_AREA(16),0(%r12)
0: st %r13,4(%r12)
st %r12,__LC_SAVE_AREA+48 # argh
- SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+ SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
l %r12,__LC_SAVE_AREA+48 # argh
st %r15,12(%r12)
@@ -971,6 +1011,7 @@ cleanup_io_leave_insn:
.Ltrace: .long syscall_trace
.Lvfork: .long sys_vfork
.Lschedtail: .long schedule_tail
+.Lsysc_table: .long sys_call_table
.Lcritical_start:
.long __critical_start + 0x80000000
@@ -979,9 +1020,8 @@ cleanup_io_leave_insn:
.Lcleanup_critical:
.long cleanup_critical
+ .section .rodata, "a"
#define SYSCALL(esa,esame,emu) .long esa
- .globl sys_call_table
sys_call_table:
#include "syscalls.S"
#undef SYSCALL
-