patch-2.4.2 linux/arch/s390/kernel/entry.S

Next file: linux/arch/s390/kernel/head.S
Previous file: linux/arch/s390/kernel/ebcdic.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/entry.S linux/arch/s390/kernel/entry.S
@@ -81,6 +81,7 @@
 flags        =  4
 sigpending   =  8
 need_resched = 24
+tsk_ptrace   = 28
 processor    = 60
 
 /* PSW related defines */
@@ -88,6 +89,13 @@
 enable       = 0x03
 daton        = 0x04
 
+/*
+ * Base Address of this Module --- saved in __LC_ENTRY_BASE
+ */
+       .globl entry_base
+entry_base:
+
+#define BASED(name) name-entry_base(%r13)
 
 #if 0
 /* some code left lying around in case we need a
@@ -118,39 +126,37 @@
  */
 
 #define SAVE_ALL(psworg) \
-	st      %r15,__LC_SAVE_AREA   ; \
+	stm     %r13,%r15,__LC_SAVE_AREA ; \
+        stam    %a2,%a4,__LC_SAVE_AREA+12 ; \
+        basr    %r13,0                ; /* temp base pointer */ \
+        l       %r13,.Lentry_base-.(%r13) ; /* load &entry_base to %r13 */ \
         tm      psworg+1,0x01         ; /* test problem state bit */ \
-	jz	0f		      ; /* skip stack setup save */ \
+	bz	BASED(.+12)           ; /* skip stack setup save */ \
 	l	%r15,__LC_KERNEL_STACK ; /* problem state -> load ksp */ \
-0:	ahi     %r15,-SP_SIZE         ; /* make room for registers & psw */ \
-        srl     %r15,3                ; \
-        sll     %r15,3                ; /* align stack pointer to 8 */ \
-        stm     %r0,%r14,SP_R0(%r15)  ; /* store gprs 0-14 to kernel stack */ \
+        lam     %a2,%a4,BASED(.Lc_ac) ; /* set ac.reg. 2 to primary space */ \
+                                        /* and access reg. 4 to home space */ \
+0:	s       %r15,BASED(.Lc_spsize); /* make room for registers & psw */ \
+        n       %r15,BASED(.Lc0xfffffff8) ; /* align stack pointer to 8 */ \
+        stm     %r0,%r12,SP_R0(%r15)  ; /* store gprs 0-12 to kernel stack */ \
         st      %r2,SP_ORIG_R2(%r15)  ; /* store original content of gpr 2 */ \
-        mvc     SP_RF(4,%r15),__LC_SAVE_AREA   ; /* move R15 to stack */ \
+        mvc     SP_RD(12,%r15),__LC_SAVE_AREA  ; /* move R13-R15 to stack */ \
         stam    %a0,%a15,SP_AREGS(%r15) ; /* store access registers to kst. */ \
+        mvc     SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 ; /* store ac. regs */ \
         mvc     SP_PSW(8,%r15),psworg ; /* move user PSW to stack */ \
-        lhi     %r0,psworg            ; /* store trap indication */ \
+        la      %r0,psworg            ; /* store trap indication */ \
         st      %r0,SP_TRAP(%r15)     ; \
-        xc      0(4,%r15),0(%r15)     ; /* clear back chain */ \
-        tm      psworg+1,0x01         ; /* kmod.c .wishes the set_fs & gs */ \
-        jz      1f                    ; /* to work across syscalls */ \
-        slr     %r0,%r0               ; \
-        sar     %a2,%r0               ; /* set ac.reg. 2 to primary space */ \
-        lhi     %r0,1                 ; \
-        sar     %a4,%r0               ; /* set access reg. 4 to home space */ \
-1:
+        xc      0(4,%r15),0(%r15)     ; /* clear back chain */
 
 #define RESTORE_ALL \
-        mvc     __LC_RETURN_PSW(8,0),SP_PSW(%r15) ; /* move user PSW to lowcore */ \
-        lam     %a0,%a15,SP_AREGS(%r15)   ; /* load the access registers */ \
-        lm      %r0,%r15,SP_R0(%r15)      ; /* load gprs 0-15 of user */ \
-        ni      __LC_RETURN_PSW+1(0),0xfd ; /* clear wait state bit */ \
-        lpsw    __LC_RETURN_PSW             /* back to caller */
+        mvc     __LC_RETURN_PSW(8),SP_PSW(%r15) ; /* move user PSW to lowcore */ \
+        lam     %a0,%a15,SP_AREGS(%r15) ; /* load the access registers */ \
+        lm      %r0,%r15,SP_R0(%r15)    ; /* load gprs 0-15 of user */ \
+        ni      __LC_RETURN_PSW+1,0xfd  ; /* clear wait state bit */ \
+        lpsw    __LC_RETURN_PSW           /* back to caller */
 
 #define GET_CURRENT /* load pointer to task_struct to R9 */ \
