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

📄 virtual.c

📁 深圳市微逻辑电子有限公司 巨果&#8226 Kingmos&reg 系统核心
💻 C
📖 第 1 页 / 共 5 页
字号:
				{	// 有有效的物理页,释放它
					DEBUGMSG( DEBUG_SEG_DECOMMITPAGES, ( "Phy=%x,b=%d,p=%d.\r\n", *lpui, idxStartBlk, idxStartPages ) );
					Page_Free( (LPVOID)_GetVirtualPageAdr( *lpui ) );
					*lpui = 0;

					//更新页表-2005-02-03
					if( bWriteToSecondPage && 
						PAGE_IN_RANGE( uStartPage, uMinPage, uMaxPage ) )
					{
						lpProcessSeg->lpdwSecondPageTable[uStartPage] = *lpui;
					}

					bFlush = TRUE; //刷新CACHE
				}
				uStartPage++;

				iPages--;
				lpui++;
				idxStartPages++;				
			}
		}
		idxStartPages = 0;
		lppBlks++;//下一个块
	}
	return bFlush;
}


// ********************************************************************
// 声明:BOOL AutoCommitPage( LPMEMBLOCK lpBlk, int idxStartPage )
// 参数:
//		IN lpBlk - MEMBLOCK(内存块)结构指针
//		IN idxStartPage - 块内的开始页
// 返回值:
//		假如提交成功,返回TRUE;否则,返回FALSE
// 功能描述:
//		自动提交物理页。通常被异常处理调用
// 引用:
//		
// ********************************************************************
// handle by exception handler
#define DEBUG_AUTOCOMMITPAGE 0
//BOOL AutoCommitPage( LPMEMBLOCK lpBlk, int idxStartPage )
BOOL AutoCommitPage( LPMEMBLOCK lpBlk, DWORD dwAddress )
{
	UINT uiPhyPage;
	DWORD dwPhyFlagMask = GetPhyPageFlagMask();
	int idxStartPage = PAGE_INDEX( dwAddress );
	LPPROCESS_SEGMENTS lpProcessSeg;

	ASSERT( lpBlk->uiPages[idxStartPage] == 0 );
	uiPhyPage = (UINT)Page_Alloc( TRUE );//cache 地址
	if( uiPhyPage )
	{
#ifdef __DEBUG
		// 这里是否有一个错误 ?!,因为uiPhyPage是内核CACHE地址>0x80000000,
		// 而该页随后要被用到,并且是已另一个CACHE地址 < 0x80000000 出现.
		// 因此我用UNCACHE地址去清除
	    //memset( (LPVOID)uiPhyPage, 0xCCCCCCCC, PAGE_SIZE );
		//
		memset( (LPVOID)CACHE_TO_UNCACHE(uiPhyPage), 0xCCCCCCCC, PAGE_SIZE );
		//
#endif
		// 得到对应的物理页和属性组合
		uiPhyPage = _GetPhysicalPageAdr( uiPhyPage ) | (lpBlk->uiFlag & dwPhyFlagMask);
	    lpBlk->uiPages[idxStartPage] = uiPhyPage;
		if( ( lpProcessSeg = Seg_FindProcessSegment( dwAddress ) ) )
		{
			ASSERT( lpProcessSeg->lpdwSecondPageTable );
			if( PAGE_INDEX_IN_SEGMENT( dwAddress ) >= lpProcessSeg->uiPageTableStart &&
				PAGE_INDEX_IN_SEGMENT( dwAddress ) < lpProcessSeg->uiPageTableStart + PAGES_PER_MEGA )
			{
				lpProcessSeg->lpdwSecondPageTable[PAGE_INDEX_IN_MEGA( dwAddress )] = uiPhyPage;
			}
		}
		DEBUGMSG( DEBUG_AUTOCOMMITPAGE, ( "auto commit sucess=%x.\r\n", uiPhyPage ) );
	}
	else
	{
#ifdef __DEBUG
		RETAILMSG( 1, ( "auto commit error: no physical page!!! .\r\n" ) );
		RETAILMSG( 1, ( "auto commit error: no physical page!!! .\r\n" ) );
		RETAILMSG( 1, ( "auto commit error: no physical page!!! .\r\n" ) );
		RETAILMSG( 1, ( "auto commit error: no physical page!!! .\r\n" ) );
		while(1);//ASSERT( 0 );  // no physical page!!!
#else
		return FALSE;
#endif
	}
	return TRUE;
}

