root/arch/i386/entry.S

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

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