2 * linux/arch/i386/entry.S
4 * Copyright (C) 1991, 1992 Linus Torvalds
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.
12 * NOTE: This code handles signal-recognition, which happens every time
13 * after a timer-interrupt and after each system call.
15 * I changed all the .align's to 4 (16 byte alignment), as that's faster
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
40 * "current" is in register %ebx during any slow entries.
43 #include <linux/sys.h>
44 #include <linux/linkage.h>
45 #include <asm/segment.h>
71 * these are offsets into the task-struct.
94 movl $(__KERNEL_DS),%edx; \
110 .section fixup,"ax"; \
120 .section __ex_table,"a";\
127 #define GET_CURRENT(reg) \
132 pushfl # We get a different stack layout with call gates,
133 pushl %eax # which has to be cleaned up later..
135 movl EIP(%esp),%eax # due to call gates, this is eflags, not eip..
136 movl CS(%esp),%edx # this is eip..
137 movl EFLAGS(%esp),%ecx # and this is cs..
138 movl %eax,EFLAGS(%esp) #
139 movl %edx,EIP(%esp) # Now we move them to their "normal" places
143 andl $-8192,%ebx # GET_CURRENT
144 movl exec_domain(%ebx),%edx # Get the execution domain
145 movl 4(%edx),%edx # Get the lcall7 handler for the domain
148 jmp ret_from_sys_call
153 .globl ret_from_smpfork
157 btrl $0, SYMBOL_NAME(scheduler_lock)
158 jmp ret_from_sys_call
162 * Return to user mode is not as complex as all this looks,
163 * but we want the default path for a system call return to
164 * go as quickly as possible which is why some of this is
165 * less clear than it otherwise should be.
169 pushl %eax # save orig_eax
172 cmpl $(NR_syscalls),%eax
174 testb $0x20,flags(%ebx) # PF_TRACESYS
176 call *SYMBOL_NAME(sys_call_table)(,%eax,4)
177 movl %eax,EAX(%esp) # save the return value
179 .globl ret_from_sys_call
182 movl SYMBOL_NAME(bh_mask),%eax
183 andl SYMBOL_NAME(bh_active),%eax
184 jne handle_bottom_half
186 cmpl $0,need_resched(%ebx)
188 cmpl $0,sigpending(%ebx)
193 testl $(VM_MASK),EFLAGS(%esp)
195 jne v86_signal_return
197 call SYMBOL_NAME(do_signal)
202 call SYMBOL_NAME(save_v86_state)
206 call SYMBOL_NAME(do_signal)
211 movl $-ENOSYS,EAX(%esp)
212 call SYMBOL_NAME(syscall_trace)
213 movl ORIG_EAX(%esp),%eax
214 call *SYMBOL_NAME(sys_call_table)(,%eax,4)
215 movl %eax,EAX(%esp) # save the return value
216 call SYMBOL_NAME(syscall_trace)
217 jmp ret_from_sys_call
219 movl $-ENOSYS,EAX(%esp)
220 jmp ret_from_sys_call
224 movl SYMBOL_NAME(bh_mask),%eax
225 andl SYMBOL_NAME(bh_active),%eax
226 jne handle_bottom_half
230 movl EFLAGS(%esp),%eax # mix EFLAGS and CS
232 testl $(VM_MASK | 3),%eax # return to VM86 mode or non-supervisor?
233 jne ret_with_reschedule
239 jmp SYMBOL_NAME(do_bottom_half)
243 pushl $ret_from_sys_call
244 jmp SYMBOL_NAME(schedule) # test
248 pushl $0 # no error code
249 pushl $ SYMBOL_NAME(do_divide_error)
264 xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. )
266 xchgl %ecx, ES(%esp) # get the address and save es.
267 pushl %eax # push the error code
269 movl $(__KERNEL_DS),%edx
275 jmp ret_from_exception
277 ENTRY(coprocessor_error)
279 pushl $ SYMBOL_NAME(do_coprocessor_error)
282 ENTRY(device_not_available)
283 pushl $-1 # mark this as an int
286 pushl $ret_from_exception
288 testl $0x4,%eax # EM (math emulation bit)
289 je SYMBOL_NAME(math_state_restore)
290 pushl $0 # temporary storage for ORIG_EIP
291 call SYMBOL_NAME(math_emulate)
297 pushl $ SYMBOL_NAME(do_debug)
302 pushl $ SYMBOL_NAME(do_nmi)
307 pushl $ SYMBOL_NAME(do_int3)
312 pushl $ SYMBOL_NAME(do_overflow)
317 pushl $ SYMBOL_NAME(do_bounds)
322 pushl $ SYMBOL_NAME(do_invalid_op)
325 ENTRY(coprocessor_segment_overrun)
327 pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun)
332 pushl $ SYMBOL_NAME(do_reserved)
336 pushl $ SYMBOL_NAME(do_double_fault)
340 pushl $ SYMBOL_NAME(do_invalid_TSS)
343 ENTRY(segment_not_present)
344 pushl $ SYMBOL_NAME(do_segment_not_present)
348 pushl $ SYMBOL_NAME(do_stack_segment)
351 ENTRY(general_protection)
352 pushl $ SYMBOL_NAME(do_general_protection)
355 ENTRY(alignment_check)
356 pushl $ SYMBOL_NAME(do_alignment_check)
360 pushl $ SYMBOL_NAME(do_page_fault)
363 ENTRY(spurious_interrupt_bug)
365 pushl $ SYMBOL_NAME(do_spurious_interrupt_bug)
369 ENTRY(sys_call_table)
370 .long SYMBOL_NAME(sys_setup) /* 0 */
371 .long SYMBOL_NAME(sys_exit)
372 .long SYMBOL_NAME(sys_fork)
373 .long SYMBOL_NAME(sys_read)
374 .long SYMBOL_NAME(sys_write)
375 .long SYMBOL_NAME(sys_open) /* 5 */
376 .long SYMBOL_NAME(sys_close)
377 .long SYMBOL_NAME(sys_waitpid)
378 .long SYMBOL_NAME(sys_creat)
379 .long SYMBOL_NAME(sys_link)
380 .long SYMBOL_NAME(sys_unlink) /* 10 */
381 .long SYMBOL_NAME(sys_execve)
382 .long SYMBOL_NAME(sys_chdir)
383 .long SYMBOL_NAME(sys_time)
384 .long SYMBOL_NAME(sys_mknod)
385 .long SYMBOL_NAME(sys_chmod) /* 15 */
386 .long SYMBOL_NAME(sys_lchown)
387 .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */
388 .long SYMBOL_NAME(sys_stat)
389 .long SYMBOL_NAME(sys_lseek)
390 .long SYMBOL_NAME(sys_getpid) /* 20 */
391 .long SYMBOL_NAME(sys_mount)
392 .long SYMBOL_NAME(sys_oldumount)
393 .long SYMBOL_NAME(sys_setuid)
394 .long SYMBOL_NAME(sys_getuid)
395 .long SYMBOL_NAME(sys_stime) /* 25 */
396 .long SYMBOL_NAME(sys_ptrace)
397 .long SYMBOL_NAME(sys_alarm)
398 .long SYMBOL_NAME(sys_fstat)
399 .long SYMBOL_NAME(sys_pause)
400 .long SYMBOL_NAME(sys_utime) /* 30 */
401 .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */
402 .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */
403 .long SYMBOL_NAME(sys_access)
404 .long SYMBOL_NAME(sys_nice)
405 .long SYMBOL_NAME(sys_ni_syscall) /* 35 */ /* old ftime syscall holder */
406 .long SYMBOL_NAME(sys_sync)
407 .long SYMBOL_NAME(sys_kill)
408 .long SYMBOL_NAME(sys_rename)
409 .long SYMBOL_NAME(sys_mkdir)
410 .long SYMBOL_NAME(sys_rmdir) /* 40 */
411 .long SYMBOL_NAME(sys_dup)
412 .long SYMBOL_NAME(sys_pipe)
413 .long SYMBOL_NAME(sys_times)
414 .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */
415 .long SYMBOL_NAME(sys_brk) /* 45 */
416 .long SYMBOL_NAME(sys_setgid)
417 .long SYMBOL_NAME(sys_getgid)
418 .long SYMBOL_NAME(sys_signal)
419 .long SYMBOL_NAME(sys_geteuid)
420 .long SYMBOL_NAME(sys_getegid) /* 50 */
421 .long SYMBOL_NAME(sys_acct)
422 .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */
423 .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */
424 .long SYMBOL_NAME(sys_ioctl)
425 .long SYMBOL_NAME(sys_fcntl) /* 55 */
426 .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */
427 .long SYMBOL_NAME(sys_setpgid)
428 .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */
429 .long SYMBOL_NAME(sys_olduname)
430 .long SYMBOL_NAME(sys_umask) /* 60 */
431 .long SYMBOL_NAME(sys_chroot)
432 .long SYMBOL_NAME(sys_ustat)
433 .long SYMBOL_NAME(sys_dup2)
434 .long SYMBOL_NAME(sys_getppid)
435 .long SYMBOL_NAME(sys_getpgrp) /* 65 */
436 .long SYMBOL_NAME(sys_setsid)
437 .long SYMBOL_NAME(sys_sigaction)
438 .long SYMBOL_NAME(sys_sgetmask)
439 .long SYMBOL_NAME(sys_ssetmask)
440 .long SYMBOL_NAME(sys_setreuid) /* 70 */
441 .long SYMBOL_NAME(sys_setregid)
442 .long SYMBOL_NAME(sys_sigsuspend)
443 .long SYMBOL_NAME(sys_sigpending)
444 .long SYMBOL_NAME(sys_sethostname)
445 .long SYMBOL_NAME(sys_setrlimit) /* 75 */
446 .long SYMBOL_NAME(sys_getrlimit)
447 .long SYMBOL_NAME(sys_getrusage)
448 .long SYMBOL_NAME(sys_gettimeofday)
449 .long SYMBOL_NAME(sys_settimeofday)
450 .long SYMBOL_NAME(sys_getgroups) /* 80 */
451 .long SYMBOL_NAME(sys_setgroups)
452 .long SYMBOL_NAME(old_select)
453 .long SYMBOL_NAME(sys_symlink)
454 .long SYMBOL_NAME(sys_lstat)
455 .long SYMBOL_NAME(sys_readlink) /* 85 */
456 .long SYMBOL_NAME(sys_uselib)
457 .long SYMBOL_NAME(sys_swapon)
458 .long SYMBOL_NAME(sys_reboot)
459 .long SYMBOL_NAME(old_readdir)
460 .long SYMBOL_NAME(old_mmap) /* 90 */
461 .long SYMBOL_NAME(sys_munmap)
462 .long SYMBOL_NAME(sys_truncate)
463 .long SYMBOL_NAME(sys_ftruncate)
464 .long SYMBOL_NAME(sys_fchmod)
465 .long SYMBOL_NAME(sys_fchown) /* 95 */
466 .long SYMBOL_NAME(sys_getpriority)
467 .long SYMBOL_NAME(sys_setpriority)
468 .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */
469 .long SYMBOL_NAME(sys_statfs)
470 .long SYMBOL_NAME(sys_fstatfs) /* 100 */
471 .long SYMBOL_NAME(sys_ioperm)
472 .long SYMBOL_NAME(sys_socketcall)
473 .long SYMBOL_NAME(sys_syslog)
474 .long SYMBOL_NAME(sys_setitimer)
475 .long SYMBOL_NAME(sys_getitimer) /* 105 */
476 .long SYMBOL_NAME(sys_newstat)
477 .long SYMBOL_NAME(sys_newlstat)
478 .long SYMBOL_NAME(sys_newfstat)
479 .long SYMBOL_NAME(sys_uname)
480 .long SYMBOL_NAME(sys_iopl) /* 110 */
481 .long SYMBOL_NAME(sys_vhangup)
482 .long SYMBOL_NAME(sys_idle)
483 .long SYMBOL_NAME(sys_vm86old)
484 .long SYMBOL_NAME(sys_wait4)
485 .long SYMBOL_NAME(sys_swapoff) /* 115 */
486 .long SYMBOL_NAME(sys_sysinfo)
487 .long SYMBOL_NAME(sys_ipc)
488 .long SYMBOL_NAME(sys_fsync)
489 .long SYMBOL_NAME(sys_sigreturn)
490 .long SYMBOL_NAME(sys_clone) /* 120 */
491 .long SYMBOL_NAME(sys_setdomainname)
492 .long SYMBOL_NAME(sys_newuname)
493 .long SYMBOL_NAME(sys_modify_ldt)
494 .long SYMBOL_NAME(sys_adjtimex)
495 .long SYMBOL_NAME(sys_mprotect) /* 125 */
496 .long SYMBOL_NAME(sys_sigprocmask)
497 .long SYMBOL_NAME(sys_create_module)
498 .long SYMBOL_NAME(sys_init_module)
499 .long SYMBOL_NAME(sys_delete_module)
500 .long SYMBOL_NAME(sys_get_kernel_syms) /* 130 */
501 .long SYMBOL_NAME(sys_quotactl)
502 .long SYMBOL_NAME(sys_getpgid)
503 .long SYMBOL_NAME(sys_fchdir)
504 .long SYMBOL_NAME(sys_bdflush)
505 .long SYMBOL_NAME(sys_sysfs) /* 135 */
506 .long SYMBOL_NAME(sys_personality)
507 .long SYMBOL_NAME(sys_ni_syscall) /* for afs_syscall */
508 .long SYMBOL_NAME(sys_setfsuid)
509 .long SYMBOL_NAME(sys_setfsgid)
510 .long SYMBOL_NAME(sys_llseek) /* 140 */
511 .long SYMBOL_NAME(sys_getdents)
512 .long SYMBOL_NAME(sys_select)
513 .long SYMBOL_NAME(sys_flock)
514 .long SYMBOL_NAME(sys_msync)
515 .long SYMBOL_NAME(sys_readv) /* 145 */
516 .long SYMBOL_NAME(sys_writev)
517 .long SYMBOL_NAME(sys_getsid)
518 .long SYMBOL_NAME(sys_fdatasync)
519 .long SYMBOL_NAME(sys_sysctl)
520 .long SYMBOL_NAME(sys_mlock) /* 150 */
521 .long SYMBOL_NAME(sys_munlock)
522 .long SYMBOL_NAME(sys_mlockall)
523 .long SYMBOL_NAME(sys_munlockall)
524 .long SYMBOL_NAME(sys_sched_setparam)
525 .long SYMBOL_NAME(sys_sched_getparam) /* 155 */
526 .long SYMBOL_NAME(sys_sched_setscheduler)
527 .long SYMBOL_NAME(sys_sched_getscheduler)
528 .long SYMBOL_NAME(sys_sched_yield)
529 .long SYMBOL_NAME(sys_sched_get_priority_max)
530 .long SYMBOL_NAME(sys_sched_get_priority_min) /* 160 */
531 .long SYMBOL_NAME(sys_sched_rr_get_interval)
532 .long SYMBOL_NAME(sys_nanosleep)
533 .long SYMBOL_NAME(sys_mremap)
534 .long SYMBOL_NAME(sys_setresuid)
535 .long SYMBOL_NAME(sys_getresuid) /* 165 */
536 .long SYMBOL_NAME(sys_vm86)
537 .long SYMBOL_NAME(sys_query_module)
538 .long SYMBOL_NAME(sys_poll)
539 .long SYMBOL_NAME(sys_nfsservctl)
540 .long SYMBOL_NAME(sys_setresgid) /* 170 */
541 .long SYMBOL_NAME(sys_getresgid)
542 .long SYMBOL_NAME(sys_prctl)
543 .long SYMBOL_NAME(sys_rt_sigreturn)
544 .long SYMBOL_NAME(sys_rt_sigaction)
545 .long SYMBOL_NAME(sys_rt_sigprocmask) /* 175 */
546 .long SYMBOL_NAME(sys_rt_sigpending)
547 .long SYMBOL_NAME(sys_rt_sigtimedwait)
548 .long SYMBOL_NAME(sys_rt_sigqueueinfo)
549 .long SYMBOL_NAME(sys_rt_sigsuspend)
550 .long SYMBOL_NAME(sys_pread) /* 180 */
551 .long SYMBOL_NAME(sys_pwrite)
552 .long SYMBOL_NAME(sys_chown)
553 .long SYMBOL_NAME(sys_getcwd)
554 .long SYMBOL_NAME(sys_capget)
555 .long SYMBOL_NAME(sys_capset) /* 185 */
556 .long SYMBOL_NAME(sys_sigaltstack)
557 .long SYMBOL_NAME(sys_sendfile)
558 .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
559 .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
561 .rept NR_syscalls-187
562 .long SYMBOL_NAME(sys_ni_syscall)