Import 2.2.0pre6
[davej-history.git] / arch / i386 / kernel / entry.S
blob0153c4b40218af9bafc33fd618249193393d23b9
1 /*
2  *  linux/arch/i386/entry.S
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  */
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) - orig_eax
34  *      28(%esp) - %eip
35  *      2C(%esp) - %cs
36  *      30(%esp) - %eflags
37  *      34(%esp) - %oldesp
38  *      38(%esp) - %oldss
39  *
40  * "current" is in register %ebx during any slow entries.
41  */
43 #include <linux/sys.h>
44 #include <linux/linkage.h>
45 #include <asm/segment.h>
46 #define ASSEMBLY
47 #include <asm/smp.h>
49 EBX             = 0x00
50 ECX             = 0x04
51 EDX             = 0x08
52 ESI             = 0x0C
53 EDI             = 0x10
54 EBP             = 0x14
55 EAX             = 0x18
56 DS              = 0x1C
57 ES              = 0x20
58 ORIG_EAX        = 0x24
59 EIP             = 0x28
60 CS              = 0x2C
61 EFLAGS          = 0x30
62 OLDESP          = 0x34
63 OLDSS           = 0x38
65 CF_MASK         = 0x00000001
66 IF_MASK         = 0x00000200
67 NT_MASK         = 0x00004000
68 VM_MASK         = 0x00020000
71  * these are offsets into the task-struct.
72  */
73 state           =  0
74 flags           =  4
75 sigpending      =  8
76 addr_limit      = 12
77 exec_domain     = 16
78 need_resched    = 20
80 ENOSYS = 38
83 #define SAVE_ALL \
84         cld; \
85         pushl %es; \
86         pushl %ds; \
87         pushl %eax; \
88         pushl %ebp; \
89         pushl %edi; \
90         pushl %esi; \
91         pushl %edx; \
92         pushl %ecx; \
93         pushl %ebx; \
94         movl $(__KERNEL_DS),%edx; \
95         movl %dx,%ds; \
96         movl %dx,%es;
98 #define RESTORE_ALL     \
99         popl %ebx;      \
100         popl %ecx;      \
101         popl %edx;      \
102         popl %esi;      \
103         popl %edi;      \
104         popl %ebp;      \
105         popl %eax;      \
106 1:      popl %ds;       \
107 2:      popl %es;       \
108         addl $4,%esp;   \
109 3:      iret;           \
110 .section .fixup,"ax";   \
111 4:      movl $0,(%esp); \
112         jmp 1b;         \
113 5:      movl $0,(%esp); \
114         jmp 2b;         \
115 6:      pushl %ss;      \
116         popl %ds;       \
117         pushl %ss;      \
118         popl %es;       \
119         pushl $11;      \
120         call do_exit;   \
121 .previous;              \
122 .section __ex_table,"a";\
123         .align 4;       \
124         .long 1b,4b;    \
125         .long 2b,5b;    \
126         .long 3b,6b;    \
127 .previous
129 #define GET_CURRENT(reg) \
130         movl %esp, reg; \
131         andl $-8192, reg;
133 ENTRY(lcall7)
134         pushfl                  # We get a different stack layout with call gates,
135         pushl %eax              # which has to be cleaned up later..
136         SAVE_ALL
137         movl EIP(%esp),%eax     # due to call gates, this is eflags, not eip..
138         movl CS(%esp),%edx      # this is eip..
139         movl EFLAGS(%esp),%ecx  # and this is cs..
140         movl %eax,EFLAGS(%esp)  #
141         movl %edx,EIP(%esp)     # Now we move them to their "normal" places
142         movl %ecx,CS(%esp)      #
143         movl %esp,%ebx
144         pushl %ebx
145         andl $-8192,%ebx        # GET_CURRENT
146         movl exec_domain(%ebx),%edx     # Get the execution domain
147         movl 4(%edx),%edx       # Get the lcall7 handler for the domain
148         call *%edx
149         popl %eax
150         jmp ret_from_sys_call
153         ALIGN
154         .globl  ret_from_fork
155 ret_from_fork:
156 #ifdef __SMP__
157         call SYMBOL_NAME(schedule_tail)
158 #endif /* __SMP__ */
159         GET_CURRENT(%ebx)
160         jmp     ret_from_sys_call
163  * Return to user mode is not as complex as all this looks,
164  * but we want the default path for a system call return to
165  * go as quickly as possible which is why some of this is
166  * less clear than it otherwise should be.
167  */
169 ENTRY(system_call)
170         pushl %eax                      # save orig_eax
171         SAVE_ALL
172         GET_CURRENT(%ebx)
173         cmpl $(NR_syscalls),%eax
174         jae badsys
175         testb $0x20,flags(%ebx)         # PF_TRACESYS
176         jne tracesys
177         call *SYMBOL_NAME(sys_call_table)(,%eax,4)
178         movl %eax,EAX(%esp)             # save the return value
179         ALIGN
180         .globl ret_from_sys_call
181         .globl ret_from_intr
182 ret_from_sys_call:
183         movl SYMBOL_NAME(bh_mask),%eax
184         andl SYMBOL_NAME(bh_active),%eax
185         jne handle_bottom_half
186 ret_with_reschedule:
187         cmpl $0,need_resched(%ebx)
188         jne reschedule
189         cmpl $0,sigpending(%ebx)
190         jne signal_return
191 restore_all:
192         RESTORE_ALL
194         ALIGN
195 signal_return:
196         sti                             # we can get here from an interrupt handler
197         testl $(VM_MASK),EFLAGS(%esp)
198         movl %esp,%eax
199         jne v86_signal_return
200         xorl %edx,%edx
201         call SYMBOL_NAME(do_signal)
202         jmp restore_all
204         ALIGN
205 v86_signal_return:
206         call SYMBOL_NAME(save_v86_state)
207         movl %eax,%esp
208         xorl %edx,%edx
209         call SYMBOL_NAME(do_signal)
210         jmp restore_all
212         ALIGN
213 tracesys:
214         movl $-ENOSYS,EAX(%esp)
215         call SYMBOL_NAME(syscall_trace)
216         movl ORIG_EAX(%esp),%eax
217         call *SYMBOL_NAME(sys_call_table)(,%eax,4)
218         movl %eax,EAX(%esp)             # save the return value
219         call SYMBOL_NAME(syscall_trace)
220         jmp ret_from_sys_call
221 badsys:
222         movl $-ENOSYS,EAX(%esp)
223         jmp ret_from_sys_call
225         ALIGN
226 ret_from_exception:
227         movl SYMBOL_NAME(bh_mask),%eax
228         andl SYMBOL_NAME(bh_active),%eax
229         jne handle_bottom_half
230         ALIGN
231 ret_from_intr:
232         GET_CURRENT(%ebx)
233         movl EFLAGS(%esp),%eax          # mix EFLAGS and CS
234         movb CS(%esp),%al
235         testl $(VM_MASK | 3),%eax       # return to VM86 mode or non-supervisor?
236         jne ret_with_reschedule
237         jmp restore_all
239         ALIGN
240 handle_bottom_half:
241         call SYMBOL_NAME(do_bottom_half)
242         jmp ret_from_intr
244         ALIGN
245 reschedule:
246         call SYMBOL_NAME(schedule)    # test
247         jmp ret_from_sys_call
249 ENTRY(divide_error)
250         pushl $0                # no error code
251         pushl $ SYMBOL_NAME(do_divide_error)
252         ALIGN
253 error_code:
254         pushl %ds
255         pushl %eax
256         xorl %eax,%eax
257         pushl %ebp
258         pushl %edi
259         pushl %esi
260         pushl %edx
261         decl %eax                       # eax = -1
262         pushl %ecx
263         pushl %ebx
264         cld
265         movl %es,%cx
266         xchgl %eax, ORIG_EAX(%esp)      # orig_eax (get the error code. )
267         movl %esp,%edx
268         xchgl %ecx, ES(%esp)            # get the address and save es.
269         pushl %eax                      # push the error code
270         pushl %edx
271         movl $(__KERNEL_DS),%edx
272         movl %dx,%ds
273         movl %dx,%es
274         GET_CURRENT(%ebx)
275         call *%ecx
276         addl $8,%esp
277         jmp ret_from_exception
279 ENTRY(coprocessor_error)
280         pushl $0
281         pushl $ SYMBOL_NAME(do_coprocessor_error)
282         jmp error_code
284 ENTRY(device_not_available)
285         pushl $-1               # mark this as an int
286         SAVE_ALL
287         GET_CURRENT(%ebx)
288         pushl $ret_from_exception
289         movl %cr0,%eax
290         testl $0x4,%eax                 # EM (math emulation bit)
291         je SYMBOL_NAME(math_state_restore)
292         pushl $0                # temporary storage for ORIG_EIP
293         call  SYMBOL_NAME(math_emulate)
294         addl $4,%esp
295         ret
297 ENTRY(debug)
298         pushl $0
299         pushl $ SYMBOL_NAME(do_debug)
300         jmp error_code
302 ENTRY(nmi)
303         pushl $0
304         pushl $ SYMBOL_NAME(do_nmi)
305         jmp error_code
307 ENTRY(int3)
308         pushl $0
309         pushl $ SYMBOL_NAME(do_int3)
310         jmp error_code
312 ENTRY(overflow)
313         pushl $0
314         pushl $ SYMBOL_NAME(do_overflow)
315         jmp error_code
317 ENTRY(bounds)
318         pushl $0
319         pushl $ SYMBOL_NAME(do_bounds)
320         jmp error_code
322 ENTRY(invalid_op)
323         pushl $0
324         pushl $ SYMBOL_NAME(do_invalid_op)
325         jmp error_code
327 ENTRY(coprocessor_segment_overrun)
328         pushl $0
329         pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun)
330         jmp error_code
332 ENTRY(reserved)
333         pushl $0
334         pushl $ SYMBOL_NAME(do_reserved)
335         jmp error_code
337 ENTRY(double_fault)
338         pushl $ SYMBOL_NAME(do_double_fault)
339         jmp error_code
341 ENTRY(invalid_TSS)
342         pushl $ SYMBOL_NAME(do_invalid_TSS)
343         jmp error_code
345 ENTRY(segment_not_present)
346         pushl $ SYMBOL_NAME(do_segment_not_present)
347         jmp error_code
349 ENTRY(stack_segment)
350         pushl $ SYMBOL_NAME(do_stack_segment)
351         jmp error_code
353 ENTRY(general_protection)
354         pushl $ SYMBOL_NAME(do_general_protection)
355         jmp error_code
357 ENTRY(alignment_check)
358         pushl $ SYMBOL_NAME(do_alignment_check)
359         jmp error_code
361 ENTRY(page_fault)
362         pushl $ SYMBOL_NAME(do_page_fault)
363         jmp error_code
365 ENTRY(spurious_interrupt_bug)
366         pushl $0
367         pushl $ SYMBOL_NAME(do_spurious_interrupt_bug)
368         jmp error_code
370 .data
371 ENTRY(sys_call_table)
372         .long SYMBOL_NAME(sys_ni_syscall)       /* 0  -  old "setup()" system call*/
373         .long SYMBOL_NAME(sys_exit)
374         .long SYMBOL_NAME(sys_fork)
375         .long SYMBOL_NAME(sys_read)
376         .long SYMBOL_NAME(sys_write)
377         .long SYMBOL_NAME(sys_open)             /* 5 */
378         .long SYMBOL_NAME(sys_close)
379         .long SYMBOL_NAME(sys_waitpid)
380         .long SYMBOL_NAME(sys_creat)
381         .long SYMBOL_NAME(sys_link)
382         .long SYMBOL_NAME(sys_unlink)           /* 10 */
383         .long SYMBOL_NAME(sys_execve)
384         .long SYMBOL_NAME(sys_chdir)
385         .long SYMBOL_NAME(sys_time)
386         .long SYMBOL_NAME(sys_mknod)
387         .long SYMBOL_NAME(sys_chmod)            /* 15 */
388         .long SYMBOL_NAME(sys_lchown)
389         .long SYMBOL_NAME(sys_ni_syscall)                               /* old break syscall holder */
390         .long SYMBOL_NAME(sys_stat)
391         .long SYMBOL_NAME(sys_lseek)
392         .long SYMBOL_NAME(sys_getpid)           /* 20 */
393         .long SYMBOL_NAME(sys_mount)
394         .long SYMBOL_NAME(sys_oldumount)
395         .long SYMBOL_NAME(sys_setuid)
396         .long SYMBOL_NAME(sys_getuid)
397         .long SYMBOL_NAME(sys_stime)            /* 25 */
398         .long SYMBOL_NAME(sys_ptrace)
399         .long SYMBOL_NAME(sys_alarm)
400         .long SYMBOL_NAME(sys_fstat)
401         .long SYMBOL_NAME(sys_pause)
402         .long SYMBOL_NAME(sys_utime)            /* 30 */
403         .long SYMBOL_NAME(sys_ni_syscall)                               /* old stty syscall holder */
404         .long SYMBOL_NAME(sys_ni_syscall)                               /* old gtty syscall holder */
405         .long SYMBOL_NAME(sys_access)
406         .long SYMBOL_NAME(sys_nice)
407         .long SYMBOL_NAME(sys_ni_syscall)       /* 35 */                /* old ftime syscall holder */
408         .long SYMBOL_NAME(sys_sync)
409         .long SYMBOL_NAME(sys_kill)
410         .long SYMBOL_NAME(sys_rename)
411         .long SYMBOL_NAME(sys_mkdir)
412         .long SYMBOL_NAME(sys_rmdir)            /* 40 */
413         .long SYMBOL_NAME(sys_dup)
414         .long SYMBOL_NAME(sys_pipe)
415         .long SYMBOL_NAME(sys_times)
416         .long SYMBOL_NAME(sys_ni_syscall)                               /* old prof syscall holder */
417         .long SYMBOL_NAME(sys_brk)              /* 45 */
418         .long SYMBOL_NAME(sys_setgid)
419         .long SYMBOL_NAME(sys_getgid)
420         .long SYMBOL_NAME(sys_signal)
421         .long SYMBOL_NAME(sys_geteuid)
422         .long SYMBOL_NAME(sys_getegid)          /* 50 */
423         .long SYMBOL_NAME(sys_acct)
424         .long SYMBOL_NAME(sys_umount)                                   /* recycled never used phys() */
425         .long SYMBOL_NAME(sys_ni_syscall)                               /* old lock syscall holder */
426         .long SYMBOL_NAME(sys_ioctl)
427         .long SYMBOL_NAME(sys_fcntl)            /* 55 */
428         .long SYMBOL_NAME(sys_ni_syscall)                               /* old mpx syscall holder */
429         .long SYMBOL_NAME(sys_setpgid)
430         .long SYMBOL_NAME(sys_ni_syscall)                               /* old ulimit syscall holder */
431         .long SYMBOL_NAME(sys_olduname)
432         .long SYMBOL_NAME(sys_umask)            /* 60 */
433         .long SYMBOL_NAME(sys_chroot)
434         .long SYMBOL_NAME(sys_ustat)
435         .long SYMBOL_NAME(sys_dup2)
436         .long SYMBOL_NAME(sys_getppid)
437         .long SYMBOL_NAME(sys_getpgrp)          /* 65 */
438         .long SYMBOL_NAME(sys_setsid)
439         .long SYMBOL_NAME(sys_sigaction)
440         .long SYMBOL_NAME(sys_sgetmask)
441         .long SYMBOL_NAME(sys_ssetmask)
442         .long SYMBOL_NAME(sys_setreuid)         /* 70 */
443         .long SYMBOL_NAME(sys_setregid)
444         .long SYMBOL_NAME(sys_sigsuspend)
445         .long SYMBOL_NAME(sys_sigpending)
446         .long SYMBOL_NAME(sys_sethostname)
447         .long SYMBOL_NAME(sys_setrlimit)        /* 75 */
448         .long SYMBOL_NAME(sys_getrlimit)
449         .long SYMBOL_NAME(sys_getrusage)
450         .long SYMBOL_NAME(sys_gettimeofday)
451         .long SYMBOL_NAME(sys_settimeofday)
452         .long SYMBOL_NAME(sys_getgroups)        /* 80 */
453         .long SYMBOL_NAME(sys_setgroups)
454         .long SYMBOL_NAME(old_select)
455         .long SYMBOL_NAME(sys_symlink)
456         .long SYMBOL_NAME(sys_lstat)
457         .long SYMBOL_NAME(sys_readlink)         /* 85 */
458         .long SYMBOL_NAME(sys_uselib)
459         .long SYMBOL_NAME(sys_swapon)
460         .long SYMBOL_NAME(sys_reboot)
461         .long SYMBOL_NAME(old_readdir)
462         .long SYMBOL_NAME(old_mmap)             /* 90 */
463         .long SYMBOL_NAME(sys_munmap)
464         .long SYMBOL_NAME(sys_truncate)
465         .long SYMBOL_NAME(sys_ftruncate)
466         .long SYMBOL_NAME(sys_fchmod)
467         .long SYMBOL_NAME(sys_fchown)           /* 95 */
468         .long SYMBOL_NAME(sys_getpriority)
469         .long SYMBOL_NAME(sys_setpriority)
470         .long SYMBOL_NAME(sys_ni_syscall)                               /* old profil syscall holder */
471         .long SYMBOL_NAME(sys_statfs)
472         .long SYMBOL_NAME(sys_fstatfs)          /* 100 */
473         .long SYMBOL_NAME(sys_ioperm)
474         .long SYMBOL_NAME(sys_socketcall)
475         .long SYMBOL_NAME(sys_syslog)
476         .long SYMBOL_NAME(sys_setitimer)
477         .long SYMBOL_NAME(sys_getitimer)        /* 105 */
478         .long SYMBOL_NAME(sys_newstat)
479         .long SYMBOL_NAME(sys_newlstat)
480         .long SYMBOL_NAME(sys_newfstat)
481         .long SYMBOL_NAME(sys_uname)
482         .long SYMBOL_NAME(sys_iopl)             /* 110 */
483         .long SYMBOL_NAME(sys_vhangup)
484         .long SYMBOL_NAME(sys_idle)
485         .long SYMBOL_NAME(sys_vm86old)
486         .long SYMBOL_NAME(sys_wait4)
487         .long SYMBOL_NAME(sys_swapoff)          /* 115 */
488         .long SYMBOL_NAME(sys_sysinfo)
489         .long SYMBOL_NAME(sys_ipc)
490         .long SYMBOL_NAME(sys_fsync)
491         .long SYMBOL_NAME(sys_sigreturn)
492         .long SYMBOL_NAME(sys_clone)            /* 120 */
493         .long SYMBOL_NAME(sys_setdomainname)
494         .long SYMBOL_NAME(sys_newuname)
495         .long SYMBOL_NAME(sys_modify_ldt)
496         .long SYMBOL_NAME(sys_adjtimex)
497         .long SYMBOL_NAME(sys_mprotect)         /* 125 */
498         .long SYMBOL_NAME(sys_sigprocmask)
499         .long SYMBOL_NAME(sys_create_module)
500         .long SYMBOL_NAME(sys_init_module)
501         .long SYMBOL_NAME(sys_delete_module)
502         .long SYMBOL_NAME(sys_get_kernel_syms)  /* 130 */
503         .long SYMBOL_NAME(sys_quotactl)
504         .long SYMBOL_NAME(sys_getpgid)
505         .long SYMBOL_NAME(sys_fchdir)
506         .long SYMBOL_NAME(sys_bdflush)
507         .long SYMBOL_NAME(sys_sysfs)            /* 135 */
508         .long SYMBOL_NAME(sys_personality)
509         .long SYMBOL_NAME(sys_ni_syscall)       /* for afs_syscall */
510         .long SYMBOL_NAME(sys_setfsuid)
511         .long SYMBOL_NAME(sys_setfsgid)
512         .long SYMBOL_NAME(sys_llseek)           /* 140 */
513         .long SYMBOL_NAME(sys_getdents)
514         .long SYMBOL_NAME(sys_select)
515         .long SYMBOL_NAME(sys_flock)
516         .long SYMBOL_NAME(sys_msync)
517         .long SYMBOL_NAME(sys_readv)            /* 145 */
518         .long SYMBOL_NAME(sys_writev)
519         .long SYMBOL_NAME(sys_getsid)
520         .long SYMBOL_NAME(sys_fdatasync)
521         .long SYMBOL_NAME(sys_sysctl)
522         .long SYMBOL_NAME(sys_mlock)            /* 150 */
523         .long SYMBOL_NAME(sys_munlock)
524         .long SYMBOL_NAME(sys_mlockall)
525         .long SYMBOL_NAME(sys_munlockall)
526         .long SYMBOL_NAME(sys_sched_setparam)
527         .long SYMBOL_NAME(sys_sched_getparam)   /* 155 */
528         .long SYMBOL_NAME(sys_sched_setscheduler)
529         .long SYMBOL_NAME(sys_sched_getscheduler)
530         .long SYMBOL_NAME(sys_sched_yield)
531         .long SYMBOL_NAME(sys_sched_get_priority_max)
532         .long SYMBOL_NAME(sys_sched_get_priority_min)  /* 160 */
533         .long SYMBOL_NAME(sys_sched_rr_get_interval)
534         .long SYMBOL_NAME(sys_nanosleep)
535         .long SYMBOL_NAME(sys_mremap)
536         .long SYMBOL_NAME(sys_setresuid)
537         .long SYMBOL_NAME(sys_getresuid)        /* 165 */
538         .long SYMBOL_NAME(sys_vm86)
539         .long SYMBOL_NAME(sys_query_module)
540         .long SYMBOL_NAME(sys_poll)
541         .long SYMBOL_NAME(sys_nfsservctl)
542         .long SYMBOL_NAME(sys_setresgid)        /* 170 */
543         .long SYMBOL_NAME(sys_getresgid)
544         .long SYMBOL_NAME(sys_prctl)
545         .long SYMBOL_NAME(sys_rt_sigreturn)
546         .long SYMBOL_NAME(sys_rt_sigaction)
547         .long SYMBOL_NAME(sys_rt_sigprocmask)   /* 175 */
548         .long SYMBOL_NAME(sys_rt_sigpending)
549         .long SYMBOL_NAME(sys_rt_sigtimedwait)
550         .long SYMBOL_NAME(sys_rt_sigqueueinfo)
551         .long SYMBOL_NAME(sys_rt_sigsuspend)
552         .long SYMBOL_NAME(sys_pread)            /* 180 */
553         .long SYMBOL_NAME(sys_pwrite)
554         .long SYMBOL_NAME(sys_chown)
555         .long SYMBOL_NAME(sys_getcwd)
556         .long SYMBOL_NAME(sys_capget)
557         .long SYMBOL_NAME(sys_capset)           /* 185 */
558         .long SYMBOL_NAME(sys_sigaltstack)
559         .long SYMBOL_NAME(sys_sendfile)
560         .long SYMBOL_NAME(sys_ni_syscall)               /* streams1 */
561         .long SYMBOL_NAME(sys_ni_syscall)               /* streams2 */
562         .long SYMBOL_NAME(sys_vfork)            /* 190 */
564         /*
565          * NOTE!! This doesn't have to be exact - we just have
566          * to make sure we have _enough_ of the "sys_ni_syscall"
567          * entries. Don't panic if you notice that this hasn't
568          * been shrunk every time we add a new system call.
569          */
570         .rept NR_syscalls-190
571                 .long SYMBOL_NAME(sys_ni_syscall)
572         .endr