patch-2.2.16 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 -urN v2.2.15/linux/arch/s390/kernel/entry.S linux/arch/s390/kernel/entry.S
@@ -89,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,59 +125,38 @@
  *    R15 - kernel stack pointer
  */
 
-#define SAVE_ALL1(psworg) \
-	st      %r15,__LC_SAVE_AREA   ; \
+#define SAVE_ALL(psworg) \
+	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 & access regs setup */ \
 	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 */ \
-        xc      0(7,%r15),0(%r15)     ; /* clear back chain & trap ind. */ \
-        mvi     SP_TRAP+3(%r15),psworg ; /* store trap indication in pt_regs */ \
-        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 */
+        la      %r0,psworg            ; /* store trap indication */ \
+        st      %r0,SP_TRAP(%r15)     ; \
+        xc      0(4,%r15),0(%r15)     ; /* clear back chain */
 
-#define RESTORE_ALL1 \
-        mvc     0x50(8,0),SP_PSW(%r15)  ; /* move user PSW to lowcore */ \
+#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      0x51(0),0xfd          ; /* clear wait state bit */ \
-        lpsw    0x50                    /* back to caller */
-
-#if CONFIG_REMOTE_DEBUG
-#define SAVE_ALL(psworg) \
-	SAVE_ALL1(psworg) \
-	tm      psworg+1,0x01         ; /* test problem state bit */ \
-	jz	0f		      ; /* skip stack setup save */ \
-	stctl    %c0,%c15,SP_CRREGS(%r15) ; /* save control regs for remote debugging */ \
-0:
-
-#define RESTORE_ALL  \
-	tm      SP_PSW+1(%r15),0x01          ; /* test problem state bit */ \
-	jz	0f		             ; /* skip cr restore */ \
-	lctl    %c0,%c15,SP_CRREGS(%r15) ; /* store control regs for remote debugging */ \
-0:	RESTORE_ALL1 
-#else
-	
-#define SAVE_ALL(psworg)  \
-	SAVE_ALL1(psworg)
-
-#define RESTORE_ALL  \
-	RESTORE_ALL1 
-#endif
+        ni      __LC_RETURN_PSW+1(0),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)
 
 /*
  * Scheduler resume function, called by switch_to
@@ -181,22 +167,24 @@
  */
         .globl  resume
 resume:
+	basr    %r1,0                   # setup base pointer
+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
+        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
+        be      resume_noper-resume_base(%r1) # we got away w/o bashing TLB's
         lctl    %c9,%c11,_TSS_PER(%r3)  # Nope we didn't
-RES_DN1:
+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
@@ -213,40 +201,19 @@
  * are executed with interrupts enabled.
  */
 
-sysc_lit:
-  sysc_bhmask:        .long  bh_mask
-  sysc_bhactive:      .long  bh_active
-  sysc_do_signal:     .long  do_signal
-  sysc_do_bottom_half:.long  do_bottom_half
-  sysc_schedule:      .long  schedule
-  sysc_trace:         .long  syscall_trace
-#ifdef __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
+        l       %r8,sys_call_table-entry_base(8,%r13) # get address of system call
         tm      flags+3(%r9),0x20 # PF_TRACESYS
-        jnz     sysc_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
@@ -255,26 +222,26 @@
 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       %r1,sysc_bhmask-sysc_lit(%r13)
+        l       %r1,BASED(.Lbhmask)
         l       %r0,0(%r1)
-        l       %r1,sysc_bhactive-sysc_lit(%r13)
+        l       %r1,BASED(.Lbhactive)
         n       %r0,0(%r1)
-        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
 
@@ -284,24 +251,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
 
 
@@ -310,16 +277,16 @@
 # is zero
 #
 sysc_handle_bottom_half:        
-        l       %r1,sysc_do_bottom_half-sysc_lit(%r13)
-	la      %r14,sysc_return_bh-sysc_lit(%r13)
+        l       %r1,BASED(.Ldo_bottom_half)
+	la      %r14,BASED(sysc_return_bh)
         br      %r1               # call do_bottom_half
 
 #
 # 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
 
 #
@@ -328,17 +295,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 __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
 
 #
@@ -349,22 +316,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
@@ -374,12 +341,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
 
 #
@@ -394,7 +361,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
 
@@ -402,7 +369,7 @@
         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
 
@@ -415,7 +382,7 @@
         .long  sys_write
         .long  sys_open                  /* 5 */
         .long  sys_close
-        .long  sys_waitpid
+        .long  sys_ni_syscall           /* old waitpid syscall holder */
         .long  sys_creat
         .long  sys_link
         .long  sys_unlink                /* 10 */
@@ -426,7 +393,7 @@
         .long  sys_chmod                /* 15 */
         .long  sys_lchown
         .long  sys_ni_syscall           /* old break syscall holder */
-        .long  sys_stat
+        .long  sys_ni_syscall           /* old stat syscall holder */
         .long  sys_lseek
         .long  sys_getpid               /* 20 */
         .long  sys_mount