-        lhi     %r9,-8192             ; \
-        nr      %r9,15
+        lr      %r9,%r15              ; \
+        n       %r9,BASED(.Lc0xffffe000)
 
 
 /*
@@ -162,22 +168,24 @@
  */
         .globl  resume
 resume:
+        basr    %r1,0
+resume_base:
         l       %r4,_TSS_PTREGS(%r3)
         tm      SP_PSW-SP_PTREGS(%r4),0x40 # is the new process using per ?
-        jz      RES_DN1                 # if not we're fine
-        stctl   %r9,%r11,24(%r15)       # We are using per stuff
+        bz      resume_noper-resume_base(%r1) # if not we're fine
+        stctl   %r9,%r11,24(%r15)             # We are using per stuff
         clc     _TSS_PER(12,%r3),24(%r15)
-        je      RES_DN1                 # we got away without bashing TLB's
-        lctl    %c9,%c11,_TSS_PER(%r3)  # Nope we didn't
-RES_DN1:
+        be      resume_noper-resume_base(%r1) # we got away w/o bashing TLB's
+        lctl    %c9,%c11,_TSS_PER(%r3)        # Nope we didn't
+resume_noper:
         stm     %r6,%r15,24(%r15)       # store resume registers of prev task
         st      %r15,_TSS_KSP(%r2) # store kernel stack ptr to prev->tss.ksp
-        lhi     %r0,-8192
-        nr      %r0,%r15
+        lr      %r0,%r15
+        n       %r0,.Lc0xffffe000-resume_base(%r1)
         l       %r15,_TSS_KSP(%r3) # load kernel stack ptr from next->tss.ksp
-        lhi     %r1,8191
+        l       %r1,.Lc8191-resume_base(%r1)
         or      %r1,%r15
-        ahi     %r1,1
+        la      %r1,1(%r1)
         st      %r1,__LC_KERNEL_STACK   # __LC_KERNEL_STACK = new kernel stack
         stam    %a2,%a2,_TSS_AR2(%r2)   # store kernel access reg. 2
         stam    %a4,%a4,_TSS_AR4(%r2)   # store kernel access reg. 4
@@ -192,38 +200,19 @@
  * are executed with interrupts enabled.
  */
 
-sysc_lit:
-  sysc_do_signal:     .long  do_signal
-  sysc_do_softirq:    .long  do_softirq
-  sysc_schedule:      .long  schedule
-  sysc_trace:         .long  syscall_trace
-#ifdef CONFIG_SMP
-  sysc_schedtail:     .long  schedule_tail
-#endif
-  sysc_clone:         .long  sys_clone
-  sysc_fork:          .long  sys_fork
-  sysc_vfork:         .long  sys_vfork
-  sysc_sigreturn:     .long  sys_sigreturn
-  sysc_rt_sigreturn:  .long  sys_rt_sigreturn
-  sysc_execve:        .long  sys_execve
-  sysc_sigsuspend:    .long  sys_sigsuspend
-  sysc_rt_sigsuspend: .long  sys_rt_sigsuspend
-
 	.globl  system_call
 system_call:
         SAVE_ALL(0x20)
-	XC      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
+	xc      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
 pgm_system_call:	
-        basr    %r13,0
-        ahi     %r13,sysc_lit-.   # setup base pointer R13 to sysc_lit
         slr     %r8,%r8           # gpr 8 is call save (-> tracesys)
         ic      %r8,0x8B          # get svc number from lowcore
         stosm   24(%r15),0x03     # reenable interrupts
         GET_CURRENT               # load pointer to task_struct to R9
         sll     %r8,2
-        l       %r8,sys_call_table-sysc_lit(8,%r13) # get address of system call
-        tm      flags+3(%r9),0x20 # PF_TRACESYS
-        jnz     sysc_tracesys
+        l       %r8,sys_call_table-entry_base(8,%r13) # get address of system call
+        tm      tsk_ptrace+3(%r9),0x02 # PT_TRACESYS
+        bnz     BASED(sysc_tracesys)
         basr    %r14,%r8          # call sys_xxxx
         st      %r2,SP_R2(%r15)   # store return value (change R2 on stack)
                                   # ATTENTION: check sys_execve_glue before
