/*
* linux/kernel/system_call.s
* !--int 0x80中断调用,内核提供的各种功能服务
* (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':
* /*系统调用返回ret_froom_system_call时堆栈的内容*/
* 0(%esp) - %eax
* 4(%esp) - %ebx
* 8(%esp) - %ecx
* C(%esp) - %edx
* 10(%esp) - original %eax (-1 if not system call)
* 14(%esp) - %fs
* 18(%esp) - %es
* 1C(%esp) - %ds
* 20(%esp) - %eip
* 24(%esp) - %cs
* 28(%esp) - %eflags
* 2C(%esp) - %oldesp
* 30(%esp) - %oldss
*/
SIG_CHLD = 17 !--子进程结束信号
EAX = 0x00 !--堆栈中各个寄存器的偏移值
EBX = 0x04
ECX = 0x08
EDX = 0x0C
ORIG_EAX = 0x10
FS = 0x14
ES = 0x18
DS = 0x1C
EIP = 0x20 !--CPU自动入栈
CS = 0x24
EFLAGS = 0x28
OLDESP = 0x2C
OLDSS = 0x30
state = 0 # these are offsets into the task-struct.
counter = 4 !--------------结构体struct task
priority = 8
signal = 12
sigaction = 16 # MUST be 16 (=len of sigaction)
blocked = (33*16)
# offsets within sigaction !--结构体sigaction中的偏移量
sa_handler = 0
sa_mask = 4
sa_flags = 8
sa_restorer = 12
nr_system_calls = 82
ENOSYS = 38
/*
* Ok, I get parallel printer interrupts while using the floppy for some
* strange reason. Urgel. Now I just ignore them.
*/
.globl _system_call,_sys_fork,_timer_interrupt,_sys_execve
.globl _hd_interrupt,_floppy_interrupt,_parallel_interrupt
.globl _device_not_available, _coprocessor_error
.align 2
bad_sys_call: !--出错信息
pushl $-ENOSYS
jmp ret_from_sys_call
.align 2
reschedule: !--调用调度函数
pushl $ret_from_sys_call
jmp _schedule
.align 2
_system_call: !--linux系统调用入口
push %ds
push %es
push %fs
pushl %eax # save the orig_eax
pushl %edx
pushl %ecx # push %ebx,%ecx,%edx as parameters !--3个参数
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) !--_sys_call_table[]指针数组,设置了内核82个系统调用C处理函数的地址
pushl %eax !--系统调用返回值入栈
2:
movl _current,%eax !--如果当前进程没就绪/时间片用完,这调度其它程序执行
cmpl $0,state(%eax) # state
jne reschedule
cmpl $0,counter(%eax) # counter
je reschedule
ret_from_sys_call: !--判断是否是任务0,是则退出
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 signals
3: popl %eax !--按100行的入栈的返回值返回
popl %ebx
popl %ecx
popl %edx
addl $4, %esp # skip orig_eax
pop %fs
pop %es
pop %ds
iret
.align 2
_coprocessor_error: !--处理器错误中断
push %ds
push %es
push %fs
pushl $-1 # fill in -1 for orig_eax
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
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: !--设备不存在或协处理器不存在
push %ds
push %es
push %fs
pushl $-1 # fill in -1 for orig_eax
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
movl $0x10,%eax
mov %ax,%ds
mov %ax,%es
movl $0x17,%eax
mov %ax,%fs
pushl $ret_from_sys_call !--清CR0中任务已交换标志TS,并取CR0值
clts # clear TS so that we can use math
movl %cr0,%eax
testl $0x4,%eax # EM (math emulation bit)
je _math_state_restore !--数学仿真程序math_emulate()
pushl %ebp
pushl %esi
pushl %edi
pushl $0 # temporary storage for ORIG_EIP
call _math_emulate
addl $4,%esp
popl %edi
popl %esi
popl %ebp
ret
.align 2
_timer_interrupt: !--时钟中断处理程序
push %ds # save ds,es and put kernel data space
push %es # into them. %fs is used by _system_call
push %fs
pushl $-1 # fill in -1 for orig_eax
pushl %edx # we save %eax,%ecx,%edx as gcc doesn't
pushl %ecx # save those across function calls. %ebx
pushl %ebx # is saved as we use that in ret_sys_call
pushl %eax
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: !--sys_execve()系统调用
lea EIP(%esp),%eax
pushl %eax
call _do_execve
addl $4,%esp
ret
.align 2
_sys_fork: !--sys_fork()调用
call _find_empty_process
testl %eax,%eax
js 1f
push %gs
pushl %esi
pushl %edi
pushl %ebp
pushl %eax
call _copy_process
addl $20,%esp
1: ret
_hd_interrupt: !--int46,硬盘中断处理程序
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 breathe
1: jmp 1f
1: xorl %edx,%edx
movl %edx,_hd_timeout
xchgl _do_hd,%edx !--do_hd函数指针,指向read_init()或write_init();
testl %edx,%edx
jne 1f
movl $_unexpected_hd_interrupt,%edx
1: outb %al,$0x20
call *%edx # "interesting" way of handling intr.
pop %fs
pop %es
pop %ds
popl %edx
popl %ecx
popl %eax
iret
_floppy_interrupt: !--int38,软盘中断处理程序
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 !--do_floppy函数指针
testl %eax,%eax
jne 1f
movl $_unexpected_floppy_interrupt,%eax
1: call *%eax # "interesting" way of handling intr.
pop %fs
pop %es
pop %ds
popl %edx
popl %ecx
popl %eax
iret
_parallel_interrupt: !--int39,并行口中断处理程序
pushl %eax
movb $0x20,%al
outb %al,$0x20
popl %eax
iret
|xGv00|fcc8d4de8197f69fde70263fb4d52380