vserver 1.9.3
[linux-2.6.git] / arch / s390 / kernel / entry.S
index 1f87bf2..06312d0 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/thread_info.h>
 #include <asm/offsets.h>
 #include <asm/unistd.h>
+#include <asm/page.h>
 
 /*
  * Stack layout for the system_call stack entry.
@@ -52,6 +53,9 @@ _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
                 _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
 
+STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
+STACK_SIZE  = 1 << STACK_SHIFT
+
 #define BASED(name) name-system_call(%r13)
 
 /*
@@ -86,10 +90,16 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
        bnz     BASED(1f)
 0:     l       %r14,__LC_ASYNC_STACK   # are we already on the async stack ?
        slr     %r14,%r15
-       sra     %r14,13
+       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
+       bz      BASED(stack_overflow)
+3:
+#endif
 2:     s       %r15,BASED(.Lc_spsize)  # make room for registers & psw
        mvc     SP_PSW(8,%r15),0(%r12)  # move user PSW to stack
        la      %r12,\psworg
@@ -99,7 +109,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
        st      %r12,SP_ILC(%r15)
        mvc     SP_R12(16,%r15),\savearea # move %r12-%r15 to stack
        la      %r12,0
-       st      %r12,0(%r15)            # clear back chain
+       st      %r12,__SF_BACKCHAIN(%r15)       # clear back chain
        .endm
 
        .macro  RESTORE_ALL sync
@@ -124,46 +134,22 @@ __switch_to:
 __switch_to_base:
        tm      __THREAD_per(%r3),0xe8          # new process is using per ?
        bz      __switch_to_noper-__switch_to_base(%r1) # if not we're fine
-        stctl   %c9,%c11,24(%r15)              # We are using per stuff
-        clc     __THREAD_per(12,%r3),24(%r15)
+        stctl   %c9,%c11,__SF_EMPTY(%r15)      # We are using per stuff
+        clc     __THREAD_per(12,%r3),__SF_EMPTY(%r15)
         be      __switch_to_noper-__switch_to_base(%r1)        # we got away w/o bashing TLB's
         lctl    %c9,%c11,__THREAD_per(%r3)     # Nope we didn't
 __switch_to_noper:
-        stm     %r6,%r15,24(%r15)       # store __switch_to registers of prev task
+        stm     %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
        st      %r15,__THREAD_ksp(%r2)  # store kernel stack to prev->tss.ksp
        l       %r15,__THREAD_ksp(%r3)  # load kernel stack from next->tss.ksp
-       lm      %r6,%r15,24(%r15)       # load __switch_to registers of next task
+       lm      %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
        st      %r3,__LC_CURRENT        # __LC_CURRENT = current task struct
        l       %r3,__THREAD_info(%r3)  # load thread_info from task struct
        st      %r3,__LC_THREAD_INFO
-       ahi     %r3,8192
+       ahi     %r3,STACK_SIZE
        st      %r3,__LC_KERNEL_STACK   # __LC_KERNEL_STACK = new kernel stack
        br      %r14
 
-/*
- * do_softirq calling function. We want to run the softirq functions on the
- * asynchronous interrupt stack.
- */
-       .global do_call_softirq
-do_call_softirq:
-       stnsm   24(%r15),0xfc
-       stm     %r12,%r15,28(%r15)
-       lr      %r12,%r15
-        basr    %r13,0
-do_call_base:
-       l       %r0,__LC_ASYNC_STACK
-       slr     %r0,%r15
-       sra     %r0,13
-       be      0f-do_call_base(%r13)
-       l       %r15,__LC_ASYNC_STACK
-0:     sl      %r15,.Lc_overhead-do_call_base(%r13)
-        st     %r12,0(%r15)    # store backchain
-       l       %r1,.Ldo_softirq-do_call_base(%r13)
-       basr    %r14,%r1
-       lm      %r12,%r15,28(%r12)
-       ssm     24(%r15)
-       br      %r14
-       
 __critical_start:
 /*
  * SVC interrupt handler routine. System calls are synchronous events and
@@ -304,9 +290,12 @@ sysc_tracenogo:
 ret_from_fork:
        l       %r13,__LC_SVC_NEW_PSW+4
        l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
-        l       %r1,BASED(.Lschedtail)
+       tm      SP_PSW+1(%r15),0x01     # forking a kernel thread ?
+       bo      BASED(0f)
+       st      %r15,SP_R15(%r15)       # store stack pointer for new kthread
+0:     l       %r1,BASED(.Lschedtail)
        basr    %r14,%r1
-        stosm   24(%r15),0x03     # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03     # reenable interrupts
        b       BASED(sysc_return)
 
 #
@@ -457,7 +446,7 @@ pgm_svcper:
        mvc     __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
        mvc     __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
        oi      __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
-       stosm   24(%r15),0x03           # reenable interrupts
+       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
        b       BASED(sysc_do_svc)
 
 /*
@@ -493,16 +482,16 @@ io_preempt:
        l       %r1,SP_R15(%r15)
        s       %r1,BASED(.Lc_spsize)
        mvc     SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      0(4,%r1),0(%r1)        # clear back chain
+        xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
        lr      %r15,%r1
 io_resume_loop:
        tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
        bno     BASED(io_leave)
        mvc     __TI_precount(4,%r9),BASED(.Lc_pactive)
-        stosm   24(%r15),0x03          # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
         l       %r1,BASED(.Lschedule)
        basr    %r14,%r1               # call schedule
-        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
+        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
        xc      __TI_precount(4,%r9),__TI_precount(%r9)
        b       BASED(io_resume_loop)
 #endif
@@ -514,7 +503,7 @@ io_work:
        l       %r1,__LC_KERNEL_STACK
        s       %r1,BASED(.Lc_spsize)
        mvc     SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      0(4,%r1),0(%r1)        # clear back chain
+        xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
        lr      %r15,%r1
 #
 # One of the work bits is on. Find out which one.
@@ -532,9 +521,9 @@ io_work_loop:
 #      
 io_reschedule:        
         l       %r1,BASED(.Lschedule)
-        stosm   24(%r15),0x03          # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
        basr    %r14,%r1               # call scheduler
-        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
+        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
        tm      __TI_flags+3(%r9),_TIF_WORK_INT
        bz      BASED(io_leave)        # there is no work to do
        b       BASED(io_work_loop)
@@ -543,12 +532,12 @@ io_reschedule:
 # _TIF_SIGPENDING is set, call do_signal
 #
 io_sigpending:     
-        stosm   24(%r15),0x03          # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
         sr      %r3,%r3                # clear *oldset
         l       %r1,BASED(.Ldo_signal)
        basr    %r14,%r1               # call do_signal
-        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
+        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
        b       BASED(io_leave)        # out of here, do NOT recheck
 
 /*
@@ -589,8 +578,8 @@ restart_int_handler:
         l       %r15,__LC_SAVE_AREA+60 # load ksp
         lctl    %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
         lam     %a0,%a15,__LC_AREGS_SAVE_AREA
-        stosm   0(%r15),0x04           # now we can turn dat on
-        lm      %r6,%r15,24(%r15)      # load registers from clone
+        lm      %r6,%r15,__SF_GPRS(%r15) # load registers from clone
+        stosm   __SF_EMPTY(%r15),0x04    # now we can turn dat on
         basr    %r14,0
         l       %r14,restart_addr-.(%r14)
         br      %r14                   # branch to start_secondary
@@ -611,6 +600,31 @@ restart_crash:
 restart_go:
 #endif
 
+#ifdef CONFIG_CHECK_STACK
+/*
+ * The synchronous or the asynchronous stack overflowed. We are dead.
+ * No need to properly save the registers, we are going to panic anyway.
+ * Setup a pt_regs so that show_trace can provide a good call trace.
+ */
+stack_overflow:
+       l       %r15,__LC_PANIC_STACK   # change to panic stack
+       sl      %r15,BASED(.Lc_spsize)
+       mvc     SP_PSW(8,%r15),0(%r12)  # move user PSW to stack
+       stm     %r0,%r11,SP_R0(%r15)    # store gprs %r0-%r11 to kernel stack
+       la      %r1,__LC_SAVE_AREA
+       ch      %r12,BASED(.L0x020)     # old psw addr == __LC_SVC_OLD_PSW ?
+       be      BASED(0f)
+       ch      %r12,BASED(.L0x028)     # old psw addr == __LC_PGM_OLD_PSW ?
+       be      BASED(0f)
+       la      %r1,__LC_SAVE_AREA+16
+0:     mvc     SP_R12(16,%r15),0(%r1)  # move %r12-%r15 to stack
+        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear back chain
+       l       %r1,BASED(1f)           # branch to kernel_stack_overflow
+        la      %r2,SP_PTREGS(%r15)    # load pt_regs
+       br      %r1
+1:     .long  kernel_stack_overflow
+#endif
+
 cleanup_table_system_call:
        .long   system_call + 0x80000000, sysc_do_svc + 0x80000000
 cleanup_table_sysc_return:
@@ -695,7 +709,6 @@ cleanup_sysc_leave_lpsw:
 .Ldo_IRQ:      .long  do_IRQ
 .Ldo_extint:   .long  do_extint
 .Ldo_signal:   .long  do_signal
-.Ldo_softirq:  .long  do_softirq
 .Lhandle_per:  .long  do_single_step
 .Ljump_table:  .long  pgm_check_table
 .Lschedule:    .long  schedule