@@ -232,24 +221,24 @@
 sysc_return:
         GET_CURRENT               # load pointer to task_struct to R9
         tm      SP_PSW+1(%r15),0x01 # returning to user ?
-        jno     sysc_leave        # no-> skip bottom half, resched & signal
+        bno     BASED(sysc_leave) # no-> skip bottom half, resched & signal
 #
 # check, if bottom-half has to be done
 #
         l       %r0,__LC_IRQ_STAT     # get softirq_active
         n       %r0,__LC_IRQ_STAT+4   # and it with softirq_mask
-        jnz     sysc_handle_bottom_half
+        bnz     BASED(sysc_handle_bottom_half)
 #
 # check, if reschedule is needed
 #
 sysc_return_bh:	
         icm     %r0,15,need_resched(%r9) # get need_resched from task_struct
-        jnz     sysc_reschedule
+        bnz     BASED(sysc_reschedule)
         icm     %r0,15,sigpending(%r9)   # get sigpending from task_struct
-        jnz     sysc_signal_return
+        bnz     BASED(sysc_signal_return)
 sysc_leave:
 	icm     %r0,15,SP_SVC_STEP(%r15)   # get sigpending from task_struct
-        jnz     pgm_svcret
+        bnz     BASED(pgm_svcret)
 	stnsm   24(%r15),disable  # disable I/O and ext. interrupts
         RESTORE_ALL
 
@@ -259,24 +248,24 @@
 sysc_signal_return:     
         la      %r2,SP_PTREGS(%r15) # load pt_regs
         sr      %r3,%r3           # clear *oldset
-        l       %r1,sysc_do_signal-sysc_lit(%r13)
-	la      %r14,sysc_leave-sysc_lit(%r13)
+        l       %r1,BASED(.Ldo_signal)
+	la      %r14,BASED(sysc_leave)
         br      %r1               # return point is sysc_leave
 
 #
 # call trace before and after sys_call
 #
 sysc_tracesys:
-        l       %r1,sysc_trace-sysc_lit(%r13)
-	lhi     %r2,-ENOSYS
+        l       %r1,BASED(.Ltrace)
+	l       %r2,BASED(.Lc_ENOSYS)
 	st      %r2,SP_R2(%r15)   # give sysc_trace an -ENOSYS retval
         basr    %r14,%r1
 	lm      %r3,%r6,SP_R3(%r15)
 	l       %r2,SP_ORIG_R2(%r15)
         basr    %r14,%r8          # call sys_xxx
         st      %r2,SP_R2(%r15)   # store return value
-        l       %r1,sysc_trace-sysc_lit(%r13)
-	la      %r14,sysc_return-sysc_lit(%r13)
+        l       %r1,BASED(.Ltrace)
+	la      %r14,BASED(sysc_return)
         br      %r1               # return point is sysc_return
 
 
@@ -285,16 +274,16 @@
 # is zero
 #
 sysc_handle_bottom_half:        
-        l       %r1,sysc_do_softirq-sysc_lit(%r13)
-	la      %r14,sysc_return_bh-sysc_lit(%r13)
+        l       %r1,BASED(.Ldo_softirq)
+	la      %r14,BASED(sysc_return_bh)
         br      %r1               # call do_softirq
 
 #
 # call schedule with sysc_return as return-address
 #
 sysc_reschedule:        
-        l       %r1,sysc_schedule-sysc_lit(%r13)
-	la      %r14,sysc_return-sysc_lit(%r13)
+        l       %r1,BASED(.Lschedule)
+	la      %r14,BASED(sysc_return)
         br      %r1               # call scheduler, return to sysc_return
 
 #
@@ -303,17 +292,17 @@
         .globl  ret_from_fork
 ret_from_fork:  
         basr    %r13,0
-        ahi     %r13,sysc_lit-.   # setup base pointer R13 to $SYSCDAT
+        l       %r13,.Lentry_base-.(%r13)  # setup base pointer to &entry_base
         GET_CURRENT               # load pointer to task_struct to R9
         stosm   24(%r15),0x03     # reenable interrupts
         sr      %r0,%r0           # child returns 0
         st      %r0,SP_R2(%r15)   # store return value (change R2 on stack)
 #ifdef CONFIG_SMP
-        l       %r1,sysc_schedtail-sysc_lit(%r13)
-	la      %r14,sysc_return-sysc_lit(%r13)
+        l       %r1,BASED(.Lschedtail)
+	la      %r14,BASED(sysc_return)
         br      %r1               # call schedule_tail, return to sysc_return
 #else
-        j       sysc_return
+        b       BASED(sysc_return)
 #endif
 
 #
