root/arch/i386/kernel/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 #include <linux/sys.h>
  44 #include <linux/linkage.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 #define SAVE_ALL \
  87         cld; \
  88         push %gs; \
  89         push %fs; \
  90         push %es; \
  91         push %ds; \
  92         pushl %eax; \
  93         pushl %ebp; \
  94         pushl %edi; \
  95         pushl %esi; \
  96         pushl %edx; \
  97         pushl %ecx; \
  98         pushl %ebx; \
  99         movl $(KERNEL_DS),%edx; \
 100         mov %dx,%ds; \
 101         mov %dx,%es; \
 102         movl $(USER_DS),%edx; \
 103         mov %dx,%fs;
 104 
 105 #define RESTORE_ALL \
 106         cmpw $(KERNEL_CS),CS(%esp); \
 107         je 1f;   \
 108         movl SYMBOL_NAME(current),%eax; \
 109         movl dbgreg7(%eax),%ebx; \
 110         movl %ebx,%db7; \
 111 1:      popl %ebx; \
 112         popl %ecx; \
 113         popl %edx; \
 114         popl %esi; \
 115         popl %edi; \
 116         popl %ebp; \
 117         popl %eax; \
 118         pop %ds; \
 119         pop %es; \
 120         pop %fs; \
 121         pop %gs; \
 122         addl $4,%esp; \
 123         iret
 124 
 125 ENTRY(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         movl SYMBOL_NAME(current),%edx
 137         pushl %eax
 138         movl exec_domain(%edx),%edx     # Get the execution domain
 139         movl 4(%edx),%edx       # Get the lcall7 handler for the domain
 140         call *%edx
 141         popl %eax
 142         jmp ret_from_sys_call
 143 
 144         ALIGN
 145 handle_bottom_half:
 146         pushfl
 147         incl SYMBOL_NAME(intr_count)
 148         sti
 149         call SYMBOL_NAME(do_bottom_half)
 150         popfl
 151         decl SYMBOL_NAME(intr_count)
 152         jmp 9f
 153         ALIGN
 154 reschedule:
 155         pushl $ret_from_sys_call
 156         jmp SYMBOL_NAME(schedule)
 157 
 158 ENTRY(system_call)
 159         pushl %eax                      # save orig_eax
 160         SAVE_ALL
 161         movl $-ENOSYS,EAX(%esp)
 162         cmpl $(NR_syscalls),%eax
 163         jae ret_from_sys_call
 164         movl SYMBOL_NAME(sys_call_table)(,%eax,4),%eax
 165         testl %eax,%eax
 166         je ret_from_sys_call
 167         movl SYMBOL_NAME(current),%ebx
 168         andl $~CF_MASK,EFLAGS(%esp)     # clear carry - assume no errors
 169         movl $0,errno(%ebx)
 170         movl %db6,%edx
 171         movl %edx,dbgreg6(%ebx)  # save current hardware debugging status
 172         testb $0x20,flags(%ebx)         # PF_TRACESYS
 173         jne 1f
 174         call *%eax
 175         movl %eax,EAX(%esp)             # save the return value
 176         movl errno(%ebx),%edx
 177         negl %edx
 178         je ret_from_sys_call
 179         movl %edx,EAX(%esp)
 180         orl $(CF_MASK),EFLAGS(%esp)     # set carry to indicate error
 181         jmp ret_from_sys_call
 182         ALIGN
 183 1:      call SYMBOL_NAME(syscall_trace)
 184         movl ORIG_EAX(%esp),%eax
 185         call SYMBOL_NAME(sys_call_table)(,%eax,4)
 186         movl %eax,EAX(%esp)             # save the return value
 187         movl SYMBOL_NAME(current),%eax
 188         movl errno(%eax),%edx
 189         negl %edx
 190         je 1f
 191         movl %edx,EAX(%esp)
 192         orl $(CF_MASK),EFLAGS(%esp)     # set carry to indicate error
 193 1:      call SYMBOL_NAME(syscall_trace)
 194 
 195         ALIGN
 196         .globl ret_from_sys_call
 197 ret_from_sys_call:
 198         cmpl $0,SYMBOL_NAME(intr_count)
 199         jne 2f
 200 9:      movl SYMBOL_NAME(bh_mask),%eax
 201         andl SYMBOL_NAME(bh_active),%eax
 202         jne handle_bottom_half
 203         movl EFLAGS(%esp),%eax          # check VM86 flag: CS/SS are
 204         testl $(VM_MASK),%eax           # different then
 205         jne 1f
 206         cmpw $(KERNEL_CS),CS(%esp)      # was old code segment supervisor ?
 207         je 2f
 208 1:      sti
 209         orl $(IF_MASK),%eax             # these just try to make sure
 210         andl $~NT_MASK,%eax             # the program doesn't do anything
 211         movl %eax,EFLAGS(%esp)          # stupid
 212         cmpl $0,SYMBOL_NAME(need_resched)
 213         jne reschedule
 214         movl SYMBOL_NAME(current),%eax
 215         cmpl SYMBOL_NAME(task),%eax     # task[0] cannot have signals
 216         je 2f
 217         cmpl $0,state(%eax)             # state
 218         jne reschedule
 219         cmpl $0,counter(%eax)           # counter
 220         je reschedule
 221         movl blocked(%eax),%ecx
 222         movl %ecx,%ebx                  # save blocked in %ebx for signal handling
 223         notl %ecx
 224         andl signal(%eax),%ecx
 225         jne signal_return
 226 2:      RESTORE_ALL
 227         ALIGN
 228 signal_return:
 229         movl %esp,%ecx
 230         pushl %ecx
 231         testl $(VM_MASK),EFLAGS(%ecx)
 232         jne v86_signal_return
 233         pushl %ebx
 234         call SYMBOL_NAME(do_signal)
 235         popl %ebx
 236         popl %ebx
 237         RESTORE_ALL
 238         ALIGN
 239 v86_signal_return:
 240         call SYMBOL_NAME(save_v86_state)
 241         movl %eax,%esp
 242         pushl %eax
 243         pushl %ebx
 244         call SYMBOL_NAME(do_signal)
 245         popl %ebx
 246         popl %ebx
 247         RESTORE_ALL
 248 
 249 ENTRY(divide_error)
 250         pushl $0                # no error code
 251         pushl $ SYMBOL_NAME(do_divide_error)
 252         ALIGN
 253 error_code:
 254         push %fs
 255         push %es
 256         push %ds
 257         pushl %eax
 258         pushl %ebp
 259         pushl %edi
 260         pushl %esi
 261         pushl %edx
 262         pushl %ecx
 263         pushl %ebx
 264         movl $0,%eax
 265         movl %eax,%db7                  # disable hardware debugging...
 266         cld
 267         movl $-1, %eax
 268         xchgl %eax, ORIG_EAX(%esp)      # orig_eax (get the error code. )
 269         xorl %ebx,%ebx                  # zero ebx
 270         mov %gs,%bx                     # get the lower order bits of gs
 271         xchgl %ebx, GS(%esp)            # get the address and save gs.
 272         pushl %eax                      # push the error code
 273         lea 4(%esp),%edx
 274         pushl %edx
 275         movl $(KERNEL_DS),%edx
 276         mov %dx,%ds
 277         mov %dx,%es
 278         movl $(USER_DS),%edx
 279         mov %dx,%fs
 280         pushl %eax
 281         movl SYMBOL_NAME(current),%eax
 282         movl %db6,%edx
 283         movl %edx,dbgreg6(%eax)  # save current hardware debugging status
 284         popl %eax
 285         call *%ebx
 286         addl $8,%esp
 287         jmp ret_from_sys_call
 288 
 289 ENTRY(coprocessor_error)
 290         pushl $0
 291         pushl $ SYMBOL_NAME(do_coprocessor_error)
 292         jmp error_code
 293 
 294 ENTRY(device_not_available)
 295         pushl $-1               # mark this as an int
 296         SAVE_ALL
 297         pushl $ret_from_sys_call
 298         movl %cr0,%eax
 299         testl $0x4,%eax                 # EM (math emulation bit)
 300         je SYMBOL_NAME(math_state_restore)
 301         pushl $0                # temporary storage for ORIG_EIP
 302         call  SYMBOL_NAME(math_emulate)
 303         addl $4,%esp
 304         ret
 305 
 306 ENTRY(debug)
 307         pushl $0
 308         pushl $ SYMBOL_NAME(do_debug)
 309         jmp error_code
 310 
 311 ENTRY(nmi)
 312         pushl $0
 313         pushl $ SYMBOL_NAME(do_nmi)
 314         jmp error_code
 315 
 316 ENTRY(int3)
 317         pushl $0
 318         pushl $ SYMBOL_NAME(do_int3)
 319         jmp error_code
 320 
 321 ENTRY(overflow)
 322         pushl $0
 323         pushl $ SYMBOL_NAME(do_overflow)
 324         jmp error_code
 325 
 326 ENTRY(bounds)
 327         pushl $0
 328         pushl $ SYMBOL_NAME(do_bounds)
 329         jmp error_code
 330 
 331 ENTRY(invalid_op)
 332         pushl $0
 333         pushl $ SYMBOL_NAME(do_invalid_op)
 334         jmp error_code
 335 
 336 ENTRY(coprocessor_segment_overrun)
 337         pushl $0
 338         pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun)
 339         jmp error_code
 340 
 341 ENTRY(reserved)
 342         pushl $0
 343         pushl $ SYMBOL_NAME(do_reserved)
 344         jmp error_code
 345 
 346 ENTRY(double_fault)
 347         pushl $ SYMBOL_NAME(do_double_fault)
 348         jmp error_code
 349 
 350 ENTRY(invalid_TSS)
 351         pushl $ SYMBOL_NAME(do_invalid_TSS)
 352         jmp error_code
 353 
 354 ENTRY(segment_not_present)
 355         pushl $ SYMBOL_NAME(do_segment_not_present)
 356         jmp error_code
 357 
 358 ENTRY(stack_segment)
 359         pushl $ SYMBOL_NAME(do_stack_segment)
 360         jmp error_code
 361 
 362 ENTRY(general_protection)
 363         pushl $ SYMBOL_NAME(do_general_protection)
 364         jmp error_code
 365 
 366 ENTRY(alignment_check)
 367         pushl $ SYMBOL_NAME(do_alignment_check)
 368         jmp error_code
 369 
 370 ENTRY(page_fault)
 371         pushl $ SYMBOL_NAME(do_page_fault)
 372         jmp error_code
 373 
 374 .data
 375 ENTRY(sys_call_table)
 376         .long SYMBOL_NAME(sys_setup)            /* 0 */
 377         .long SYMBOL_NAME(sys_exit)
 378         .long SYMBOL_NAME(sys_fork)
 379         .long SYMBOL_NAME(sys_read)
 380         .long SYMBOL_NAME(sys_write)
 381         .long SYMBOL_NAME(sys_open)             /* 5 */
 382         .long SYMBOL_NAME(sys_close)
 383         .long SYMBOL_NAME(sys_waitpid)
 384         .long SYMBOL_NAME(sys_creat)
 385         .long SYMBOL_NAME(sys_link)
 386         .long SYMBOL_NAME(sys_unlink)           /* 10 */
 387         .long SYMBOL_NAME(sys_execve)
 388         .long SYMBOL_NAME(sys_chdir)
 389         .long SYMBOL_NAME(sys_time)
 390         .long SYMBOL_NAME(sys_mknod)
 391         .long SYMBOL_NAME(sys_chmod)            /* 15 */
 392         .long SYMBOL_NAME(sys_chown)
 393         .long SYMBOL_NAME(sys_break)
 394         .long SYMBOL_NAME(sys_stat)
 395         .long SYMBOL_NAME(sys_lseek)
 396         .long SYMBOL_NAME(sys_getpid)           /* 20 */
 397         .long SYMBOL_NAME(sys_mount)
 398         .long SYMBOL_NAME(sys_umount)
 399         .long SYMBOL_NAME(sys_setuid)
 400         .long SYMBOL_NAME(sys_getuid)
 401         .long SYMBOL_NAME(sys_stime)            /* 25 */
 402         .long SYMBOL_NAME(sys_ptrace)
 403         .long SYMBOL_NAME(sys_alarm)
 404         .long SYMBOL_NAME(sys_fstat)
 405         .long SYMBOL_NAME(sys_pause)
 406         .long SYMBOL_NAME(sys_utime)            /* 30 */
 407         .long SYMBOL_NAME(sys_stty)
 408         .long SYMBOL_NAME(sys_gtty)
 409         .long SYMBOL_NAME(sys_access)
 410         .long SYMBOL_NAME(sys_nice)
 411         .long SYMBOL_NAME(sys_ftime)            /* 35 */
 412         .long SYMBOL_NAME(sys_sync)
 413         .long SYMBOL_NAME(sys_kill)
 414         .long SYMBOL_NAME(sys_rename)
 415         .long SYMBOL_NAME(sys_mkdir)
 416         .long SYMBOL_NAME(sys_rmdir)            /* 40 */
 417         .long SYMBOL_NAME(sys_dup)
 418         .long SYMBOL_NAME(sys_pipe)
 419         .long SYMBOL_NAME(sys_times)
 420         .long SYMBOL_NAME(sys_prof)
 421         .long SYMBOL_NAME(sys_brk)              /* 45 */
 422         .long SYMBOL_NAME(sys_setgid)
 423         .long SYMBOL_NAME(sys_getgid)
 424         .long SYMBOL_NAME(sys_signal)
 425         .long SYMBOL_NAME(sys_geteuid)
 426         .long SYMBOL_NAME(sys_getegid)          /* 50 */
 427         .long SYMBOL_NAME(sys_acct)
 428         .long SYMBOL_NAME(sys_phys)
 429         .long SYMBOL_NAME(sys_lock)
 430         .long SYMBOL_NAME(sys_ioctl)
 431         .long SYMBOL_NAME(sys_fcntl)            /* 55 */
 432         .long SYMBOL_NAME(sys_mpx)
 433         .long SYMBOL_NAME(sys_setpgid)
 434         .long SYMBOL_NAME(sys_ulimit)
 435         .long SYMBOL_NAME(sys_olduname)
 436         .long SYMBOL_NAME(sys_umask)            /* 60 */
 437         .long SYMBOL_NAME(sys_chroot)
 438         .long SYMBOL_NAME(sys_ustat)
 439         .long SYMBOL_NAME(sys_dup2)
 440         .long SYMBOL_NAME(sys_getppid)
 441         .long SYMBOL_NAME(sys_getpgrp)          /* 65 */
 442         .long SYMBOL_NAME(sys_setsid)
 443         .long SYMBOL_NAME(sys_sigaction)
 444         .long SYMBOL_NAME(sys_sgetmask)
 445         .long SYMBOL_NAME(sys_ssetmask)
 446         .long SYMBOL_NAME(sys_setreuid)         /* 70 */
 447         .long SYMBOL_NAME(sys_setregid)
 448         .long SYMBOL_NAME(sys_sigsuspend)
 449         .long SYMBOL_NAME(sys_sigpending)
 450         .long SYMBOL_NAME(sys_sethostname)
 451         .long SYMBOL_NAME(sys_setrlimit)        /* 75 */
 452         .long SYMBOL_NAME(sys_getrlimit)
 453         .long SYMBOL_NAME(sys_getrusage)
 454         .long SYMBOL_NAME(sys_gettimeofday)
 455         .long SYMBOL_NAME(sys_settimeofday)
 456         .long SYMBOL_NAME(sys_getgroups)        /* 80 */
 457         .long SYMBOL_NAME(sys_setgroups)
 458         .long SYMBOL_NAME(old_select)
 459         .long SYMBOL_NAME(sys_symlink)
 460         .long SYMBOL_NAME(sys_lstat)
 461         .long SYMBOL_NAME(sys_readlink)         /* 85 */
 462         .long SYMBOL_NAME(sys_uselib)
 463         .long SYMBOL_NAME(sys_swapon)
 464         .long SYMBOL_NAME(sys_reboot)
 465         .long SYMBOL_NAME(old_readdir)
 466         .long SYMBOL_NAME(old_mmap)             /* 90 */
 467         .long SYMBOL_NAME(sys_munmap)
 468         .long SYMBOL_NAME(sys_truncate)
 469         .long SYMBOL_NAME(sys_ftruncate)
 470         .long SYMBOL_NAME(sys_fchmod)
 471         .long SYMBOL_NAME(sys_fchown)           /* 95 */
 472         .long SYMBOL_NAME(sys_getpriority)
 473         .long SYMBOL_NAME(sys_setpriority)
 474         .long SYMBOL_NAME(sys_profil)
 475         .long SYMBOL_NAME(sys_statfs)
 476         .long SYMBOL_NAME(sys_fstatfs)          /* 100 */
 477         .long SYMBOL_NAME(sys_ioperm)
 478         .long SYMBOL_NAME(sys_socketcall)
 479         .long SYMBOL_NAME(sys_syslog)
 480         .long SYMBOL_NAME(sys_setitimer)
 481         .long SYMBOL_NAME(sys_getitimer)        /* 105 */
 482         .long SYMBOL_NAME(sys_newstat)
 483         .long SYMBOL_NAME(sys_newlstat)
 484         .long SYMBOL_NAME(sys_newfstat)
 485         .long SYMBOL_NAME(sys_uname)
 486         .long SYMBOL_NAME(sys_iopl)             /* 110 */
 487         .long SYMBOL_NAME(sys_vhangup)
 488         .long SYMBOL_NAME(sys_idle)
 489         .long SYMBOL_NAME(sys_vm86)
 490         .long SYMBOL_NAME(sys_wait4)
 491         .long SYMBOL_NAME(sys_swapoff)          /* 115 */
 492         .long SYMBOL_NAME(sys_sysinfo)
 493         .long SYMBOL_NAME(sys_ipc)
 494         .long SYMBOL_NAME(sys_fsync)
 495         .long SYMBOL_NAME(sys_sigreturn)
 496         .long SYMBOL_NAME(sys_clone)            /* 120 */
 497         .long SYMBOL_NAME(sys_setdomainname)
 498         .long SYMBOL_NAME(sys_newuname)
 499         .long SYMBOL_NAME(sys_modify_ldt)
 500         .long SYMBOL_NAME(sys_adjtimex)
 501         .long SYMBOL_NAME(sys_mprotect)         /* 125 */
 502         .long SYMBOL_NAME(sys_sigprocmask)
 503         .long SYMBOL_NAME(sys_create_module)
 504         .long SYMBOL_NAME(sys_init_module)
 505         .long SYMBOL_NAME(sys_delete_module)
 506         .long SYMBOL_NAME(sys_get_kernel_syms)  /* 130 */
 507         .long SYMBOL_NAME(sys_quotactl)
 508         .long SYMBOL_NAME(sys_getpgid)
 509         .long SYMBOL_NAME(sys_fchdir)
 510         .long SYMBOL_NAME(sys_bdflush)
 511         .long SYMBOL_NAME(sys_sysfs)            /* 135 */
 512         .long SYMBOL_NAME(sys_personality)
 513         .long 0                                 /* for afs_syscall */
 514         .long SYMBOL_NAME(sys_setfsuid)
 515         .long SYMBOL_NAME(sys_setfsgid)
 516         .long SYMBOL_NAME(sys_llseek)           /* 140 */
 517         .long SYMBOL_NAME(sys_getdents)
 518         .long SYMBOL_NAME(sys_select)
 519         .long SYMBOL_NAME(sys_flock)
 520         .space (NR_syscalls-143)*4

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