// ********************************************************************
// 声明:BOOL Seg_MapPhyPages( 
//					  LPPROCESS_SEGMENTS lpProcessSeg,
//					  LPSEGMENT lpSeg, 
//					  int idxCommitBlk, 
//					  int idxPageOffset, 
//					  int iNeedPages, 
//					  int iAllocPages,
//					  UINT uiAllocType,
//					  DWORD * lpdwPhycialPages,
//					  DWORD dwProtect
//					  )
// 参数:
//		IN lpProcessSeg - 进程段组
//		IN lpSeg - 段结构指针 
//		IN idxCommitBlk - 需要提交的开始块
//		IN idxPageOffset - 开始块内的开始页
//		IN iNeedPages - 需要查找的页
//		IN iAllocPages - 需要提交的页
//		IN uiAllocType - 分配类型,为以下值:
//					MEM_PHYSICAL - lpdwPhycialPages 包含物理页,如果没有MEM_CONTIGUOUS属性,
//									则 lpdwPhycialPages[n] 包含第n个物理页。
//									如果没有该属性,则由该函数分配物理页
//					MEM_CONTIGUOUS - 物理页是连续的,并且lpdwPhycialPages本身表示物理页地址的开始
//		IN lpdwPhycialPages - 指向物理页或物理页地址(依赖于uiAllocType)。
//		IN dwProtect - 保护属性
// 返回值:
//		假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
//		将物理页映射到相应的虚空间
// 引用:
//		
// ********************************************************************
#define DEBUG_SEG_MAPPHYPAGES 0
BOOL Seg_MapPhyPages(
					  LPPROCESS_SEGMENTS lpProcessSeg,
					  LPSEGMENT lpSeg, 
					  int idxCommitBlk, 
					  int idxPageOffset, 
					  int iNeedPages, 
					  int iAllocPages,
					  UINT uiAllocType,
					  DWORD * lpdwPhycialPages,
					  DWORD dwProtect
					  )
{
	LPMEMBLOCK * lppBlks = lpSeg->lpBlks + idxCommitBlk; // 开始页
	LPMEMBLOCK lpBlk;
	int iPages = 0;
    BOOL bFlush = FALSE;
	UINT uStartPage, uMinPage, uMaxPage; 
	BOOL bWriteToSecondPage;

	if( (uiAllocType & MEM_PHYSICAL) == 0 )	//由本函数分配物理页吗 ?
	{	// 是
	    if( Page_Lock( iAllocPages ) == FALSE )  // 锁住需要的页
		{	// 不成功
			WARNMSG( DEBUG_SEG_MAPPHYPAGES, ( "Seg_MapPhyPages: failure to LockPages=%d.\r\n", iAllocPages ) );
		    return FALSE;
		}
	}
	// 得到CPU对应的页属性
	dwProtect = GetAttribFromProtect( dwProtect );
	
	//需要CACHE ?-2005-02-02
	uMinPage = uStartPage = idxCommitBlk * PAGES_PER_BLOCK + idxPageOffset;
	uMaxPage = uStartPage + iNeedPages;
	bWriteToSecondPage = GetPagesInCacheRange( lpProcessSeg, &uMinPage, &uMaxPage );
	//
	while( iPages < iNeedPages )
	{
		lpBlk = *lppBlks++;
		ASSERT( lpBlk && lpBlk > RESERVED_BLOCK );

		// 搜索块内的所有页,search the block's all pages
		while( idxPageOffset < PAGES_PER_BLOCK &&
			   iPages < iNeedPages )
		{
			if( lpBlk->uiPages[idxPageOffset] == 0 ) // 分配了物理页吗 ?
			{   // 没有,为其分配一个。now, to alloc a physical page
				int iTryCount = 0;
				UINT uiPhyPage;
				// 虽然不应该出现没有物理页的情况,之前已用Page_Lock锁住需要的页面,但多试几次也无访
				// 不过,现在我觉得应该将循环检查的代码 移到 Page_Lock 部分!!!!
				//	改变它以后
				for( ; iTryCount < 10; iTryCount++ )
				{
					if( (uiAllocType & MEM_PHYSICAL) == 0 )
					{	// 自动分配
					    uiPhyPage = (UINT)Page_Alloc( FALSE );
						if( uiPhyPage )
						    uiPhyPage = _GetPhysicalPageAdr( uiPhyPage );
					}
					else
					{   //用参数给的物理地址 MEM_PHYSICAL
						if( uiAllocType & MEM_CONTIGUOUS )
						{	// 连续的地址,lpdwPhycialPages本身就是物理页地址
							uiPhyPage = (UINT)lpdwPhycialPages; // 当前的物理页地址
							lpdwPhycialPages = (DWORD*)NEXT_PHYSICAL_PAGE( lpdwPhycialPages );
						}
						else
						{   // 非连续的物理页,physical pages is not contigous, put in the pointer
							uiPhyPage = *lpdwPhycialPages;
							lpdwPhycialPages++; // 下一个物理页
						}
					}

					if( uiPhyPage )
					{
						uiPhyPage |= dwProtect; // 或上保护属性
						lpBlk->uiPages[idxPageOffset] = uiPhyPage;
						bFlush = TRUE;  // 刷新CACHE
						//2005-02-02是否CACHE
						if( bWriteToSecondPage && 
							PAGE_IN_RANGE( uStartPage, uMinPage, uMaxPage ) )
						{
							lpProcessSeg->lpdwSecondPageTable[uStartPage] = uiPhyPage;
						}
						//
						break;
					}
					WARNMSG( DEBUG_SEG_MAPPHYPAGES, ("Seg_MapPhyPages, entry sleep.\r\n" ) );
					Sleep(200);
				}
				if( uiPhyPage == 0 )
				{	// 不应该发生,某些错误!
					ERRORMSG( DEBUG_SEG_MAPPHYPAGES, ( "error in Seg_MapPhyPages: fault error!, no enough phypage.\r\n" ) );
				}
			}
			idxPageOffset++; // 块内的下一个页
			iPages++;
			uStartPage++;
		}
		idxPageOffset = 0;
	}
	//
	// 我假定所有虚内存管理中的释放功能将会调用FlushCacheAndClearTLB功能,
	// 所以我在分配功能里不调用FlushCacheAndClearTLB功能
	// 这就是为什么我去掉了以下的代码
	//if( bFlush )
	  //  FlushCacheAndClearTLB();
	return TRUE;
}

