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/linkage.h>
45 #include <asm/thread_info.h>
46 #include <asm/errno.h>
47 #include <asm/segment.h>
50 #include "irq_vectors.h"
52 #define nr_syscalls ((syscall_table_size)/4)
78 #define preempt_stop cli
81 #define resume_kernel restore_all
95 movl $(__USER_DS), %edx; \
99 #define RESTORE_INT_REGS \
108 #define RESTORE_REGS \
112 .section .fixup,"ax"; \
118 .section __ex_table,"a";\
125 #define RESTORE_ALL \
129 .section .fixup,"ax"; \
131 movl $(__USER_DS), %edx; \
137 .section __ex_table,"a";\
146 GET_THREAD_INFO(%ebp)
151 * Return to user mode is not as complex as all this looks,
152 * but we want the default path for a system call return to
153 * go as quickly as possible which is why some of this is
154 * less clear than it otherwise should be.
157 # userspace resumption stub bypassing syscall exit tracing
162 GET_THREAD_INFO(%ebp)
163 movl EFLAGS(%esp), %eax # mix EFLAGS and CS
165 testl $(VM_MASK | 3), %eax
166 jz resume_kernel # returning to kernel or vm86-space
167 ENTRY(resume_userspace)
168 cli # make sure we don't miss an interrupt
169 # setting need_resched or sigpending
170 # between sampling and the iret
171 movl TI_flags(%ebp), %ecx
172 andl $_TIF_WORK_MASK, %ecx # is there any work to be done on
173 # int/exception return?
177 #ifdef CONFIG_PREEMPT
179 cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
182 movl TI_flags(%ebp), %ecx # need_resched set ?
183 testb $_TIF_NEED_RESCHED, %cl
185 testl $IF_MASK,EFLAGS(%esp) # interrupts off (exception path) ?
188 call preempt_schedule
190 movl $0,TI_preempt_count(%ebp)
194 /* SYSENTER_RETURN points to after the "sysenter" instruction in
195 the vsyscall page. See vsyscall-sysentry.S, which defines the symbol. */
197 # sysenter call handler stub
198 ENTRY(sysenter_entry)
199 movl TSS_sysenter_esp0(%esp),%esp
206 pushl $SYSENTER_RETURN
209 * Load the potential sixth argument from user stack.
210 * Careful about security.
212 cmpl $__PAGE_OFFSET-3,%ebp
215 .section __ex_table,"a"
217 .long 1b,syscall_fault
222 GET_THREAD_INFO(%ebp)
224 testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
225 jnz syscall_trace_entry
226 cmpl $(nr_syscalls), %eax
228 call *sys_call_table(,%eax,4)
231 movl TI_flags(%ebp), %ecx
232 testw $_TIF_ALLWORK_MASK, %cx
233 jne syscall_exit_work
234 /* if something modifies registers it must also disable sysexit */
236 movl OLDESP(%esp), %ecx
242 # system call handler stub
244 pushl %eax # save orig_eax
246 GET_THREAD_INFO(%ebp)
247 # system call tracing in operation
248 testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
249 jnz syscall_trace_entry
250 cmpl $(nr_syscalls), %eax
253 call *sys_call_table(,%eax,4)
254 movl %eax,EAX(%esp) # store the return value
256 cli # make sure we don't miss an interrupt
257 # setting need_resched or sigpending
258 # between sampling and the iret
259 movl TI_flags(%ebp), %ecx
260 testw $_TIF_ALLWORK_MASK, %cx # current->work
261 jne syscall_exit_work
265 # perform work that needs to be done immediately before resumption
268 testb $_TIF_NEED_RESCHED, %cl
272 cli # make sure we don't miss an interrupt
273 # setting need_resched or sigpending
274 # between sampling and the iret
275 movl TI_flags(%ebp), %ecx
276 andl $_TIF_WORK_MASK, %ecx # is there any work to be done other
277 # than syscall tracing?
279 testb $_TIF_NEED_RESCHED, %cl
282 work_notifysig: # deal with pending signals and
283 # notify-resume requests
284 testl $VM_MASK, EFLAGS(%esp)
286 jne work_notifysig_v86 # returning to kernel-space or
289 call do_notify_resume
294 pushl %ecx # save ti_flags for do_notify_resume
295 call save_v86_state # %eax contains pt_regs pointer
299 call do_notify_resume
302 # perform syscall exit tracing
305 movl $-ENOSYS,EAX(%esp)
308 call do_syscall_trace
309 movl ORIG_EAX(%esp), %eax
310 cmpl $(nr_syscalls), %eax
314 # perform syscall exit tracing
317 testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
319 sti # could let do_syscall_trace() call
323 call do_syscall_trace
328 pushl %eax # save orig_eax
330 GET_THREAD_INFO(%ebp)
331 movl $-EFAULT,EAX(%esp)
336 movl $-ENOSYS,EAX(%esp)
340 * Build the entry stubs and pointer table with
341 * some assembler magic.
348 ENTRY(irq_entries_start)
366 #define BUILD_INTERRUPT(name, nr) \
374 /* The include is where all of the SMP etc. interrupts come from */
375 #include "entry_arch.h"
378 pushl $0 # no error code
379 pushl $do_divide_error
394 movl ES(%esp), %edi # get the function address
395 movl ORIG_EAX(%esp), %edx # get the error code
396 movl %eax, ORIG_EAX(%esp)
398 movl $(__USER_DS), %ecx
401 movl %esp,%eax # pt_regs pointer
403 jmp ret_from_exception
405 ENTRY(coprocessor_error)
407 pushl $do_coprocessor_error
410 ENTRY(simd_coprocessor_error)
412 pushl $do_simd_coprocessor_error
415 ENTRY(device_not_available)
416 pushl $-1 # mark this as an int
419 testl $0x4, %eax # EM (math emulation bit)
420 jne device_not_available_emulate
422 call math_state_restore
423 jmp ret_from_exception
424 device_not_available_emulate:
425 pushl $0 # temporary storage for ORIG_EIP
428 jmp ret_from_exception
431 * Debug traps and NMI can happen at the one SYSENTER instruction
432 * that sets up the real kernel stack. Check here, since we can't
433 * allow the wrong stack to be used.
435 * "TSS_sysenter_esp0+12" is because the NMI/debug handler will have
436 * already pushed 3 words if it hits on the sysenter instruction:
437 * eflags, cs and eip.
439 * We just load the right stack, and push the three (known) values
440 * by hand onto the new stack - while updating the return eip past
441 * the instruction that would have done it for sysenter.
443 #define FIX_STACK(offset, ok, label) \
444 cmpw $__KERNEL_CS,4(%esp); \
447 movl TSS_sysenter_esp0+offset(%esp),%esp; \
449 pushl $__KERNEL_CS; \
450 pushl $sysenter_past_esp
453 cmpl $sysenter_entry,(%esp)
454 jne debug_stack_correct
455 FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
457 pushl $-1 # mark this as an int
459 xorl %edx,%edx # error code 0
460 movl %esp,%eax # pt_regs pointer
464 jmp ret_from_exception
467 * NMI is doubly nasty. It can happen _while_ we're handling
468 * a debug fault, and the debug fault hasn't yet been able to
469 * clear up the stack. So we first check whether we got an
470 * NMI on the sysenter entry path, but after that we need to
471 * check whether we got an NMI on the debug path where the debug
472 * fault happened on the sysenter path.
475 cmpl $sysenter_entry,(%esp)
479 /* Do not access memory above the end of our stack page,
480 * it might not exist.
482 andl $(THREAD_SIZE-1),%eax
483 cmpl $(THREAD_SIZE-20),%eax
485 jae nmi_stack_correct
486 cmpl $sysenter_entry,12(%esp)
487 je nmi_debug_stack_check
491 xorl %edx,%edx # zero error code
492 movl %esp,%eax # pt_regs pointer
497 FIX_STACK(12,nmi_stack_correct, 1)
498 jmp nmi_stack_correct
499 nmi_debug_stack_check:
500 cmpw $__KERNEL_CS,16(%esp)
501 jne nmi_stack_correct
502 cmpl $debug - 1,(%esp)
503 jle nmi_stack_correct
504 cmpl $debug_esp_fix_insn,(%esp)
505 jle nmi_debug_stack_fixup
506 nmi_debug_stack_fixup:
507 FIX_STACK(24,nmi_stack_correct, 1)
508 jmp nmi_stack_correct
511 pushl $-1 # mark this as an int
513 xorl %edx,%edx # zero error code
514 movl %esp,%eax # pt_regs pointer
518 jmp ret_from_exception
535 ENTRY(coprocessor_segment_overrun)
537 pushl $do_coprocessor_segment_overrun
541 pushl $do_invalid_TSS
544 ENTRY(segment_not_present)
545 pushl $do_segment_not_present
549 pushl $do_stack_segment
552 ENTRY(general_protection)
553 pushl $do_general_protection
556 ENTRY(alignment_check)
557 pushl $do_alignment_check
564 #ifdef CONFIG_X86_MCE
567 pushl machine_check_vector
571 ENTRY(spurious_interrupt_bug)
573 pushl $do_spurious_interrupt_bug
577 ENTRY(sys_call_table)
578 .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
583 .long sys_open /* 5 */
588 .long sys_unlink /* 10 */
593 .long sys_chmod /* 15 */
595 .long sys_ni_syscall /* old break syscall holder */
598 .long sys_getpid /* 20 */
603 .long sys_stime /* 25 */
608 .long sys_utime /* 30 */
609 .long sys_ni_syscall /* old stty syscall holder */
610 .long sys_ni_syscall /* old gtty syscall holder */
613 .long sys_ni_syscall /* 35 - old ftime syscall holder */
618 .long sys_rmdir /* 40 */
622 .long sys_ni_syscall /* old prof syscall holder */
623 .long sys_brk /* 45 */
628 .long sys_getegid16 /* 50 */
630 .long sys_umount /* recycled never used phys() */
631 .long sys_ni_syscall /* old lock syscall holder */
633 .long sys_fcntl /* 55 */
634 .long sys_ni_syscall /* old mpx syscall holder */
636 .long sys_ni_syscall /* old ulimit syscall holder */
638 .long sys_umask /* 60 */
643 .long sys_getpgrp /* 65 */
648 .long sys_setreuid16 /* 70 */
652 .long sys_sethostname
653 .long sys_setrlimit /* 75 */
654 .long sys_old_getrlimit
656 .long sys_gettimeofday
657 .long sys_settimeofday
658 .long sys_getgroups16 /* 80 */
659 .long sys_setgroups16
663 .long sys_readlink /* 85 */
668 .long old_mmap /* 90 */
673 .long sys_fchown16 /* 95 */
674 .long sys_getpriority
675 .long sys_setpriority
676 .long sys_ni_syscall /* old profil syscall holder */
678 .long sys_fstatfs /* 100 */
683 .long sys_getitimer /* 105 */
688 .long sys_iopl /* 110 */
690 .long sys_ni_syscall /* old "idle" system call */
693 .long sys_swapoff /* 115 */
698 .long sys_clone /* 120 */
699 .long sys_setdomainname
703 .long sys_mprotect /* 125 */
704 .long sys_sigprocmask
705 .long sys_ni_syscall /* old "create_module" */
706 .long sys_init_module
707 .long sys_delete_module
708 .long sys_ni_syscall /* 130: old "get_kernel_syms" */
713 .long sys_sysfs /* 135 */
714 .long sys_personality
715 .long sys_ni_syscall /* reserved for afs_syscall */
718 .long sys_llseek /* 140 */
723 .long sys_readv /* 145 */
728 .long sys_mlock /* 150 */
732 .long sys_sched_setparam
733 .long sys_sched_getparam /* 155 */
734 .long sys_sched_setscheduler
735 .long sys_sched_getscheduler
736 .long sys_sched_yield
737 .long sys_sched_get_priority_max
738 .long sys_sched_get_priority_min /* 160 */
739 .long sys_sched_rr_get_interval
742 .long sys_setresuid16
743 .long sys_getresuid16 /* 165 */
745 .long sys_ni_syscall /* Old sys_query_module */
748 .long sys_setresgid16 /* 170 */
749 .long sys_getresgid16
751 .long sys_rt_sigreturn
752 .long sys_rt_sigaction
753 .long sys_rt_sigprocmask /* 175 */
754 .long sys_rt_sigpending
755 .long sys_rt_sigtimedwait
756 .long sys_rt_sigqueueinfo
757 .long sys_rt_sigsuspend
758 .long sys_pread64 /* 180 */
763 .long sys_capset /* 185 */
764 .long sys_sigaltstack
766 .long sys_ni_syscall /* reserved for streams1 */
767 .long sys_ni_syscall /* reserved for streams2 */
768 .long sys_vfork /* 190 */
772 .long sys_ftruncate64
773 .long sys_stat64 /* 195 */
778 .long sys_getgid /* 200 */
783 .long sys_getgroups /* 205 */
788 .long sys_setresgid /* 210 */
793 .long sys_setfsuid /* 215 */
798 .long sys_getdents64 /* 220 */
800 .long sys_ni_syscall /* reserved for TUX */
803 .long sys_readahead /* 225 */
808 .long sys_lgetxattr /* 230 */
813 .long sys_removexattr /* 235 */
814 .long sys_lremovexattr
815 .long sys_fremovexattr
818 .long sys_futex /* 240 */
819 .long sys_sched_setaffinity
820 .long sys_sched_getaffinity
821 .long sys_set_thread_area
822 .long sys_get_thread_area
823 .long sys_io_setup /* 245 */
825 .long sys_io_getevents
828 .long sys_fadvise64 /* 250 */
831 .long sys_lookup_dcookie
832 .long sys_epoll_create
833 .long sys_epoll_ctl /* 255 */
835 .long sys_remap_file_pages
836 .long sys_set_tid_address
837 .long sys_timer_create
838 .long sys_timer_settime /* 260 */
839 .long sys_timer_gettime
840 .long sys_timer_getoverrun
841 .long sys_timer_delete
842 .long sys_clock_settime
843 .long sys_clock_gettime /* 265 */
844 .long sys_clock_getres
845 .long sys_clock_nanosleep
848 .long sys_tgkill /* 270 */
850 .long sys_fadvise64_64
851 .long sys_ni_syscall /* sys_vserver */
853 .long sys_get_mempolicy
854 .long sys_set_mempolicy
857 .long sys_mq_timedsend
858 .long sys_mq_timedreceive /* 280 */
860 .long sys_mq_getsetattr
861 .long sys_ni_syscall /* reserved for kexec */
863 .long sys_ni_syscall /* 285 */ /* available */
865 .long sys_request_key
868 syscall_table_size=(.-sys_call_table)