@@ -436,7 +403,7 @@
         .long  sys_stime                /* 25 */
         .long  sys_ptrace
         .long  sys_alarm
-        .long  sys_fstat
+        .long  sys_ni_syscall           /* old fstat syscall holder */
         .long  sys_pause
         .long  sys_utime                /* 30 */
         .long  sys_ni_syscall           /* old stty syscall holder */
@@ -467,7 +434,7 @@
         .long  sys_ni_syscall           /* old mpx syscall holder */
         .long  sys_setpgid
         .long  sys_ni_syscall           /* old ulimit syscall holder */
-        .long  sys_olduname
+        .long  sys_ni_syscall           /* old uname syscall holder */
         .long  sys_umask                /* 60 */
         .long  sys_chroot
         .long  sys_ustat
@@ -476,8 +443,8 @@
         .long  sys_getpgrp              /* 65 */
         .long  sys_setsid
         .long  sys_sigaction
-        .long  sys_sgetmask
-        .long  sys_ssetmask
+        .long  sys_ni_syscall           /* old sgetmask syscall holder */
+        .long  sys_ni_syscall           /* old ssetmask syscall holder */
         .long  sys_setreuid             /* 70 */
         .long  sys_setregid
         .long  sys_sigsuspend_glue
@@ -490,9 +457,9 @@
         .long  sys_settimeofday
         .long  sys_getgroups            /* 80 */
         .long  sys_setgroups
-        .long  old_select
+        .long  sys_ni_syscall           /* old select syscall holder */
         .long  sys_symlink
-        .long  sys_lstat
+        .long  sys_ni_syscall           /* old lstat syscall holder */
         .long  sys_readlink             /* 85 */
         .long  sys_uselib
         .long  sys_swapon
@@ -517,7 +484,7 @@
         .long  sys_newstat
         .long  sys_newlstat
         .long  sys_newfstat
-        .long  sys_uname
+        .long  sys_ni_syscall            /* old uname syscall holder */
         .long  sys_ni_syscall            /* 110 */ /* iopl for i386 */
         .long  sys_vhangup
         .long  sys_idle
@@ -599,22 +566,14 @@
         .long  sys_ni_syscall            /* streams1 */
         .long  sys_ni_syscall            /* streams2 */
         .long  sys_vfork_glue            /* 190 */
-	.rept  254-190
+	.rept  255-190
         .long  sys_ni_syscall
 	.endr
-        .long  sys_msgcp         /* 255 */
 
 /*
  * 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:
 /*
@@ -630,115 +589,132 @@
  * 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
+        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:
-        mvc     __LC_PGM_ILC(4),SP_PGM_OLD_ILC(%r15)  # restore program check info
-	lhi     %r0,0x28
-	st      %r0,SP_TRAP(%r15) # set new trap indicator
-	j       pgm_no_sv	 
+        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)
+	b       BASED(pgm_no_sv)
 pgm_sv:
-        SAVE_ALL(0x28)
-pgm_no_sv:
-	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
-
-default_trap_handler:
-        .globl  default_trap_handler
-        lpsw    112
+        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_bhmask:        .long  bh_mask
-  io_bhactive:      .long  bh_active
-  io_do_bottom_half:.long  do_bottom_half
-
         .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       %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       %r1,io_bhmask-io_lit(%r13)
+        l       %r1,BASED(.Lbhmask)
         l       %r0,0(%r1)
-        l       %r1,io_bhactive-io_lit(%r13)
+        l       %r1,BASED(.Lbhactive)
         n       %r0,0(%r1)
-        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
@@ -748,16 +724,16 @@
 # is zero
 #
 io_handle_bottom_half:        
-        l       %r1,io_do_bottom_half-io_lit(%r13)
-	la      %r14,io_return_bh-io_lit(%r13)
+        l       %r1,BASED(.Ldo_bottom_half)
+	la      %r14,BASED(io_return_bh)
         br      %r1               # call do_bottom_half
 
 #
 # 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
 
 #
@@ -766,103 +742,48 @@
 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 __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 __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)
+        lr      %r1,%r3                # calculate index
+        srl     %r1,8                  #  = (code + (code >> 8)) & 0xff
+        alr     %r1,%r3
+        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
-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
 
 /*
  * 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
 
@@ -877,11 +798,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 ...
@@ -898,8 +819,49 @@
 #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
+ */
+.Lbhactive:    .long  bh_active
+.Lbhmask:      .long  bh_mask
+.Ls390_mcck:   .long  s390_do_machine_check
+.Ldo_IRQ:      .long  do_IRQ
+.Ldo_bottom_half:
+	       .long  do_bottom_half
+.Ldo_signal:   .long  do_signal
+.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
+.Ltrace:       .long  syscall_trace
+.Lvfork:       .long  sys_vfork
 
-
-
-
+#ifdef __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)