entry.S
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:33k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  arch/s390/kernel/entry.S
  3.  *    S390 low-level entry points.
  4.  *
  5.  *  S390 version
  6.  *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  7.  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  8.  *               Hartmut Penner (hp@de.ibm.com),
  9.  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  10.  */
  11. #include <linux/sys.h>
  12. #include <linux/linkage.h>
  13. #include <linux/config.h>
  14. #include <asm/cache.h>
  15. #include <asm/lowcore.h>
  16. #include <asm/errno.h>
  17. #include <asm/smp.h>
  18. #include <asm/ptrace.h>
  19. /*
  20.  * Stack layout for the system_call stack entry.
  21.  * The first few entries are identical to the user_regs_struct.
  22.  */
  23. SP_PTREGS    =  STACK_FRAME_OVERHEAD 
  24. SP_PSW       =  STACK_FRAME_OVERHEAD + PT_PSWMASK
  25. SP_R0        =  STACK_FRAME_OVERHEAD + PT_GPR0
  26. SP_R1        =  STACK_FRAME_OVERHEAD + PT_GPR1
  27. SP_R2        =  STACK_FRAME_OVERHEAD + PT_GPR2
  28. SP_R3        =  STACK_FRAME_OVERHEAD + PT_GPR3
  29. SP_R4        =  STACK_FRAME_OVERHEAD + PT_GPR4
  30. SP_R5        =  STACK_FRAME_OVERHEAD + PT_GPR5
  31. SP_R6        =  STACK_FRAME_OVERHEAD + PT_GPR6
  32. SP_R7        =  STACK_FRAME_OVERHEAD + PT_GPR7
  33. SP_R8        =  STACK_FRAME_OVERHEAD + PT_GPR8
  34. SP_R9        =  STACK_FRAME_OVERHEAD + PT_GPR9
  35. SP_R10       =  STACK_FRAME_OVERHEAD + PT_GPR10
  36. SP_R11       =  STACK_FRAME_OVERHEAD + PT_GPR11
  37. SP_R12       =  STACK_FRAME_OVERHEAD + PT_GPR12
  38. SP_R13       =  STACK_FRAME_OVERHEAD + PT_GPR13
  39. SP_R14       =  STACK_FRAME_OVERHEAD + PT_GPR14
  40. SP_R15       =  STACK_FRAME_OVERHEAD + PT_GPR15
  41. SP_AREGS     =  STACK_FRAME_OVERHEAD + PT_ACR0
  42. SP_ORIG_R2   =  STACK_FRAME_OVERHEAD + PT_ORIGGPR2
  43. /* Now the additional entries */
  44. SP_TRAP      =  (SP_ORIG_R2+GPR_SIZE)
  45. #if CONFIG_REMOTE_DEBUG
  46. SP_CRREGS    =  (SP_TRAP+4)
  47. /* fpu registers are saved & restored by the gdb stub itself */
  48. SP_FPC       =  (SP_CRREGS+(NUM_CRS*CR_SIZE))
  49. SP_FPRS      =  (SP_FPC+FPC_SIZE+FPC_PAD_SIZE)
  50. SP_PGM_OLD_ILC= (SP_FPRS+(NUM_FPRS*FPR_SIZE))
  51. #else
  52. SP_PGM_OLD_ILC= (SP_TRAP+4)
  53. #endif
  54. SP_SIZE      =  (SP_PGM_OLD_ILC+4)
  55. /*
  56.  * these defines are offsets into the thread_struct
  57.  */
  58. _TSS_PTREGS  = 0
  59. _TSS_FPRS    = (_TSS_PTREGS+8)
  60. _TSS_AR2     = (_TSS_FPRS+136)
  61. _TSS_AR4     = (_TSS_AR2+4)
  62. _TSS_KSP     = (_TSS_AR4+4)
  63. _TSS_USERSEG = (_TSS_KSP+4)
  64. _TSS_ERROR   = (_TSS_USERSEG+4)
  65. _TSS_PROT    = (_TSS_ERROR+4)
  66. _TSS_TRAP    = (_TSS_PROT+4)
  67. _TSS_MM      = (_TSS_TRAP+4)
  68. _TSS_PER     = (_TSS_MM+8)
  69. _TSS_IEEE    = (_TSS_PER+36)
  70. _TSS_FLAGS   = (_TSS_IEEE+4)
  71. /*
  72.  * these are offsets into the task-struct.
  73.  */
  74. state        =  0
  75. flags        =  4
  76. sigpending   =  8
  77. need_resched = 24
  78. tsk_ptrace   = 28
  79. processor    = 52
  80. /*
  81.  * Base Address of this Module --- saved in __LC_ENTRY_BASE
  82.  */
  83.        .globl entry_base
  84. entry_base:
  85. #define BASED(name) name-entry_base(%r13)
  86. /*
  87.  * Register usage in interrupt handlers:
  88.  *    R9  - pointer to current task structure
  89.  *    R13 - pointer to literal pool
  90.  *    R14 - return register for function calls
  91.  *    R15 - kernel stack pointer
  92.  */
  93.         .macro  SAVE_ALL psworg,sync      # system entry macro
  94.         stm     %r13,%r15,__LC_SAVE_AREA
  95.         basr    %r13,0                    #  temp base pointer
  96.         l       %r13,.Lentry_base-.(%r13) # load &entry_base to %r13 
  97.         tm      psworg+1,0x01            # test problem state bit
  98.         stam    %a2,%a4,__LC_SAVE_AREA+12
  99. .if sync
  100.         bz      BASED(1f)                 # skip stack setup save
  101. .else
  102.         bnz     BASED(0f)                 # from user -> load kernel stack
  103. l %r14,__LC_ASYNC_STACK   # are we already on the async stack ?
  104. slr     %r14,%r15
  105. sra %r14,13
  106. be BASED(1f)
  107.         l       %r15,__LC_ASYNC_STACK     # load async. stack
  108. b BASED(1f)
  109. .endif
  110. 0:      l       %r15,__LC_KERNEL_STACK    # problem state -> load ksp
  111. lam %a2,%a4,BASED(.Lc_ac)   # set ac.reg. 2 to primary space
  112.   # and ac.reg. 4 to home space
  113. 1:      s       %r15,BASED(.Lc_spsize)    # make room for registers & psw
  114.         n       %r15,BASED(.Lc0xfffffff8) # align stack pointer to 8
  115.         stm     %r0,%r12,SP_R0(%r15)      # store gprs 0-12 to kernel stack
  116.         st      %r2,SP_ORIG_R2(%r15)      # store original content of gpr 2
  117.         mvc     SP_R13(12,%r15),__LC_SAVE_AREA  # move R13-R15 to stack
  118.         stam    %a0,%a15,SP_AREGS(%r15)   # store access registers to kst.
  119.         mvc     SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 # store ac. regs
  120.         mvc     SP_PSW(8,%r15),psworg    # move user PSW to stack
  121.         la      %r0,psworg               # store trap indication
  122.         st      %r0,SP_TRAP(%r15)
  123.         xc      0(4,%r15),0(%r15)         # clear back chain
  124.         .endm
  125.         .macro  RESTORE_ALL sync          # system exit macro
  126.         mvc     __LC_RETURN_PSW(8),SP_PSW(%r15)  # move user PSW to lowcore
  127.         lam     %a0,%a15,SP_AREGS(%r15)   # load the access registers
  128.         lm      %r0,%r15,SP_R0(%r15)      # load gprs 0-15 of user
  129.         ni      __LC_RETURN_PSW+1,0xfd    # clear wait state bit
  130.         lpsw    __LC_RETURN_PSW           # back to caller
  131.         .endm
  132.         .macro  GET_CURRENT
  133. l %r9,BASED(.Lc0xffffe000)  # load pointer to task_struct to %r9
  134. al %r9,__LC_KERNEL_STACK
  135.         .endm
  136. /*
  137.  * Scheduler resume function, called by switch_to
  138.  *  grp2 = (thread_struct *) prev->tss
  139.  *  grp3 = (thread_struct *) next->tss
  140.  * Returns:
  141.  *  gpr2 = prev
  142.  */
  143.         .globl  resume
  144. resume:
  145.         basr    %r1,0
  146. resume_base:
  147.         l       %r4,_TSS_PTREGS(%r3)
  148.         tm      SP_PSW-SP_PTREGS(%r4),0x40 # is the new process using per ?
  149.         bz      resume_noper-resume_base(%r1) # if not we're fine
  150.         stctl   %c9,%c11,24(%r15)             # We are using per stuff
  151.         clc     _TSS_PER(12,%r3),24(%r15)
  152.         be      resume_noper-resume_base(%r1) # we got away w/o bashing TLB's
  153.         lctl    %c9,%c11,_TSS_PER(%r3)        # Nope we didn't
  154. resume_noper:
  155.         stm     %r6,%r15,24(%r15)       # store resume registers of prev task
  156.         st      %r15,_TSS_KSP(%r2) # store kernel stack ptr to prev->tss.ksp
  157.         lr      %r0,%r15
  158.         n       %r0,.Lc0xffffe000-resume_base(%r1)
  159.         l       %r15,_TSS_KSP(%r3) # load kernel stack ptr from next->tss.ksp
  160.         l       %r1,.Lc8191-resume_base(%r1)
  161.         or      %r1,%r15
  162.         la      %r1,1(%r1)
  163.         st      %r1,__LC_KERNEL_STACK   # __LC_KERNEL_STACK = new kernel stack
  164.         stam    %a2,%a2,_TSS_AR2(%r2)   # store kernel access reg. 2
  165.         stam    %a4,%a4,_TSS_AR4(%r2)   # store kernel access reg. 4
  166.         lam     %a2,%a2,_TSS_AR2(%r3)   # load kernel access reg. 2
  167.         lam     %a4,%a4,_TSS_AR4(%r3)   # load kernel access reg. 4
  168.         lr      %r2,%r0                 # return task_struct of last task
  169.         lm      %r6,%r15,24(%r15)       # load resume registers of next task
  170.         br      %r14
  171. /*
  172.  * do_softirq calling function. We want to run the softirq functions on the
  173.  * asynchronous interrupt stack.
  174.  */
  175. .global do_call_softirq
  176. do_call_softirq:
  177. stm %r12,%r15,24(%r15)
  178. lr %r12,%r15
  179.         basr    %r13,0
  180. do_call_base:
  181. l %r0,__LC_ASYNC_STACK
  182. slr     %r0,%r15
  183. sra %r0,13
  184. be 0f-do_call_base(%r13)
  185. l %r15,__LC_ASYNC_STACK
  186. 0: sl %r15,.Lc_overhead-do_call_base(%r13)
  187.         st %r12,0(%r15) # store backchain
  188. l %r1,.Ldo_softirq-do_call_base(%r13)
  189. basr %r14,%r1
  190. lm %r12,%r15,24(%r12)
  191. br %r14
  192. /*
  193.  * SVC interrupt handler routine. System calls are synchronous events and
  194.  * are executed with interrupts enabled.
  195.  */
  196. .globl  system_call
  197. system_call:
  198.         SAVE_ALL __LC_SVC_OLD_PSW,1
  199. mvi     SP_PGM_OLD_ILC(%r15),1  # mark PGM_OLD_ILC as invalid
  200. pgm_system_call:
  201.         GET_CURRENT               # load pointer to task_struct to R9
  202.         slr     %r8,%r8           # gpr 8 is call save (-> tracesys)
  203.         ic      %r8,0x8B          # get svc number from lowcore
  204.         stosm   24(%r15),0x03     # reenable interrupts
  205.         sll     %r8,2
  206.         l       %r8,sys_call_table-entry_base(8,%r13) # get address of system call
  207.         tm      tsk_ptrace+3(%r9),0x02 # PT_TRACESYS
  208.         bnz     BASED(sysc_tracesys)
  209.         basr    %r14,%r8          # call sys_xxxx
  210.         st      %r2,SP_R2(%r15)   # store return value (change R2 on stack)
  211.                                   # ATTENTION: check sys_execve_glue before
  212.                                   # changing anything here !!
  213. sysc_return:
  214.         tm      SP_PSW+1(%r15),0x01 # returning to user ?
  215.         bno     BASED(sysc_leave) # no-> skip resched & signal
  216. #
  217. # check, if reschedule is needed
  218. #
  219.         icm     %r0,15,need_resched(%r9) # get need_resched from task_struct
  220.         bnz     BASED(sysc_reschedule)
  221.         icm     %r0,15,sigpending(%r9)   # get sigpending from task_struct
  222.         bnz     BASED(sysc_signal_return)
  223. sysc_leave:
  224. tm      SP_PGM_OLD_ILC(%r15),0xff
  225.         bz      BASED(pgm_svcret)
  226. stnsm   24(%r15),0xfc            # disable I/O and ext. interrupts
  227.         RESTORE_ALL 1
  228. #
  229. # call do_signal before return
  230. #
  231. sysc_signal_return:     
  232.         la      %r2,SP_PTREGS(%r15) # load pt_regs
  233.         sr      %r3,%r3           # clear *oldset
  234.         l       %r1,BASED(.Ldo_signal)
  235. la      %r14,BASED(sysc_leave)
  236.         br      %r1               # return point is sysc_leave
  237. #
  238. # call trace before and after sys_call
  239. #
  240. sysc_tracesys:
  241.         l       %r1,BASED(.Ltrace)
  242. l       %r7,BASED(.Lc_ENOSYS)
  243. st      %r7,SP_R2(%r15)   # give sysc_trace an -ENOSYS retval
  244.         basr    %r14,%r1
  245. l       %r2,SP_R2(%r15)
  246. cr      %r2,%r7 # compare with saved -ENOSYS
  247. be      BASED(sysc_tracesys_dn1)
  248. # strace wants to change the syscall
  249. sll     %r2,24
  250. srl     %r2,22
  251.         l       %r8,sys_call_table-entry_base(2,%r13) # get address of system call    
  252. sysc_tracesys_dn1:
  253. lm      %r3,%r6,SP_R3(%r15)
  254. l       %r2,SP_ORIG_R2(%r15)
  255.         basr    %r14,%r8          # call sys_xxx
  256.         st      %r2,SP_R2(%r15)   # store return value
  257.         l       %r1,BASED(.Ltrace)
  258. la      %r14,BASED(sysc_return)
  259.         br      %r1               # return point is sysc_return
  260. #
  261. # call schedule with sysc_return as return-address
  262. #
  263. sysc_reschedule:        
  264.         l       %r1,BASED(.Lschedule)
  265. la      %r14,BASED(sysc_return)
  266.         br      %r1               # call scheduler, return to sysc_return
  267. #
  268. # a new process exits the kernel with ret_from_fork
  269. #
  270.         .globl  ret_from_fork
  271. ret_from_fork:  
  272.         basr    %r13,0
  273.         l       %r13,.Lentry_base-.(%r13)  # setup base pointer to &entry_base
  274.         GET_CURRENT               # load pointer to task_struct to R9
  275.         stosm   24(%r15),0x03     # reenable interrupts
  276.         sr      %r0,%r0           # child returns 0
  277.         st      %r0,SP_R2(%r15)   # store return value (change R2 on stack)
  278. #ifdef CONFIG_SMP
  279.         l       %r1,BASED(.Lschedtail)
  280. la      %r14,BASED(sysc_return)
  281.         br      %r1               # call schedule_tail, return to sysc_return
  282. #else
  283.         b       BASED(sysc_return)
  284. #endif
  285. #
  286. # clone, fork, vfork, exec and sigreturn need glue,
  287. # because they all expect pt_regs as parameter,
  288. # but are called with different parameter.
  289. # return-address is set up above
  290. #
  291. sys_clone_glue: 
  292.         la      %r2,SP_PTREGS(%r15)    # load pt_regs
  293.         l       %r1,BASED(.Lclone)
  294.         br      %r1                   # branch to sys_clone
  295. sys_fork_glue:  
  296.         la      %r2,SP_PTREGS(%r15)    # load pt_regs
  297.         l       %r1,BASED(.Lfork)
  298.         br      %r1                   # branch to sys_fork
  299. sys_vfork_glue: 
  300.         la      %r2,SP_PTREGS(%r15)    # load pt_regs
  301.         l       %r1,BASED(.Lvfork)
  302.         br      %r1                   # branch to sys_vfork
  303. sys_execve_glue:        
  304.         la      %r2,SP_PTREGS(%r15)   # load pt_regs
  305.         l       %r1,BASED(.Lexecve)
  306. lr      %r12,%r14             # save return address
  307.         basr    %r14,%r1              # call sys_execve
  308.         ltr     %r2,%r2               # check if execve failed
  309.         bnz     0(%r12)               # it did fail -> store result in gpr2
  310.         b       4(%r12)               # SKIP ST 2,SP_R2(15) after BASR 14,8
  311.                                       # in system_call/sysc_tracesys
  312. sys_sigreturn_glue:     
  313.         la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
  314.         l       %r1,BASED(.Lsigreturn)
  315.         br      %r1                   # branch to sys_sigreturn
  316. sys_rt_sigreturn_glue:     
  317.         la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
  318.         l       %r1,BASED(.Lrt_sigreturn)
  319.         br      %r1                   # branch to sys_sigreturn
  320. #
  321. # sigsuspend and rt_sigsuspend need pt_regs as an additional
  322. # parameter and they have to skip the store of %r2 into the
  323. # user register %r2 because the return value was set in 
  324. # sigsuspend and rt_sigsuspend already and must not be overwritten!
  325. #
  326. sys_sigsuspend_glue:    
  327.         lr      %r5,%r4               # move mask back
  328.         lr      %r4,%r3               # move history1 parameter
  329.         lr      %r3,%r2               # move history0 parameter
  330.         la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
  331.         l       %r1,BASED(.Lsigsuspend)
  332. la      %r14,4(%r14)          # skip store of return value
  333.         br      %r1                   # branch to sys_sigsuspend
  334. sys_rt_sigsuspend_glue: 
  335.         lr      %r4,%r3               # move sigsetsize parameter
  336.         lr      %r3,%r2               # move unewset parameter
  337.         la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
  338.         l       %r1,BASED(.Lrt_sigsuspend)
  339. la      %r14,4(%r14)          # skip store of return value
  340.         br      %r1                   # branch to sys_rt_sigsuspend
  341. sys_sigaltstack_glue:
  342.         la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
  343.         l       %r1,BASED(.Lsigaltstack)
  344.         br      %r1                   # branch to sys_sigreturn
  345. .globl  sys_call_table
  346. sys_call_table:
  347.         .long  sys_ni_syscall            /* 0 */
  348.         .long  sys_exit
  349.         .long  sys_fork_glue
  350.         .long  sys_read
  351.         .long  sys_write
  352.         .long  sys_open                  /* 5 */
  353.         .long  sys_close
  354.         .long  sys_ni_syscall           /* old waitpid syscall holder */
  355.         .long  sys_creat
  356.         .long  sys_link
  357.         .long  sys_unlink                /* 10 */
  358.         .long  sys_execve_glue
  359.         .long  sys_chdir
  360.         .long  sys_time
  361.         .long  sys_mknod
  362.         .long  sys_chmod                /* 15 */
  363.         .long  sys_lchown16
  364.         .long  sys_ni_syscall           /* old break syscall holder */
  365.         .long  sys_ni_syscall           /* old stat syscall holder */
  366.         .long  sys_lseek
  367.         .long  sys_getpid               /* 20 */
  368.         .long  sys_mount
  369.         .long  sys_oldumount
  370.         .long  sys_setuid16
  371.         .long  sys_getuid16
  372.         .long  sys_stime                /* 25 */
  373.         .long  sys_ptrace
  374.         .long  sys_alarm
  375.         .long  sys_ni_syscall           /* old fstat syscall holder */
  376.         .long  sys_pause
  377.         .long  sys_utime                /* 30 */
  378.         .long  sys_ni_syscall           /* old stty syscall holder */
  379.         .long  sys_ni_syscall           /* old gtty syscall holder */
  380.         .long  sys_access
  381.         .long  sys_nice
  382.         .long  sys_ni_syscall           /* 35 */  /* old ftime syscall holder */
  383.         .long  sys_sync
  384.         .long  sys_kill
  385.         .long  sys_rename
  386.         .long  sys_mkdir
  387.         .long  sys_rmdir                /* 40 */
  388.         .long  sys_dup
  389.         .long  sys_pipe
  390.         .long  sys_times
  391.         .long  sys_ni_syscall           /* old prof syscall holder */
  392.         .long  sys_brk                  /* 45 */
  393.         .long  sys_setgid16
  394.         .long  sys_getgid16
  395.         .long  sys_signal
  396.         .long  sys_geteuid16
  397.         .long  sys_getegid16            /* 50 */
  398.         .long  sys_acct
  399.         .long  sys_umount
  400.         .long  sys_ni_syscall           /* old lock syscall holder */
  401.         .long  sys_ioctl
  402.         .long  sys_fcntl                /* 55 */
  403.         .long  sys_ni_syscall           /* old mpx syscall holder */
  404.         .long  sys_setpgid
  405.         .long  sys_ni_syscall           /* old ulimit syscall holder */
  406.         .long  sys_ni_syscall           /* old uname syscall holder */
  407.         .long  sys_umask                /* 60 */
  408.         .long  sys_chroot
  409.         .long  sys_ustat
  410.         .long  sys_dup2
  411.         .long  sys_getppid
  412.         .long  sys_getpgrp              /* 65 */
  413.         .long  sys_setsid
  414.         .long  sys_sigaction
  415.         .long  sys_ni_syscall           /* old sgetmask syscall holder */
  416.         .long  sys_ni_syscall           /* old ssetmask syscall holder */
  417.         .long  sys_setreuid16           /* 70 */
  418.         .long  sys_setregid16
  419.         .long  sys_sigsuspend_glue
  420.         .long  sys_sigpending
  421.         .long  sys_sethostname
  422.         .long  sys_setrlimit            /* 75 */
  423.         .long  sys_old_getrlimit
  424.         .long  sys_getrusage
  425.         .long  sys_gettimeofday
  426.         .long  sys_settimeofday
  427.         .long  sys_getgroups16          /* 80 */
  428.         .long  sys_setgroups16
  429.         .long  sys_ni_syscall           /* old select syscall holder */
  430.         .long  sys_symlink
  431.         .long  sys_ni_syscall           /* old lstat syscall holder */
  432.         .long  sys_readlink             /* 85 */
  433.         .long  sys_uselib
  434.         .long  sys_swapon
  435.         .long  sys_reboot
  436.         .long  sys_ni_syscall           /* old readdir syscall holder */
  437.         .long  old_mmap                 /* 90 */
  438.         .long  sys_munmap
  439.         .long  sys_truncate
  440.         .long  sys_ftruncate
  441.         .long  sys_fchmod
  442.         .long  sys_fchown16              /* 95 */
  443.         .long  sys_getpriority
  444.         .long  sys_setpriority
  445.         .long  sys_ni_syscall            /* old profil syscall holder */
  446.         .long  sys_statfs
  447.         .long  sys_fstatfs               /* 100 */
  448.         .long  sys_ioperm
  449.         .long  sys_socketcall
  450.         .long  sys_syslog
  451.         .long  sys_setitimer
  452.         .long  sys_getitimer             /* 105 */
  453.         .long  sys_newstat
  454.         .long  sys_newlstat
  455.         .long  sys_newfstat
  456.         .long  sys_ni_syscall            /* old uname syscall holder */
  457.         .long  sys_ni_syscall            /* 110 */ /* iopl for i386 */
  458.         .long  sys_vhangup
  459.         .long  sys_ni_syscall            /* old "idle" system call */
  460.         .long  sys_ni_syscall            /* vm86old for i386 */
  461.         .long  sys_wait4
  462.         .long  sys_swapoff               /* 115 */
  463.         .long  sys_sysinfo
  464.         .long  sys_ipc
  465.         .long  sys_fsync
  466.         .long  sys_sigreturn_glue
  467.         .long  sys_clone_glue            /* 120 */
  468.         .long  sys_setdomainname
  469.         .long  sys_newuname
  470.         .long  sys_ni_syscall            /* modify_ldt for i386 */
  471.         .long  sys_adjtimex
  472.         .long  sys_mprotect              /* 125 */
  473.         .long  sys_sigprocmask
  474.         .long  sys_create_module
  475.         .long  sys_init_module
  476.         .long  sys_delete_module
  477.         .long  sys_get_kernel_syms       /* 130 */
  478.         .long  sys_quotactl
  479.         .long  sys_getpgid
  480.         .long  sys_fchdir
  481.         .long  sys_bdflush
  482.         .long  sys_sysfs                 /* 135 */
  483.         .long  sys_personality
  484.         .long  sys_ni_syscall            /* for afs_syscall */
  485.         .long  sys_setfsuid16
  486.         .long  sys_setfsgid16
  487.         .long  sys_llseek                /* 140 */
  488.         .long  sys_getdents
  489.         .long  sys_select
  490.         .long  sys_flock
  491.         .long  sys_msync
  492.         .long  sys_readv                 /* 145 */
  493.         .long  sys_writev
  494.         .long  sys_getsid
  495.         .long  sys_fdatasync
  496.         .long  sys_sysctl
  497.         .long  sys_mlock                 /* 150 */
  498.         .long  sys_munlock
  499.         .long  sys_mlockall
  500.         .long  sys_munlockall
  501.         .long  sys_sched_setparam
  502.         .long  sys_sched_getparam        /* 155 */
  503.         .long  sys_sched_setscheduler
  504.         .long  sys_sched_getscheduler
  505.         .long  sys_sched_yield
  506.         .long  sys_sched_get_priority_max
  507.         .long  sys_sched_get_priority_min  /* 160 */
  508.         .long  sys_sched_rr_get_interval
  509.         .long  sys_nanosleep
  510.         .long  sys_mremap
  511.         .long  sys_setresuid16
  512.         .long  sys_getresuid16           /* 165 */
  513.         .long  sys_ni_syscall            /* for vm86 */
  514.         .long  sys_query_module
  515.         .long  sys_poll
  516.         .long  sys_nfsservctl
  517.         .long  sys_setresgid16           /* 170 */
  518.         .long  sys_getresgid16
  519.         .long  sys_prctl
  520.         .long  sys_rt_sigreturn_glue
  521.         .long  sys_rt_sigaction
  522.         .long  sys_rt_sigprocmask        /* 175 */
  523.         .long  sys_rt_sigpending
  524.         .long  sys_rt_sigtimedwait
  525.         .long  sys_rt_sigqueueinfo
  526.         .long  sys_rt_sigsuspend_glue
  527.         .long  sys_pread                 /* 180 */
  528.         .long  sys_pwrite
  529.         .long  sys_chown16
  530.         .long  sys_getcwd
  531.         .long  sys_capget
  532.         .long  sys_capset                /* 185 */
  533.         .long  sys_sigaltstack_glue
  534.         .long  sys_sendfile
  535.         .long  sys_ni_syscall            /* streams1 */
  536.         .long  sys_ni_syscall            /* streams2 */
  537.         .long  sys_vfork_glue            /* 190 */
  538.         .long  sys_getrlimit
  539. .long  sys_mmap2
  540.         .long  sys_truncate64
  541.         .long  sys_ftruncate64
  542.         .long  sys_stat64                /* 195 */
  543.         .long  sys_lstat64
  544.         .long  sys_fstat64
  545. .long  sys_lchown
  546. .long  sys_getuid
  547. .long  sys_getgid  /* 200 */
  548. .long  sys_geteuid
  549. .long  sys_getegid
  550. .long  sys_setreuid
  551. .long  sys_setregid
  552. .long  sys_getgroups             /* 205 */
  553. .long  sys_setgroups
  554. .long  sys_fchown
  555. .long  sys_setresuid
  556. .long  sys_getresuid
  557. .long  sys_setresgid             /* 210 */
  558. .long  sys_getresgid
  559. .long  sys_chown
  560. .long  sys_setuid
  561. .long  sys_setgid
  562. .long  sys_setfsuid              /* 215 */
  563. .long  sys_setfsgid
  564.         .long  sys_pivot_root
  565.         .long  sys_mincore
  566.         .long  sys_madvise
  567. .long  sys_getdents64  /* 220 */
  568.         .long  sys_fcntl64 
  569. .long  sys_ni_syscall  /* 222 - reserved for posix_acl */
  570. .long  sys_ni_syscall  /* 223 - reserved for posix_acl */
  571. .long  sys_ni_syscall  /* 224 - reserved for posix_acl */
  572. .rept  255-224
  573. .long  sys_ni_syscall
  574. .endr
  575. /*
  576.  * Program check handler routine
  577.  */
  578.         .globl  pgm_check_handler
  579. pgm_check_handler:
  580. /*
  581.  * First we need to check for a special case:
  582.  * Single stepping an instruction that disables the PER event mask will
  583.  * cause a PER event AFTER the mask has been set. Example: SVC or LPSW.
  584.  * For a single stepped SVC the program check handler gets control after
  585.  * the SVC new PSW has been loaded. But we want to execute the SVC first and
  586.  * then handle the PER event. Therefore we update the SVC old PSW to point
  587.  * to the pgm_check_handler and branch to the SVC handler after we checked
  588.  * if we have to load the kernel stack register.
  589.  * For every other possible cause for PER event without the PER mask set
  590.  * we just ignore the PER event (FIXME: is there anything we have to do
  591.  * for LPSW?).
  592.  */
  593. stm     %r13,%r15,__LC_SAVE_AREA
  594. basr    %r13,0                   # temp base pointer
  595. l       %r13,.Lentry_base-.(%r13)# load &entry_base to %r13
  596.         tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
  597. stam    %a2,%a4,__LC_SAVE_AREA+12
  598.         bz      BASED(pgm_sv)            # skip if not
  599.         tm      __LC_PGM_OLD_PSW,0x40    # test if per event recording is on
  600.         bnz     BASED(pgm_sv)            # skip if it is
  601. # ok its one of the special cases, now we need to find out which one
  602.         clc     __LC_PGM_OLD_PSW(8),__LC_SVC_NEW_PSW
  603.         be      BASED(pgm_svcper)
  604. # no interesting special case, ignore PER event
  605.         lm      %r13,%r15,__LC_SAVE_AREA
  606. lpsw    0x28
  607. # it was a single stepped SVC that is causing all the trouble
  608. pgm_svcper:
  609.         tm      0x21,0x01                # test problem state bit
  610. bz BASED(.+12)              # skip stack & access regs setup
  611. l %r15,__LC_KERNEL_STACK   # problem state -> load ksp
  612. lam     %a2,%a4,BASED(.Lc_ac)    # set ac.reg. 2 to primary space
  613.                                          # and access reg. 4 to home space
  614. s       %r15,BASED(.Lc_spsize)   # make room for registers & psw
  615.         n       %r15,BASED(.Lc0xfffffff8) # align stack pointer to 8
  616.         stm     %r0,%r12,SP_R0(%r15)     # store gprs 0-12 to kernel stack
  617.         st      %r2,SP_ORIG_R2(%r15)     # store original content of gpr 2
  618.         mvc     SP_R13(12,%r15),__LC_SAVE_AREA # move R13-R15 to stack
  619.         stam    %a0,%a15,SP_AREGS(%r15)  # store access registers to kst.
  620. mvc     SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 # store ac. regs
  621.         mvc     SP_PSW(8,%r15),0x20      # move user PSW to stack
  622.         la      %r0,0x20                 # store trap indication
  623.         st      %r0,SP_TRAP(%r15)
  624.         xc      0(4,%r15),0(%r15)        # clear back chain
  625.         mvc     SP_PGM_OLD_ILC(4,%r15),__LC_PGM_ILC # save program check information
  626.         b       BASED(pgm_system_call)   # now do the svc
  627. pgm_svcret:
  628.         mvi     SP_TRAP+3(%r15),0x28     # set trap indication back to pgm_chk
  629.         lh      %r7,SP_PGM_OLD_ILC(%r15) # get ilc from stack
  630. mvi     SP_PGM_OLD_ILC(%r15),1   # mark PGM_OLD_ILC as invalid
  631. b       BASED(pgm_no_sv)
  632. pgm_sv:
  633.         tm      0x29,0x01                # test problem state bit
  634. bz BASED(.+12)              # skip stack & access regs setup
  635. l %r15,__LC_KERNEL_STACK   # problem state -> load ksp
  636. lam     %a2,%a4,BASED(.Lc_ac)    # set ac.reg. 2 to primary space
  637.                                          # and access reg. 4 to home space
  638. s       %r15,BASED(.Lc_spsize)   # make room for registers & psw
  639.         n       %r15,BASED(.Lc0xfffffff8) # align stack pointer to 8
  640.         stm     %r0,%r12,SP_R0(%r15)     # store gprs 0-12 to kernel stack
  641.         st      %r2,SP_ORIG_R2(%r15)     # store original content of gpr 2
  642.         mvc     SP_R13(12,%r15),__LC_SAVE_AREA # move R13-R15 to stack
  643.         stam    %a0,%a15,SP_AREGS(%r15)  # store access registers to kst.
  644. mvc     SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 # store ac. regs
  645.         mvc     SP_PSW(8,%r15),0x28      # move user PSW to stack
  646.         la      %r0,0x28                 # store trap indication
  647.         st      %r0,SP_TRAP(%r15)
  648.         xc      0(4,%r15),0(%r15)        # clear back chain
  649. mvi     SP_PGM_OLD_ILC(%r15),1   # mark PGM_OLD_ILC as invalid
  650.         lh      %r7,__LC_PGM_ILC         # load instruction length
  651. GET_CURRENT
  652. pgm_no_sv:
  653. la %r3,0x7f
  654.         lh      %r8,__LC_PGM_INT_CODE  # N.B. saved int code used later KEEP it
  655. nr      %r3,%r8           # reload & clear per-event-bit
  656.         be      BASED(pgm_dn)     # none of Martins exceptions occurred bypass
  657.         l       %r1,BASED(.Ljump_table)
  658.         sll     %r3,2
  659.         l       %r1,0(%r3,%r1)    # load address of handler routine
  660.         la      %r2,SP_PTREGS(%r15) # address of register-save area
  661.         srl     %r3,2
  662.         cl      %r3,BASED(.Lc4)   # protection-exception ?
  663.         bne     BASED(pgm_per)    # if not,
  664.         l       %r5,SP_PSW+4(15)  # load psw addr
  665.         sr      %r5,%r7           # substract ilc from psw
  666.         st      %r5,SP_PSW+4(15)  # store corrected psw addr
  667. pgm_per:basr    %r14,%r1          # branch to interrupt-handler
  668. pgm_dn: n %r8,BASED(.Lc128) # check for per excepton
  669.         be      BASED(pgm_return)
  670.         la      %r2,SP_PTREGS(15) # address of register-save area
  671.         l       %r1,BASED(.Lhandle_per) # load adr. of per handler
  672.         la      %r14,BASED(sysc_return) # load adr. of system return
  673.         br      %r1               # branch to handle_per_exception
  674. #
  675. # the backend code is the same as for sys-call
  676. #
  677. pgm_return:
  678.         b       BASED(sysc_return)
  679. /*
  680.  * IO interrupt handler routine
  681.  */
  682.         .globl io_int_handler
  683. io_int_handler:
  684.         SAVE_ALL __LC_IO_OLD_PSW,0
  685.         GET_CURRENT               # load pointer to task_struct to R9
  686.         la      %r2,SP_PTREGS(%r15) # address of register-save area
  687.         sr      %r3,%r3
  688.         icm     %r3,%r3,__LC_SUBCHANNEL_NR # load subchannel nr & extend to int
  689.         l       %r4,__LC_IO_INT_PARM       # load interuption parm
  690. l       %r5,__LC_IO_INT_WORD       # load interuption word
  691.         l       %r1,BASED(.Ldo_IRQ)        # load address of do_IRQ
  692.         basr    %r14,%r1          # branch to standard irq handler
  693. io_return:
  694. #
  695. # check, if bottom-half has to be done
  696. #
  697.         l       %r1,processor(%r9)    # get cpu number from task struture
  698.         sll     %r1,L1_CACHE_SHIFT
  699.         al      %r1,BASED(.Lirq_stat) # get address of irq_stat
  700.         icm     %r0,15,0(%r1)         # test irq_stat[#cpu].__softirq_pending
  701.         bnz     BASED(io_handle_bottom_half)
  702. io_return_bh:
  703.         tm      SP_PSW+1(%r15),0x01 # returning to user ?
  704.         bno     BASED(io_leave)   # no-> skip resched & signal
  705.         stosm   24(%r15),0x03     # reenable interrupts
  706. #
  707. # check, if reschedule is needed
  708. #
  709.         icm     %r0,15,need_resched(%r9) # get need_resched from task_struct
  710.         bnz     BASED(io_reschedule)
  711.         icm     %r0,15,sigpending(%r9)   # get sigpending from task_struct
  712.         bnz     BASED(io_signal_return)
  713. io_leave:
  714.         stnsm   24(%r15),0xfc            # disable I/O and ext. interrupts
  715.         RESTORE_ALL 0
  716. #
  717. # call do_softirq
  718. #
  719. io_handle_bottom_half:
  720.         l       %r1,BASED(.Ldo_softirq)
  721.         la      %r14,BASED(io_return_bh)
  722.         br      %r1               # call do_softirq
  723. #
  724. # call schedule with io_return as return-address
  725. #
  726. io_reschedule:        
  727.         l       %r1,BASED(.Lschedule)
  728. la      %r14,BASED(io_return)
  729.         br      %r1               # call scheduler, return to io_return
  730. #
  731. # call do_signal before return
  732. #
  733. io_signal_return:     
  734.         la      %r2,SP_PTREGS(%r15) # load pt_regs
  735.         sr      %r3,%r3           # clear *oldset
  736.         l       %r1,BASED(.Ldo_signal)
  737. la      %r14,BASED(io_leave)
  738.         br      %r1               # return point is io_leave
  739. /*
  740.  * External interrupt handler routine
  741.  */
  742.         .globl  ext_int_handler
  743. ext_int_handler:
  744.         SAVE_ALL __LC_EXT_OLD_PSW,0
  745.         GET_CURRENT                    # load pointer to task_struct to R9
  746.         la      %r2,SP_PTREGS(%r15)    # address of register-save area
  747.         lh      %r3,__LC_EXT_INT_CODE  # error code
  748.         lr      %r1,%r3                # calculate index = code & 0xff
  749.         n       %r1,BASED(.Lc0xff)
  750.         sll     %r1,2
  751.         l       %r4,BASED(.Lext_hash)
  752.         l       %r4,0(%r1,%r4)         # get first list entry for hash value
  753.         ltr     %r4,%r4                # == NULL ?
  754.         bz      BASED(io_return)       # yes, nothing to do, exit
  755. ext_int_loop:
  756.         ch      %r3,8(%r4)             # compare external interrupt code
  757.         be      BASED(ext_int_found)
  758.         icm     %r4,15,0(%r4)          # next list entry
  759.         bnz     BASED(ext_int_loop)
  760.         b       BASED(io_return)
  761. ext_int_found:
  762.         l       %r4,4(%r4)             # get handler address
  763.         la      %r14,BASED(io_return)
  764.         br      %r4                    # branch to ext call handler
  765. /*
  766.  * Machine check handler routines
  767.  */
  768.         .globl mcck_int_handler
  769. mcck_int_handler:
  770.         SAVE_ALL __LC_MCK_OLD_PSW,0
  771. l       %r1,BASED(.Ls390_mcck)
  772. basr    %r14,%r1   # call machine check handler
  773. mcck_return:
  774.         RESTORE_ALL 0
  775. #ifdef CONFIG_SMP
  776. /*
  777.  * Restart interruption handler, kick starter for additional CPUs
  778.  */
  779.         .globl restart_int_handler
  780. restart_int_handler:
  781.         l       %r15,__LC_SAVE_AREA+60 # load ksp
  782.         lctl    %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
  783.         lam     %a0,%a15,__LC_AREGS_SAVE_AREA
  784.         stosm   0(%r15),0x04           # now we can turn dat on
  785.         lm      %r6,%r15,24(%r15)      # load registers from clone
  786.         basr    %r14,0
  787.         l       %r14,restart_addr-.(%r14)
  788.         br      %r14                   # branch to start_secondary
  789. restart_addr:
  790.         .long   start_secondary
  791. #else
  792. /*
  793.  * If we do not run with SMP enabled, let the new CPU crash ...
  794.  */
  795.         .globl restart_int_handler
  796. restart_int_handler:
  797.         basr    %r1,0
  798. restart_base:
  799.         lpsw    restart_crash-restart_base(%r1)
  800.         .align 8
  801. restart_crash:
  802.         .long  0x000a0000,0x00000000
  803. restart_go:
  804. #endif
  805. /*
  806.  * Integer constants
  807.  */
  808.                .align 4
  809. .Lc0xfffffff8: .long  -8           # to align stack pointer to 8
  810. .Lc0xffffe000: .long  -8192        # to round stack pointer to &task_struct
  811. .Lc8191:       .long  8191
  812. .Lc_spsize:    .long  SP_SIZE
  813. .Lc_overhead:  .long  STACK_FRAME_OVERHEAD
  814. .Lc_ac:        .long  0,0,1
  815. .Lc_ENOSYS:    .long  -ENOSYS
  816. .Lc4:          .long  4
  817. .Lc20:         .long  20
  818. .Lc0x1202:     .long  0x1202
  819. .Lc0x1004:     .long  0x1004
  820. .Lc0x2401:     .long  0x2401
  821. .Lc0x4000:     .long  0x4000
  822. .Lc0xff:       .long  0xff
  823. .Lc128:        .long  128
  824. /*
  825.  * Symbol constants
  826.  */
  827. .Ls390_mcck:   .long  s390_do_machine_check
  828. .Ldo_IRQ:      .long  do_IRQ
  829. .Ldo_signal:   .long  do_signal
  830. .Ldo_softirq:  .long  do_softirq
  831. .Lentry_base:  .long  entry_base
  832. .Lext_hash:    .long  ext_int_hash
  833. .Lhandle_per:  .long  handle_per_exception
  834. .Lirq_stat:    .long  irq_stat
  835. .Ljump_table:  .long  pgm_check_table
  836. .Lschedule:    .long  schedule
  837. .Lclone:       .long  sys_clone
  838. .Lexecve:      .long  sys_execve
  839. .Lfork:        .long  sys_fork
  840. .Lrt_sigreturn:.long  sys_rt_sigreturn
  841. .Lrt_sigsuspend:
  842.                .long  sys_rt_sigsuspend
  843. .Lsigreturn:   .long  sys_sigreturn
  844. .Lsigsuspend:  .long  sys_sigsuspend
  845. .Lsigaltstack: .long  sys_sigaltstack
  846. .Ltrace:       .long  syscall_trace
  847. .Lvfork:       .long  sys_vfork
  848. #ifdef CONFIG_SMP
  849. .Lschedtail:   .long  schedule_tail
  850. #endif