@@ -324,22 +313,22 @@
 #
 sys_clone_glue: 
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,sysc_clone-sysc_lit(%r13)
+        l       %r1,BASED(.Lclone)
         br      %r1                   # branch to sys_clone
 
 sys_fork_glue:  
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,sysc_fork-sysc_lit(%r13)
+        l       %r1,BASED(.Lfork)
         br      %r1                   # branch to sys_fork
 
 sys_vfork_glue: 
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,sysc_vfork-sysc_lit(%r13)
+        l       %r1,BASED(.Lvfork)
         br      %r1                   # branch to sys_vfork
 
 sys_execve_glue:        
         la      %r2,SP_PTREGS(%r15)   # load pt_regs
-        l       %r1,sysc_execve-sysc_lit(%r13)
+        l       %r1,BASED(.Lexecve)
 	lr      %r12,%r14             # save return address
         basr    %r14,%r1              # call sys_execve
         ltr     %r2,%r2               # check if execve failed
@@ -349,12 +338,12 @@
 
 sys_sigreturn_glue:     
         la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        l       %r1,sysc_sigreturn-sysc_lit(%r13)
+        l       %r1,BASED(.Lsigreturn)
         br      %r1                   # branch to sys_sigreturn
 
 sys_rt_sigreturn_glue:     
         la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        l       %r1,sysc_rt_sigreturn-sysc_lit(%r13)
+        l       %r1,BASED(.Lrt_sigreturn)
         br      %r1                   # branch to sys_sigreturn
 
 #
@@ -369,7 +358,7 @@
         lr      %r4,%r3               # move history1 parameter
         lr      %r3,%r2               # move history0 parameter
         la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-        l       %r1,sysc_sigsuspend-sysc_lit(%r13)
+        l       %r1,BASED(.Lsigsuspend)
 	la      %r14,4(%r14)          # skip store of return value
         br      %r1                   # branch to sys_sigsuspend
 
@@ -377,10 +366,15 @@
         lr      %r4,%r3               # move sigsetsize parameter
         lr      %r3,%r2               # move unewset parameter
         la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-        l       %r1,sysc_rt_sigsuspend-sysc_lit(%r13)
+        l       %r1,BASED(.Lrt_sigsuspend)
 	la      %r14,4(%r14)          # skip store of return value
         br      %r1                   # branch to sys_rt_sigsuspend
 
+sys_sigaltstack_glue:
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
+        l       %r1,BASED(.Lsigaltstack)
+        br      %r1                   # branch to sys_sigreturn
+
 	.globl  sys_call_table	
 sys_call_table:
         .long  sys_ni_syscall            /* 0 */
@@ -459,7 +453,7 @@
         .long  sys_sigpending
         .long  sys_sethostname
         .long  sys_setrlimit            /* 75 */
-        .long  sys_getrlimit
+        .long  sys_old_getrlimit
         .long  sys_getrusage
         .long  sys_gettimeofday
         .long  sys_settimeofday
@@ -569,13 +563,13 @@
         .long  sys_getcwd
         .long  sys_capget
         .long  sys_capset                /* 185 */
-        .long  sys_sigaltstack
+        .long  sys_sigaltstack_glue
         .long  sys_sendfile
         .long  sys_ni_syscall            /* streams1 */
         .long  sys_ni_syscall            /* streams2 */
         .long  sys_vfork_glue            /* 190 */
         .long  sys_getrlimit
-	.long  sys_ni_syscall  /* FIXME: problem with sys_mmap2: 6 parms */
+	.long  sys_mmap2
         .long  sys_truncate64
         .long  sys_ftruncate64
         .long  sys_stat64                /* 195 */
@@ -604,7 +598,8 @@
         .long  sys_mincore
         .long  sys_madvise
 	.long  sys_getdents64		 /* 220 */
-	.rept  255-220
+        .long  sys_fcntl64 
+	.rept  255-221
 	.long  sys_ni_syscall
 	.endr
 
@@ -612,13 +607,6 @@
  * Program check handler routine
  */
 
-pgm_lit:
-  pgm_handle_per:  .long  handle_per_exception
-  pgm_jump_table:  .long  pgm_check_table
-  pgm_sysc_ret:    .long  sysc_return
-  pgm_sysc_lit:    .long  sysc_lit
-  pgm_do_signal:   .long  do_signal
-
         .globl  pgm_check_handler
 pgm_check_handler:
 /*
@@ -634,110 +622,131 @@
  * we just ignore the PER event (FIXME: is there anything we have to do
  * for LPSW?).
  */
