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 #include <linux/sys.h>
  45 
  46 EBX             = 0x00
  47 ECX             = 0x04
  48 EDX             = 0x08
  49 ESI             = 0x0C
  50 EDI             = 0x10
  51 EBP             = 0x14
  52 EAX             = 0x18
  53 DS              = 0x1C
  54 ES              = 0x20
  55 FS              = 0x24
  56 GS              = 0x28
  57 ORIG_EAX        = 0x2C
  58 EIP             = 0x30
  59 CS              = 0x34
  60 EFLAGS          = 0x38
  61 OLDESP          = 0x3C
  62 OLDSS           = 0x40
  63 
  64 CF_MASK         = 0x00000001
  65 IF_MASK         = 0x00000200
  66 NT_MASK         = 0x00004000
  67 VM_MASK         = 0x00020000
  68 
  69 /*
  70  * these are offsets into the task-struct.
  71  */
  72 state           =  0
  73 counter         =  4
  74 priority        =  8
  75 signal          = 12
  76 blocked         = 16
  77 flags           = 20
  78 errno           = 24
  79 dbgreg6         = 52
  80 dbgreg7         = 56
  81 lcall7          = 60
  82 
  83 ENOSYS = 38
  84 
  85 .globl _system_call,_lcall7
  86 .globl _device_not_available, _coprocessor_error
  87 .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
  88 .globl _double_fault,_coprocessor_segment_overrun
  89 .globl _invalid_TSS,_segment_not_present,_stack_segment
  90 .globl _general_protection,_reserved
  91 .globl _alignment_check,_page_fault
  92 .globl ret_from_sys_call, _sys_call_table
  93 
  94 #define SAVE_ALL \
  95         cld; \
  96         push %gs; \
  97         push %fs; \
  98         push %es; \
  99         push %ds; \
 100         pushl %eax; \
 101         pushl %ebp; \
 102         pushl %edi; \
 103         pushl %esi; \
 104         pushl %edx; \
 105         pushl %ecx; \
 106         pushl %ebx; \
 107         movl $(KERNEL_DS),%edx; \
 108         mov %dx,%ds; \
 109         mov %dx,%es; \
 110         movl $(USER_DS),%edx; \
 111         mov %dx,%fs;
 112 
 113 #define RESTORE_ALL \
 114         cmpw $(KERNEL_CS),CS(%esp); \
 115         je 1f;   \
 116         movl _current,%eax; \
 117         movl dbgreg7(%eax),%ebx; \
 118         movl %ebx,%db7; \
 119 1:      popl %ebx; \
 120         popl %ecx; \
 121         popl %edx; \
 122         popl %esi; \
 123         popl %edi; \
 124         popl %ebp; \
 125         popl %eax; \
 126         pop %ds; \
 127         pop %es; \
 128         pop %fs; \
 129         pop %gs; \
 130         addl $4,%esp; \
 131         iret
 132 
 133 .align 4
 134 _lcall7:
 135         pushfl                  # We get a different stack layout with call gates,
 136         pushl %eax              # which has to be cleaned up later..
 137         SAVE_ALL
 138         movl EIP(%esp),%eax     # due to call gates, this is eflags, not eip..
 139         movl CS(%esp),%edx      # this is eip..
 140         movl EFLAGS(%esp),%ecx  # and this is cs..
 141         movl %eax,EFLAGS(%esp)  #
 142         movl %edx,EIP(%esp)     # Now we move them to their "normal" places
 143         movl %ecx,CS(%esp)      #
 144         movl %esp,%eax
 145         movl _current,%edx
 146         pushl %eax
 147         movl lcall7(%edx),%edx
 148         call *%edx
 149         popl %eax
 150         jmp ret_from_sys_call
 151 
 152 .align 4
 153 handle_bottom_half:
 154         pushfl
 155         incl _intr_count
 156         sti
 157         call _do_bottom_half
 158         popfl
 159         decl _intr_count
 160         jmp 9f
 161 .align 4
 162 reschedule:
 163         pushl $ret_from_sys_call
 164         jmp _schedule
 165 .align 4
 166 _system_call:
 167         pushl %eax                      # save orig_eax
 168         SAVE_ALL
 169         movl $-ENOSYS,EAX(%esp)
 170         cmpl $(NR_syscalls),%eax
 171         jae ret_from_sys_call
 172         movl _sys_call_table(,%eax,4),%eax
 173         testl %eax,%eax
 174         je ret_from_sys_call
 175         movl _current,%ebx
 176         andl $~CF_MASK,EFLAGS(%esp)     # clear carry - assume no errors
 177         movl $0,errno(%ebx)
 178         movl %db6,%edx
 179         movl %edx,dbgreg6(%ebx)  # save current hardware debugging status
 180         testb $0x20,flags(%ebx)         # PF_TRACESYS
 181         jne 1f
 182         call *%eax
 183         movl %eax,EAX(%esp)             # save the return value
 184         movl errno(%ebx),%edx
 185         negl %edx
 186         je ret_from_sys_call
 187         movl %edx,EAX(%esp)
 188         orl $(CF_MASK),EFLAGS(%esp)     # set carry to indicate error
 189         jmp ret_from_sys_call
 190 .align 4
 191 1:      call _syscall_trace
 192         movl ORIG_EAX(%esp),%eax
 193         call _sys_call_table(,%eax,4)
 194         movl %eax,EAX(%esp)             # save the return value
 195         movl _current,%eax
 196         movl errno(%eax),%edx
 197         negl %edx
 198         je 1f
 199         movl %edx,EAX(%esp)
 200         orl $(CF_MASK),EFLAGS(%esp)     # set carry to indicate error
 201 1:      call _syscall_trace
 202 
 203         .align 4,0x90
 204 ret_from_sys_call:
 205         cmpl $0,_intr_count
 206         jne 2f
 207         movl _bh_mask,%eax
 208         andl _bh_active,%eax
 209         jne handle_bottom_half
 210 9:      movl EFLAGS(%esp),%eax          # check VM86 flag: CS/SS are
 211         testl $(VM_MASK),%eax           # different then
 212         jne 1f
 213         cmpw $(KERNEL_CS),CS(%esp)      # was old code segment supervisor ?
 214         je 2f
 215 1:      sti
 216         orl $(IF_MASK),%eax             # these just try to make sure
 217         andl $~NT_MASK,%eax             # the program doesn't do anything
 218         movl %eax,EFLAGS(%esp)          # stupid
 219         cmpl $0,_need_resched
 220         jne reschedule
 221         movl _current,%eax
 222         cmpl _task,%eax                 # task[0] cannot have signals
 223         je 2f
 224         cmpl $0,state(%eax)             # state
 225         jne reschedule
 226         cmpl $0,counter(%eax)           # counter
 227         je reschedule
 228         movl blocked(%eax),%ecx
 229         movl %ecx,%ebx                  # save blocked in %ebx for signal handling
 230         notl %ecx
 231         andl signal(%eax),%ecx
 232         jne signal_return
 233 2:      RESTORE_ALL
 234 .align 4
 235 signal_return:
 236         movl %esp,%ecx
 237         pushl %ecx
 238         testl $(VM_MASK),EFLAGS(%ecx)
 239         jne v86_signal_return
 240         pushl %ebx
 241         call _do_signal
 242         popl %ebx
 243         popl %ebx
 244         RESTORE_ALL
 245 .align 4
 246 v86_signal_return:
 247         call _save_v86_state
 248         movl %eax,%esp
 249         pushl %eax
 250         pushl %ebx
 251         call _do_signal
 252         popl %ebx
 253         popl %ebx
 254         RESTORE_ALL
 255 
 256 .align 4
 257 _divide_error:
 258         pushl $0                # no error code
 259         pushl $_do_divide_error
 260 .align 4,0x90
 261 error_code:
 262         push %fs
 263         push %es
 264         push %ds
 265         pushl %eax
 266         pushl %ebp
 267         pushl %edi
 268         pushl %esi
 269         pushl %edx
 270         pushl %ecx
 271         pushl %ebx
 272         movl $0,%eax
 273         movl %eax,%db7                  # disable hardware debugging...
 274         cld
 275         movl $-1, %eax
 276         xchgl %eax, ORIG_EAX(%esp)      # orig_eax (get the error code. )
 277         xorl %ebx,%ebx                  # zero ebx
 278         mov %gs,%bx                     # get the lower order bits of gs
 279         xchgl %ebx, GS(%esp)            # get the address and save gs.
 280         pushl %eax                      # push the error code
 281         lea 4(%esp),%edx
 282         pushl %edx
 283         movl $(KERNEL_DS),%edx
 284         mov %dx,%ds
 285         mov %dx,%es
 286         movl $(USER_DS),%edx
 287         mov %dx,%fs
 288         pushl %eax
 289         movl _current,%eax
 290         movl %db6,%edx
 291         movl %edx,dbgreg6(%eax)  # save current hardware debugging status
 292         popl %eax
 293         call *%ebx
 294         addl $8,%esp
 295         jmp ret_from_sys_call
 296 
 297 .align 4
 298 _coprocessor_error:
 299         pushl $0
 300         pushl $_do_coprocessor_error
 301         jmp error_code
 302 
 303 .align 4
 304 _device_not_available:
 305         pushl $-1               # mark this as an int
 306         SAVE_ALL
 307         pushl $ret_from_sys_call
 308         movl %cr0,%eax
 309         testl $0x4,%eax                 # EM (math emulation bit)
 310         je _math_state_restore
 311         pushl $0                # temporary storage for ORIG_EIP
 312         call _math_emulate
 313         addl $4,%esp
 314         ret
 315 
 316 .align 4
 317 _debug:
 318         pushl $0
 319         pushl $_do_debug
 320         jmp error_code
 321 
 322 .align 4
 323 _nmi:
 324         pushl $0
 325         pushl $_do_nmi
 326         jmp error_code
 327 
 328 .align 4
 329 _int3:
 330         pushl $0
 331         pushl $_do_int3
 332         jmp error_code
 333 
 334 .align 4
 335 _overflow:
 336         pushl $0
 337         pushl $_do_overflow
 338         jmp error_code
 339 
 340 .align 4
 341 _bounds:
 342         pushl $0
 343         pushl $_do_bounds
 344         jmp error_code
 345 
 346 .align 4
 347 _invalid_op:
 348         pushl $0
 349         pushl $_do_invalid_op
 350         jmp error_code
 351 
 352 .align 4
 353 _coprocessor_segment_overrun:
 354         pushl $0
 355         pushl $_do_coprocessor_segment_overrun
 356         jmp error_code
 357 
 358 .align 4
 359 _reserved:
 360         pushl $0
 361         pushl $_do_reserved
 362         jmp error_code
 363 
 364 .align 4
 365 _double_fault:
 366         pushl $_do_double_fault
 367         jmp error_code
 368 
 369 .align 4
 370 _invalid_TSS:
 371         pushl $_do_invalid_TSS
 372         jmp error_code
 373 
 374 .align 4
 375 _segment_not_present:
 376         pushl $_do_segment_not_present
 377         jmp error_code
 378 
 379 .align 4
 380 _stack_segment:
 381         pushl $_do_stack_segment
 382         jmp error_code
 383 
 384 .align 4
 385 _general_protection:
 386         pushl $_do_general_protection
 387         jmp error_code
 388 
 389 .align 4
 390 _alignment_check:
 391         pushl $_do_alignment_check
 392         jmp error_code
 393 
 394 .align 4
 395 _page_fault:
 396         pushl $_do_page_fault
 397         jmp error_code
 398 
 399 .data
 400 .align 4
 401 _sys_call_table:
 402         .long _sys_setup                /* 0 */
 403         .long _sys_exit
 404         .long _sys_fork
 405         .long _sys_read
 406         .long _sys_write
 407         .long _sys_open                 /* 5 */
 408         .long _sys_close
 409         .long _sys_waitpid
 410         .long _sys_creat
 411         .long _sys_link
 412         .long _sys_unlink               /* 10 */
 413         .long _sys_execve
 414         .long _sys_chdir
 415         .long _sys_time
 416         .long _sys_mknod
 417         .long _sys_chmod                /* 15 */
 418         .long _sys_chown
 419         .long _sys_break
 420         .long _sys_stat
 421         .long _sys_lseek
 422         .long _sys_getpid               /* 20 */
 423         .long _sys_mount
 424         .long _sys_umount
 425         .long _sys_setuid
 426         .long _sys_getuid
 427         .long _sys_stime                /* 25 */
 428         .long _sys_ptrace
 429         .long _sys_alarm
 430         .long _sys_fstat
 431         .long _sys_pause
 432         .long _sys_utime                /* 30 */
 433         .long _sys_stty
 434         .long _sys_gtty
 435         .long _sys_access
 436         .long _sys_nice
 437         .long _sys_ftime                /* 35 */
 438         .long _sys_sync
 439         .long _sys_kill
 440         .long _sys_rename
 441         .long _sys_mkdir
 442         .long _sys_rmdir                /* 40 */
 443         .long _sys_dup
 444         .long _sys_pipe
 445         .long _sys_times
 446         .long _sys_prof
 447         .long _sys_brk                  /* 45 */
 448         .long _sys_setgid
 449         .long _sys_getgid
 450         .long _sys_signal
 451         .long _sys_geteuid
 452         .long _sys_getegid              /* 50 */
 453         .long _sys_acct
 454         .long _sys_phys
 455         .long _sys_lock
 456         .long _sys_ioctl
 457         .long _sys_fcntl                /* 55 */
 458         .long _sys_mpx
 459         .long _sys_setpgid
 460         .long _sys_ulimit
 461         .long _sys_olduname
 462         .long _sys_umask                /* 60 */
 463         .long _sys_chroot
 464         .long _sys_ustat
 465         .long _sys_dup2
 466         .long _sys_getppid
 467         .long _sys_getpgrp              /* 65 */
 468         .long _sys_setsid
 469         .long _sys_sigaction
 470         .long _sys_sgetmask
 471         .long _sys_ssetmask
 472         .long _sys_setreuid             /* 70 */
 473         .long _sys_setregid
 474         .long _sys_sigsuspend
 475         .long _sys_sigpending
 476         .long _sys_sethostname
 477         .long _sys_setrlimit            /* 75 */
 478         .long _sys_getrlimit
 479         .long _sys_getrusage
 480         .long _sys_gettimeofday
 481         .long _sys_settimeofday
 482         .long _sys_getgroups            /* 80 */
 483         .long _sys_setgroups
 484         .long _sys_select
 485         .long _sys_symlink
 486         .long _sys_lstat
 487         .long _sys_readlink             /* 85 */
 488         .long _sys_uselib
 489         .long _sys_swapon
 490         .long _sys_reboot
 491         .long _sys_readdir
 492         .long _sys_mmap                 /* 90 */
 493         .long _sys_munmap
 494         .long _sys_truncate
 495         .long _sys_ftruncate
 496         .long _sys_fchmod
 497         .long _sys_fchown               /* 95 */
 498         .long _sys_getpriority
 499         .long _sys_setpriority
 500         .long _sys_profil
 501         .long _sys_statfs
 502         .long _sys_fstatfs              /* 100 */
 503         .long _sys_ioperm
 504         .long _sys_socketcall
 505         .long _sys_syslog
 506         .long _sys_setitimer
 507         .long _sys_getitimer            /* 105 */
 508         .long _sys_newstat
 509         .long _sys_newlstat
 510         .long _sys_newfstat
 511         .long _sys_uname
 512         .long _sys_iopl                 /* 110 */
 513         .long _sys_vhangup
 514         .long _sys_idle
 515         .long _sys_vm86
 516         .long _sys_wait4
 517         .long _sys_swapoff              /* 115 */
 518         .long _sys_sysinfo
 519         .long _sys_ipc
 520         .long _sys_fsync
 521         .long _sys_sigreturn
 522         .long _sys_clone                /* 120 */
 523         .long _sys_setdomainname
 524         .long _sys_newuname
 525         .long _sys_modify_ldt
 526         .long _sys_adjtimex
 527         .long _sys_mprotect             /* 125 */
 528         .long _sys_sigprocmask
 529         .long _sys_create_module
 530         .long _sys_init_module
 531         .long _sys_delete_module
 532         .long _sys_get_kernel_syms      /* 130 */
 533         .long _sys_quotactl
 534         .long _sys_getpgid
 535         .long _sys_fchdir
 536         .long _sys_bdflush
 537         .long _sys_sysfs                /* 135 */
 538 
 539         .space (NR_syscalls-135)*4

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