// ********************************************************************
// 声明:LPSEGMENT Seg_FindSegmentByIndex( UINT index )
// 参数:
//		IN index - 段索引
// 返回值:
//		段结构指针
// 功能描述:
//		由段索引得到其所在的段
// 引用:
//		
// ********************************************************************
LPSEGMENT Seg_FindSegmentByIndex( UINT index )
{
	if( index < 64 )
	{	// 用户空间 user space
		if( lppProcessSegmentSlots[index] )
		    return (LPSEGMENT)lppProcessSegmentSlots[index]->lpSeg;
	}
	else 
	{	// 内核空间 0x80000000
		if( index == KERNEL_SEGMENT_INDEX )
		{
			return InitKernelProcess.lpProcessSegments->lpSeg;
		}
	}
	return NULL;
}


// ********************************************************************
// 声明:LPSEGMENT Seg_FindSegment( DWORD dwAddress )
// 参数:
//		IN dwAddress - 虚地址
// 返回值:
//		段结构指针
// 功能描述:
//		由虚地址得到其所在的段
// 引用:
//		
// ********************************************************************
#define DEBUG_SEG_FINDSEGMENT 0
static LPSEGMENT Seg_FindSegment( DWORD dwAddress )
{
	return Seg_FindSegmentByIndex( GET_SEGMENT_INDEX( dwAddress ) );
}

