📄 interrupt.s
字号:
#if 0 jmp dump_state#endif jmp fault_keynot_fault_key: /* Save the keyInfo value. */ movl %ebx,keyinfo /* Recipient may be faulted. */ cmpl $0,PR_OFF_processFlags(%ebp) jnz Standard_Gate_Path /* recipient is faulted or hazarded */#if 1 /* verify that the exit block keys are well-formed */ testl $0xe0e0e0e0,PR_OFF_rcvKeys(%ebp) jnz Standard_Gate_Path#endif #if 0 /* if exit block accepts keys, take long path */ testl $0x001f1f00,PR_OFF_rcvKeys(%ebp) jnz Standard_Gate_Path#endif /* #define EXPERIMENT1 */#ifdef EXPERIMENT1 movl PR_OFF_ESI(%ebp),%ecx movl PR_OFF_rcvKeys(%ebp),%edx addl %ecx,%edx jnz L_complex_case subl $PR_OFF_FIXREGS,%eax jmp done_keys L_complex_case: cmpl %ecx,FX_OFF_sndLen(%eax) jbe got_str_len movl FX_OFF_sndLen(%eax),%ecx#else movl FX_OFF_sndLen(%eax),%ecx cmpl %ecx,PR_OFF_ESI(%ebp) jae got_str_len movl PR_OFF_ESI(%ebp),%ecx#endif got_str_len: /* I tried jecx here, but it did not work. This is faster anyway. */ testl %ecx,%ecx jz no_send_string#ifndef FAST_IPC_STRINGS jmp Standard_Gate_Path#else#ifdef FAST_IPC_STATS incl EXT(nFastIpcString)#endif /* jmp Standard_Gate_Path */ /* We know that the length is <= 64k (because we checked the send string length against this and %ecx now holds the shorter of the two lengths), verify that the recipient string is within the proper bounds... */ movl PR_OFF_EDI(%ebp),%edx#ifdef OPTION_SMALL_SPACES cmpl %edx,PR_OFF_limit(%ebp) jb Standard_Gate_Path /* string bounds violation */#else cmpl $UMSGTOP,%edx jae Standard_Gate_Path /* string bounds violation */#endif addl %edx,%ecx /* establish upper bound */#ifdef OPTION_SMALL_SPACES cmpl %ecx,PR_OFF_limit(%ebp) jb Standard_Gate_Path /* string bounds violation */#else cmpl $UMSGTOP,%ecx jae Standard_Gate_Path /* string bounds violation */#endif /* The OLD logic validated both the send string and the receive string. The NEW logic does not -- it simply cause both strings to be mapped and then optimistically does the copy. THE COPY MAY FAULT ON EITHER SENDER OR RECEIVER SIDE. A consequence of this design is that the string may be partially delivered, we may fault, and someone else may get scheduled with the data just sitting there. After discussion with Norm and the list, I've decided that this is okay. Note that there is no real way to prevent this on an SMP machine, as some other processor might be diddling the mapping tables out from under us anyway. */ /* For mappping the receive string, there are three cases: 1. Recipient space is small space 2. Recipient space is large space same as current space 3. Recipient space is large space different from current space Case (2) can currently be handled the same as case (1) OR case (3). The current code handles it like case (1) Note that we *could* make return to large space from small space fall under case (2) by rewriting the address space pointer here, but remapping the window is cheaper because it avoids taking TLB miss costs. */#ifdef OPTION_SMALL_SPACES /* Yes, Mathilda, we really SHOULD be checking this before checking for KERNPAGEDIR, because it is okay for small spaces to run out of the kernel map. */ cmpl $0,PR_OFF_bias(%ebp) jnz same_space#endif cmpl $KERNPAGEDIR,PR_OFF_MappingTable(%ebp) jz Standard_Gate_Path #ifdef OPTION_SMALL_SPACES#if 1 /* Flip this ifdef to handle case 2 like case 3. It's rare enough that it may not be worth it. */ jmp other_space#else jnz same_space movl FX_OFF_MappingTable(%eax),%ebx cmpl %ebx,PR_OFF_MappingTable(%ebp) jnz other_space#endif same_space:#if defined(FAST_IPC_BPT) && 0 int3#endif#ifdef FAST_IPC_STATS incl EXT(nFastIpcSmallString)#endif addl PR_OFF_bias(%ebp),%ecx addl PR_OFF_bias(%ebp),%edx addl $KUVA,%ecx addl $KUVA,%edx /* inherit %es as dest segment, which in theory still names active user space. */ jmp probe_receive_string#endif /* OPTION_SMALL_SPACES */other_space:#if defined(FAST_IPC_BPT) && 0 int3#endif#ifdef FAST_IPC_STATS incl EXT(nFastIpcLargeString)#endif /* Map the receive string into the kernel by copying the associated page *directory* entries. At this point, %EDX holds the properly biased start offset, so we can simply shift it to compute the PDE address. In principle, we need to check that the mappings are user mode, valid, and writable. The first follows from the fact that they are mapped in the user portion of the address space. The latter two will be tested by using a non-modifying probe instruction. */ #if 0 movl _3PTE.kern_fstbuf,%edi#endif subl %edx,%ecx /* recover xfer length */ movl FX_OFF_MappingTable(%eax),%edi addl $0xff0,%edi movl PR_OFF_MappingTable(%ebp),%esi shrl $22,%edx movl (%esi,%edx,4),%ebx /* load PDE */ movl %ebx,(%edi) movl 4(%esi,%edx,4),%ebx /* load PDE */ movl %ebx,4(%edi) movl PR_OFF_EDI(%ebp),%edx andl $0x3fffff,%edx orl $KVA_FSTBUF,%edx addl %edx,%ecx probe_receive_string: movl %edx,%edi /* save string start position */#ifdef ASM_VALIDATE_STRINGS #if defined(FAST_IPC_BPT) && 0 int3#endif /* %edx now holds string base, %ecx holds exclusive bound. Length is known to be nonzero. */#if 0 jmp Standard_Gate_Path#endif movl %edx,%edi /* save string start position */#if defined(FAST_IPC_BPT) && 0 int3#endifL_rcv_string_probe:#if defined(FAST_IPC_BPT) int3#endif andb $0xff,(%edx) addl $EROS_PAGE_SIZE,%edx cmpl %edx,%ecx ja L_rcv_string_probeL_rcv_string_probe_resid: andb $0xff,-1(%ecx)#endif /* ASM_VALIDATE_STRINGS */ /* Receive string is valid. DO THE COPY. EDI holds dest ptr from above. %DS and %ES hold kernel seg, so need to bias the source address appropriately. Doing so is much cheaper than reloading the segment register. */ movl FX_OFF_sndPtr(%eax),%esi#ifdef OPTION_SMALL_SPACES addl PR_OFF_bias-PR_OFF_FIXREGS(%eax),%esi#endif addl $KUVA,%esi subl %edi,%ecx /* recompute count */ pushl %ecx shrl $2,%ecx jz move_bytes /* Following relies on being able to use word move with misaligned data. */string_move: rep movslmove_bytes: #if defined(FAST_IPC_BPT) && 0 int3#endif movl (%esp),%ecx andl $3,%ecx jz string_done rep movsb string_done: popl %ecx movl %ecx,PR_OFF_ESI(%ebp)#ifdef FAST_IPC_STATS decl EXT(nFastIpcNoString)#endif#endif /* FAST_IPC_STRINGS */no_send_string:#ifdef FAST_IPC_STATS incl EXT(nFastIpcNoString)#endif subl $PR_OFF_FIXREGS,%eax /* EAX NOW POINTS TO SOURCE ***PROCESS*** We are now past all of the sanity checks, and we will be proceeding via the fast path. */ cmpl $0,PR_OFF_rcvKeys(%ebp) jz done_keys xorl %ecx,%ecx #define EXPERIMENT2#ifdef EXPERIMENT2 testl $0xffffff,PR_OFF_rcvKeys(%ebp) jnz key_loop movl $2,%ecx jmp next_key#endif#if 0 addl $PR_OFF_FIXREGS,%eax jmp Standard_Gate_Path#endifkey_loop: movzbl PR_OFF_rcvKeys(%ebp,%ecx),%edi testl %edi,%edi jz next_key movzbl PR_OFF_sndKeys(%eax,%ecx),%esi /* slot no */ shll $4,%edi /* slot offset relative to key regs */ shll $4,%esi /* slot offset relative to key regs */ /* esi, edi now hold offsets within keyregs for send, received key slot respectively. Convert these to slot pointers */ leal PR_OFF_keyregs(%ebp,%edi),%edi leal PR_OFF_keyregs(%eax,%esi),%esi /* If dest key is prepared, it must be unchained. Since we are overwriting it, there is no need to mark the named object as now having on-disk keys. */ testl $0x80,(%edi) jz unchained movl 4(%edi),%ebx /* grab next ptr */ movl 8(%edi),%edx /* grab prev ptr */ movl %edx,8(%ebx) /* next->prev = prev */ movl %ebx,4(%edx) /* prev->next = next */unchained: /* next ptr and first word get unconditionally copied, as does last ptr */ movl (%esi),%edx /* first word */ movl 4(%esi),%ebx /* next ptr */ movl %edx,(%edi) /* first word */ movl %ebx,4(%edi) /* next ptr */ testl $0x80,%edx /* check if this key is prepared */ jz copy_unprepared_key movl %esi,8(%edi) /* new key prev ptr is old key */ movl %edi,4(%esi) /* old key next ptr is new key */ movl %edi,8(%ebx) /* old next prev ptr is new key */ jmp last_word copy_unprepared_key: movl 8(%esi),%ebx /* prev ptr word */ movl %ebx,8(%edi) /* prev ptr word */ last_word: movl 12(%esi),%ebx /* object ptr */ movl %ebx,12(%edi) /* object ptr */ next_key: incl %ecx cmpl $3,%ecx jb key_loop ja done_keys /* decide what to do about 4th key. If this is a CALL operation, we need to fabricate a resume key. Otherwise we need to copy the key in slot 4. */ cmpl $IT_Call,PR_OFF_invType(%eax) jne key_loop /* normal key 3 */ /* It's a call. Unprepare the destination key if needed and fabricate a resume key. */ movzbl PR_OFF_rcvKeys(%ebp,%ecx),%edi testl %edi,%edi jz done_keys /* resume key refused */ shll $4,%edi /* slot offset relative to key regs */ leal PR_OFF_keyregs(%ebp,%edi),%edi /* If dest key is prepared, it must be deprepared */ testl $0x80,(%edi) jz make_resume_key movl 4(%edi),%ebx /* grab next ptr */ movl 8(%edi),%edx /* grab prev ptr */ movl %edx,8(%ebx) /* next->prev = prev */ movl %ebx,4(%edx) /* prev->next = next */ make_resume_key: movl $0x84,(%edi) /* prepped rsm, subtype=0, keydata=0 */ movl %eax,4(%edi) /* next = sender context */ movl 8(%eax),%ebx /* fetch context prev ptr */ movl %ebx,8(%edi) /* prev = context->prev */ movl %edi,4(%ebx) /* context->prev->next = this */ movl %edi,8(%eax) /* context->prev = new key */ movl %eax,12(%edi) /* pContext = sender */ done_keys: /* We have copied all the keys. We now need to copy the register arguments. %ebp points to recipient process %eax points to sending process */ movl PR_OFF_EAX(%eax),%ebx movl PR_OFF_EBX(%eax),%edx movl %ebx,PR_OFF_EAX(%ebp) movl %edx,PR_OFF_EBX(%ebp) movl PR_OFF_ECX(%eax),%ebx movl PR_OFF_EDX(%eax),%edx movl %ebx,PR_OFF_ECX(%ebp) movl %edx,PR_OFF_EDX(%ebp) /* Also the KeyInfo field. */ movzwl 2+keyinfo,%ebx movl %bx,PR_OFF_EDI(%ebp)#if defined(FAST_IPC_REDSEG)#if defined(FAST_IPC_BPT) && 0 int3#endif /* if we invoked a red segment, we now need to patch w1 and possibly replace key argument 3. */ cmpl $0,redflags jz fault_key movl redw1,%ebx movl %ebx,PR_OFF_EBX(%ebp) /* might need to send a node key in rcv key 2 */ movl rednodekey,%esi cmpl $0,%esi jz fault_key movzbl 2+PR_OFF_rcvKeys(%ebp),%edi testl %edi,%edi jz fault_key shll $4,%edi /* slot offset relative to key regs */ /* %edi now holds offset of rcv key 2 within keyregs. Convert this to a slot pointer */ leal PR_OFF_keyregs(%ebp,%edi),%edi /* If dest key is prepared, it must be unchained. Since we are overwriting it, there is no need to mark the named object as now having on-disk keys. */ testl $0x80,(%edi) jz red_unchained movl 4(%edi),%ebx /* grab next ptr */ movl 8(%edi),%edx /* grab prev ptr */ movl %edx,8(%ebx) /* next->prev = prev */ movl %ebx,4(%edx) /* prev->next = next */red_unchained:#if defined(FAST_IPC_BPT) && 0 int3#endif /* We know that the source key is prepared, since it is the key we originally invoked. Copy the first word and the next pointer. */ movl (%esi),%edx /* first word */ movl 4(%esi),%ebx /* next ptr */ movl %edx,(%edi) /* first word */ movl %ebx,4(%edi) /* next ptr */ /* update the link pointers */ movl %esi,8(%edi) /* new key prev ptr is old key */ movl %edi,4(%esi) /* old key next ptr is new key */ movl %edi,8(%ebx) /* old next prev ptr is new key */ /* copy the last word */ movl 12(%esi),%ebx /* object ptr */ movl %ebx,12(%edi) /* object ptr */ /* original key was either a NODE key or a SEGMENT key. make the result a NODE key. */ movb $0x90,(%edi)#endif /* FAST_IPC_REDSEG */fault_key: /* recipient runstate to RS_Running, sender runstate according to invType: */ movb $RS_Running,PR_OFF_runState(%ebp) movb $0,PR_OFF_processFlags(%ebp) movl $0,PR_OFF_faultCode(%ebp) movl $0,PR_OFF_faultInfo(%ebp) movb PR_OFF_invType(%eax),%bl movb %bl,PR_OFF_runState(%eax) /* kill all outstanding recipient resume keys */zap_resume_keys: movl 8(%ebp),%edi /* %edi = ctxt->prev */ cmpl %ebp,%edi je zap_done movb (%edi),%dl /* load type byte */ andb $0xfc,%dl /* mask out hazard bits */ cmpb $0x84,%dl jne zap_done /* looking at a resume key. Revise the prev ptr in the context structure. Blow away this capability. */ movl 4(%edi),%ebx /* next = key->next */ movl 8(%edi),%edx /* prev = key->prev */ cmpl %ebx,%ebp je nxt_ok jmp dump_statenxt_ok: movl %edx,8(%ebx) /* next->prev = prev */ movl %ebx,4(%edx) /* prev->next = next */ andl $0x3,(%edi) /* preserve the hazard bits */ orl $0x1330,(%edi) /* void key: 0x13==MiscKeyType::Void 0x30==(KtMisc << 2) */ /* Following are not strictly necessary. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -