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