X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/b26d3165c52589d1f8de37bf0df27ad96f460f47..d1b1c8d9119229dbeed06cd252917e54a1cb77f6:/lunaix-os/arch/i386/exceptions/interrupt.S diff --git a/lunaix-os/arch/i386/exceptions/interrupt.S b/lunaix-os/arch/i386/exceptions/interrupt.S index d2f5543..8d82d10 100644 --- a/lunaix-os/arch/i386/exceptions/interrupt.S +++ b/lunaix-os/arch/i386/exceptions/interrupt.S @@ -1,5 +1,5 @@ #define __ASM__ -#include +#include #include #include @@ -33,6 +33,7 @@ */ .section .text + .type interrupt_wrapper, @function .global interrupt_wrapper interrupt_wrapper: cld @@ -54,10 +55,7 @@ pushl %ebx pushl %eax - movl __current, %eax - movl proc_intr_ctx(%eax), %eax - incl %eax - pushl %eax # nested intr: current depth + pushl $0 // placeholder for depth accounting movl ics(%esp), %eax /* 取出 %cs */ andl $0x3, %eax /* 判断 RPL */ @@ -70,18 +68,22 @@ movw %ax, %ds movw %ax, %es - movl __current, %ebx + movl current_thread, %ebx + movl iuesp(%esp), %eax # Save x87 context to user stack, rather than kernel's memory. # XXX what will happen if we triggered a page fault during fxsave? - # FIXME can we remove this overhead? - movl iuesp(%esp), %eax - andl $stack_alignment, %eax - subl $512, %eax - fxsave (%eax) + # FIXME I think we should defer this to scheduler, and pratice lazy save/load + # Doing this will also make it safe from nested interrupt due to potential + # page fault when saving + # FIXME Also, generalise it to any FPU context, without constraining it to x87. + + #andl $stack_alignment, %eax + #subl $512, %eax + #fxsave (%eax) # 保存用户栈顶指针。因为我们允许同级中断的产生,所以需要该手段跟踪用户栈的地址。 - movl %eax, proc_ustack_top(%ebx) # 存入__current->ustack_top + movl %eax, thread_ustack_top(%ebx) # 存入__current->ustack_top /* kernel space same-level switch */ 1: @@ -90,6 +92,7 @@ subl $16, %esp movl %eax, (%esp) + xorl %ebp, %ebp # marks the boundary of stack walking call intr_handler movl (%esp), %eax @@ -109,14 +112,15 @@ andl $3, %eax jz 1f - movl __current, %eax - movl proc_ustack_top(%eax), %eax - test %eax, %eax - jz 1f - fxrstor (%eax) + # # FIXME x87 fpu context + # movl current_thread, %eax + # movl thread_ustack_top(%eax), %eax + # test %eax, %eax + # jz 1f + # fxrstor (%eax) 1: - popl %eax # discard isr_param::depth + popl %eax # discard struct hart_state::depth popl %eax popl %ebx popl %ecx @@ -133,10 +137,10 @@ movl 16(%esp), %esp movl %eax, tmp_store - movl __current, %eax + movl current_thread, %eax # nested intr: restore saved context - popl proc_intr_ctx(%eax) + popl thread_hstate(%eax) addl $8, %esp @@ -158,54 +162,61 @@ iret - .global switch_to - switch_to: - # 约定 - # arg1: 目标进程PCB地址 (next + .type do_switch, @function + .global do_switch + do_switch: + # Assumption: __current already hold the target process - popl %ebx # next - movl __current, %eax - movl proc_page_table(%eax), %ecx # __current->pagetable - movl proc_page_table(%ebx), %eax # next->pagetable - - cmpl %ecx, %eax # if(next->pagtable != __current->pagetable) { + call proc_vmroot + + movl %eax, %ebx + movl %cr3, %eax + xorl %ebx, %eax # avoid setting cr3 if just local thread switch. jz 1f - movl %eax, %cr3 # cpu_lcr3(next->pagetable) - # } - 1: - movl %ebx, __current # __current = next - # 我们已经处在了新的地址空间,为了避免影响其先前的栈布局 - # 需要使用一个临时的栈空间 + movl %ebx, %cr3 + + 1: + # the address space could be changed. A temporary stack + # is required to prevent corrupt existing stack movl $tmp_stack, %esp call signal_dispatch # kernel/signal.c + movl current_thread, %ebx test %eax, %eax # do we have signal to handle? jz 1f - # 更新 tss - movl proc_intr_ctx(%ebx), %ecx # __current->intr_ctx + /* + 将tss.esp0设置为上次调度前的esp值。 + 当处理信号时,上下文信息是不会恢复的,而是保存在用户栈中,然后直接跳转进位于用户空间的sig_wrapper进行 + 信号的处理。当用户自定义的信号处理函数返回时,sigreturn的系统调用才开始进行上下文的恢复(或者说是进行 + 另一次调度。 + 由于这中间没有进行地址空间的交换,所以第二次跳转使用的是同一个内核栈,而之前默认tss.esp0的值是永远指向最顶部 + 这样一来就有可能会覆盖更早的上下文信息(比如嵌套的信号捕获函数) + */ + movl thread_hstate(%ebx), %ecx # __current->hstate movl %ecx, (tss_esp0_off + _tss) jmp handle_signal 1: - movl proc_intr_ctx(%ebx), %eax + movl thread_hstate(%ebx), %eax jmp soft_iret + .type handle_signal, @function .global handle_signal handle_signal: # 注意1:任何对proc_sig的布局改动,都须及时的保证这里的一致性! # 注意2:handle_signal在调用之前,须确保proc_sig已经写入用户栈! # arg1 in %eax: addr of proc_sig structure in user stack - movl psig_saved_ictx(%eax), %ebx # %ebx = &proc_sig->saved_ictx + movl psig_saved_hstate(%eax), %ebx # %ebx = &proc_sig->saved_hstate pushl $UDATA_SEG pushl %eax # esp movl iexecp(%ebx), %ebx - pushl exeflags(%ebx) # proc_sig->saved_ictx->execp->eflags + pushl exeflags(%ebx) # proc_sig->saved_hstate->execp->eflags pushl $UCODE_SEG # cs pushl psig_sigact(%eax) # %eip = proc_sig->sigact