1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #include <linux/sys.h>
44 #include <linux/linkage.h>
45 #include <asm/segment.h>
46 #define ASSEMBLY
47 #include <asm/smp.h>
48
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 FS = 0x24
59 GS = 0x28
60 ORIG_EAX = 0x2C
61 EIP = 0x30
62 CS = 0x34
63 EFLAGS = 0x38
64 OLDESP = 0x3C
65 OLDSS = 0x40
66
67 CF_MASK = 0x00000001
68 IF_MASK = 0x00000200
69 NT_MASK = 0x00004000
70 VM_MASK = 0x00020000
71
72
73
74
75 state = 0
76 counter = 4
77 priority = 8
78 signal = 12
79 blocked = 16
80 flags = 20
81 errno = 24
82 dbgreg6 = 52
83 dbgreg7 = 56
84 exec_domain = 60
85
86 ENOSYS = 38
87
88 #define SAVE_ALL \
89 cld; \
90 push %gs; \
91 push %fs; \
92 push %es; \
93 push %ds; \
94 pushl %eax; \
95 pushl %ebp; \
96 pushl %edi; \
97 pushl %esi; \
98 pushl %edx; \
99 pushl %ecx; \
100 pushl %ebx; \
101 movl $(KERNEL_DS),%edx; \
102 mov %dx,%ds; \
103 mov %dx,%es; \
104 movl $(USER_DS),%edx; \
105 mov %dx,%fs;
106
107 #ifdef __SMP__
108
109 #define GET_PROCESSOR_ID \
110 movl SYMBOL_NAME(apic_reg), %edx; \
111 movl 32(%edx), %eax;\
112 movl %eax,SYMBOL_NAME(apic_retval); \
113 shrl $24,%eax; \
114 andb $0x0F,%al;
115
116
117
118
119
120 #define GET_PROCESSOR_OFFSET(x) \
121 movl SYMBOL_NAME(apic_reg), x ; \
122 movl 32( x ), x ; \
123 shrl $22, x ; \
124 andl $0x3C, x ;
125
126
127
128 #define LEAVE_KERNEL \
129 pushfl; \
130 cli; \
131 decl SYMBOL_NAME(syscall_count); \
132 decl SYMBOL_NAME(kernel_counter); \
133 jnz 1f; \
134 movb $(NO_PROC_ID), SYMBOL_NAME(active_kernel_processor); \
135 lock; \
136 btrl $0, SYMBOL_NAME(kernel_flag); \
137 1: popfl;
138
139
140
141
142
143
144
145
146
147
148
149
150
151 #define ENTER_KERNEL \
152 pushl %eax; \
153 pushl %edx; \
154 pushfl; \
155 cli; \
156 GET_PROCESSOR_ID \
157 1: lock; \
158 btsl $0, SYMBOL_NAME(kernel_flag); \
159 jnc 3f; \
160 cmpb SYMBOL_NAME(active_kernel_processor), %al; \
161 je 4f; \
162 2: incl SYMBOL_NAME(smp_spins); \
163 btl %al, SYMBOL_NAME(smp_invalidate_needed); \
164 jnc 5f; \
165 lock; \
166 btrl %al, SYMBOL_NAME(smp_invalidate_needed); \
167 jnc 5f; \
168 movl %cr3,%edx; \
169 movl %edx,%cr3; \
170 5: btl $0, SYMBOL_NAME(kernel_flag); \
171 jc 2b; \
172 jmp 1b; \
173 3: movb %al, SYMBOL_NAME(active_kernel_processor); \
174 4: incl SYMBOL_NAME(kernel_counter); \
175 incl SYMBOL_NAME(syscall_count); \
176 popfl; \
177 popl %edx; \
178 popl %eax;
179
180
181 #define RESTORE_ALL \
182 cmpw $(KERNEL_CS),CS(%esp); \
183 je 1f; \
184 GET_PROCESSOR_OFFSET(%edx) \
185 movl SYMBOL_NAME(current_set)(,%edx), %eax ; ; \
186 movl dbgreg7(%eax),%ebx; \
187 movl %ebx,%db7; \
188 1: LEAVE_KERNEL \
189 popl %ebx; \
190 popl %ecx; \
191 popl %edx; \
192 popl %esi; \
193 popl %edi; \
194 popl %ebp; \
195 popl %eax; \
196 pop %ds; \
197 pop %es; \
198 pop %fs; \
199 pop %gs; \
200 addl $4,%esp; \
201 iret
202
203 #else
204
205 #define RESTORE_ALL \
206 cmpw $(KERNEL_CS),CS(%esp); \
207 je 1f; \
208 movl SYMBOL_NAME(current_set),%eax; \
209 movl dbgreg7(%eax),%ebx; \
210 movl %ebx,%db7; \
211 1: \
212 popl %ebx; \
213 popl %ecx; \
214 popl %edx; \
215 popl %esi; \
216 popl %edi; \
217 popl %ebp; \
218 popl %eax; \
219 pop %ds; \
220 pop %es; \
221 pop %fs; \
222 pop %gs; \
223 addl $4,%esp; \
224 iret
225 #endif
226
227
228 ENTRY(lcall7)
229 pushfl # We get a different stack layout with call gates,
230 pushl %eax # which has to be cleaned up later..
231 SAVE_ALL
232 #ifdef __SMP__
233 ENTER_KERNEL
234 #endif
235 movl EIP(%esp),%eax # due to call gates, this is eflags, not eip..
236 movl CS(%esp),%edx # this is eip..
237 movl EFLAGS(%esp),%ecx # and this is cs..
238 movl %eax,EFLAGS(%esp) #
239 movl %edx,EIP(%esp) # Now we move them to their "normal" places
240 movl %ecx,CS(%esp) #
241 movl %esp,%eax
242 #ifdef __SMP__
243 GET_PROCESSOR_OFFSET(%edx) # Processor offset into edx
244 movl SYMBOL_NAME(current_set)(,%edx),%edx
245 #else
246 movl SYMBOL_NAME(current_set),%edx
247 #endif
248 pushl %eax
249 movl exec_domain(%edx),%edx # Get the execution domain
250 movl 4(%edx),%edx # Get the lcall7 handler for the domain
251 call *%edx
252 popl %eax
253 jmp ret_from_sys_call
254
255 ALIGN
256 handle_bottom_half:
257 pushfl
258 incl SYMBOL_NAME(intr_count)
259 sti
260 call SYMBOL_NAME(do_bottom_half)
261 popfl
262 decl SYMBOL_NAME(intr_count)
263 jmp 9f
264 ALIGN
265 reschedule:
266 pushl $ret_from_sys_call
267 jmp SYMBOL_NAME(schedule) # test
268
269 ENTRY(system_call)
270 pushl %eax # save orig_eax
271 SAVE_ALL
272 #ifdef __SMP__
273 ENTER_KERNEL
274 #endif
275 movl $-ENOSYS,EAX(%esp)
276 cmpl $(NR_syscalls),%eax
277 jae ret_from_sys_call
278 movl SYMBOL_NAME(sys_call_table)(,%eax,4),%eax
279 testl %eax,%eax
280 je ret_from_sys_call
281 #ifdef __SMP__
282 GET_PROCESSOR_OFFSET(%edx)
283 movl SYMBOL_NAME(current_set)(,%edx),%ebx
284 #else
285 movl SYMBOL_NAME(current_set),%ebx
286 #endif
287 andl $~CF_MASK,EFLAGS(%esp) # clear carry - assume no errors
288 movl $0,errno(%ebx)
289 movl %db6,%edx
290 movl %edx,dbgreg6(%ebx) # save current hardware debugging status
291 testb $0x20,flags(%ebx) # PF_TRACESYS
292 jne 1f
293 call *%eax
294 movl %eax,EAX(%esp) # save the return value
295 movl errno(%ebx),%edx
296 negl %edx
297 je ret_from_sys_call
298 movl %edx,EAX(%esp)
299 orl $(CF_MASK),EFLAGS(%esp) # set carry to indicate error
300 jmp ret_from_sys_call
301 ALIGN
302 1: call SYMBOL_NAME(syscall_trace)
303 movl ORIG_EAX(%esp),%eax
304 call SYMBOL_NAME(sys_call_table)(,%eax,4)
305 movl %eax,EAX(%esp) # save the return value
306 #ifdef __SMP__
307 GET_PROCESSOR_OFFSET(%eax)
308 movl SYMBOL_NAME(current_set)(,%eax),%eax
309 #else
310 movl SYMBOL_NAME(current_set),%eax
311 #endif
312 movl errno(%eax),%edx
313 negl %edx
314 je 1f
315 movl %edx,EAX(%esp)
316 orl $(CF_MASK),EFLAGS(%esp) # set carry to indicate error
317 1: call SYMBOL_NAME(syscall_trace)
318
319 ALIGN
320 .globl ret_from_sys_call
321 ret_from_sys_call:
322 cmpl $0,SYMBOL_NAME(intr_count)
323 jne 2f
324 9: movl SYMBOL_NAME(bh_mask),%eax
325 andl SYMBOL_NAME(bh_active),%eax
326 jne handle_bottom_half
327 movl EFLAGS(%esp),%eax # check VM86 flag: CS/SS are
328 testl $(VM_MASK),%eax # different then
329 jne 1f
330 cmpw $(KERNEL_CS),CS(%esp) # was old code segment supervisor ?
331 je 2f
332 1: sti
333 orl $(IF_MASK),%eax # these just try to make sure
334 andl $~NT_MASK,%eax # the program doesn't do anything
335 movl %eax,EFLAGS(%esp) # stupid
336 cmpl $0,SYMBOL_NAME(need_resched)
337 jne reschedule
338 #ifdef __SMP__
339 GET_PROCESSOR_OFFSET(%eax)
340 movl SYMBOL_NAME(current_set)(,%eax), %eax
341 #else
342 movl SYMBOL_NAME(current_set),%eax
343 #endif
344 cmpl SYMBOL_NAME(task),%eax # task[0] cannot have signals
345 je 2f
346 movl blocked(%eax),%ecx
347 movl %ecx,%ebx # save blocked in %ebx for signal handling
348 notl %ecx
349 andl signal(%eax),%ecx
350 jne signal_return
351 2: RESTORE_ALL
352 ALIGN
353 signal_return:
354 movl %esp,%ecx
355 pushl %ecx
356 testl $(VM_MASK),EFLAGS(%ecx)
357 jne v86_signal_return
358 pushl %ebx
359 call SYMBOL_NAME(do_signal)
360 popl %ebx
361 popl %ebx
362 RESTORE_ALL
363 ALIGN
364 v86_signal_return:
365 call SYMBOL_NAME(save_v86_state)
366 movl %eax,%esp
367 pushl %eax
368 pushl %ebx
369 call SYMBOL_NAME(do_signal)
370 popl %ebx
371 popl %ebx
372 RESTORE_ALL
373
374 ENTRY(divide_error)
375 pushl $0 # no error code
376 pushl $ SYMBOL_NAME(do_divide_error)
377 ALIGN
378 error_code:
379 push %fs
380 push %es
381 push %ds
382 pushl %eax
383 pushl %ebp
384 pushl %edi
385 pushl %esi
386 pushl %edx
387 pushl %ecx
388 pushl %ebx
389 movl $0,%eax
390 movl %eax,%db7 # disable hardware debugging...
391 cld
392 movl $-1, %eax
393 xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. )
394 xorl %ebx,%ebx # zero ebx
395 mov %gs,%bx # get the lower order bits of gs
396 xchgl %ebx, GS(%esp) # get the address and save gs.
397 pushl %eax # push the error code
398 lea 4(%esp),%edx
399 pushl %edx
400 movl $(KERNEL_DS),%edx
401 mov %dx,%ds
402 mov %dx,%es
403 movl $(USER_DS),%edx
404 mov %dx,%fs
405 #ifdef __SMP__
406 ENTER_KERNEL
407 #endif
408 pushl %eax
409 #ifdef __SMP__
410 GET_PROCESSOR_OFFSET(%eax)
411 movl SYMBOL_NAME(current_set)(,%eax), %eax
412 #else
413 movl SYMBOL_NAME(current_set),%eax
414 #endif
415 movl %db6,%edx
416 movl %edx,dbgreg6(%eax) # save current hardware debugging status
417 popl %eax
418 call *%ebx
419 addl $8,%esp
420 jmp ret_from_sys_call
421
422 ENTRY(coprocessor_error)
423 pushl $0
424 pushl $ SYMBOL_NAME(do_coprocessor_error)
425 jmp error_code
426
427 ENTRY(device_not_available)
428 pushl $-1 # mark this as an int
429 SAVE_ALL
430 #ifdef __SMP__
431 ENTER_KERNEL
432 #endif
433 pushl $ret_from_sys_call
434 movl %cr0,%eax
435 testl $0x4,%eax # EM (math emulation bit)
436 je SYMBOL_NAME(math_state_restore)
437 pushl $0 # temporary storage for ORIG_EIP
438 call SYMBOL_NAME(math_emulate)
439 addl $4,%esp
440 ret
441
442 ENTRY(debug)
443 pushl $0
444 pushl $ SYMBOL_NAME(do_debug)
445 jmp error_code
446
447 ENTRY(nmi)
448 pushl $0
449 pushl $ SYMBOL_NAME(do_nmi)
450 jmp error_code
451
452 ENTRY(int3)
453 pushl $0
454 pushl $ SYMBOL_NAME(do_int3)
455 jmp error_code
456
457 ENTRY(overflow)
458 pushl $0
459 pushl $ SYMBOL_NAME(do_overflow)
460 jmp error_code
461
462 ENTRY(bounds)
463 pushl $0
464 pushl $ SYMBOL_NAME(do_bounds)
465 jmp error_code
466
467 ENTRY(invalid_op)
468 pushl $0
469 pushl $ SYMBOL_NAME(do_invalid_op)
470 jmp error_code
471
472 ENTRY(coprocessor_segment_overrun)
473 pushl $0
474 pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun)
475 jmp error_code
476
477 ENTRY(reserved)
478 pushl $0
479 pushl $ SYMBOL_NAME(do_reserved)
480 jmp error_code
481
482 ENTRY(double_fault)
483 pushl $ SYMBOL_NAME(do_double_fault)
484 jmp error_code
485
486 ENTRY(invalid_TSS)
487 pushl $ SYMBOL_NAME(do_invalid_TSS)
488 jmp error_code
489
490 ENTRY(segment_not_present)
491 pushl $ SYMBOL_NAME(do_segment_not_present)
492 jmp error_code
493
494 ENTRY(stack_segment)
495 pushl $ SYMBOL_NAME(do_stack_segment)
496 jmp error_code
497
498 ENTRY(general_protection)
499 pushl $ SYMBOL_NAME(do_general_protection)
500 jmp error_code
501
502 ENTRY(alignment_check)
503 pushl $ SYMBOL_NAME(do_alignment_check)
504 jmp error_code
505
506 ENTRY(page_fault)
507 pushl $ SYMBOL_NAME(do_page_fault)
508 jmp error_code
509
510 .data
511 ENTRY(sys_call_table)
512 .long SYMBOL_NAME(sys_setup)
513 .long SYMBOL_NAME(sys_exit)
514 .long SYMBOL_NAME(sys_fork)
515 .long SYMBOL_NAME(sys_read)
516 .long SYMBOL_NAME(sys_write)
517 .long SYMBOL_NAME(sys_open)
518 .long SYMBOL_NAME(sys_close)
519 .long SYMBOL_NAME(sys_waitpid)
520 .long SYMBOL_NAME(sys_creat)
521 .long SYMBOL_NAME(sys_link)
522 .long SYMBOL_NAME(sys_unlink)
523 .long SYMBOL_NAME(sys_execve)
524 .long SYMBOL_NAME(sys_chdir)
525 .long SYMBOL_NAME(sys_time)
526 .long SYMBOL_NAME(sys_mknod)
527 .long SYMBOL_NAME(sys_chmod)
528 .long SYMBOL_NAME(sys_chown)
529 .long SYMBOL_NAME(sys_break)
530 .long SYMBOL_NAME(sys_stat)
531 .long SYMBOL_NAME(sys_lseek)
532 .long SYMBOL_NAME(sys_getpid)
533 .long SYMBOL_NAME(sys_mount)
534 .long SYMBOL_NAME(sys_umount)
535 .long SYMBOL_NAME(sys_setuid)
536 .long SYMBOL_NAME(sys_getuid)
537 .long SYMBOL_NAME(sys_stime)
538 .long SYMBOL_NAME(sys_ptrace)
539 .long SYMBOL_NAME(sys_alarm)
540 .long SYMBOL_NAME(sys_fstat)
541 .long SYMBOL_NAME(sys_pause)
542 .long SYMBOL_NAME(sys_utime)
543 .long SYMBOL_NAME(sys_stty)
544 .long SYMBOL_NAME(sys_gtty)
545 .long SYMBOL_NAME(sys_access)
546 .long SYMBOL_NAME(sys_nice)
547 .long SYMBOL_NAME(sys_ftime)
548 .long SYMBOL_NAME(sys_sync)
549 .long SYMBOL_NAME(sys_kill)
550 .long SYMBOL_NAME(sys_rename)
551 .long SYMBOL_NAME(sys_mkdir)
552 .long SYMBOL_NAME(sys_rmdir)
553 .long SYMBOL_NAME(sys_dup)
554 .long SYMBOL_NAME(sys_pipe)
555 .long SYMBOL_NAME(sys_times)
556 .long SYMBOL_NAME(sys_prof)
557 .long SYMBOL_NAME(sys_brk)
558 .long SYMBOL_NAME(sys_setgid)
559 .long SYMBOL_NAME(sys_getgid)
560 .long SYMBOL_NAME(sys_signal)
561 .long SYMBOL_NAME(sys_geteuid)
562 .long SYMBOL_NAME(sys_getegid)
563 .long SYMBOL_NAME(sys_acct)
564 .long SYMBOL_NAME(sys_phys)
565 .long SYMBOL_NAME(sys_lock)
566 .long SYMBOL_NAME(sys_ioctl)
567 .long SYMBOL_NAME(sys_fcntl)
568 .long SYMBOL_NAME(sys_mpx)
569 .long SYMBOL_NAME(sys_setpgid)
570 .long SYMBOL_NAME(sys_ulimit)
571 .long SYMBOL_NAME(sys_olduname)
572 .long SYMBOL_NAME(sys_umask)
573 .long SYMBOL_NAME(sys_chroot)
574 .long SYMBOL_NAME(sys_ustat)
575 .long SYMBOL_NAME(sys_dup2)
576 .long SYMBOL_NAME(sys_getppid)
577 .long SYMBOL_NAME(sys_getpgrp)
578 .long SYMBOL_NAME(sys_setsid)
579 .long SYMBOL_NAME(sys_sigaction)
580 .long SYMBOL_NAME(sys_sgetmask)
581 .long SYMBOL_NAME(sys_ssetmask)
582 .long SYMBOL_NAME(sys_setreuid)
583 .long SYMBOL_NAME(sys_setregid)
584 .long SYMBOL_NAME(sys_sigsuspend)
585 .long SYMBOL_NAME(sys_sigpending)
586 .long SYMBOL_NAME(sys_sethostname)
587 .long SYMBOL_NAME(sys_setrlimit)
588 .long SYMBOL_NAME(sys_getrlimit)
589 .long SYMBOL_NAME(sys_getrusage)
590 .long SYMBOL_NAME(sys_gettimeofday)
591 .long SYMBOL_NAME(sys_settimeofday)
592 .long SYMBOL_NAME(sys_getgroups)
593 .long SYMBOL_NAME(sys_setgroups)
594 .long SYMBOL_NAME(old_select)
595 .long SYMBOL_NAME(sys_symlink)
596 .long SYMBOL_NAME(sys_lstat)
597 .long SYMBOL_NAME(sys_readlink)
598 .long SYMBOL_NAME(sys_uselib)
599 .long SYMBOL_NAME(sys_swapon)
600 .long SYMBOL_NAME(sys_reboot)
601 .long SYMBOL_NAME(old_readdir)
602 .long SYMBOL_NAME(old_mmap)
603 .long SYMBOL_NAME(sys_munmap)
604 .long SYMBOL_NAME(sys_truncate)
605 .long SYMBOL_NAME(sys_ftruncate)
606 .long SYMBOL_NAME(sys_fchmod)
607 .long SYMBOL_NAME(sys_fchown)
608 .long SYMBOL_NAME(sys_getpriority)
609 .long SYMBOL_NAME(sys_setpriority)
610 .long SYMBOL_NAME(sys_profil)
611 .long SYMBOL_NAME(sys_statfs)
612 .long SYMBOL_NAME(sys_fstatfs)
613 .long SYMBOL_NAME(sys_ioperm)
614 .long SYMBOL_NAME(sys_socketcall)
615 .long SYMBOL_NAME(sys_syslog)
616 .long SYMBOL_NAME(sys_setitimer)
617 .long SYMBOL_NAME(sys_getitimer)
618 .long SYMBOL_NAME(sys_newstat)
619 .long SYMBOL_NAME(sys_newlstat)
620 .long SYMBOL_NAME(sys_newfstat)
621 .long SYMBOL_NAME(sys_uname)
622 .long SYMBOL_NAME(sys_iopl)
623 .long SYMBOL_NAME(sys_vhangup)
624 .long SYMBOL_NAME(sys_idle)
625 .long SYMBOL_NAME(sys_vm86)
626 .long SYMBOL_NAME(sys_wait4)
627 .long SYMBOL_NAME(sys_swapoff)
628 .long SYMBOL_NAME(sys_sysinfo)
629 .long SYMBOL_NAME(sys_ipc)
630 .long SYMBOL_NAME(sys_fsync)
631 .long SYMBOL_NAME(sys_sigreturn)
632 .long SYMBOL_NAME(sys_clone)
633 .long SYMBOL_NAME(sys_setdomainname)
634 .long SYMBOL_NAME(sys_newuname)
635 .long SYMBOL_NAME(sys_modify_ldt)
636 .long SYMBOL_NAME(sys_adjtimex)
637 .long SYMBOL_NAME(sys_mprotect)
638 .long SYMBOL_NAME(sys_sigprocmask)
639 .long SYMBOL_NAME(sys_create_module)
640 .long SYMBOL_NAME(sys_init_module)
641 .long SYMBOL_NAME(sys_delete_module)
642 .long SYMBOL_NAME(sys_get_kernel_syms)
643 .long SYMBOL_NAME(sys_quotactl)
644 .long SYMBOL_NAME(sys_getpgid)
645 .long SYMBOL_NAME(sys_fchdir)
646 .long SYMBOL_NAME(sys_bdflush)
647 .long SYMBOL_NAME(sys_sysfs)
648 .long SYMBOL_NAME(sys_personality)
649 .long 0
650 .long SYMBOL_NAME(sys_setfsuid)
651 .long SYMBOL_NAME(sys_setfsgid)
652 .long SYMBOL_NAME(sys_llseek)
653 .long SYMBOL_NAME(sys_getdents)
654 .long SYMBOL_NAME(sys_select)
655 .long SYMBOL_NAME(sys_flock)
656 .long SYMBOL_NAME(sys_msync)
657 .long SYMBOL_NAME(sys_readv)
658 .long SYMBOL_NAME(sys_writev)
659 .long 0
660 .long 0
661 .long 0
662 .long SYMBOL_NAME(sys_mlock)
663 .long SYMBOL_NAME(sys_munlock)
664 .long SYMBOL_NAME(sys_mlockall)
665 .long SYMBOL_NAME(sys_munlockall)
666 .space (NR_syscalls-154)*4