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