📄 kern_segment.cxx
字号:
return true; } case KT_Segment: case KT_Node:#ifdef KT_Wrapper case KT_Wrapper:#endif case KT_Page: { Node* segNode = 0; uint32_t parentBlss = wi.segBlss; wi.segBlss = wi.pSegKey->GetBlss(); if (wi.segBlss > MAX_RED_BLSS) goto seg_malformed; /* This is NOT the same as the corresponding /if/ on many * systems -- the code generated by this expression contains * no branch. */ wi.canWrite &= !wi.pSegKey->IsReadOnly(); wi.canFullFetch &= !wi.pSegKey->IsWeak(); if (!wi.canWrite && wi.writeAccess) goto access_fault; wi.canCall &= !wi.pSegKey->IsNoCall(); wi.segObj = wi.pSegKey->ok.pObj;#ifdef KT_Wrapper wi.segObjIsWrapper = false;#else wi.segObjIsRed = false;#endif if ( keyType == KT_Node || keyType == KT_Segment ) {#ifndef KT_Wrapper if (wi.segBlss == EROS_PAGE_BLSS && wi.wantLeafNode) { WALK_DBG_MSG("lfnode") continue; } else if (wi.segBlss <= EROS_PAGE_BLSS && wi.segBlss != BLSS::RedSeg) goto seg_malformed;#endif segNode = (Node *) wi.segObj; if (segNode->PrepAsSegment() == false) goto seg_thru_process;#ifndef KT_Wrapper if (wi.pSegKey->IsRedSegmentKey()) { pFormatKey = &segNode->slot[RedSegFormat]; ADD_DEPEND(pFormatKey); /* FIX: Should we do a more general check to make sure that * reserved bits are set properly? Probably.. grumble. */ if (pFormatKey->IsType(KT_Number) == false) goto seg_malformed; wi.segBlss = REDSEG_GET_BLSS(pFormatKey->nk); if (wi.segBlss > MAX_RED_BLSS) goto seg_malformed; /* Note that we don't bother to extract the keeper key * location until we need it. */ wi.segObjIsRed = true; wi.redSeg = segNode; wi.redSegOffset = wi.offset; wi.redSpanBlss = parentBlss - 1; WALK_DBG_MSG("redseg") }#endif }#ifdef KT_Wrapper else if ( keyType == KT_Wrapper ) { segNode = (Node *) wi.segObj; if (segNode->PrepAsSegment() == false) goto seg_malformed; pFormatKey = &segNode->slot[WrapperFormat]; ADD_DEPEND(pFormatKey); wi.segBlss = WRAPPER_GET_BLSS(pFormatKey->nk); /* Note that we don't bother to extract the keeper key * location until we need it. */ wi.segObjIsWrapper = true; wi.redSeg = segNode; wi.redSegOffset = wi.offset; wi.redSpanBlss = parentBlss - 1; WALK_DBG_MSG("wrapper") }#endif ADD_DEPEND(wi.pSegKey); /* Loop around again. */ break; } case KT_Number: wi.segBlss --; wi.segObj = 0;#ifdef KT_Wrapper wi.segObjIsWrapper = false;#else wi.segObjIsRed = false;#endif /* FIX: When we implement window keys, may need to add depend * entries. */ switch(wi.pSegKey->nk.value[0] & 3) { default: goto invalid_addr; } break; default: goto seg_malformed; } } /******************************** * * END key processing logic: * ********************************/ /* Loop around again. */ } access_fault: wi.faultCode = FC_Access; goto fault_exit; invalid_addr: wi.faultCode = FC_InvalidAddr; goto fault_exit; bad_seg_depth: wi.faultCode = FC_SegDepth; goto fault_exit; seg_thru_process: seg_malformed: wi.faultCode = FC_SegMalformed; fault_exit: WALK_DBG_MSG("flt") if (wi.invokeKeeperOK) return p->InvokeSegmentKeeper(wi); return false;}boolProcess::InvokeSegmentKeeper(SegWalk& wi){ Key *keeperKey = 0; Key *pFormatKey = 0; uint32_t keptBlss = 0; bool sendNode = false; if (wi.redSeg && wi.canCall) { /* We know this key is valid or /wi.redSeg/ would not have been set. */#ifdef KT_Wrapper assert(wi.redSeg->obType == ObType::NtSegment); pFormatKey = &wi.redSeg->slot[WrapperFormat]; if (pFormatKey->nk.value[0] & WRAPPER_KEEPER) keeperKey = &wi.redSeg->slot[WrapperKeeper]; keptBlss = WRAPPER_GET_BLSS(pFormatKey->nk); sendNode = pFormatKey->nk.value[0] & WRAPPER_SEND_NODE;#else pFormatKey = &wi.redSeg->slot[RedSegFormat]; uint32_t keeperSlot = REDSEG_GET_KPR_SLOT(pFormatKey->nk); if (keeperSlot != RedSegFormat) keeperKey = &wi.redSeg->slot[keeperSlot]; keptBlss = REDSEG_GET_BLSS(pFormatKey->nk); sendNode = REDSEG_GET_SENDNODE(pFormatKey->nk);#endif if (keeperKey && keeperKey->IsType(KT_Start) == false) { /* THIS IS VALID, in the sense that it serves to suppress * reporting to the process keeper. */ keeperKey = &Key::VoidKey; } } if (keeperKey == 0 && wi.invokeProcessKeeperOK == false) return false; /* Ensure retry on yield. All segment faults are fast-path * restartable. */ SetFault(wi.faultCode, wi.vaddr, false); if (keeperKey == 0) { /* Yielding here will cause the thread to resume with a non-zero * fault code in the scheduler, at which point it will be shunted * off to the process keeper. */ Thread::Current()->Yield(); } assert(keeperKey); /* If this was a memory fault, clear the PF_Faulted bit. This * allows us to restart the instruction properly without invoking * the process keeper in the event that we are forced to yield in the * middle of preparing the keeper key or calling InvokeMyKeeper; */ processFlags &= ~PF_Faulted; /* The only policy decision to make here is whether to pass a key * argument. */ Key *keyToPass = &Key::VoidKey; if (sendNode) { /* This could be a call driven by SetupExitString(), in which the * original invocation was to a red segment key with the node * passing option turned on, so do not reuse scratchKey. */ inv.redNodeKey.InitType(KT_Node); inv.redNodeKey.SetPrepared(); wi.redSeg->TransLock(); inv.redNodeKey.ok.pObj = wi.redSeg; inv.redNodeKey.ok.next = wi.redSeg->kr.next; inv.redNodeKey.ok.prev = (KeyRing*) wi.redSeg; wi.redSeg->kr.next = (KeyRing *) &inv.redNodeKey; inv.redNodeKey.ok.next->prev = (KeyRing*) &inv.redNodeKey; inv.flags |= INV_REDNODEKEY; keyToPass = &inv.redNodeKey; } /* NOTE DELICATE ISSUE * * If the keeper is a resume key we must mark the containing * segment node dirty. See the comments in kern_Invoke.cxx for an * explanation. * * In practice, if you use a resume key in a keeper slot you are a * bogon anyway, so I'm not real worried about it... * * The following may yield, but note that all segment faults are * restartable, so it's okay. There is no need for a similar * check in InvokeProcessKeeper(), because process root is always * dirty. */ if (keeperKey->IsType(KT_Resume)) wi.redSeg->MakeObjectDirty();#ifdef OPTION_DDB if (ddb_segwalk_debug) { static uint64_t last_offset = 0x0ll; if (wi.redSegOffset != last_offset) { dprintf(true, "Invoking segment keeper. redseg 0x%x" " base 0x%X last 0x%X\n", wi.redSeg, wi.redSegOffset, last_offset); last_offset = wi.redSegOffset; } }#endif InvokeMyKeeper(OC_SEGFAULT, wi.faultCode, (uint32_t) wi.redSegOffset, (uint32_t) (wi.redSegOffset>>32), keeperKey, keyToPass, 0, 0); /* NOTREACHED */ return false;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -