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/config.h>
44 #include <linux/sys.h>
45 #include <linux/linkage.h>
46 #include <asm/segment.h>
73 * these are offsets into the task-struct.
98 movl $(__KERNEL_DS),%edx; \
102 #define RESTORE_ALL \
114 .section .fixup,"ax"; \
126 .section __ex_table,"a";\
133 #define GET_CURRENT(reg) \
138 pushfl # We get a different stack layout with call gates,
139 pushl %eax # which has to be cleaned up later..
141 movl EIP(%esp),%eax # due to call gates, this is eflags, not eip..
142 movl CS(%esp),%edx # this is eip..
143 movl EFLAGS(%esp),%ecx # and this is cs..
144 movl %eax,EFLAGS(%esp) #
145 andl $~(NT_MASK|TF_MASK|DF_MASK), %eax
148 movl %edx,EIP(%esp) # Now we move them to their "normal" places
152 andl $-8192,%ebx # GET_CURRENT
153 movl exec_domain(%ebx),%edx # Get the execution domain
154 movl 4(%edx),%edx # Get the lcall7 handler for the domain
159 jmp ret_from_sys_call
162 pushfl # We get a different stack layout with call gates,
163 pushl %eax # which has to be cleaned up later..
165 movl EIP(%esp),%eax # due to call gates, this is eflags, not eip..
166 movl CS(%esp),%edx # this is eip..
167 movl EFLAGS(%esp),%ecx # and this is cs..
168 movl %eax,EFLAGS(%esp) #
169 andl $~(NT_MASK|TF_MASK|DF_MASK), %eax
172 movl %edx,EIP(%esp) # Now we move them to their "normal" places
176 andl $-8192,%ebx # GET_CURRENT
177 movl exec_domain(%ebx),%edx # Get the execution domain
178 movl 4(%edx),%edx # Get the lcall7 handler for the domain
183 jmp ret_from_sys_call
188 call SYMBOL_NAME(schedule_tail)
191 testb $0x02,tsk_ptrace(%ebx) # PT_TRACESYS
193 jmp ret_from_sys_call
196 * Return to user mode is not as complex as all this looks,
197 * but we want the default path for a system call return to
198 * go as quickly as possible which is why some of this is
199 * less clear than it otherwise should be.
203 pushl %eax # save orig_eax
206 testb $0x02,tsk_ptrace(%ebx) # PT_TRACESYS
208 cmpl $(NR_syscalls),%eax
210 call *SYMBOL_NAME(sys_call_table)(,%eax,4)
211 movl %eax,EAX(%esp) # save the return value
212 ENTRY(ret_from_sys_call)
213 cli # need_resched and signals atomic test
214 cmpl $0,need_resched(%ebx)
216 cmpl $0,sigpending(%ebx)
223 sti # we can get here from an interrupt handler
224 testl $(VM_MASK),EFLAGS(%esp)
226 jne v86_signal_return
228 call SYMBOL_NAME(do_signal)
233 call SYMBOL_NAME(save_v86_state)
236 call SYMBOL_NAME(do_signal)
241 movl $-ENOSYS,EAX(%esp)
242 call SYMBOL_NAME(syscall_trace)
243 movl ORIG_EAX(%esp),%eax
244 cmpl $(NR_syscalls),%eax
246 call *SYMBOL_NAME(sys_call_table)(,%eax,4)
247 movl %eax,EAX(%esp) # save the return value
249 call SYMBOL_NAME(syscall_trace)
250 jmp ret_from_sys_call
252 movl $-ENOSYS,EAX(%esp)
253 jmp ret_from_sys_call
259 movl EFLAGS(%esp),%eax # mix EFLAGS and CS
261 testl $(VM_MASK | 3),%eax # return to VM86 mode or non-supervisor?
262 jne ret_from_sys_call
267 call SYMBOL_NAME(schedule) # test
268 jmp ret_from_sys_call
271 pushl $0 # no error code
272 pushl $ SYMBOL_NAME(do_divide_error)
287 movl ORIG_EAX(%esp), %esi # get the error code
288 movl ES(%esp), %edi # get the function address
289 movl %eax, ORIG_EAX(%esp)
292 pushl %esi # push the error code
293 pushl %edx # push the pt_regs pointer
294 movl $(__KERNEL_DS),%edx
300 jmp ret_from_exception
302 ENTRY(coprocessor_error)
304 pushl $ SYMBOL_NAME(do_coprocessor_error)
307 ENTRY(simd_coprocessor_error)
309 pushl $ SYMBOL_NAME(do_simd_coprocessor_error)
312 ENTRY(device_not_available)
313 pushl $-1 # mark this as an int
317 testl $0x4,%eax # EM (math emulation bit)
318 jne device_not_available_emulate
319 call SYMBOL_NAME(math_state_restore)
320 jmp ret_from_exception
321 device_not_available_emulate:
322 pushl $0 # temporary storage for ORIG_EIP
323 call SYMBOL_NAME(math_emulate)
325 jmp ret_from_exception
329 pushl $ SYMBOL_NAME(do_debug)
338 call SYMBOL_NAME(do_nmi)
344 pushl $ SYMBOL_NAME(do_int3)
349 pushl $ SYMBOL_NAME(do_overflow)
354 pushl $ SYMBOL_NAME(do_bounds)
359 pushl $ SYMBOL_NAME(do_invalid_op)
362 ENTRY(coprocessor_segment_overrun)
364 pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun)
368 pushl $ SYMBOL_NAME(do_double_fault)
372 pushl $ SYMBOL_NAME(do_invalid_TSS)
375 ENTRY(segment_not_present)
376 pushl $ SYMBOL_NAME(do_segment_not_present)
380 pushl $ SYMBOL_NAME(do_stack_segment)
383 ENTRY(general_protection)
384 pushl $ SYMBOL_NAME(do_general_protection)
387 ENTRY(alignment_check)
388 pushl $ SYMBOL_NAME(do_alignment_check)
392 pushl $ SYMBOL_NAME(do_page_fault)
397 pushl $ SYMBOL_NAME(do_machine_check)
400 ENTRY(spurious_interrupt_bug)
402 pushl $ SYMBOL_NAME(do_spurious_interrupt_bug)
406 ENTRY(sys_call_table)
407 .long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/
408 .long SYMBOL_NAME(sys_exit)
409 .long SYMBOL_NAME(sys_fork)
410 .long SYMBOL_NAME(sys_read)
411 .long SYMBOL_NAME(sys_write)
412 .long SYMBOL_NAME(sys_open) /* 5 */
413 .long SYMBOL_NAME(sys_close)
414 .long SYMBOL_NAME(sys_waitpid)
415 .long SYMBOL_NAME(sys_creat)
416 .long SYMBOL_NAME(sys_link)
417 .long SYMBOL_NAME(sys_unlink) /* 10 */
418 .long SYMBOL_NAME(sys_execve)
419 .long SYMBOL_NAME(sys_chdir)
420 .long SYMBOL_NAME(sys_time)
421 .long SYMBOL_NAME(sys_mknod)
422 .long SYMBOL_NAME(sys_chmod) /* 15 */
423 .long SYMBOL_NAME(sys_lchown16)
424 .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */
425 .long SYMBOL_NAME(sys_stat)
426 .long SYMBOL_NAME(sys_lseek)
427 .long SYMBOL_NAME(sys_getpid) /* 20 */
428 .long SYMBOL_NAME(sys_mount)
429 .long SYMBOL_NAME(sys_oldumount)
430 .long SYMBOL_NAME(sys_setuid16)
431 .long SYMBOL_NAME(sys_getuid16)
432 .long SYMBOL_NAME(sys_stime) /* 25 */
433 .long SYMBOL_NAME(sys_ptrace)
434 .long SYMBOL_NAME(sys_alarm)
435 .long SYMBOL_NAME(sys_fstat)
436 .long SYMBOL_NAME(sys_pause)
437 .long SYMBOL_NAME(sys_utime) /* 30 */
438 .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */
439 .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */
440 .long SYMBOL_NAME(sys_access)
441 .long SYMBOL_NAME(sys_nice)
442 .long SYMBOL_NAME(sys_ni_syscall) /* 35 */ /* old ftime syscall holder */
443 .long SYMBOL_NAME(sys_sync)
444 .long SYMBOL_NAME(sys_kill)
445 .long SYMBOL_NAME(sys_rename)
446 .long SYMBOL_NAME(sys_mkdir)
447 .long SYMBOL_NAME(sys_rmdir) /* 40 */
448 .long SYMBOL_NAME(sys_dup)
449 .long SYMBOL_NAME(sys_pipe)
450 .long SYMBOL_NAME(sys_times)
451 .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */
452 .long SYMBOL_NAME(sys_brk) /* 45 */
453 .long SYMBOL_NAME(sys_setgid16)
454 .long SYMBOL_NAME(sys_getgid16)
455 .long SYMBOL_NAME(sys_signal)
456 .long SYMBOL_NAME(sys_geteuid16)
457 .long SYMBOL_NAME(sys_getegid16) /* 50 */
458 .long SYMBOL_NAME(sys_acct)
459 .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */
460 .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */
461 .long SYMBOL_NAME(sys_ioctl)
462 .long SYMBOL_NAME(sys_fcntl) /* 55 */
463 .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */
464 .long SYMBOL_NAME(sys_setpgid)
465 .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */
466 .long SYMBOL_NAME(sys_olduname)
467 .long SYMBOL_NAME(sys_umask) /* 60 */
468 .long SYMBOL_NAME(sys_chroot)
469 .long SYMBOL_NAME(sys_ustat)
470 .long SYMBOL_NAME(sys_dup2)
471 .long SYMBOL_NAME(sys_getppid)
472 .long SYMBOL_NAME(sys_getpgrp) /* 65 */
473 .long SYMBOL_NAME(sys_setsid)
474 .long SYMBOL_NAME(sys_sigaction)
475 .long SYMBOL_NAME(sys_sgetmask)
476 .long SYMBOL_NAME(sys_ssetmask)
477 .long SYMBOL_NAME(sys_setreuid16) /* 70 */
478 .long SYMBOL_NAME(sys_setregid16)
479 .long SYMBOL_NAME(sys_sigsuspend)
480 .long SYMBOL_NAME(sys_sigpending)
481 .long SYMBOL_NAME(sys_sethostname)
482 .long SYMBOL_NAME(sys_setrlimit) /* 75 */
483 .long SYMBOL_NAME(sys_old_getrlimit)
484 .long SYMBOL_NAME(sys_getrusage)
485 .long SYMBOL_NAME(sys_gettimeofday)
486 .long SYMBOL_NAME(sys_settimeofday)
487 .long SYMBOL_NAME(sys_getgroups16) /* 80 */
488 .long SYMBOL_NAME(sys_setgroups16)
489 .long SYMBOL_NAME(old_select)
490 .long SYMBOL_NAME(sys_symlink)
491 .long SYMBOL_NAME(sys_lstat)
492 .long SYMBOL_NAME(sys_readlink) /* 85 */
493 .long SYMBOL_NAME(sys_uselib)
494 .long SYMBOL_NAME(sys_swapon)
495 .long SYMBOL_NAME(sys_reboot)
496 .long SYMBOL_NAME(old_readdir)
497 .long SYMBOL_NAME(old_mmap) /* 90 */
498 .long SYMBOL_NAME(sys_munmap)
499 .long SYMBOL_NAME(sys_truncate)
500 .long SYMBOL_NAME(sys_ftruncate)
501 .long SYMBOL_NAME(sys_fchmod)
502 .long SYMBOL_NAME(sys_fchown16) /* 95 */
503 .long SYMBOL_NAME(sys_getpriority)
504 .long SYMBOL_NAME(sys_setpriority)
505 .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */
506 .long SYMBOL_NAME(sys_statfs)
507 .long SYMBOL_NAME(sys_fstatfs) /* 100 */
508 .long SYMBOL_NAME(sys_ioperm)
509 .long SYMBOL_NAME(sys_socketcall)
510 .long SYMBOL_NAME(sys_syslog)
511 .long SYMBOL_NAME(sys_setitimer)
512 .long SYMBOL_NAME(sys_getitimer) /* 105 */
513 .long SYMBOL_NAME(sys_newstat)
514 .long SYMBOL_NAME(sys_newlstat)
515 .long SYMBOL_NAME(sys_newfstat)
516 .long SYMBOL_NAME(sys_uname)
517 .long SYMBOL_NAME(sys_iopl) /* 110 */
518 .long SYMBOL_NAME(sys_vhangup)
519 .long SYMBOL_NAME(sys_ni_syscall) /* old "idle" system call */
520 .long SYMBOL_NAME(sys_vm86old)
521 .long SYMBOL_NAME(sys_wait4)
522 .long SYMBOL_NAME(sys_swapoff) /* 115 */
523 .long SYMBOL_NAME(sys_sysinfo)
524 .long SYMBOL_NAME(sys_ipc)
525 .long SYMBOL_NAME(sys_fsync)
526 .long SYMBOL_NAME(sys_sigreturn)
527 .long SYMBOL_NAME(sys_clone) /* 120 */
528 .long SYMBOL_NAME(sys_setdomainname)
529 .long SYMBOL_NAME(sys_newuname)
530 .long SYMBOL_NAME(sys_modify_ldt)
531 .long SYMBOL_NAME(sys_adjtimex)
532 .long SYMBOL_NAME(sys_mprotect) /* 125 */
533 .long SYMBOL_NAME(sys_sigprocmask)
534 .long SYMBOL_NAME(sys_create_module)
535 .long SYMBOL_NAME(sys_init_module)
536 .long SYMBOL_NAME(sys_delete_module)
537 .long SYMBOL_NAME(sys_get_kernel_syms) /* 130 */
538 .long SYMBOL_NAME(sys_quotactl)
539 .long SYMBOL_NAME(sys_getpgid)
540 .long SYMBOL_NAME(sys_fchdir)
541 .long SYMBOL_NAME(sys_bdflush)
542 .long SYMBOL_NAME(sys_sysfs) /* 135 */
543 .long SYMBOL_NAME(sys_personality)
544 .long SYMBOL_NAME(sys_ni_syscall) /* for afs_syscall */
545 .long SYMBOL_NAME(sys_setfsuid16)
546 .long SYMBOL_NAME(sys_setfsgid16)
547 .long SYMBOL_NAME(sys_llseek) /* 140 */
548 .long SYMBOL_NAME(sys_getdents)
549 .long SYMBOL_NAME(sys_select)
550 .long SYMBOL_NAME(sys_flock)
551 .long SYMBOL_NAME(sys_msync)
552 .long SYMBOL_NAME(sys_readv) /* 145 */
553 .long SYMBOL_NAME(sys_writev)
554 .long SYMBOL_NAME(sys_getsid)
555 .long SYMBOL_NAME(sys_fdatasync)
556 .long SYMBOL_NAME(sys_sysctl)
557 .long SYMBOL_NAME(sys_mlock) /* 150 */
558 .long SYMBOL_NAME(sys_munlock)
559 .long SYMBOL_NAME(sys_mlockall)
560 .long SYMBOL_NAME(sys_munlockall)
561 .long SYMBOL_NAME(sys_sched_setparam)
562 .long SYMBOL_NAME(sys_sched_getparam) /* 155 */
563 .long SYMBOL_NAME(sys_sched_setscheduler)
564 .long SYMBOL_NAME(sys_sched_getscheduler)
565 .long SYMBOL_NAME(sys_sched_yield)
566 .long SYMBOL_NAME(sys_sched_get_priority_max)
567 .long SYMBOL_NAME(sys_sched_get_priority_min) /* 160 */
568 .long SYMBOL_NAME(sys_sched_rr_get_interval)
569 .long SYMBOL_NAME(sys_nanosleep)
570 .long SYMBOL_NAME(sys_mremap)
571 .long SYMBOL_NAME(sys_setresuid16)
572 .long SYMBOL_NAME(sys_getresuid16) /* 165 */
573 .long SYMBOL_NAME(sys_vm86)
574 .long SYMBOL_NAME(sys_query_module)
575 .long SYMBOL_NAME(sys_poll)
576 .long SYMBOL_NAME(sys_nfsservctl)
577 .long SYMBOL_NAME(sys_setresgid16) /* 170 */
578 .long SYMBOL_NAME(sys_getresgid16)
579 .long SYMBOL_NAME(sys_prctl)
580 .long SYMBOL_NAME(sys_rt_sigreturn)
581 .long SYMBOL_NAME(sys_rt_sigaction)
582 .long SYMBOL_NAME(sys_rt_sigprocmask) /* 175 */
583 .long SYMBOL_NAME(sys_rt_sigpending)
584 .long SYMBOL_NAME(sys_rt_sigtimedwait)
585 .long SYMBOL_NAME(sys_rt_sigqueueinfo)
586 .long SYMBOL_NAME(sys_rt_sigsuspend)
587 .long SYMBOL_NAME(sys_pread) /* 180 */
588 .long SYMBOL_NAME(sys_pwrite)
589 .long SYMBOL_NAME(sys_chown16)
590 .long SYMBOL_NAME(sys_getcwd)
591 .long SYMBOL_NAME(sys_capget)
592 .long SYMBOL_NAME(sys_capset) /* 185 */
593 .long SYMBOL_NAME(sys_sigaltstack)
594 .long SYMBOL_NAME(sys_sendfile)
595 .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
596 .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
597 .long SYMBOL_NAME(sys_vfork) /* 190 */
598 .long SYMBOL_NAME(sys_getrlimit)
599 .long SYMBOL_NAME(sys_mmap2)
600 .long SYMBOL_NAME(sys_truncate64)
601 .long SYMBOL_NAME(sys_ftruncate64)
602 .long SYMBOL_NAME(sys_stat64) /* 195 */
603 .long SYMBOL_NAME(sys_lstat64)
604 .long SYMBOL_NAME(sys_fstat64)
605 .long SYMBOL_NAME(sys_lchown)
606 .long SYMBOL_NAME(sys_getuid)
607 .long SYMBOL_NAME(sys_getgid) /* 200 */
608 .long SYMBOL_NAME(sys_geteuid)
609 .long SYMBOL_NAME(sys_getegid)
610 .long SYMBOL_NAME(sys_setreuid)
611 .long SYMBOL_NAME(sys_setregid)
612 .long SYMBOL_NAME(sys_getgroups) /* 205 */
613 .long SYMBOL_NAME(sys_setgroups)
614 .long SYMBOL_NAME(sys_fchown)
615 .long SYMBOL_NAME(sys_setresuid)
616 .long SYMBOL_NAME(sys_getresuid)
617 .long SYMBOL_NAME(sys_setresgid) /* 210 */
618 .long SYMBOL_NAME(sys_getresgid)
619 .long SYMBOL_NAME(sys_chown)
620 .long SYMBOL_NAME(sys_setuid)
621 .long SYMBOL_NAME(sys_setgid)
622 .long SYMBOL_NAME(sys_setfsuid) /* 215 */
623 .long SYMBOL_NAME(sys_setfsgid)
624 .long SYMBOL_NAME(sys_pivot_root)
625 .long SYMBOL_NAME(sys_mincore)
626 .long SYMBOL_NAME(sys_madvise)
627 .long SYMBOL_NAME(sys_getdents64) /* 220 */
628 .long SYMBOL_NAME(sys_fcntl64)
629 .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */
630 .long SYMBOL_NAME(sys_ni_syscall) /* Reserved for Security */
631 .long SYMBOL_NAME(sys_gettid)
632 .long SYMBOL_NAME(sys_readahead) /* 225 */
633 .long SYMBOL_NAME(sys_setxattr)
634 .long SYMBOL_NAME(sys_lsetxattr)
635 .long SYMBOL_NAME(sys_fsetxattr)
636 .long SYMBOL_NAME(sys_getxattr)
637 .long SYMBOL_NAME(sys_lgetxattr) /* 230 */
638 .long SYMBOL_NAME(sys_fgetxattr)
639 .long SYMBOL_NAME(sys_listxattr)
640 .long SYMBOL_NAME(sys_llistxattr)
641 .long SYMBOL_NAME(sys_flistxattr)
642 .long SYMBOL_NAME(sys_removexattr) /* 235 */
643 .long SYMBOL_NAME(sys_lremovexattr)
644 .long SYMBOL_NAME(sys_fremovexattr)
645 .long SYMBOL_NAME(sys_tkill)
646 .long SYMBOL_NAME(sys_sendfile64)
647 .long SYMBOL_NAME(sys_ni_syscall) /* 240 reserved for futex */
648 .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sched_setaffinity */
649 .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sched_getaffinity */
650 .long SYMBOL_NAME(sys_ni_syscall) /* sys_set_thread_area */
651 .long SYMBOL_NAME(sys_ni_syscall) /* sys_get_thread_area */
652 .long SYMBOL_NAME(sys_ni_syscall) /* 245 sys_io_setup */
653 .long SYMBOL_NAME(sys_ni_syscall) /* sys_io_destroy */
654 .long SYMBOL_NAME(sys_ni_syscall) /* sys_io_getevents */
655 .long SYMBOL_NAME(sys_ni_syscall) /* sys_io_submit */
656 .long SYMBOL_NAME(sys_ni_syscall) /* sys_io_cancel */
657 .long SYMBOL_NAME(sys_ni_syscall) /* 250 sys_alloc_hugepages */
658 .long SYMBOL_NAME(sys_ni_syscall) /* sys_free_hugepages */
659 .long SYMBOL_NAME(sys_ni_syscall) /* sys_exit_group */
660 .long SYMBOL_NAME(sys_ni_syscall) /* sys_lookup_dcookie */
661 .long SYMBOL_NAME(sys_ni_syscall) /* sys_epoll_create */
662 .long SYMBOL_NAME(sys_ni_syscall) /* sys_epoll_ctl 255 */
663 .long SYMBOL_NAME(sys_ni_syscall) /* sys_epoll_wait */
664 .long SYMBOL_NAME(sys_ni_syscall) /* sys_remap_file_pages */
665 .long SYMBOL_NAME(sys_ni_syscall) /* sys_set_tid_address */
667 .rept NR_syscalls-(.-sys_call_table)/4
668 .long SYMBOL_NAME(sys_ni_syscall)