+	stm     %r13,%r15,__LC_SAVE_AREA
+	stam    %a2,%a4,__LC_SAVE_AREA+12
+	basr    %r13,0                   # temp base pointer
+	l       %r13,.Lentry_base-.(%r13)# load &entry_base to %r13
         tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
-        jz      pgm_sv                   # skip if not
+        bz      BASED(pgm_sv)            # skip if not
         tm      __LC_PGM_OLD_PSW,0x40    # test if per event recording is on
-        jnz     pgm_sv                   # skip if it is
+        bnz     BASED(pgm_sv)            # skip if it is
 # ok its one of the special cases, now we need to find out which one
         clc     __LC_PGM_OLD_PSW(8),__LC_SVC_NEW_PSW
-        je      pgm_svcper
+        be      BASED(pgm_svcper)
 # no interesting special case, ignore PER event
-        lpsw    0x28
+        lm      %r13,%r15,__LC_SAVE_AREA
+	lpsw    0x28
 # it was a single stepped SVC that is causing all the trouble
 pgm_svcper:
-        SAVE_ALL(0x20)
+        tm      0x21,0x01                # test problem state bit
+	bz	BASED(.+12)              # skip stack & access regs setup
+	l	%r15,__LC_KERNEL_STACK   # problem state -> load ksp
+	lam     %a2,%a4,BASED(.Lc_ac)    # set ac.reg. 2 to primary space
+                                         # and access reg. 4 to home space
+	s       %r15,BASED(.Lc_spsize)   # make room for registers & psw
+        n       %r15,BASED(.Lc0xfffffff8) # align stack pointer to 8
+        stm     %r0,%r12,SP_R0(%r15)     # store gprs 0-12 to kernel stack
+        st      %r2,SP_ORIG_R2(%r15)     # store original content of gpr 2
+        mvc     SP_RD(12,%r15),__LC_SAVE_AREA # move R13-R15 to stack
+        stam    %a0,%a15,SP_AREGS(%r15)  # store access registers to kst.
+	mvc     SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 # store ac. regs
+        mvc     SP_PSW(8,%r15),0x20      # move user PSW to stack
+        la      %r0,0x20                 # store trap indication
+        st      %r0,SP_TRAP(%r15)
+        xc      0(4,%r15),0(%r15)        # clear back chain
         mvi     SP_SVC_STEP(%r15),1 # make SP_SVC_STEP nonzero
         mvc     SP_PGM_OLD_ILC(4,%r15),__LC_PGM_ILC # save program check information
-        j       pgm_system_call              # now do the svc
+        b       BASED(pgm_system_call)   # now do the svc
 pgm_svcret:
-        lh      %r7,SP_PGM_OLD_ILC(%r15)     # get ilc from stack
-        lhi     %r0,0x28
-        st      %r0,SP_TRAP(%r15) # set new trap indicator
+        mvi     SP_TRAP+3(%r15),0x28     # set trap indication back to pgm_chk
+        lh      %r7,SP_PGM_OLD_ILC(%r15) # get ilc from stack
         xc      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
-        basr    %r13,0
-        ahi     %r13,pgm_lit-.    # setup base pointer
-        j       pgm_no_sv
+	b       BASED(pgm_no_sv)
 pgm_sv:
-        SAVE_ALL(0x28)
-        XC      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
-        basr    %r13,0
-        ahi     %r13,pgm_lit-.    # setup base pointer R13 to $PGMDAT
+        tm      0x29,0x01                # test problem state bit
+	bz	BASED(.+12)              # skip stack & access regs setup
+	l	%r15,__LC_KERNEL_STACK   # problem state -> load ksp
+	lam     %a2,%a4,BASED(.Lc_ac)    # set ac.reg. 2 to primary space
+                                         # and access reg. 4 to home space
+	s       %r15,BASED(.Lc_spsize)   # make room for registers & psw
+        n       %r15,BASED(.Lc0xfffffff8) # align stack pointer to 8
+        stm     %r0,%r12,SP_R0(%r15)     # store gprs 0-12 to kernel stack
+        st      %r2,SP_ORIG_R2(%r15)     # store original content of gpr 2
+        mvc     SP_RD(12,%r15),__LC_SAVE_AREA # move R13-R15 to stack
+        stam    %a0,%a15,SP_AREGS(%r15)  # store access registers to kst.
+	mvc     SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 # store ac. regs
+        mvc     SP_PSW(8,%r15),0x28      # move user PSW to stack
+        la      %r0,0x28                 # store trap indication
+        st      %r0,SP_TRAP(%r15)
+        xc      0(4,%r15),0(%r15)        # clear back chain
+        xc      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
         lh      %r7,__LC_PGM_ILC  # load instruction length
 pgm_no_sv:
         lh      %r8,__LC_PGM_INT_CODE  # N.B. saved int code used later KEEP it
         stosm   24(%r15),0x03     # reenable interrupts
         lr      %r3,%r8
