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>
72 * these are offsets into the task-struct.
97 movl $(__KERNEL_DS),%edx; \
101 #define RESTORE_ALL \
113 .section .fixup,"ax"; \
125 .section __ex_table,"a";\
132 #define GET_CURRENT(reg) \
137 pushfl # We get a different stack layout with call gates,
138 pushl %eax # which has to be cleaned up later..
140 movl EIP(%esp),%eax # due to call gates, this is eflags, not eip..
141 movl CS(%esp),%edx # this is eip..
142 movl EFLAGS(%esp),%ecx # and this is cs..
143 movl %eax,EFLAGS(%esp) #
144 movl %edx,EIP(%esp) # Now we move them to their "normal" places
148 andl $-8192,%ebx # GET_CURRENT
149 movl exec_domain(%ebx),%edx # Get the execution domain
150 movl 4(%edx),%edx # Get the lcall7 handler for the domain
155 jmp ret_from_sys_call
158 pushfl # We get a different stack layout with call gates,
159 pushl %eax # which has to be cleaned up later..
161 movl EIP(%esp),%eax # due to call gates, this is eflags, not eip..
162 movl CS(%esp),%edx # this is eip..
163 movl EFLAGS(%esp),%ecx # and this is cs..
164 movl %eax,EFLAGS(%esp) #
165 movl %edx,EIP(%esp) # Now we move them to their "normal" places
169 andl $-8192,%ebx # GET_CURRENT
170 movl exec_domain(%ebx),%edx # Get the execution domain
171 movl 4(%edx),%edx # Get the lcall7 handler for the domain
176 jmp ret_from_sys_call
181 call SYMBOL_NAME(schedule_tail)
184 testb $0x02,tsk_ptrace(%ebx) # PT_TRACESYS
186 jmp ret_from_sys_call
189 * Return to user mode is not as complex as all this looks,
190 * but we want the default path for a system call return to
191 * go as quickly as possible which is why some of this is
192 * less clear than it otherwise should be.
196 pushl %eax # save orig_eax
199 cmpl $(NR_syscalls),%eax
201 testb $0x02,tsk_ptrace(%ebx) # PT_TRACESYS
203 call *SYMBOL_NAME(sys_call_table)(,%eax,4)
204 movl %eax,EAX(%esp) # save the return value
205 ENTRY(ret_from_sys_call)
207 movl processor(%ebx),%eax
208 shll $CONFIG_X86_L1_CACHE_SHIFT,%eax
209 movl SYMBOL_NAME(irq_stat)(,%eax),%ecx # softirq_active
210 testl SYMBOL_NAME(irq_stat)+4(,%eax),%ecx # softirq_mask
212 movl SYMBOL_NAME(irq_stat),%ecx # softirq_active
213 testl SYMBOL_NAME(irq_stat)+4,%ecx # softirq_mask
218 cmpl $0,need_resched(%ebx)
220 cmpl $0,sigpending(%ebx)
227 sti # we can get here from an interrupt handler
228 testl $(VM_MASK),EFLAGS(%esp)
230 jne v86_signal_return
232 call SYMBOL_NAME(do_signal)
237 call SYMBOL_NAME(save_v86_state)
240 call SYMBOL_NAME(do_signal)
245 movl $-ENOSYS,EAX(%esp)
246 call SYMBOL_NAME(syscall_trace)
247 movl ORIG_EAX(%esp),%eax
248 cmpl $(NR_syscalls),%eax
250 call *SYMBOL_NAME(sys_call_table)(,%eax,4)
251 movl %eax,EAX(%esp) # save the return value
253 call SYMBOL_NAME(syscall_trace)
254 jmp ret_from_sys_call
256 movl $-ENOSYS,EAX(%esp)
257 jmp ret_from_sys_call
263 movl processor(%ebx),%eax
264 shll $CONFIG_X86_L1_CACHE_SHIFT,%eax
265 movl SYMBOL_NAME(irq_stat)(,%eax),%ecx # softirq_active
266 testl SYMBOL_NAME(irq_stat)+4(,%eax),%ecx # softirq_mask
268 movl SYMBOL_NAME(irq_stat),%ecx # softirq_active
269 testl SYMBOL_NAME(irq_stat)+4,%ecx # softirq_mask
275 movl EFLAGS(%esp),%eax # mix EFLAGS and CS
277 testl $(VM_MASK | 3),%eax # return to VM86 mode or non-supervisor?
278 jne ret_with_reschedule
283 call SYMBOL_NAME(do_softirq)
288 call SYMBOL_NAME(schedule) # test
289 jmp ret_from_sys_call
292 pushl $0 # no error code
293 pushl $ SYMBOL_NAME(do_divide_error)
308 movl ORIG_EAX(%esp), %esi # get the error code
309 movl ES(%esp), %edi # get the function address
310 movl %eax, ORIG_EAX(%esp)
313 pushl %esi # push the error code
314 pushl %edx # push the pt_regs pointer
315 movl $(__KERNEL_DS),%edx
321 jmp ret_from_exception
323 ENTRY(coprocessor_error)
325 pushl $ SYMBOL_NAME(do_coprocessor_error)
328 ENTRY(simd_coprocessor_error)
330 pushl $ SYMBOL_NAME(do_simd_coprocessor_error)
333 ENTRY(device_not_available)
334 pushl $-1 # mark this as an int
337 pushl $ret_from_exception
339 testl $0x4,%eax # EM (math emulation bit)
340 je SYMBOL_NAME(math_state_restore)
341 pushl $0 # temporary storage for ORIG_EIP
342 call SYMBOL_NAME(math_emulate)
348 pushl $ SYMBOL_NAME(do_debug)
357 call SYMBOL_NAME(do_nmi)
363 pushl $ SYMBOL_NAME(do_int3)
368 pushl $ SYMBOL_NAME(do_overflow)
373 pushl $ SYMBOL_NAME(do_bounds)
378 pushl $ SYMBOL_NAME(do_invalid_op)
381 ENTRY(coprocessor_segment_overrun)
383 pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun)
387 pushl $ SYMBOL_NAME(do_double_fault)
391 pushl $ SYMBOL_NAME(do_invalid_TSS)
394 ENTRY(segment_not_present)
395 pushl $ SYMBOL_NAME(do_segment_not_present)
399 pushl $ SYMBOL_NAME(do_stack_segment)
402 ENTRY(general_protection)
403 pushl $ SYMBOL_NAME(do_general_protection)
406 ENTRY(alignment_check)
407 pushl $ SYMBOL_NAME(do_alignment_check)
411 pushl $ SYMBOL_NAME(do_page_fault)
416 pushl $ SYMBOL_NAME(do_machine_check)
419 ENTRY(spurious_interrupt_bug)
421 pushl $ SYMBOL_NAME(do_spurious_interrupt_bug)
425 ENTRY(sys_call_table)
426 .long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/
427 .long SYMBOL_NAME(sys_exit)
428 .long SYMBOL_NAME(sys_fork)
429 .long SYMBOL_NAME(sys_read)
430 .long SYMBOL_NAME(sys_write)
431 .long SYMBOL_NAME(sys_open) /* 5 */
432 .long SYMBOL_NAME(sys_close)
433 .long SYMBOL_NAME(sys_waitpid)
434 .long SYMBOL_NAME(sys_creat)
435 .long SYMBOL_NAME(sys_link)
436 .long SYMBOL_NAME(sys_unlink) /* 10 */
437 .long SYMBOL_NAME(sys_execve)
438 .long SYMBOL_NAME(sys_chdir)
439 .long SYMBOL_NAME(sys_time)
440 .long SYMBOL_NAME(sys_mknod)
441 .long SYMBOL_NAME(sys_chmod) /* 15 */
442 .long SYMBOL_NAME(sys_lchown16)
443 .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */
444 .long SYMBOL_NAME(sys_stat)
445 .long SYMBOL_NAME(sys_lseek)
446 .long SYMBOL_NAME(sys_getpid) /* 20 */
447 .long SYMBOL_NAME(sys_mount)
448 .long SYMBOL_NAME(sys_oldumount)
449 .long SYMBOL_NAME(sys_setuid16)
450 .long SYMBOL_NAME(sys_getuid16)
451 .long SYMBOL_NAME(sys_stime) /* 25 */
452 .long SYMBOL_NAME(sys_ptrace)
453 .long SYMBOL_NAME(sys_alarm)
454 .long SYMBOL_NAME(sys_fstat)
455 .long SYMBOL_NAME(sys_pause)
456 .long SYMBOL_NAME(sys_utime) /* 30 */
457 .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */
458 .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */
459 .long SYMBOL_NAME(sys_access)
460 .long SYMBOL_NAME(sys_nice)
461 .long SYMBOL_NAME(sys_ni_syscall) /* 35 */ /* old ftime syscall holder */
462 .long SYMBOL_NAME(sys_sync)
463 .long SYMBOL_NAME(sys_kill)
464 .long SYMBOL_NAME(sys_rename)
465 .long SYMBOL_NAME(sys_mkdir)
466 .long SYMBOL_NAME(sys_rmdir) /* 40 */
467 .long SYMBOL_NAME(sys_dup)
468 .long SYMBOL_NAME(sys_pipe)
469 .long SYMBOL_NAME(sys_times)
470 .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */
471 .long SYMBOL_NAME(sys_brk) /* 45 */
472 .long SYMBOL_NAME(sys_setgid16)
473 .long SYMBOL_NAME(sys_getgid16)
474 .long SYMBOL_NAME(sys_signal)
475 .long SYMBOL_NAME(sys_geteuid16)
476 .long SYMBOL_NAME(sys_getegid16) /* 50 */
477 .long SYMBOL_NAME(sys_acct)
478 .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */
479 .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */
480 .long SYMBOL_NAME(sys_ioctl)
481 .long SYMBOL_NAME(sys_fcntl) /* 55 */
482 .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */
483 .long SYMBOL_NAME(sys_setpgid)
484 .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */
485 .long SYMBOL_NAME(sys_olduname)
486 .long SYMBOL_NAME(sys_umask) /* 60 */
487 .long SYMBOL_NAME(sys_chroot)
488 .long SYMBOL_NAME(sys_ustat)
489 .long SYMBOL_NAME(sys_dup2)
490 .long SYMBOL_NAME(sys_getppid)
491 .long SYMBOL_NAME(sys_getpgrp) /* 65 */
492 .long SYMBOL_NAME(sys_setsid)
493 .long SYMBOL_NAME(sys_sigaction)
494 .long SYMBOL_NAME(sys_sgetmask)
495 .long SYMBOL_NAME(sys_ssetmask)
496 .long SYMBOL_NAME(sys_setreuid16) /* 70 */
497 .long SYMBOL_NAME(sys_setregid16)
498 .long SYMBOL_NAME(sys_sigsuspend)
499 .long SYMBOL_NAME(sys_sigpending)
500 .long SYMBOL_NAME(sys_sethostname)
501 .long SYMBOL_NAME(sys_setrlimit) /* 75 */
502 .long SYMBOL_NAME(sys_old_getrlimit)
503 .long SYMBOL_NAME(sys_getrusage)
504 .long SYMBOL_NAME(sys_gettimeofday)
505 .long SYMBOL_NAME(sys_settimeofday)
506 .long SYMBOL_NAME(sys_getgroups16) /* 80 */
507 .long SYMBOL_NAME(sys_setgroups16)
508 .long SYMBOL_NAME(old_select)
509 .long SYMBOL_NAME(sys_symlink)
510 .long SYMBOL_NAME(sys_lstat)
511 .long SYMBOL_NAME(sys_readlink) /* 85 */
512 .long SYMBOL_NAME(sys_uselib)
513 .long SYMBOL_NAME(sys_swapon)
514 .long SYMBOL_NAME(sys_reboot)
515 .long SYMBOL_NAME(old_readdir)
516 .long SYMBOL_NAME(old_mmap) /* 90 */
517 .long SYMBOL_NAME(sys_munmap)
518 .long SYMBOL_NAME(sys_truncate)
519 .long SYMBOL_NAME(sys_ftruncate)
520 .long SYMBOL_NAME(sys_fchmod)
521 .long SYMBOL_NAME(sys_fchown16) /* 95 */
522 .long SYMBOL_NAME(sys_getpriority)
523 .long SYMBOL_NAME(sys_setpriority)
524 .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */
525 .long SYMBOL_NAME(sys_statfs)
526 .long SYMBOL_NAME(sys_fstatfs) /* 100 */
527 .long SYMBOL_NAME(sys_ioperm)
528 .long SYMBOL_NAME(sys_socketcall)
529 .long SYMBOL_NAME(sys_syslog)
530 .long SYMBOL_NAME(sys_setitimer)
531 .long SYMBOL_NAME(sys_getitimer) /* 105 */
532 .long SYMBOL_NAME(sys_newstat)
533 .long SYMBOL_NAME(sys_newlstat)
534 .long SYMBOL_NAME(sys_newfstat)
535 .long SYMBOL_NAME(sys_uname)
536 .long SYMBOL_NAME(sys_iopl) /* 110 */
537 .long SYMBOL_NAME(sys_vhangup)
538 .long SYMBOL_NAME(sys_ni_syscall) /* old "idle" system call */
539 .long SYMBOL_NAME(sys_vm86old)
540 .long SYMBOL_NAME(sys_wait4)
541 .long SYMBOL_NAME(sys_swapoff) /* 115 */
542 .long SYMBOL_NAME(sys_sysinfo)
543 .long SYMBOL_NAME(sys_ipc)
544 .long SYMBOL_NAME(sys_fsync)
545 .long SYMBOL_NAME(sys_sigreturn)
546 .long SYMBOL_NAME(sys_clone) /* 120 */
547 .long SYMBOL_NAME(sys_setdomainname)
548 .long SYMBOL_NAME(sys_newuname)
549 .long SYMBOL_NAME(sys_modify_ldt)
550 .long SYMBOL_NAME(sys_adjtimex)
551 .long SYMBOL_NAME(sys_mprotect) /* 125 */
552 .long SYMBOL_NAME(sys_sigprocmask)
553 .long SYMBOL_NAME(sys_create_module)
554 .long SYMBOL_NAME(sys_init_module)
555 .long SYMBOL_NAME(sys_delete_module)
556 .long SYMBOL_NAME(sys_get_kernel_syms) /* 130 */
557 .long SYMBOL_NAME(sys_quotactl)
558 .long SYMBOL_NAME(sys_getpgid)
559 .long SYMBOL_NAME(sys_fchdir)
560 .long SYMBOL_NAME(sys_bdflush)
561 .long SYMBOL_NAME(sys_sysfs) /* 135 */
562 .long SYMBOL_NAME(sys_personality)
563 .long SYMBOL_NAME(sys_ni_syscall) /* for afs_syscall */
564 .long SYMBOL_NAME(sys_setfsuid16)
565 .long SYMBOL_NAME(sys_setfsgid16)
566 .long SYMBOL_NAME(sys_llseek) /* 140 */
567 .long SYMBOL_NAME(sys_getdents)
568 .long SYMBOL_NAME(sys_select)
569 .long SYMBOL_NAME(sys_flock)
570 .long SYMBOL_NAME(sys_msync)
571 .long SYMBOL_NAME(sys_readv) /* 145 */
572 .long SYMBOL_NAME(sys_writev)
573 .long SYMBOL_NAME(sys_getsid)
574 .long SYMBOL_NAME(sys_fdatasync)
575 .long SYMBOL_NAME(sys_sysctl)
576 .long SYMBOL_NAME(sys_mlock) /* 150 */
577 .long SYMBOL_NAME(sys_munlock)
578 .long SYMBOL_NAME(sys_mlockall)
579 .long SYMBOL_NAME(sys_munlockall)
580 .long SYMBOL_NAME(sys_sched_setparam)
581 .long SYMBOL_NAME(sys_sched_getparam) /* 155 */
582 .long SYMBOL_NAME(sys_sched_setscheduler)
583 .long SYMBOL_NAME(sys_sched_getscheduler)
584 .long SYMBOL_NAME(sys_sched_yield)
585 .long SYMBOL_NAME(sys_sched_get_priority_max)
586 .long SYMBOL_NAME(sys_sched_get_priority_min) /* 160 */
587 .long SYMBOL_NAME(sys_sched_rr_get_interval)
588 .long SYMBOL_NAME(sys_nanosleep)
589 .long SYMBOL_NAME(sys_mremap)
590 .long SYMBOL_NAME(sys_setresuid16)
591 .long SYMBOL_NAME(sys_getresuid16) /* 165 */
592 .long SYMBOL_NAME(sys_vm86)
593 .long SYMBOL_NAME(sys_query_module)
594 .long SYMBOL_NAME(sys_poll)
595 .long SYMBOL_NAME(sys_nfsservctl)
596 .long SYMBOL_NAME(sys_setresgid16) /* 170 */
597 .long SYMBOL_NAME(sys_getresgid16)
598 .long SYMBOL_NAME(sys_prctl)
599 .long SYMBOL_NAME(sys_rt_sigreturn)
600 .long SYMBOL_NAME(sys_rt_sigaction)
601 .long SYMBOL_NAME(sys_rt_sigprocmask) /* 175 */
602 .long SYMBOL_NAME(sys_rt_sigpending)
603 .long SYMBOL_NAME(sys_rt_sigtimedwait)
604 .long SYMBOL_NAME(sys_rt_sigqueueinfo)
605 .long SYMBOL_NAME(sys_rt_sigsuspend)
606 .long SYMBOL_NAME(sys_pread) /* 180 */
607 .long SYMBOL_NAME(sys_pwrite)
608 .long SYMBOL_NAME(sys_chown16)
609 .long SYMBOL_NAME(sys_getcwd)
610 .long SYMBOL_NAME(sys_capget)
611 .long SYMBOL_NAME(sys_capset) /* 185 */
612 .long SYMBOL_NAME(sys_sigaltstack)
613 .long SYMBOL_NAME(sys_sendfile)
614 .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
615 .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
616 .long SYMBOL_NAME(sys_vfork) /* 190 */
617 .long SYMBOL_NAME(sys_getrlimit)
618 .long SYMBOL_NAME(sys_mmap2)
619 .long SYMBOL_NAME(sys_truncate64)
620 .long SYMBOL_NAME(sys_ftruncate64)
621 .long SYMBOL_NAME(sys_stat64) /* 195 */
622 .long SYMBOL_NAME(sys_lstat64)
623 .long SYMBOL_NAME(sys_fstat64)
624 .long SYMBOL_NAME(sys_lchown)
625 .long SYMBOL_NAME(sys_getuid)
626 .long SYMBOL_NAME(sys_getgid) /* 200 */
627 .long SYMBOL_NAME(sys_geteuid)
628 .long SYMBOL_NAME(sys_getegid)
629 .long SYMBOL_NAME(sys_setreuid)
630 .long SYMBOL_NAME(sys_setregid)
631 .long SYMBOL_NAME(sys_getgroups) /* 205 */
632 .long SYMBOL_NAME(sys_setgroups)
633 .long SYMBOL_NAME(sys_fchown)
634 .long SYMBOL_NAME(sys_setresuid)
635 .long SYMBOL_NAME(sys_getresuid)
636 .long SYMBOL_NAME(sys_setresgid) /* 210 */
637 .long SYMBOL_NAME(sys_getresgid)
638 .long SYMBOL_NAME(sys_chown)
639 .long SYMBOL_NAME(sys_setuid)
640 .long SYMBOL_NAME(sys_setgid)
641 .long SYMBOL_NAME(sys_setfsuid) /* 215 */
642 .long SYMBOL_NAME(sys_setfsgid)
643 .long SYMBOL_NAME(sys_pivot_root)
644 .long SYMBOL_NAME(sys_mincore)
645 .long SYMBOL_NAME(sys_madvise)
646 .long SYMBOL_NAME(sys_getdents64) /* 220 */
647 .long SYMBOL_NAME(sys_fcntl64)
648 .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */
651 * NOTE!! This doesn't have to be exact - we just have
652 * to make sure we have _enough_ of the "sys_ni_syscall"
653 * entries. Don't panic if you notice that this hasn't
654 * been shrunk every time we add a new system call.
656 .rept NR_syscalls-221
657 .long SYMBOL_NAME(sys_ni_syscall)