2 #include <sys/interrupts.h>
4 #include <sys/interrupt.S.inc>
6 #include <lunaix/syscall.h>
8 #define __ASM_INTR_DIAGNOSIS
10 #ifdef __ASM_INTR_DIAGNOSIS
26 This perhaps the ugliest part in the project.
27 It contains code to handle arbitrary depth of
28 nested interrupt and all those corner cases and
31 Be aware the twists, offsets and hidden dependencies!
36 .global interrupt_wrapper
58 movl proc_intr_ctx(%eax), %eax
60 pushl %eax # nested intr: current depth
62 movl ics(%esp), %eax /* 取出 %cs */
63 andl $0x3, %eax /* 判断 RPL */
66 /* crossing the user/kernel boundary */
75 # Save x87 context to user stack, rather than kernel's memory.
76 # XXX what will happen if we triggered a page fault during fxsave?
77 # FIXME can we remove this overhead?
78 movl iuesp(%esp), %eax
79 andl $stack_alignment, %eax
83 # 保存用户栈顶指针。因为我们允许同级中断的产生,所以需要该手段跟踪用户栈的地址。
84 movl %eax, proc_ustack_top(%ebx) # 存入__current->ustack_top
86 /* kernel space same-level switch */
89 andl $stack_alignment, %esp
101 #ifdef __ASM_INTR_DIAGNOSIS
102 movl %eax, (debug_resv + 8)
103 movl iesp(%esp), %eax
104 movl exeip(%eax), %eax
105 movl %eax, (debug_resv + 4) # eip
113 movl proc_ustack_top(%eax), %eax
119 popl %eax # discard isr_param::depth
138 # nested intr: restore saved context
139 popl proc_intr_ctx(%eax)
143 #ifdef __ASM_INTR_DIAGNOSIS
145 movl %eax, debug_resv
147 # 处理TSS.ESP的一些边界条件。如果是正常iret(即从内核模式*优雅地*退出)
148 # 那么TSS.ESP0应该为iret进行弹栈后,%esp的值。
149 # 所以这里的边界条件是:如返回用户模式,iret会额外弹出8个字节(ss,esp)
156 movl %eax, (_tss + tss_esp0_off)
164 # arg1: 目标进程PCB地址 (next
168 movl proc_page_table(%eax), %ecx # __current->pagetable
169 movl proc_page_table(%ebx), %eax # next->pagetable
171 cmpl %ecx, %eax # if(next->pagtable != __current->pagetable) {
173 movl %eax, %cr3 # cpu_lcr3(next->pagetable)
176 movl %ebx, __current # __current = next
178 # 我们已经处在了新的地址空间,为了避免影响其先前的栈布局
180 movl $tmp_stack, %esp
182 call signal_dispatch # kernel/signal.c
184 test %eax, %eax # do we have signal to handle?
188 movl proc_intr_ctx(%ebx), %ecx # __current->intr_ctx
189 movl %ecx, (tss_esp0_off + _tss)
194 movl proc_intr_ctx(%ebx), %eax
197 .global handle_signal
199 # 注意1:任何对proc_sig的布局改动,都须及时的保证这里的一致性!
200 # 注意2:handle_signal在调用之前,须确保proc_sig已经写入用户栈!
201 # arg1 in %eax: addr of proc_sig structure in user stack
202 movl psig_saved_ictx(%eax), %ebx # %ebx = &proc_sig->saved_ictx
207 movl iexecp(%ebx), %ebx
208 pushl exeflags(%ebx) # proc_sig->saved_ictx->execp->eflags
210 pushl $UCODE_SEG # cs
211 pushl psig_sigact(%eax) # %eip = proc_sig->sigact
213 movw $UDATA_SEG, %cx # switch data seg to user mode