-        lhi     %r0,0x7f
+        la      %r0,0x7f
         nr      %r3,%r0           # clear per-event-bit
-        je      pgm_dn            # none of Martins exceptions occured bypass
-        l       %r9,pgm_jump_table-pgm_lit(%r13)
+        be      BASED(pgm_dn)     # none of Martins exceptions occured bypass
+        l       %r9,BASED(.Ljump_table)
         sll     %r3,2
         l       %r9,0(%r3,%r9)    # load address of handler routine
         la      %r2,SP_PTREGS(%r15) # address of register-save area
         srl     %r3,2
-        chi     %r3,0x4           # protection-exception ?
-        jne     pgm_go            # if not,
+        cl      %r3,BASED(.Lc4)   # protection-exception ?
+        bne     BASED(pgm_go)     # if not,
         l       %r5,SP_PSW+4(15)  # load psw addr
         sr      %r5,%r7           # substract ilc from psw
         st      %r5,SP_PSW+4(15)  # store corrected psw addr
 pgm_go: basr    %r14,%r9          # branch to interrupt-handler
-pgm_dn: lhi     %r0,0x80
+pgm_dn: la      %r0,0x80
         nr      %r8,%r0           # check for per exception
-        je      pgm_return
+        be      BASED(pgm_return)
         la      %r2,SP_PTREGS(15) # address of register-save area
-        l       %r9,pgm_handle_per-pgm_lit(%r13) # load adr. of per handler
-        l       %r14,pgm_sysc_ret-pgm_lit(%r13)  # load adr. of system return
-        l       %r13,pgm_sysc_lit-pgm_lit(%r13)
+        l       %r9,BASED(.Lhandle_per) # load adr. of per handler
+        la      %r14,BASED(sysc_return) # load adr. of system return
         br      %r9               # branch to handle_per_exception
+
 #
 # the backend code is the same as for sys-call
 #
 pgm_return:
-        l       %r14,pgm_sysc_ret-pgm_lit(%r13)
-        l       %r13,pgm_sysc_lit-pgm_lit(%r13)
-        br      %r14
+        b       BASED(sysc_return)
 
 /*
  * IO interrupt handler routine
  */
 
-io_lit:
-  io_do_IRQ:        .long do_IRQ
-  io_schedule:	    .long schedule
-  io_do_signal:     .long do_signal
-  io_do_softirq:    .long  do_softirq
-
         .globl io_int_handler
 io_int_handler:
         SAVE_ALL(0x38)
-        basr    %r13,0
-        ahi     %r13,io_lit-.     # setup base pointer R13 to $IODAT
         la      %r2,SP_PTREGS(%r15) # address of register-save area
         sr      %r3,%r3
         icm     %r3,%r3,__LC_SUBCHANNEL_NR # load subchannel nr & extend to int
-        l       %r4,__LC_IO_INT_PARM       # load interuption parm
-        l       %r9,io_do_IRQ-io_lit(%r13) # load address of do_IRQ
+        l       %r4,__LC_IO_INT_PARM       # load interruption parm
+	l       %r5,__LC_IO_INT_WORD       # load interruption word
+        l       %r9,BASED(.Ldo_IRQ)        # load address of do_IRQ
         basr    %r14,%r9          # branch to standard irq handler
 
 io_return:
         GET_CURRENT               # load pointer to task_struct to R9
         tm      SP_PSW+1(%r15),0x01 # returning to user ?
-        jz      io_leave          # no-> skip resched & signal
+        bz      BASED(io_leave)   # no-> skip resched & signal
         stosm   24(%r15),0x03     # reenable interrupts
 #
 # check, if bottom-half has to be done
 #
         l       %r0,__LC_IRQ_STAT     # get softirq_active
         n       %r0,__LC_IRQ_STAT+4   # and it with softirq_mask
-        jnz     io_handle_bottom_half
+        bnz     BASED(io_handle_bottom_half)
 io_return_bh:	
 #
 # check, if reschedule is needed
 #
         icm     %r0,15,need_resched(%r9) # get need_resched from task_struct
-        jnz     io_reschedule
+        bnz     BASED(io_reschedule)
         icm     %r0,15,sigpending(%r9)   # get sigpending from task_struct
