2 #include <arch/x86/interrupts.h>
3 #include <arch/x86/i386_asm.h>
4 #include <arch/x86/tss.h>
5 #include <lunaix/syscall.h>
6 #include <arch/x86/interrupt.S.inc>
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
39 Stack layout (layout of struct isr_param)
46 vector > offset = 52 -> 4
47 [saved_prev_ctx] > offset = 0
53 ds > offset = 8 * 4 = 32
61 lsa: depth > offset = 0
63 las: Least Significant Address
64 msa: Most Significant Address
86 movl proc_intr_ctx(%eax), %eax
88 pushl %eax # nested intr: current depth
90 movl ics(%esp), %eax /* 取出 %cs */
91 andl $0x3, %eax /* 判断 RPL */
94 /* crossing the user/kernel boundary */
103 # 保存用户栈顶指针。因为我们允许同级中断的产生,所以需要该手段跟踪用户栈的地址。
104 movl iuesp(%esp), %ebx # 取出esp
105 movl %ebx, proc_ustack_top(%eax) # 存入__current->ustack_top
107 # Save x87 context to user stack, rather than kernel's memory.
108 # XXX: what will happen if we triggered a page fault during fxsave?
109 movl iuesp(%esp), %eax
110 andl $stack_alignment, %eax
114 /* kernel space same-level switch */
117 andl $stack_alignment, %esp
129 #ifdef __ASM_INTR_DIAGNOSIS
130 movl %eax, (debug_resv + 8)
131 movl iesp(%esp), %eax
132 movl exeip(%eax), %eax
133 movl %eax, (debug_resv + 4) # eip
135 // movl __current, %eax
136 // movl proc_fxstate(%eax), %eax
138 // test %eax, %eax # do we have stored x87 context?
144 movl iuesp(%esp), %eax
145 andl $stack_alignment, %eax
150 popl %eax # discard isr_param::depth
170 # nested intr: restore saved context
171 popl proc_intr_ctx(%eax)
175 #ifdef __ASM_INTR_DIAGNOSIS
177 movl %eax, debug_resv
179 # 处理TSS.ESP的一些边界条件。如果是正常iret(即从内核模式*优雅地*退出)
180 # 那么TSS.ESP0应该为iret进行弹栈后,%esp的值。
181 # 所以这里的边界条件是:如返回用户模式,iret会额外弹出8个字节(ss,esp)
188 movl %eax, (_tss + tss_esp0_off)
196 # arg1: 目标进程PCB地址 (next
200 movl proc_page_table(%eax), %ecx # __current->pagetable
201 movl proc_page_table(%ebx), %eax # next->pagetable
203 cmpl %ecx, %eax # if(next->pagtable != __current->pagetable) {
205 movl %eax, %cr3 # cpu_lcr3(next->pagetable)
208 movl %ebx, __current # __current = next
210 # 我们已经处在了新的地址空间,为了避免影响其先前的栈布局
212 movl $tmp_stack, %esp
214 call signal_dispatch # kernel/signal.c
216 test %eax, %eax # do we have signal to handle?
220 movl proc_intr_ctx(%ebx), %ecx # __current->intr_ctx
221 movl %ecx, (tss_esp0_off + _tss)
225 movl proc_intr_ctx(%ebx), %eax
228 .global handle_signal
230 # 注意1:任何对proc_sig的布局改动,都须及时的保证这里的一致性!
231 # 注意2:handle_signal在调用之前,须确保proc_sig已经写入用户栈!
232 # arg1 in %eax: addr of proc_sig structure in user stack
233 movl psig_saved_ictx(%eax), %ebx # %ebx = &proc_sig->saved_ictx
238 movl iexecp(%ebx), %ebx
239 pushl exeflags(%ebx) # proc_sig->saved_ictx->execp->eflags
241 pushl $UCODE_SEG # cs
242 pushl psig_sigact(%eax) # %eip = proc_sig->sigact
244 movw $UDATA_SEG, %cx # switch data seg to user mode