// ********************************************************************
// 声明:LPPROCESS_SEGMENTS Seg_FindProcessSegment( DWORD dwAddress )
// 参数:
//		IN dwAddress - 虚地址
// 返回值:
//		段结构指针
// 功能描述:
//		由虚地址得到其所在的段
// 引用:
//		
// ********************************************************************
#define DEBUG_SEG_FINDSEGMENT 0
static LPPROCESS_SEGMENTS Seg_FindProcessSegment( DWORD dwAddress )
{
	UINT index = GET_SEGMENT_INDEX( dwAddress );
	if( index < 64 )
	{	// 用户空间 user space
		return lppProcessSegmentSlots[index];
	}
	else 
	{	// 内核空间 0x80000000
		if( index == KERNEL_SEGMENT_INDEX )
		{
			return InitKernelProcess.lpProcessSegments;
		}
	}
	return NULL;

}


// ********************************************************************
// 声明:BOOL Seg_Copy( 
//				LPPROCESS_SEGMENTS lpProcessSeg,
//				LPSEGMENT lpSegDst, 
//			    UINT idxDstStartBlk,
//				UINT idxStartPage,
//				DWORD dwCopyPages,
//		        LPSEGMENT lpSegSrc,
//				UINT idxSrcStartBlk,
//				DWORD dwProtect )
// 参数:
//		IN lpProcessSeg - 进程段组
//		IN lpSegDst - 目标段结构指针 
//		IN idxDstStartBlk - 目标段开始块
//		IN idxStartPage - 目标段块内开始页
//		IN dwCopyPages - 需要拷贝的页
//		IN lpSegSrc - 源段结构指针
//		IN idxSrcStartBlk - 源段开始块
//		IN dwProtect - 保护属性
// 返回值:
//		假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
//		将源区域的物理页映射到目标区域
// 引用:
//		
// ********************************************************************
BOOL Seg_Copy( 
			    LPPROCESS_SEGMENTS lpProcessSeg,
				LPSEGMENT lpSegDst, 
			    UINT idxDstStartBlk,
				UINT idxStartPage,
				DWORD dwCopyPages,
		        LPSEGMENT lpSegSrc,
				UINT idxSrcStartBlk,
				DWORD dwProtect )
{
	LPMEMBLOCK * lppDstBlks, * lppSrcBlks;
	DWORD dwPhysAddrMask = GetPhyPageAdrMask();
	BOOL bWriteToSecondPage;
	UINT uStartPage, uMinPage, uMaxPage; 
	
	dwProtect = GetAttribFromProtect( dwProtect );//得到CPU的属性
    lppDstBlks = lpSegDst->lpBlks + idxDstStartBlk; // 开始目标块
	lppSrcBlks = lpSegSrc->lpBlks + idxSrcStartBlk;//开始源块


	//需要CACHE ?-2005-02-03, add
	uMinPage = uStartPage = idxDstStartBlk * PAGES_PER_BLOCK + idxStartPage;
	uMaxPage = uStartPage + dwCopyPages;
	bWriteToSecondPage = GetPagesInCacheRange( lpProcessSeg, &uMinPage, &uMaxPage );

	//

	while( dwCopyPages )
	{
		UINT * lpuiDstPage = &(*lppDstBlks)->uiPages[idxStartPage];//开始目标页
		UINT * lpuiSrcPage = &(*lppSrcBlks)->uiPages[idxStartPage];//开始源页

		lppDstBlks++; lppSrcBlks++;

		while( idxStartPage < PAGES_PER_BLOCK &&
			   dwCopyPages )
		{
			DWORD dwPhy = *lpuiSrcPage & dwPhysAddrMask; //得到物理地址
			// 拷贝
			Page_Duplicate( (LPVOID)_GetVirtualPageAdr( dwPhy ) );
			// 

⌨️ 快捷键说明

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