root/kernel/sys_call.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 /*
   2  *  linux/kernel/sys_call.S
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 /*
   8  * sys_call.S  contains the system-call and fault low-level handling routines.
   9  * This also contains the timer-interrupt handler, as well as all interrupts
  10  * and faults that can result in a task-switch.
  11  *
  12  * NOTE: This code handles signal-recognition, which happens every time
  13  * after a timer-interrupt and after each system call.
  14  *
  15  * I changed all the .align's to 4 (16 byte alignment), as that's faster
  16  * on a 486.
  17  *
  18  * Stack layout in 'ret_from_system_call':
  19  *      ptrace needs to have all regs on the stack.
  20  *      if the order here is changed, it needs to be 
  21  *      updated in fork.c:copy_process, signal.c:do_signal,
  22  *      ptrace.c and ptrace.h
  23  *
  24  *       0(%esp) - %ebx
  25  *       4(%esp) - %ecx
  26  *       8(%esp) - %edx
  27  *       C(%esp) - %esi
  28  *      10(%esp) - %edi
  29  *      14(%esp) - %ebp
  30  *      18(%esp) - %eax
  31  *      1C(%esp) - %ds
  32  *      20(%esp) - %es
  33  *      24(%esp) - %fs
  34  *      28(%esp) - %gs
  35  *      2C(%esp) - orig_eax
  36  *      30(%esp) - %eip
  37  *      34(%esp) - %cs
  38  *      38(%esp) - %eflags
  39  *      3C(%esp) - %oldesp
  40  *      40(%esp) - %oldss
  41  */
  42 
  43 EBX             = 0x00
  44 ECX             = 0x04
  45 EDX             = 0x08
  46 ESI             = 0x0C
  47 EDI             = 0x10
  48 EBP             = 0x14
  49 EAX             = 0x18
  50 DS              = 0x1C
  51 ES              = 0x20
  52 FS              = 0x24
  53 GS              = 0x28
  54 ORIG_EAX        = 0x2C
  55 EIP             = 0x30
  56 CS              = 0x34
  57 EFLAGS          = 0x38
  58 OLDESP          = 0x3C
  59 OLDSS           = 0x40
  60 
  61 IF_MASK         = 0x00000200
  62 NT_MASK         = 0x00004000
  63 VM_MASK         = 0x00020000
  64 
  65 /*
  66  * these are offsets into the task-struct.
  67  */
  68 state           = 0
  69 counter         = 4
  70 priority        = 8
  71 signal          = 12
  72 sigaction       = 16            # MUST be 16 (=len of sigaction)
  73 blocked         = (33*16)
  74 saved_kernel_stack = ((33*16)+4)
  75 
  76 /*
  77  * offsets within sigaction
  78  */
  79 sa_handler      = 0
  80 sa_mask         = 4
  81 sa_flags        = 8
  82 sa_restorer     = 12
  83 
  84 ENOSYS = 38
  85 
  86 .globl _system_call,_sys_execve
  87 .globl _device_not_available, _coprocessor_error
  88 .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
  89 .globl _double_fault,_coprocessor_segment_overrun
  90 .globl _invalid_TSS,_segment_not_present,_stack_segment
  91 .globl _general_protection,_reserved
  92 .globl _alignment_check,_page_fault
  93 .globl ret_from_sys_call
  94 
  95 #define SAVE_ALL \
  96         cld; \
  97         push %gs; \
  98         push %fs; \
  99         push %es; \
 100         push %ds; \
 101         pushl %eax; \
 102         pushl %ebp; \
 103         pushl %edi; \
 104         pushl %esi; \
 105         pushl %edx; \
 106         pushl %ecx; \
 107         pushl %ebx; \
 108         movl $0x10,%edx; \
 109         mov %dx,%ds; \
 110         mov %dx,%es; \
 111         movl $0x17,%edx; \
 112         mov %dx,%fs
 113 
 114 .align 4
 115 reschedule:
 116         pushl $ret_from_sys_call
 117         jmp _schedule
 118 .align 4
 119 _system_call:
 120         pushl %eax                      # save orig_eax
 121         SAVE_ALL
 122         movl $-ENOSYS,EAX(%esp)
 123         cmpl _NR_syscalls,%eax
 124         jae ret_from_sys_call
 125         call _sys_call_table(,%eax,4)
 126         movl %eax,EAX(%esp)             # save the return value
 127         .align 4,0x90
 128 ret_from_sys_call:
 129         movl EFLAGS(%esp),%eax          # check VM86 flag: CS/SS are
 130         testl $VM_MASK,%eax             # different then
 131         jne 4f
 132         cmpw $0x0f,CS(%esp)             # was old code segment supervisor ?
 133         jne 2f
 134         cmpw $0x17,OLDSS(%esp)          # was stack segment = 0x17 ?
 135         jne 2f
 136 4:      orl $IF_MASK,%eax               # these just try to make sure
 137         andl $~NT_MASK,%eax             # the program doesn't do anything
 138         movl %eax,EFLAGS(%esp)          # stupid
 139 1:      cmpl $0,_need_resched
 140         jne reschedule
 141         movl _current,%eax
 142         cmpl _task,%eax                 # task[0] cannot have signals
 143         je 2f
 144         cmpl $0,state(%eax)             # state
 145         jne reschedule
 146         cmpl $0,counter(%eax)           # counter
 147         je reschedule
 148         movl signal(%eax),%ebx
 149         movl blocked(%eax),%ecx
 150         notl %ecx
 151         andl %ebx,%ecx
 152         bsfl %ecx,%ecx
 153         je 2f
 154         btrl %ecx,%ebx
 155         incl %ecx
 156         movl %ebx,signal(%eax)
 157         movl %esp,%ebx
 158         testl $VM_MASK,EFLAGS(%esp)
 159         je 3f
 160         pushl %ebx
 161         pushl %ecx
 162         call _save_v86_state
 163         popl %ecx
 164         movl %eax,%ebx
 165         movl %eax,%esp
 166 3:      pushl %ebx
 167         pushl %ecx
 168         call _do_signal
 169         popl %ecx
 170         popl %ebx
 171         testl %eax, %eax
 172         jne 1b                  # see if we need to switch tasks, or do more signals
 173 2:      popl %ebx
 174         popl %ecx
 175         popl %edx
 176         popl %esi
 177         popl %edi
 178         popl %ebp
 179         popl %eax
 180         pop %ds
 181         pop %es
 182         pop %fs
 183         pop %gs
 184         addl $4,%esp            # skip the orig_eax
 185         iret
 186 
 187 .align 4
 188 _sys_execve:
 189         lea (EIP+4)(%esp),%eax  # don't forget about the return address.
 190         pushl %eax
 191         call _do_execve
 192         addl $4,%esp
 193         ret
 194 
 195 .align 4
 196 _divide_error:
 197         pushl $0                # no error code
 198         pushl $_do_divide_error
 199 .align 4,0x90
 200 error_code:
 201         push %fs
 202         push %es
 203         push %ds
 204         pushl %eax
 205         pushl %ebp
 206         pushl %edi
 207         pushl %esi
 208         pushl %edx
 209         pushl %ecx
 210         pushl %ebx
 211         cld
 212         movl $-1, %eax
 213         xchgl %eax, ORIG_EAX(%esp)      # orig_eax (get the error code. )
 214         xorl %ebx,%ebx                  # zero ebx
 215         mov %gs,%bx                     # get the lower order bits of gs
 216         xchgl %ebx, GS(%esp)            # get the address and save gs.
 217         pushl %eax                      # push the error code
 218         lea 52(%esp),%edx
 219         pushl %edx
 220         movl $0x10,%edx
 221         mov %dx,%ds
 222         mov %dx,%es
 223         movl $0x17,%edx
 224         mov %dx,%fs
 225         call *%ebx
 226         addl $8,%esp
 227         jmp ret_from_sys_call
 228 
 229 .align 4
 230 _coprocessor_error:
 231         pushl $0
 232         pushl $_do_coprocessor_error
 233         jmp error_code
 234 
 235 .align 4
 236 _device_not_available:
 237         pushl $-1               # mark this as an int
 238         SAVE_ALL
 239         pushl $ret_from_sys_call
 240         clts                            # clear TS so that we can use math
 241         movl %cr0,%eax
 242         testl $0x4,%eax                 # EM (math emulation bit)
 243         je _math_state_restore
 244         pushl $0                # temporary storage for ORIG_EIP
 245         call _math_emulate
 246         addl $4,%esp
 247         ret
 248 
 249 .align 4
 250 _debug:
 251         pushl $0
 252         pushl $_do_debug
 253         jmp error_code
 254 
 255 .align 4
 256 _nmi:
 257         pushl $0
 258         pushl $_do_nmi
 259         jmp error_code
 260 
 261 .align 4
 262 _int3:
 263         pushl $0
 264         pushl $_do_int3
 265         jmp error_code
 266 
 267 .align 4
 268 _overflow:
 269         pushl $0
 270         pushl $_do_overflow
 271         jmp error_code
 272 
 273 .align 4
 274 _bounds:
 275         pushl $0
 276         pushl $_do_bounds
 277         jmp error_code
 278 
 279 .align 4
 280 _invalid_op:
 281         pushl $0
 282         pushl $_do_invalid_op
 283         jmp error_code
 284 
 285 .align 4
 286 _coprocessor_segment_overrun:
 287         pushl $0
 288         pushl $_do_coprocessor_segment_overrun
 289         jmp error_code
 290 
 291 .align 4
 292 _reserved:
 293         pushl $0
 294         pushl $_do_reserved
 295         jmp error_code
 296 
 297 .align 4
 298 _double_fault:
 299         pushl $_do_double_fault
 300         jmp error_code
 301 
 302 .align 4
 303 _invalid_TSS:
 304         pushl $_do_invalid_TSS
 305         jmp error_code
 306 
 307 .align 4
 308 _segment_not_present:
 309         pushl $_do_segment_not_present
 310         jmp error_code
 311 
 312 .align 4
 313 _stack_segment:
 314         pushl $_do_stack_segment
 315         jmp error_code
 316 
 317 .align 4
 318 _general_protection:
 319         pushl $_do_general_protection
 320         jmp error_code
 321 
 322 .align 4
 323 _alignment_check:
 324         pushl $_do_alignment_check
 325         jmp error_code
 326 
 327 .align 4
 328 _page_fault:
 329         pushl $_do_page_fault
 330         jmp error_code

/* [previous][next][first][last][top][bottom][index][help] */