📄 sys_call.s
字号:
/* * linux/kernel/system_call.s * * (C) 1991 Linus Torvalds *//* * system_call.s contains the system-call low-level handling routines. * This also contains the timer-interrupt handler, as some of the code is * the same. The hd- and flopppy-interrupts are also here. * * NOTE: This code handles signal-recognition, which happens every time * after a timer-interrupt and after each system call. Ordinary interrupts * don't handle signal-recognition, as that would clutter them up totally * unnecessarily. * * Stack layout in 'ret_from_system_call': * ptrace needs to have all regs on the stack. * if the order here is changed, it needs to be * updated in fork.c:copy_process, signal.c:do_signal, * ptrace.c ptrace.h * * 0(%esp) - %ebx * 4(%esp) - %ecx * 8(%esp) - %edx * C(%esp) - %esi * 10(%esp) - %edi * 14(%esp) - %ebp * 18(%esp) - %eax * 1C(%esp) - %ds * 20(%esp) - %es * 24(%esp) - %fs * 28(%esp) - %gs * 2C(%esp) - orig_eax * 30(%esp) - %eip * 34(%esp) - %cs * 38(%esp) - %eflags * 3C(%esp) - %oldesp * 40(%esp) - %oldss */SIG_CHLD = 17EBX = 0x00ECX = 0x04EDX = 0x08ESI = 0x0CEDI = 0x10EBP = 0x14EAX = 0x18DS = 0x1CES = 0x20FS = 0x24GS = 0x28ORIG_EAX = 0x2CEIP = 0x30CS = 0x34EFLAGS = 0x38OLDESP = 0x3COLDSS = 0x40state = 0 # these are offsets into the task-struct.counter = 4priority = 8signal = 12sigaction = 16 # MUST be 16 (=len of sigaction)blocked = (33*16)# offsets within sigactionsa_handler = 0sa_mask = 4sa_flags = 8sa_restorer = 12nr_system_calls = 82ENOSYS = 38/* * Ok, I get parallel printer interrupts while using the floppy for some * strange reason. Urgel. Now I just ignore them. */.globl _system_call,_timer_interrupt,_sys_execve.globl _hd_interrupt,_floppy_interrupt,_parallel_interrupt.globl _device_not_available, _coprocessor_error.align 2bad_sys_call: pushl $-ENOSYS jmp ret_from_sys_call.align 2reschedule: pushl $ret_from_sys_call jmp _schedule.align 2_system_call: cld pushl %eax # save orig_eax push %gs push %fs push %es push %ds pushl %eax # save eax. The return value will be put here. pushl %ebp pushl %edi pushl %esi pushl %edx pushl %ecx # push %ebx,%ecx,%edx as parameters pushl %ebx # to the system call movl $0x10,%edx # set up ds,es to kernel space mov %dx,%ds mov %dx,%es movl $0x17,%edx # fs points to local data space mov %dx,%fs cmpl _NR_syscalls,%eax jae bad_sys_call call _sys_call_table(,%eax,4) movl %eax,EAX(%esp) # save the return value2: movl _current,%eax cmpl $0,state(%eax) # state jne reschedule cmpl $0,counter(%eax) # counter je rescheduleret_from_sys_call: movl _current,%eax cmpl _task,%eax # task[0] cannot have signals je 3f cmpw $0x0f,CS(%esp) # was old code segment supervisor ? jne 3f cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ? jne 3f movl signal(%eax),%ebx movl blocked(%eax),%ecx notl %ecx andl %ebx,%ecx bsfl %ecx,%ecx je 3f btrl %ecx,%ebx movl %ebx,signal(%eax) incl %ecx pushl %ecx call _do_signal popl %ecx testl %eax, %eax jne 2b # see if we need to switch tasks, or do more signals3: popl %ebx popl %ecx popl %edx popl %esi popl %edi popl %ebp popl %eax pop %ds pop %es pop %fs pop %gs addl $4,%esp # skip the orig_eax iret.align 2_coprocessor_error: cld pushl $-1 # mark this as an int. push %gs push %fs push %es push %ds pushl %eax # save eax. pushl %ebp pushl %edi pushl %esi pushl %edx pushl %ecx pushl %ebx movl $0x10,%eax mov %ax,%ds mov %ax,%es movl $0x17,%eax mov %ax,%fs pushl $ret_from_sys_call jmp _math_error.align 2_device_not_available: cld pushl $-1 # mark this as an int push %gs push %fs push %es push %ds pushl %eax pushl %ebp pushl %edi pushl %esi pushl %edx pushl %ecx pushl %ebx movl $0x10,%eax mov %ax,%ds mov %ax,%es movl $0x17,%eax mov %ax,%fs pushl $ret_from_sys_call clts # clear TS so that we can use math movl %cr0,%eax testl $0x4,%eax # EM (math emulation bit) je _math_state_restore pushl $0 # temporary storage for ORIG_EIP call _math_emulate addl $4,%esp ret.align 2_timer_interrupt: cld pushl $-1 # mark this as an int push %gs push %fs push %es push %ds pushl %eax pushl %ebp pushl %edi pushl %esi pushl %edx pushl %ecx pushl %ebx movl $0x10,%eax mov %ax,%ds mov %ax,%es movl $0x17,%eax mov %ax,%fs incl _jiffies movb $0x20,%al # EOI to interrupt controller #1 outb %al,$0x20 movl CS(%esp),%eax andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor) pushl %eax call _do_timer # 'do_timer(long CPL)' does everything from addl $4,%esp # task switching to accounting ... jmp ret_from_sys_call.align 2_sys_execve: lea (EIP+4)(%esp),%eax # don't forget about the return address. pushl %eax call _do_execve addl $4,%esp ret_hd_interrupt: cld pushl %eax pushl %ecx pushl %edx push %ds push %es push %fs movl $0x10,%eax mov %ax,%ds mov %ax,%es movl $0x17,%eax mov %ax,%fs movb $0x20,%al outb %al,$0xA0 # EOI to interrupt controller #1 jmp 1f # give port chance to breathe1: jmp 1f1: outb %al,$0x20 andl $0xfffeffff,_timer_active xorl %edx,%edx xchgl _do_hd,%edx testl %edx,%edx jne 1f movl $_unexpected_hd_interrupt,%edx1: call *%edx # "interesting" way of handling intr. pop %fs pop %es pop %ds popl %edx popl %ecx popl %eax iret_floppy_interrupt: cld pushl %eax pushl %ecx pushl %edx push %ds push %es push %fs movl $0x10,%eax mov %ax,%ds mov %ax,%es movl $0x17,%eax mov %ax,%fs movb $0x20,%al outb %al,$0x20 # EOI to interrupt controller #1 xorl %eax,%eax xchgl _do_floppy,%eax testl %eax,%eax jne 1f movl $_unexpected_floppy_interrupt,%eax1: call *%eax # "interesting" way of handling intr. pop %fs pop %es pop %ds popl %edx popl %ecx popl %eax iret_parallel_interrupt: cld pushl %eax movb $0x20,%al outb %al,$0x20 popl %eax iret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -