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 #include <linux/segment.h>
  44 
  45 EBX             = 0x00
  46 ECX             = 0x04
  47 EDX             = 0x08
  48 ESI             = 0x0C
  49 EDI             = 0x10
  50 EBP             = 0x14
  51 EAX             = 0x18
  52 DS              = 0x1C
  53 ES              = 0x20
  54 FS              = 0x24
  55 GS              = 0x28
  56 ORIG_EAX        = 0x2C
  57 EIP             = 0x30
  58 CS              = 0x34
  59 EFLAGS          = 0x38
  60 OLDESP          = 0x3C
  61 OLDSS           = 0x40
  62 
  63 CF_MASK         = 0x00000001
  64 IF_MASK         = 0x00000200
  65 NT_MASK         = 0x00004000
  66 VM_MASK         = 0x00020000
  67 
  68 /*
  69  * these are offsets into the task-struct.
  70  */
  71 state           =  0
  72 counter         =  4
  73 priority        =  8
  74 signal          = 12
  75 blocked         = 16
  76 flags           = 20
  77 errno           = 24
  78 
  79 ENOSYS = 38
  80 
  81 .globl _system_call,_lcall7
  82 .globl _device_not_available, _coprocessor_error
  83 .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
  84 .globl _double_fault,_coprocessor_segment_overrun
  85 .globl _invalid_TSS,_segment_not_present,_stack_segment
  86 .globl _general_protection,_reserved
  87 .globl _alignment_check,_page_fault
  88 .globl ret_from_sys_call
  89 
  90 #define SAVE_ALL \
  91         cld; \
  92         push %gs; \
  93         push %fs; \
  94         push %es; \
  95         push %ds; \
  96         pushl %eax; \
  97         pushl %ebp; \
  98         pushl %edi; \
  99         pushl %esi; \
 100         pushl %edx; \
 101         pushl %ecx; \
 102         pushl %ebx; \
 103         movl $(KERNEL_DS),%edx; \
 104         mov %dx,%ds; \
 105         mov %dx,%es; \
 106         movl $(USER_DS),%edx; \
 107         mov %dx,%fs
 108 
 109 #define RESTORE_ALL \
 110         popl %ebx; \
 111         popl %ecx; \
 112         popl %edx; \
 113         popl %esi; \
 114         popl %edi; \
 115         popl %ebp; \
 116         popl %eax; \
 117         pop %ds; \
 118         pop %es; \
 119         pop %fs; \
 120         pop %gs; \
 121         addl $4,%esp; \
 122         iret
 123 
 124 .align 4
 125 _lcall7:
 126         pushfl                  # We get a different stack layout with call gates,
 127         pushl %eax              # which has to be cleaned up later..
 128         SAVE_ALL
 129         movl EIP(%esp),%eax     # due to call gates, this is eflags, not eip..
 130         movl CS(%esp),%edx      # this is eip..
 131         movl EFLAGS(%esp),%ecx  # and this is cs..
 132         movl %eax,EFLAGS(%esp)  #
 133         movl %edx,EIP(%esp)     # Now we move them to their "normal" places
 134         movl %ecx,CS(%esp)      #
 135         movl %esp,%eax
 136         pushl %eax
 137         call _iABI_emulate
 138         popl %eax
 139         jmp ret_from_sys_call
 140 
 141 .align 4
 142 handle_bottom_half:
 143         pushfl
 144         incl _intr_count
 145         sti
 146         call _do_bottom_half
 147         popfl
 148         decl _intr_count
 149         jmp 9f
 150 .align 4
 151 reschedule:
 152         pushl $ret_from_sys_call
 153         jmp _schedule
 154 .align 4
 155 _system_call:
 156         pushl %eax                      # save orig_eax
 157         SAVE_ALL
 158         movl $-ENOSYS,EAX(%esp)
 159         cmpl _NR_syscalls,%eax
 160         jae ret_from_sys_call
 161         movl _current,%ebx
 162         andl $~CF_MASK,EFLAGS(%esp)     # clear carry - assume no errors
 163         movl $0,errno(%ebx)
 164         testb $0x20,flags(%ebx)         # PF_TRACESYS
 165         jne 1f
 166         call _sys_call_table(,%eax,4)
 167         movl %eax,EAX(%esp)             # save the return value
 168         movl errno(%ebx),%edx
 169         negl %edx
 170         je ret_from_sys_call
 171         movl %edx,EAX(%esp)
 172         orl $(CF_MASK),EFLAGS(%esp)     # set carry to indicate error
 173         jmp ret_from_sys_call
 174 .align 4
 175 1:      call _syscall_trace
 176         movl ORIG_EAX(%esp),%eax
 177         call _sys_call_table(,%eax,4)
 178         movl %eax,EAX(%esp)             # save the return value
 179         movl _current,%eax
 180         movl errno(%eax),%edx
 181         negl %edx
 182         je 1f
 183         movl %edx,EAX(%esp)
 184         orl $(CF_MASK),EFLAGS(%esp)     # set carry to indicate error
 185 1:      call _syscall_trace
 186 
 187         .align 4,0x90
 188 ret_from_sys_call:
 189         cmpl $0,_intr_count
 190         jne 2f
 191         movl _bh_mask,%eax
 192         andl _bh_active,%eax
 193         jne handle_bottom_half
 194 9:      movl EFLAGS(%esp),%eax          # check VM86 flag: CS/SS are
 195         testl $(VM_MASK),%eax           # different then
 196         jne 1f
 197         cmpw $(USER_CS),CS(%esp)        # was old code segment supervisor ?
 198         jne 2f
 199         cmpw $(USER_DS),OLDSS(%esp)     # was stack segment user segment ?
 200         jne 2f
 201 1:      sti
 202         orl $(IF_MASK),%eax             # these just try to make sure
 203         andl $~NT_MASK,%eax             # the program doesn't do anything
 204         movl %eax,EFLAGS(%esp)          # stupid
 205         cmpl $0,_need_resched
 206         jne reschedule
 207         movl _current,%eax
 208         cmpl _task,%eax                 # task[0] cannot have signals
 209         je 2f
 210         cmpl $0,state(%eax)             # state
 211         jne reschedule
 212         cmpl $0,counter(%eax)           # counter
 213         je reschedule
 214         movl blocked(%eax),%ecx
 215         movl %ecx,%ebx                  # save blocked in %ebx for signal handling
 216         notl %ecx
 217         andl signal(%eax),%ecx
 218         jne signal_return
 219 2:      RESTORE_ALL
 220 .align 4
 221 signal_return:
 222         movl %esp,%ecx
 223         pushl %ecx
 224         testl $(VM_MASK),EFLAGS(%ecx)
 225         jne v86_signal_return
 226         pushl %ebx
 227         call _do_signal
 228         popl %ebx
 229         popl %ebx
 230         RESTORE_ALL
 231 .align 4
 232 v86_signal_return:
 233         call _save_v86_state
 234         movl %eax,%esp
 235         pushl %eax
 236         pushl %ebx
 237         call _do_signal
 238         popl %ebx
 239         popl %ebx
 240         RESTORE_ALL
 241 
 242 .align 4
 243 _divide_error:
 244         pushl $0                # no error code
 245         pushl $_do_divide_error
 246 .align 4,0x90
 247 error_code:
 248         push %fs
 249         push %es
 250         push %ds
 251         pushl %eax
 252         pushl %ebp
 253         pushl %edi
 254         pushl %esi
 255         pushl %edx
 256         pushl %ecx
 257         pushl %ebx
 258         cld
 259         movl $-1, %eax
 260         xchgl %eax, ORIG_EAX(%esp)      # orig_eax (get the error code. )
 261         xorl %ebx,%ebx                  # zero ebx
 262         mov %gs,%bx                     # get the lower order bits of gs
 263         xchgl %ebx, GS(%esp)            # get the address and save gs.
 264         pushl %eax                      # push the error code
 265         lea 4(%esp),%edx
 266         pushl %edx
 267         movl $(KERNEL_DS),%edx
 268         mov %dx,%ds
 269         mov %dx,%es
 270         movl $(USER_DS),%edx
 271         mov %dx,%fs
 272         call *%ebx
 273         addl $8,%esp
 274         jmp ret_from_sys_call
 275 
 276 .align 4
 277 _coprocessor_error:
 278         pushl $0
 279         pushl $_do_coprocessor_error
 280         jmp error_code
 281 
 282 .align 4
 283 _device_not_available:
 284         pushl $-1               # mark this as an int
 285         SAVE_ALL
 286         pushl $ret_from_sys_call
 287         movl %cr0,%eax
 288         testl $0x4,%eax                 # EM (math emulation bit)
 289         je _math_state_restore
 290         pushl $0                # temporary storage for ORIG_EIP
 291         call _math_emulate
 292         addl $4,%esp
 293         ret
 294 
 295 .align 4
 296 _debug:
 297         pushl $0
 298         pushl $_do_debug
 299         jmp error_code
 300 
 301 .align 4
 302 _nmi:
 303         pushl $0
 304         pushl $_do_nmi
 305         jmp error_code
 306 
 307 .align 4
 308 _int3:
 309         pushl $0
 310         pushl $_do_int3
 311         jmp error_code
 312 
 313 .align 4
 314 _overflow:
 315         pushl $0
 316         pushl $_do_overflow
 317         jmp error_code
 318 
 319 .align 4
 320 _bounds:
 321         pushl $0
 322         pushl $_do_bounds
 323         jmp error_code
 324 
 325 .align 4
 326 _invalid_op:
 327         pushl $0
 328         pushl $_do_invalid_op
 329         jmp error_code
 330 
 331 .align 4
 332 _coprocessor_segment_overrun:
 333         pushl $0
 334         pushl $_do_coprocessor_segment_overrun
 335         jmp error_code
 336 
 337 .align 4
 338 _reserved:
 339         pushl $0
 340         pushl $_do_reserved
 341         jmp error_code
 342 
 343 .align 4
 344 _double_fault:
 345         pushl $_do_double_fault
 346         jmp error_code
 347 
 348 .align 4
 349 _invalid_TSS:
 350         pushl $_do_invalid_TSS
 351         jmp error_code
 352 
 353 .align 4
 354 _segment_not_present:
 355         pushl $_do_segment_not_present
 356         jmp error_code
 357 
 358 .align 4
 359 _stack_segment:
 360         pushl $_do_stack_segment
 361         jmp error_code
 362 
 363 .align 4
 364 _general_protection:
 365         pushl $_do_general_protection
 366         jmp error_code
 367 
 368 .align 4
 369 _alignment_check:
 370         pushl $_do_alignment_check
 371         jmp error_code
 372 
 373 .align 4
 374 _page_fault:
 375         pushl $_do_page_fault
 376         jmp error_code

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