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 kernel_stack_page = ((33*16)+8)
  76 flags           = ((33*16)+12)
  77 
  78 /*
  79  * offsets within sigaction
  80  */
  81 sa_handler      = 0
  82 sa_mask         = 4
  83 sa_flags        = 8
  84 sa_restorer     = 12
  85 
  86 ENOSYS = 38
  87 
  88 .globl _system_call,_sys_execve
  89 .globl _device_not_available, _coprocessor_error
  90 .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
  91 .globl _double_fault,_coprocessor_segment_overrun
  92 .globl _invalid_TSS,_segment_not_present,_stack_segment
  93 .globl _general_protection,_reserved
  94 .globl _alignment_check,_page_fault
  95 .globl ret_from_sys_call
  96 
  97 #define SAVE_ALL \
  98         cld; \
  99         push %gs; \
 100         push %fs; \
 101         push %es; \
 102         push %ds; \
 103         pushl %eax; \
 104         pushl %ebp; \
 105         pushl %edi; \
 106         pushl %esi; \
 107         pushl %edx; \
 108         pushl %ecx; \
 109         pushl %ebx; \
 110         movl $0x10,%edx; \
 111         mov %dx,%ds; \
 112         mov %dx,%es; \
 113         movl $0x17,%edx; \
 114         mov %dx,%fs
 115 
 116 .align 4
 117 reschedule:
 118         pushl $ret_from_sys_call
 119         jmp _schedule
 120 .align 4
 121 _system_call:
 122         pushl %eax                      # save orig_eax
 123         SAVE_ALL
 124         movl $-ENOSYS,EAX(%esp)
 125         cmpl _NR_syscalls,%eax
 126         jae ret_from_sys_call
 127         movl _current,%ebx
 128         testl $0x20,flags(%ebx)         # PF_TRACESYS
 129         je 1f
 130         pushl $0
 131         pushl %ebx
 132         pushl $5                        # SIGTRAP
 133         call _send_sig
 134         addl $12,%esp
 135         call _schedule
 136         movl ORIG_EAX(%esp),%eax
 137 1:      call _sys_call_table(,%eax,4)
 138         movl %eax,EAX(%esp)             # save the return value
 139         movl _current,%eax
 140         testl $0x20,flags(%eax)         # PF_TRACESYS
 141         je ret_from_sys_call
 142         cmpl $0,signal(%eax)
 143         jne ret_from_sys_call           # ptrace would clear signal
 144         pushl $0
 145         pushl %eax
 146         pushl $5                        # SIGTRAP
 147         call _send_sig
 148         addl $12,%esp
 149         call _schedule
 150         .align 4,0x90
 151 ret_from_sys_call:
 152         movl EFLAGS(%esp),%eax          # check VM86 flag: CS/SS are
 153         testl $VM_MASK,%eax             # different then
 154         jne 4f
 155         cmpw $0x0f,CS(%esp)             # was old code segment supervisor ?
 156         jne 2f
 157         cmpw $0x17,OLDSS(%esp)          # was stack segment = 0x17 ?
 158         jne 2f
 159 4:      sti                             # slow interrupts get here with interrupts disabled
 160         orl $IF_MASK,%eax               # these just try to make sure
 161         andl $~NT_MASK,%eax             # the program doesn't do anything
 162         movl %eax,EFLAGS(%esp)          # stupid
 163 1:      cmpl $0,_need_resched
 164         jne reschedule
 165         movl _current,%eax
 166         cmpl _task,%eax                 # task[0] cannot have signals
 167         je 2f
 168         cmpl $0,state(%eax)             # state
 169         jne reschedule
 170         cmpl $0,counter(%eax)           # counter
 171         je reschedule
 172         movl signal(%eax),%ebx
 173         movl blocked(%eax),%ecx
 174         notl %ecx
 175         andl %ebx,%ecx
 176         je 2f                           # XXX - branch is almost always taken
 177         bsfl %ecx,%ecx
 178         btrl %ecx,signal(%eax)          # change atomically (%ebx is stale)
 179         jnc 2f                          # bit became clear (can't happen?)
 180         incl %ecx
 181         movl %esp,%ebx
 182         testl $VM_MASK,EFLAGS(%esp)
 183         je 3f
 184         pushl %ebx
 185         pushl %ecx
 186         call _save_v86_state
 187         popl %ecx
 188         movl %eax,%ebx
 189         movl %eax,%esp
 190 3:      pushl %ebx
 191         pushl %ecx
 192         call _do_signal
 193         popl %ecx
 194         popl %ebx
 195         testl %eax, %eax
 196         jne 1b                  # see if we need to switch tasks, or do more signals
 197 2:      popl %ebx
 198         popl %ecx
 199         popl %edx
 200         popl %esi
 201         popl %edi
 202         popl %ebp
 203         popl %eax
 204         pop %ds
 205         pop %es
 206         pop %fs
 207         pop %gs
 208         addl $4,%esp            # skip the orig_eax
 209         iret
 210 
 211 .align 4
 212 _sys_execve:
 213         lea (EIP+4)(%esp),%eax  # don't forget about the return address.
 214         pushl %eax
 215         call _do_execve
 216         addl $4,%esp
 217         ret
 218 
 219 .align 4
 220 _divide_error:
 221         pushl $0                # no error code
 222         pushl $_do_divide_error
 223 .align 4,0x90
 224 error_code:
 225         push %fs
 226         push %es
 227         push %ds
 228         pushl %eax
 229         pushl %ebp
 230         pushl %edi
 231         pushl %esi
 232         pushl %edx
 233         pushl %ecx
 234         pushl %ebx
 235         cld
 236         movl $-1, %eax
 237         xchgl %eax, ORIG_EAX(%esp)      # orig_eax (get the error code. )
 238         xorl %ebx,%ebx                  # zero ebx
 239         mov %gs,%bx                     # get the lower order bits of gs
 240         xchgl %ebx, GS(%esp)            # get the address and save gs.
 241         pushl %eax                      # push the error code
 242         lea 52(%esp),%edx
 243         pushl %edx
 244         movl $0x10,%edx
 245         mov %dx,%ds
 246         mov %dx,%es
 247         movl $0x17,%edx
 248         mov %dx,%fs
 249         call *%ebx
 250         addl $8,%esp
 251         jmp ret_from_sys_call
 252 
 253 .align 4
 254 _coprocessor_error:
 255         pushl $0
 256         pushl $_do_coprocessor_error
 257         jmp error_code
 258 
 259 .align 4
 260 _device_not_available:
 261         pushl $-1               # mark this as an int
 262         SAVE_ALL
 263         pushl $ret_from_sys_call
 264         clts                            # clear TS so that we can use math
 265         movl %cr0,%eax
 266         testl $0x4,%eax                 # EM (math emulation bit)
 267         je _math_state_restore
 268         pushl $0                # temporary storage for ORIG_EIP
 269         call _math_emulate
 270         addl $4,%esp
 271         ret
 272 
 273 .align 4
 274 _debug:
 275         pushl $0
 276         pushl $_do_debug
 277         jmp error_code
 278 
 279 .align 4
 280 _nmi:
 281         pushl $0
 282         pushl $_do_nmi
 283         jmp error_code
 284 
 285 .align 4
 286 _int3:
 287         pushl $0
 288         pushl $_do_int3
 289         jmp error_code
 290 
 291 .align 4
 292 _overflow:
 293         pushl $0
 294         pushl $_do_overflow
 295         jmp error_code
 296 
 297 .align 4
 298 _bounds:
 299         pushl $0
 300         pushl $_do_bounds
 301         jmp error_code
 302 
 303 .align 4
 304 _invalid_op:
 305         pushl $0
 306         pushl $_do_invalid_op
 307         jmp error_code
 308 
 309 .align 4
 310 _coprocessor_segment_overrun:
 311         pushl $0
 312         pushl $_do_coprocessor_segment_overrun
 313         jmp error_code
 314 
 315 .align 4
 316 _reserved:
 317         pushl $0
 318         pushl $_do_reserved
 319         jmp error_code
 320 
 321 .align 4
 322 _double_fault:
 323         pushl $_do_double_fault
 324         jmp error_code
 325 
 326 .align 4
 327 _invalid_TSS:
 328         pushl $_do_invalid_TSS
 329         jmp error_code
 330 
 331 .align 4
 332 _segment_not_present:
 333         pushl $_do_segment_not_present
 334         jmp error_code
 335 
 336 .align 4
 337 _stack_segment:
 338         pushl $_do_stack_segment
 339         jmp error_code
 340 
 341 .align 4
 342 _general_protection:
 343         pushl $_do_general_protection
 344         jmp error_code
 345 
 346 .align 4
 347 _alignment_check:
 348         pushl $_do_alignment_check
 349         jmp error_code
 350 
 351 .align 4
 352 _page_fault:
 353         pushl $_do_page_fault
 354         jmp error_code

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