📄 interrupt.s
字号:
movl $0,4(%edi) movl $0,8(%edi) movl $0,12(%edi) jmp zap_resume_keyszap_done: /* migrate the thread */ movl PR_OFF_curThread(%eax),%ebx movl $0,PR_OFF_curThread(%eax) movl %ebx,PR_OFF_curThread(%ebp) movl %ebp,OFF_THRD_CTXT(%ebx) /* update context pointer */#if 0 jmp dump_state#endif #if 0 mov $0x10,%cx mov %cx,%ds#endif #if 0 jmp dump_state#endif /* FIX: set up recipient process code/data segments here!!! Limit is expressed in pages. offset sz (bits) field new value 0 16 seg.loLimit (nPages & 0xffffu); 2 16 seg.loBase (linearBase & 0xffffu); 4 8 seg.midBase (linearBase >> 16) & 0xffu; 6 4 seg.hiLimit ((nPages >> 16) & 0xfu); 7 8 seg.hiBase (linearBase >> 24) & 0xffu; */ /* Load pointer to domain code GDT entry: */ movl $EXT(_3GDT.GdtTable),%ebx addl $0x20,%ebx /* set all base and limit fields to zero */ movl $0,(%ebx) /* domain code seg */ andl $0x00f0ff00,4(%ebx) /* domain code seg */ movl $0,8(%ebx) /* domain data seg */ andl $0x00f0ff00,12(%ebx) /* domain data seg */ #ifdef OPTION_SMALL_SPACES movl PR_OFF_bias(%ebp),%ecx testl %ecx,%ecx jz large_space_seg small_space_seg: /* Set base to value of bias. Set (inclusive) limit to 31 pages */ movw %cx,2(%ebx) /* domain code seg loBase*/ movw %cx,8+2(%ebx) /* domain data seg loBase */ shrl $16,%ecx movb %cl,4(%ebx) /* domain code seg midBase*/ movb %cl,8+4(%ebx) /* domain data seg midBase*/ movb %ch,7(%ebx) /* domain code seg hiBase*/ movb %ch,8+7(%ebx) /* domain data seg hiBase*/ movw $31,(%ebx) movw $31,8(%ebx) jmp user_seg_adjusted#endiflarge_space_seg: /* Base is already set to zero. Set (inclusive) limit to 0xCFFFF pages */ movw $0xffff,(%ebx) orl $0xc0000,4(%ebx) movw $0xffff,8(%ebx) orl $0xc0000,12(%ebx) user_seg_adjusted:#if 1 smsw %ax cmpl %ebp,_7Process.fpuOwner je fpu_enablefpu_disable: orl $0xa,%ax jmp reload_fpufpu_enable: andl $0xfff1,%eaxreload_fpu: lmsw %axfpu_adjusted:#endif#ifdef FAST_IPC_STATS incl EXT(nFastIpcEnd)#endif #ifndef FAST_IPC_RETURN pushl %ebp call EXT(resume_process)#else movl %ebp,%esp /* * We are now on our way back to whatever we interrupted. If the * interrupt routine enabled interrupts, it was responsible for * disabling them before returning, so interrupts are now * disabled. * * %esp holds a pointer to the bottom of the context we are * restoring from. */#if 0 /* * Decrement the interrupt depth counter here. Doing this from * the assembly code eliminates the need to play sleazy games in * the C part of the return path. */ decl EXT(_3IRQ.DisableDepth);#endif /* ANY CHANGE TO THIS PATH FROM HERE DOWN SHOULD BE IMPLEMENTED IN THE FAST_GATE_PATH AS WELL */ /* PROCESS_SIZE */ leal PR_OFF_INTR_SP(%ESP),%EDX movl %EDX,4+EXT(_3TSS.TaskTable) /* PROCESS_SIZE */ addl $PR_OFF_MappingTable,%ESP /* find base of save area */#if defined(DOMAIN_TRACING) /* ESP POINTS TO BOTTOM OF SAVE AREA */ cmpl $5,EXT(CpuType) jb 1f /* don't call it if not supported */ .byte 0x0f .byte 0x31 /* RDTSC instr - results to %edx:%eax */ movl %eax,EXT(DomainTracingScratchpad) movl %edx,EXT(DomainTracingScratchpad)+41: #endif /* Reload target address space: */ movl %cr3,%ebx #ifdef OPTION_SMALL_SPACES cmpl $0,PR_OFF_bias-PR_OFF_MappingTable(%esp) jnz 1f#endif cmpl %ebx,(%esp) je 1f movl (%esp),%ebx movl %ebx,%cr3 /* restore user address space */ 1: movl %EBX,28+EXT(_3TSS.TaskTable) movl %ebx,(%esp) addl $4,%esp popa#if 0 movl $EXT(InterruptStackTop),%esp jmp dump_state#endif /* * Skip over the pushed error number and exception number: */ addl $8,%esp /* * Reload the segment registers by reaching up past the critical * stuff with movl so that if we fault we always defecate at the * same point on the stack: */L_fast_reload_es: movl FX_OFF_ES-FX_OFF_EIP(%esp),%esL_fast_reload_ds: movl FX_OFF_DS-FX_OFF_EIP(%esp),%dsL_fast_reload_fs: movl FX_OFF_FS-FX_OFF_EIP(%esp),%fsL_fast_reload_gs: movl FX_OFF_GS-FX_OFF_EIP(%esp),%gs /* * ONCE BELOW THIS POINT, ALL REFERENCES MUST BE TO THE CODE * OR STACK SEGMENTS. BECAUSE DS NOW HOLDS THE USER DATA * SEGMENT, WE CANNOT TRUST THAT THE DATA SEGMENT IS VALID. */ #if 0 movl $EXT(InterruptStackTop),%esp jmp dump_state#endif /* * Sayonara, interrupt context. The iret will restore interrupts * automagically. */L_fast_iret_pc: iret#endif /* FAST_IPC_RETURN */#endif /* FAST_IPC */ kern_seg_load: /* * Now load the kernel segments. We will continue to run code * out of the Window. */ mov $0x10,%cx mov %cx,%ds mov %cx,%es /* for string copies */Standard_Gate_Path: /* * Bump the interrupt depth counter here. All of our entry * points use interrupt gates, so interrupts are definitely * disabled. Doing this from the assembly code eliminates * the need to play sleazy games in the C part of the return * path. * * Doing this AFTER the %ESP adjustment allows the SUBL to settle, * preventing subsequent AGEN interlocks on Pentium and later * processors. */ movl $1,EXT(_3IRQ.DisableDepth) /* * Call the interrupt dispatch routine, passing it a pointer * to the register save area. It is entirely up to the interrupt * routines to decide whether or not to re-enable interrupts. */ pushl %eax call EXT(OnKeyInvocationTrap__3IDTP9fixregs_t) /* This should NEVER return */ jmp EXT(halt) #if defined(FAST_IPC_REDSEG) /* VARIOUS OUT OF LINE CODE FOR THE FAST PATH. */maybe_red_seg: /* ON ENTRY: %eax points to the invoking process's fixregs structure. %ecx points to the invoked key, which is prepared. and may or may not be a red segment key. %ebx contains the first word of that key. ON EXIT: either branches to Standard_Gate_Path, in which case %eax must not be diddled but nothing else really matters. If it proves to be a fast-path case, however: %eax points to the invoking process's fixregs structure. %ecx should point to the keeper key. %ebx should contain the first word of that key. We must first verify that the key type makes it a red segmode key. If it is, we must examine the format key and decide what to do about it (if anything). STALE (applied while there were still Capability Pages): A prepared red SEGMENT key will have a keyType field of 0x94, a subtype field of 0x00, and a keyInfo field of 0x1: 0x00010094 A prepared red NODE key will have a keyType field of 0x90, a subtype field of 0x00, and a keyInfo field of 0x1: 0x00010090 CORRECT (now that Capability Pages are gone): A prepared red SEGMENT key will have a keyType field of 0x90, a subtype field of 0x00, and a keyInfo field of 0x1: 0x00010090 A prepared red NODE key will have a keyType field of 0x8C, a subtype field of 0x00, and a keyInfo field of 0x1: 0x0001008C */ cmpl $0x10090,%ebx jne Standard_Gate_Path#if 0 cmpl $0x1008c,%ebx jne Standard_Gate_Path#endif #ifdef FAST_IPC_STATS incl EXT(nFastIpcOK)#endif /* We now know that this is a prepared red segmode key. We need to determine if this segment has a keeper, and if so, whether that keeper is a gate key (and therefore eligable for the fast path logic). */ movl 12(%ecx),%ebp /* ptr to node */ /* Check if key in format slot is a number key. Format slot is 31. Node has ObHdr + callCount (1 word) before the actual key slots. We are going to need to do a bunch of arithmetic around that, so make %ebp point to base of key array: */ leal 4+OBHDR_SZ(%ebp),%ebp cmpb $0x20,0x1F0(%ebp) jne Standard_Gate_Path /* not number key */ /* Load format word */ movl 4+0x1F0(%ebp),%edx movl $0,rednodekey /* until proven otherwise */ /* check sendnode: */ andl $0x3E0,%edx jz no_sendnode cmpl $0x20,%edx jne Standard_Gate_Path /* malformed format key */#if defined(FAST_IPC_BPT) && 0 int3#endif /* we are sending a node key in slot 3. */ movl %ecx,rednodekey no_sendnode: /* Load w1 value */ movl 8+0x1F0(%ebp),%edx movl %edx,redw1 /* Find the keeper key, if any. */ movl 4+0x1F0(%ebp),%edx /* format word */ shrl $6,%edx /* right shift 10 bits to get field. left shift 4 bits to compute slot offset */ andl $0x1f0,%edx /* want ONLY this field */ cmpl $0x1f0,%edx je Standard_Gate_Path /* no keeper key! */ /* we have found the keeper key. Get pointer to it into %ecx where it belongs. */ leal (%ebp,%edx),%ecx movl (%ecx),%ebx /* load first word */ /* Provided the gate key is prepared, we can now branch back to the main path and let that path complete the key type checks. */ movl $1,redflags#ifdef FAST_IPC_STATS incl EXT(nFastIpcRedSeg)#endif testl $0x80,%ebx jnz examine_invoked_key #ifdef FAST_IPC_STATS decl EXT(nFastIpcRedSeg)#endif jmp Standard_Gate_Path /* not prepared */#endif /* THINGS THAT CAN GO WRONG IN THE MAIN IPC PATH GO HERE * * These are taken out of line in the interest of locality. */bogus_ipc_arg_block: ss movl FX_OFF_EIP(%eax),%ebx ss movl $FC_BadEntryBlock,PR_OFF_faultCode-PR_OFF_FIXREGS(%eax) ss movl %ebx,PR_OFF_faultInfo-PR_OFF_FIXREGS(%eax) jmp kern_seg_load /* * Following code implements the string move probe portion of * the invocation. It is out of line because slightly less than * 50% of all invocations move a string */ /* INTERRUPTS MUST BE DISABLED ON ENTRY TO THIS FUNCTION */ .align 16ENTRY(resume_process) pushl %ebp movl %esp,%ebp movl 0x8(%ebp),%esp /* * We are now on our way back to whatever we interrupted. If the * interrupt routine enabled interrupts, it was responsible for * disabling them before returning, so interrupts are now * disabled. * * %esp holds a pointer to the bottom of the context we are * restoring from. */ /* * Decrement the interrupt depth counter here. Doing this from * the assembly code eliminates the need to play sleazy games in * the C part of the return path. */ decl EXT(_3IRQ.DisableDepth); /* ANY CHANGE TO THIS PATH FROM HERE DOWN SHOULD BE IMPLEMENTED IN THE FAST_GATE_PATH AS WELL */ /* PROCESS_SIZE */ leal PR_OFF_INTR_SP(%ESP),%EDX movl %EDX,4+EXT(_3TSS.TaskTable) /* PROCESS_SIZE */ addl $PR_OFF_MappingTable,%ESP /* find base of save area */ #if defined(DOMAIN_TRACING) /* ESP POINTS TO BOTTOM OF SAVE AREA */ cmpl $5,EXT(CpuType) jb 1f /* don't call it if not supported */ .byte 0x0f .byte 0x31 /* RDTSC instr - results to %edx:%eax */ movl %eax,EXT(DomainTracingScratchpad) movl %edx,EXT(DomainTracingScratchpad)+41: #endif /* Reload target address space: */ movl %cr3,%ebx #ifdef OPTION_SMALL_SPACES cmpl $0,PR_OFF_bias-PR_OFF_MappingTable(%esp) jnz 1f#endif cmpl %ebx,(%esp) je 1f movl (%esp),%ebx movl %ebx,%cr3 /* restore user address space */ 1: movl %EBX,28+EXT(_3TSS.TaskTable) movl %ebx,(%esp) addl $4,%esp popa /* * Skip over the pushed error number and exception number: */ addl $8,%esp /* * Reload the segment registers by reaching up past the critical * stuff with movl so that if we fault we always defecate at the * same point on the stack: */L_reload_es: movl FX_OFF_ES-FX_OFF_EIP(%esp),%esL_reload_ds: movl FX_OFF_DS-FX_OFF_EIP(%esp),%dsL_reload_fs: movl FX_OFF_FS-FX_OFF_EIP(%esp),%fsL_reload_gs: movl FX_OFF_GS-FX_OFF_EIP(%esp),%gs /* * ONCE BELOW THIS POINT, ALL REFERENCES MUST BE TO THE CODE * OR STACK SEGMENTS. BECAUSE DS NOW HOLDS THE USER DATA * SEGMENT, WE CANNOT TRUST THAT THE DATA SEGMENT IS VALID. */ /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -