4 #include <asm/variants/interrupt64.S.inc>
6 #include <lunaix/syscall.h>
18 This perhaps the ugliest part in the project.
19 It contains code to handle arbitrary depth of
20 nested interrupt and all those corner cases and
23 Be aware the twists, offsets and hidden dependencies!
28 .type interrupt_wrapper, @function
29 .global interrupt_wrapper
53 pushq $0 // placeholder for depth accounting
55 movq ics(%rsp), %rax /* 取出 %cs */
56 andq $0x3, %rax /* 判断 RPL */
59 /* crossing the user/kernel boundary */
60 # x86_64 ignore {d,e}s, Lunaix does not use {f,g}s
62 movq current_thread, %rbx
63 movq iursp(%rsp), %rax
65 # Save x87 context to user stack, rather than kernel's memory.
66 # XXX what will happen if we triggered a page fault during fxsave?
67 # FIXME I think we should defer this to scheduler, and pratice lazy save/load
68 # Doing this will also make it safe from nested interrupt due to potential
69 # page fault when saving
70 # FIXME Also, generalise it to any FPU context, without constraining it to x87.
72 #andl $stack_alignment, %eax
76 # 保存用户栈顶指针。因为我们允许同级中断的产生,所以需要该手段跟踪用户栈的地址。
77 movq %rax, thread_ustack_top(%rbx) # 存入__current->ustack_top
79 /* kernel space same-level switch */
82 andq $stack_alignment, %rsp
86 xorq %rbp, %rbp # marks the boundary of stack walking
97 # # FIXME x87 fpu context
98 # movl current_thread, %eax
99 # movl thread_ustack_top(%eax), %eax
105 popq %rax # discard struct hart_state::depth
127 movq current_thread, %rax
129 # nested intr: restore saved context
130 popq thread_hstate(%rax)
134 addq $16, %rsp # skip: err_code and vector
136 # calculate stack after iretq
137 # Thank god they finally make things consistent in x86_64
139 movq %rsp, (_tss + rsp_0)
144 .type do_switch, @function
147 # Assumption: __current already hold the target process
153 xorq %rbx, %rax # avoid setting cr3 if just local thread switch.
159 # the address space could be changed. A temporary stack
160 # is required to prevent corrupt existing stack
161 movq $tmp_stack, %rsp
163 call switch_signposting # kernel/process/switch.c
165 movq current_thread, %rbx
166 test %rax, %rax # do we have signal to handle?
170 将tss.esp0设置为上次调度前的esp值。
171 当处理信号时,上下文信息是不会恢复的,而是保存在用户栈中,然后直接跳转进位于用户空间的sig_wrapper进行
172 信号的处理。当用户自定义的信号处理函数返回时,sigreturn的系统调用才开始进行上下文的恢复(或者说是进行
174 由于这中间没有进行地址空间的交换,所以第二次跳转使用的是同一个内核栈,而之前默认tss.esp0的值是永远指向最顶部
175 这样一来就有可能会覆盖更早的上下文信息(比如嵌套的信号捕获函数)
184 movq thread_hstate(%rbx), %rax
187 .type handle_signal, @function
188 .global handle_signal
190 # 注意1:任何对proc_sig的布局改动,都须及时的保证这里的一致性!
191 # 注意2:handle_signal在调用之前,须确保proc_sig已经写入用户栈!
192 # arg1 in %rax: addr of proc_sig structure in user stack
193 movq psig_saved_hstate(%rax), %rbx # %rbx = &proc_sig->saved_hstate
198 movq iexecp(%rbx), %rbx
199 pushq exrflags(%rbx) # proc_sig->saved_hstate->execp->eflags
201 pushq $UCODE_SEG # cs
202 pushq psig_sigact(%rax) # %rip = proc_sig->sigact