⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kern_segment.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 1998, 1999, 2001, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <kerninc/kernel.hxx>#include <eros/SysTraceKey.h>#include <kerninc/Process.hxx>#include <kerninc/SegWalk.hxx>#include <kerninc/SysTimer.hxx>#include <kerninc/Depend.hxx>#include <kerninc/Thread.hxx>#include <kerninc/Invocation.hxx>/* Extracted as macro for clarity of code below, which is already too * complicated.  */#define ADD_DEPEND(pKey) \    assert ((wi.frameBits != EROS_PAGE_ADDR_BITS) || pPTE0); \    if (pPTE0) \      Depend_AddKey(pKey, pPTE0, canMerge); \    if (pPTE1) \      Depend_AddKey(pKey, pPTE1, canMerge);/* proc_WalkSeg() is a performance-critical path.  The segment walk   logic is complex, and it occurs in the middle of page faulting   activity, which for obvious reasons is performance-critical.   The walker is also entered in stages to allow successive   traversals.  This is mainly to keep the code machine-independent; a   machine-dependent specialization of this routine could avoid a   couple of procedure calls.   The /pPTE0/ and /pPTE1/ arguments and the /canMerge/ argument   should unquestionably be merged into the SegWalkInfo structure.   The depth of the walk is bounded by MAX_SEG_DEPTH to detect   possible loops in the segment tree.  Because the routine is   multiply entered the actual depth limit can be two or three times   the nominal limit.  The architecture guarantees a minimum traversal   depth, but does not promise any particular maximum.   The traversal process must maintain the following variables:   /pSegKey/   pointer to the node slot containing the key that names               the segment we are now considering.   /segBlss/   size of the segment represented by pSegKey.      /pKeptSeg/  pointer to the NODE that was the last red segment we               went through.  Arguably, we should track two of these:	       one for keepers and one for background segment logic.	       At the present time we do not do so.   /traverseCount/  the number of traversals we have done on this               path.  At the moment this is not properly tracked if we	       use the short-circuited fast walk.      /canWrite/  whether the path traversed already conveyed write               permission.   /canCall/   whether the path traversed already allowed keeper               invocation.      /faultCode/ the fault code, if any, associated with this               traversal.   In addition, the following members of the WalkInfo structure are   actually arguments passed from above.  They are stored in the   WalkInfo structure because they do not change across the several   calls:      /writeAccess/  whether the translation is for writing   /prompt/       whether we are willing to take a keeper fault to                  get a translation.   I have temporarily removed the support for capability pages to get   one thing right at a time.*/#define BLSS_SHIFT(lss, frameBits) \  (((lss) - EROS_PAGE_BLSS - 1) * EROS_NODE_LGSIZE + frameBits)inline uint64_tBLSS_MASK64(uint32_t blss, uint32_t frameBits){  uint32_t bits_to_shift =    (blss - EROS_PAGE_BLSS) * EROS_NODE_LGSIZE + frameBits;   uint64_t mask = (1ull << bits_to_shift);  mask -= 1ull;    return mask;}#ifdef OPTION_DDBextern bool ddb_segwalk_debug;#endifvoidsegwalk_init(SegWalk &wi, Key *pSegKey){  wi.pSegKey = pSegKey;  wi.segBlss = EROS_ADDRESS_BLSS + 1;	/* until proven otherwise */  wi.offset = wi.vaddr;  wi.redSeg = 0;  wi.redSegOffset = 0;  wi.redSpanBlss = 0;#ifdef KT_Wrapper  wi.segObjIsWrapper = false;#else  wi.segObjIsRed = false;#endif  wi.canCall = true;		/* until proven otherwise */  wi.canWrite = true;		/* until proven otherwise */  wi.canFullFetch = true;	/* until proven otherwise */}boolproc_WalkSeg(Process * p, SegWalk& wi, uint32_t stopBlss,	     PTE* pPTE0, PTE* pPTE1, bool canMerge){#ifdef OPTION_DDB#  ifdef KT_Wrapper#define WALK_DBG_MSG(prefix) \  if (ddb_segwalk_debug) dprintf(true, prefix \      " proc_WalkSeg: wi.producer 0x%x, wi.segBlss %d wi.isWrap %d\n" \      "wi.vaddr 0x%x wi.offset 0x%X flt %d  wa %d segKey 0x%x\n" \      "canCall %d canWrite %d stopBlss %d\n" \      "redSeg 0x%x redSpanBlss %d redOffset 0x%X\n", \      wi.segObj, wi.segBlss, wi.segObjIsWrapper, \      wi.vaddr, wi.offset, wi.faultCode, wi.writeAccess, wi.pSegKey, \      wi.canCall, wi.canWrite, stopBlss, \      wi.redSeg, wi.redSpanBlss, wi.redSegOffset);#  else#define WALK_DBG_MSG(prefix) \  if (ddb_segwalk_debug) dprintf(true, prefix \      " proc_WalkSeg: wi.producer 0x%x, wi.segBlss %d wi.isRed %d\n" \      "wi.vaddr 0x%x wi.offset 0x%X flt %d  wa %d segKey 0x%x\n" \      "canCall %d canWrite %d stopBlss %d\n" \      "redSeg 0x%x redSpanBlss %d redOffset 0x%X\n", \      wi.segObj, wi.segBlss, wi.segObjIsRed, \      wi.vaddr, wi.offset, wi.faultCode, wi.writeAccess, wi.pSegKey, \      wi.canCall, wi.canWrite, stopBlss, \      wi.redSeg, wi.redSpanBlss, wi.redSegOffset);#  endif#else#define WALK_DBG_MSG(prefix)#endif  const uint32_t MAX_SEG_DEPTH = 20;  KernStats.nWalkSeg++;  Key *pFormatKey = 0;  if (wi.segObj == 0)    goto process_key;    for(;;) {    /* If it's the leaf object and we wanted a node, it better be seg     * key type. Conversely, if we *didn't* want a node, it better NOT     * be seg key type. All non-page, non-node cases should already     * have been filtered out in the key processing loop below as     * malformed segments. */    if (wi.segBlss == EROS_PAGE_BLSS &&	wi.wantLeafNode != wi.pSegKey->IsSegKeyType())      goto seg_malformed;    if (wi.segBlss <= stopBlss) {      WALK_DBG_MSG("ret")      return true;    }          KernStats.nWalkLoop++;    /*********************************     *      * BEGIN Traversal step logic:     *      *********************************/    {      WALK_DBG_MSG("wlk")#ifndef NDEBUG      if (wi.segObj->obType == ObType::NtUnprepared)	fatal("Some node unprepare did not work at kern_Segment.cxx:%d\n",		      __LINE__);#endif          Node* segNode = (Node *) wi.segObj;	      assertex ( segNode,		 segNode->obType == ObType::NtSegment );	      uint32_t initialSlots = EROS_NODE_SLOT_MASK;#ifdef KT_Wrapper      if (wi.segObjIsWrapper) {	assertex (&wi, segNode->obType == ObType::NtSegment);	pFormatKey = &segNode->slot[WrapperFormat];	ADD_DEPEND(pFormatKey);	initialSlots = 0;      }#else      if (wi.segObjIsRed) {#ifdef KT_Wrapper	assert (wi.segObjIsWrapper == false);#endif	pFormatKey = &segNode->slot[RedSegFormat];	/* We know that the format key is valid.  It was checked in	 * the key-related checking above, either during the current	 * pass or when building information about the parent page	 * table.  If the format key has since been modified, then	 * the parent page table entry will have been modified, and	 * we will not have gotten here without rechecking it.	 */	  	ADD_DEPEND(pFormatKey);	initialSlots = REDSEG_GET_INITIAL_SLOTS(pFormatKey->nk);      }#endif      wi.traverseCount++;	      uint32_t shiftAmt = BLSS_SHIFT(wi.segBlss, wi.frameBits);      uint32_t ndx = wi.offset >> shiftAmt;      if (ndx > initialSlots)	goto invalid_addr;      wi.offset &= BLSS_MASK64(wi.segBlss - 1, wi.frameBits);      wi.pSegKey = &segNode->slot[ndx];    }    /******************************     *      * END Traversal step logic:     *      ******************************/    if (wi.traverseCount >= MAX_SEG_DEPTH)      goto bad_seg_depth;  process_key:    /********************************     *      * BEGIN key processing logic:     *      ********************************/    {#ifdef WALK_DBG      if (wi.segObj == 0)        WALK_DBG_MSG("key")#endif      wi.pSegKey->Prepare();          uint8_t keyType = wi.pSegKey->GetType();          /* Process everything but the per-object processing first: */      switch(keyType) {      case KT_Void:	goto invalid_addr;      case KT_TimePage:	{	  wi.canWrite = false;	  wi.canCall = false;	  wi.segBlss = EROS_PAGE_BLSS;	  wi.segObj = SysTimer::TimePageHdr;#ifdef KT_Wrapper	  wi.segObjIsWrapper = false;#else	  wi.segObjIsRed = false;#endif      	  if (wi.writeAccess)	    goto access_fault;	  ADD_DEPEND(wi.pSegKey);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -