荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: GyeaonWoo (柏林恋人), 信区: Linux
标  题: Linus's Linux--kernel/system_call.s
发信站: 荔园晨风BBS站 (Mon Aug 25 20:35:59 2003), 站内信件

/*
 *  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-interrupt is 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':
 *
 *       0(%esp) - %eax
 *       4(%esp) - %ebx
 *       8(%esp) - %ecx
 *       C(%esp) - %edx
 *      10(%esp) - %fs
 *      14(%esp) - %es
 *      18(%esp) - %ds
 *      1C(%esp) - %eip
 *      20(%esp) - %cs
 *      24(%esp) - %eflags
 *      28(%esp) - %oldesp
 *      2C(%esp) - %oldss
 */

SIG_CHLD        = 17
EAX             = 0x00
EBX             = 0x04
ECX             = 0x08
EDX             = 0x0C
FS              = 0x10
ES              = 0x14
DS              = 0x18
EIP             = 0x1C
CS              = 0x20
EFLAGS          = 0x24
OLDESP          = 0x28
OLDSS           = 0x2C

state   = 0             # these are offsets into the task-struct.
counter = 4
priority = 8
signal  = 12
restorer = 16           # address of info-restorer
sig_fn  = 20            # table of 32 signal addresses

nr_system_calls = 67

.globl _system_call,_sys_fork,_timer_interrupt,_hd_interrupt,
_sys_execve

.align 2
bad_sys_call:
        movl $-1,%eax
        iret
.align 2
reschedule:
        pushl $ret_from_sys_call
        jmp _schedule
.align 2
_system_call:
        cmpl $nr_system_calls-1,%eax
        ja bad_sys_call
        push %ds
        push %es
        push %fs
        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
        call _sys_call_table(,%eax,4)
        pushl %eax
        movl _current,%eax
        cmpl $0,state(%eax)             # state
        jne reschedule
        cmpl $0,counter(%eax)           # counter
        je reschedule
ret_from_sys_call:
        movl _current,%eax              # task[0] cannot have signals
        cmpl _task,%eax
        je 3f
        movl CS(%esp),%ebx              # was old code segment supervisor
        testl $3,%ebx                   # mode? If so - don't check signals
        je 3f
        cmpw $0x17,OLDSS(%esp)          # was stack segment = 0x17 ?
        jne 3f
2:      movl signal(%eax),%ebx          # signals (bitmap, 32 signals)
        bsfl %ebx,%ecx                  # %ecx is signal nr, return if none
        je 3f
        btrl %ecx,%ebx                  # clear it
        movl %ebx,signal(%eax)
        movl sig_fn(%eax,%ecx,4),%ebx   # %ebx is signal handler address
        cmpl $1,%ebx
        jb default_signal               # 0 is default signal handler - exit
        je 2b                           # 1 is ignore - find next signal
        movl $0,sig_fn(%eax,%ecx,4)     # reset signal handler address
        incl %ecx
        xchgl %ebx,EIP(%esp)            # put new return address on stack
        subl $28,OLDESP(%esp)
        movl OLDESP(%esp),%edx          # push old return address on stack
        pushl %eax                      # but first check that it's ok.
        pushl %ecx
        pushl $28
        pushl %edx
        call _verify_area
        popl %edx
        addl $4,%esp
        popl %ecx
        popl %eax
        movl restorer(%eax),%eax
        movl %eax,%fs:(%edx)            # flag/reg restorer
        movl %ecx,%fs:4(%edx)           # signal nr
        movl EAX(%esp),%eax
        movl %eax,%fs:8(%edx)           # old eax
        movl ECX(%esp),%eax
        movl %eax,%fs:12(%edx)          # old ecx
        movl EDX(%esp),%eax
        movl %eax,%fs:16(%edx)          # old edx
        movl EFLAGS(%esp),%eax
        movl %eax,%fs:20(%edx)          # old eflags
        movl %ebx,%fs:24(%edx)          # old return addr
3:      popl %eax
        popl %ebx
        popl %ecx
        popl %edx
        pop %fs
        pop %es
        pop %ds
        iret

default_signal:
        incl %ecx
        cmpl $SIG_CHLD,%ecx
        je 2b
        pushl %ecx
        call _do_exit           # remember to set bit 7 when dumping core
        addl $4,%esp
        jmp 3b

.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 %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:
        lea EIP(%esp),%eax
        pushl %eax
        call _do_execve
        addl $4,%esp
        ret

.align 2
_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:
        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
        jmp 1f                  # give port chance to breathe
1:      jmp 1f
1:      outb %al,$0xA0          # same to controller #2
        movl _do_hd,%eax
        testl %eax,%eax
        jne 1f
        movl $_unexpected_hd_interrupt,%eax
1:      call *%eax              # "interesting" way of handling intr.
        pop %fs
        pop %es
        pop %ds
        popl %edx
        popl %ecx
        popl %eax
        iret


--
终于能按照自己的内心写作了
却不能按照一个人的内心生活
花太香,只好梦蝶一场唉唉

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.35.5]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店