-        jnz     io_signal_return
+        bnz     BASED(io_signal_return)
 io_leave:
         stnsm   24(%r15),disable  # disable I/O and ext. interrupts
         RESTORE_ALL
@@ -747,16 +756,16 @@
 # is zero
 #
 io_handle_bottom_half:        
-        l       %r1,io_do_softirq-io_lit(%r13)
-	la      %r14,io_return_bh-io_lit(%r13)
+        l       %r1,BASED(.Ldo_softirq)
+	la      %r14,BASED(io_return_bh)
         br      %r1               # call do_softirq
 
 #
 # call schedule with io_return as return-address
 #
 io_reschedule:        
-        l       %r1,io_schedule-io_lit(%r13)
-	la      %r14,io_return-io_lit(%r13)
+        l       %r1,BASED(.Lschedule)
+	la      %r14,BASED(io_return)
         br      %r1               # call scheduler, return to io_return
 
 #
@@ -765,103 +774,46 @@
 io_signal_return:     
         la      %r2,SP_PTREGS(%r15) # load pt_regs
         sr      %r3,%r3           # clear *oldset
-        l       %r1,io_do_signal-io_lit(%r13)
-	la      %r14,io_leave-io_lit(%r13)
+        l       %r1,BASED(.Ldo_signal)
+	la      %r14,BASED(io_leave)
         br      %r1               # return point is io_leave
 
 /*
  * External interrupt handler routine
  */
 
-ext_lit:
-  ext_timer_int:     .long  do_timer_interrupt
-#ifdef CONFIG_SMP
-  ext_call_int:      .long  do_ext_call_interrupt
-#endif
-#ifdef CONFIG_HWC
-  ext_hwc_int:      .long  do_hwc_interrupt
-#endif
-#ifdef CONFIG_MDISK
-  ext_mdisk_int:     .long  do_mdisk_interrupt
-#endif
-#ifdef CONFIG_IUCV
-  ext_iucv_int:      .long  do_iucv_interrupt
-#endif
-  ext_io_lit:	     .long  io_lit
-  ext_io_return:     .long  io_return
-
         .globl  ext_int_handler
 ext_int_handler:
         SAVE_ALL(0x18)
-        basr    %r13,0
-        ahi     %r13,ext_lit-.    # setup base pointer R13 to $EXTDAT
         la      %r2,SP_PTREGS(%r15)    # address of register-save area
         lh      %r3,__LC_EXT_INT_CODE  # error code
-#ifdef CONFIG_SMP
-	chi     %r3,0x1202        # EXTERNAL_CALL
-	jne     ext_no_extcall
-	l       %r9,ext_call_int-ext_lit(%r13) # load ext_call_interrupt
-	l       %r14,ext_io_return-ext_lit(%r13)
-        l       %r13,ext_io_lit-ext_lit(%r13)
-	br      %r9               # branch to ext call handler
-ext_no_extcall:
-#endif
-        chi     %r3,0x1004        # CPU_TIMER
-        jne     ext_no_timer
-        l       %r9,ext_timer_int-ext_lit(%r13) # load timer_interrupt
-	l       %r14,ext_io_return-ext_lit(%r13)
-        l       %r13,ext_io_lit-ext_lit(%r13)
-	br      %r9               # branch to ext call handler
-ext_no_timer:   
-#ifdef CONFIG_HWC
-        chi     %r3,0x2401        # HWC interrupt
-        jne     ext_no_hwc
-        l       %r9,ext_hwc_int-ext_lit(%r13) # load addr. of hwc routine
-	l       %r14,ext_io_return-ext_lit(%r13)
-        l       %r13,ext_io_lit-ext_lit(%r13)
-	br      %r9               # branch to ext call handler
-ext_no_hwc:    
-#endif
-#ifdef CONFIG_MDISK
-        chi     %r3,0x2603        # diag 250 (VM) interrupt
-        jne     ext_no_mdisk
-        l       %r9,ext_mdisk_int-ext_lit(%r13)
-	l       %r14,ext_io_return-ext_lit(%r13)
-        l       %r13,ext_io_lit-ext_lit(%r13)
-	br      %r9               # branch to ext call handler
-ext_no_mdisk:   
-#endif
-#ifdef CONFIG_IUCV
-        chi     %r3,0x4000        # diag 250 (VM) interrupt
-        jne     ext_no_iucv
-        l       %r9,ext_iucv_int-ext_lit(%r13)
-	l       %r14,ext_io_return-ext_lit(%r13)
-        l       %r13,ext_io_lit-ext_lit(%r13)
-	br      %r9               # branch to ext call handler
-ext_no_iucv:    
-#endif
-
-	l       %r14,ext_io_return-ext_lit(%r13)
-        l       %r13,ext_io_lit-ext_lit(%r13)
-	br      %r14              # use backend code of io_int_handler
+        lr      %r1,%r3                # calculate index = code & 0xff
+        n       %r1,BASED(.Lc0xff)
+        sll     %r1,2
+        l       %r9,BASED(.Lext_hash)
+        l       %r9,0(%r1,%r9)         # get first list entry for hash value
+        ltr     %r9,%r9                # == NULL ?
+        bz      BASED(io_return)       # yes, nothing to do, exit
+ext_int_loop:
+        ch      %r3,8(%r9)             # compare external interrupt code
+        be      BASED(ext_int_found)
+        icm     %r9,15,0(%r9)          # next list entry
+        bnz     BASED(ext_int_loop)
+        b       BASED(io_return)
+ext_int_found:
+        l       %r9,4(%r9)             # get handler address
+        la      %r14,BASED(io_return)
+        br      %r9                    # branch to ext call handler
 
 /*
  * Machine check handler routines
  */
-mcck_lit:
-  mcck_crw_pending: .long  do_crw_pending
-
 
         .globl mcck_int_handler
 mcck_int_handler:
         SAVE_ALL(0x30)
-        basr    %r13,0
-        ahi     %r13,mcck_lit-.   # setup base pointer R13 to $MCCKDAT
-	tm      __LC_MCCK_CODE+1,0x40
-	jno     mcck_no_crw
-	l       %r1,mcck_crw_pending-mcck_lit(%r13)
-	basr    %r14,%r1	  # call do_crw_pending
-mcck_no_crw:
+	l       %r1,BASED(.Ls390_mcck)
+	basr    %r14,%r1	  # call machine check handler
 mcck_return:
         RESTORE_ALL
 
@@ -876,11 +828,11 @@
         lam     %a0,%a15,__LC_AREGS_SAVE_AREA
         stosm   0(%r15),daton          # now we can turn dat on
         lm      %r6,%r15,24(%r15)      # load registers from clone
-        bras    %r14,restart_go
-        .long   start_secondary
-restart_go:
-        l       %r14,0(%r14)
+        basr    %r14,0
+        l       %r14,restart_addr-.(%r14)
         br      %r14                   # branch to start_secondary
+restart_addr:
+        .long   start_secondary
 #else
 /*
  * If we do not run with SMP enabled, let the new CPU crash ...
@@ -894,5 +846,50 @@
 restart_crash:
         .long  0x000a0000,0x00000000
 restart_go:
+#endif
+
+/*
+ * Integer constants
+ */
+               .align 4
+.Lc0xfffffff8: .long  -8           # to align stack pointer to 8
+.Lc0xffffe000: .long  -8192        # to round stack pointer to &task_struct
+.Lc8191:       .long  8191
+.Lc_spsize:    .long  SP_SIZE
+.Lc_ac:        .long  0,0,1
+.Lc_ENOSYS:    .long  -ENOSYS
+.Lc4:          .long  4
+.Lc0x1202:     .long  0x1202
+.Lc0x1004:     .long  0x1004
+.Lc0x2401:     .long  0x2401
+.Lc0x4000:     .long  0x4000
+.Lc0xff:       .long  0xff
+
+/*
+ * Symbol constants
+ */
+.Ls390_mcck:   .long  s390_do_machine_check
+.Ldo_IRQ:      .long  do_IRQ
+.Ldo_signal:   .long  do_signal
+.Ldo_softirq:  .long  do_softirq
+.Lentry_base:  .long  entry_base
+.Lext_hash:    .long  ext_int_hash
+.Lhandle_per:  .long  handle_per_exception
+.Ljump_table:  .long  pgm_check_table
+.Lschedule:    .long  schedule
+.Lclone:       .long  sys_clone
+.Lexecve:      .long  sys_execve
+.Lfork:        .long  sys_fork
+.Lrt_sigreturn:.long  sys_rt_sigreturn
+.Lrt_sigsuspend:
+               .long  sys_rt_sigsuspend
+.Lsigreturn:   .long  sys_sigreturn
+.Lsigsuspend:  .long  sys_sigsuspend
+.Lsigaltstack: .long  sys_sigaltstack
+.Ltrace:       .long  syscall_trace
+.Lvfork:       .long  sys_vfork
+
+#ifdef CONFIG_SMP
+.Lschedtail:   .long  schedule_tail
 #endif
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)