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

📄 virtual.c

📁 深圳市微逻辑电子有限公司 巨果&#8226 Kingmos&reg 系统核心
💻 C
📖 第 1 页 / 共 5 页
字号:
			*lpuiDstPage = dwPhy | dwProtect;
			//更新页表-2005-02-03
			if( bWriteToSecondPage &&
				PAGE_IN_RANGE( uStartPage, uMinPage, uMaxPage) )
			{
				lpProcessSeg->lpdwSecondPageTable[uStartPage] = *lpuiDstPage;
			}
			uStartPage++;
			//			

			// 下一页
			lpuiDstPage++;
			lpuiSrcPage++;
			idxStartPage++;
			dwCopyPages--;
		}
		idxStartPage = 0;
	}
	return dwCopyPages ? FALSE : TRUE;
}


// ********************************************************************
// 声明:static LPVOID DoVirtualAlloc( 
//						LPVOID lpvAddress, 
//						DWORD dwSize, 
//						DWORD dwAllocType, 
//						DWORD dwProtect,
//						DWORD * lpdwPhycialPages )
// 参数:
//		IN lpvAddress - 虚地址
//		IN dwSize - 需要分配的大小(以byte为单位)
//		IN uiAllocType - 分配类型,为以下值的组合:
//					MEM_RESERVE - 保留虚地址
//					MEM_COMMIT - 提交物理页
//
//					MEM_PHYSICAL - lpdwPhycialPages 包含物理页,如果没有MEM_CONTIGUOUS属性,
//									则 lpdwPhycialPages[n] 包含第n个物理页。
//									如果没有该属性,则由该函数分配物理页
//					MEM_CONTIGUOUS - 物理页是连续的,并且lpdwPhycialPages本身表示物理页地址的开始
//		IN dwProtect - 保护属性
//		IN lpdwPhycialPages - 指向物理页或物理页地址(依赖于uiAllocType)。
// 返回值:
//		假如成功,返回非NULL指针;否则返回NULL
// 功能描述:
//		分配用户虚地址,假如uiAllocType有MEM_COMMIT但没有MEM_RESERVE,则该地址范围必须是之前已经被保留的
// 引用:
//		
// ********************************************************************
#define DEBUG_DOVIRTUALALLOC 0
static LPVOID DoVirtualAlloc( 
						LPVOID lpvAddress, 
						DWORD dwSize, 
						DWORD dwAllocType, 
						DWORD dwProtect,
						DWORD * lpdwPhycialPages )
{
	DWORD dwStart = (DWORD)lpvAddress;
	DWORD dwEnd = dwStart + dwSize;
	DWORD dwSegIndex = GET_SEGMENT_INDEX( dwStart );
	LPSEGMENT lpSeg;
	LPPROCESS_SEGMENTS lpProcessSeg;
	DWORD dwError = 0;
	DWORD dwRetv = NULL;


	DEBUGMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtualAlloc:lpvAddress=%x,dwSize=%d.\r\n", lpvAddress,dwSize ) );
	// 检查参数,check param
	if( (dwAllocType & MEM_PHYSICAL) && lpdwPhycialPages == NULL )
	{
        KL_SetLastError(ERROR_INVALID_PARAMETER);
		return NULL;
	}

	KL_EnterCriticalSection( &csVirtualMem );

	if( dwSize )
	{
		if( ( lpProcessSeg = Seg_FindProcessSegment( dwStart ) ) &&
			( lpSeg = lpProcessSeg->lpSeg ) )  // 查找对应的段
		{
			int iNeedPages;
			int iPages;
			int idxFirst, idxCommit, idxCommitPage;
			BOOL bReserved = FALSE;

			DEBUGMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtualAlloc:lpSeg=%x.\r\n", lpSeg ) );

		    idxFirst = -1;
			//是否需要做保留工作 ?
			if( (dwAllocType & MEM_RESERVE) ||
				( lpvAddress == NULL && (dwAllocType & MEM_COMMIT) ) 
			  )
			{   // 需要去保留相应的页 to get enough free block( NULL_BLOCK )
				// 需要的页数
			    iPages = iNeedPages = ( ( dwStart + dwSize + PAGE_SIZE - 1 ) / PAGE_SIZE ) - ( dwStart / PAGE_SIZE );

				dwAllocType |= MEM_RESERVE;
				idxFirst = 0;

				if( dwSegIndex )
				{
					dwStart &= SEGMENT_MASK;  // 32M size
				}
				if( dwStart ) // 用户指定地址 ?
				{  // 是
					dwStart &= 0xffff0000; // 下舍到64k边界 round down 64k
					idxFirst = BLOCK_INDEX( dwStart );
				}
				else // 否,从1块开始(0块系统保留)
					idxFirst = 1;  // first block reserved by sys
				
				// search enough blocks
				DEBUGMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtaulAlloc:idxFirst=%d,iNeedPages=%d.\r\n", idxFirst, iNeedPages ) );
				//得到内存域的开始块
				idxCommit = idxFirst = Seg_GetFirstBlockPos( lpSeg, idxFirst, iNeedPages, dwStart == NULL );
				DEBUGMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtaulAlloc:Reserve idxFirst=%d.\r\n", idxFirst ) );
				// 保留需要的页
				if( idxFirst &&
					Seg_ReserveNeedPages( lpSeg, idxFirst, iNeedPages, (dwAllocType & MEM_AUTO_COMMIT), dwProtect ) )
				{   // now to reserve
					bReserved = TRUE;
					dwStart = idxFirst << BLOCK_SHIFT;
				}
				else
				{
					WARNMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtaulAlloc: failuer to ReserveNeedPages(%d), idxFirst(%d), dwStart(0x%x).\r\n", iNeedPages, idxFirst, dwStart ) );
					dwError = ERROR_NOT_ENOUGH_MEMORY;
					goto _err_return;
				}
			}
			else if( dwStart && (dwAllocType & MEM_COMMIT) )
			{   // 直接提交物理页,to commit blocks which have reserved
				idxCommit = idxFirst = BLOCK_INDEX( dwStart );  // 开始块
				// align to page
				//需要的页数
			    iNeedPages = ( ( dwStart + dwSize + PAGE_SIZE - 1 ) / PAGE_SIZE ) - ( dwStart / PAGE_SIZE );
				dwStart &= ~PAGE_MASK;
				DEBUGMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtaulAlloc:dwStart=%x,idxFirst=%d.\r\n", dwStart, idxFirst ) );
                //得到该域的开始块
				idxFirst = Seg_SearchFirstBlock( lpSeg, idxFirst );
				if( idxFirst == NOT_FIND_FIRST )
				{   // 给的地址是无效的,error param
					WARNMSG( DEBUG_DOVIRTUALALLOC, ( "warn in DoVirtaulAlloc:NOT_FIND_FIRST,idxFirst=%d.\r\n", idxFirst ) );
//					ASSERT( 0 );
					dwError = ERROR_INVALID_PARAMETER;
					goto _err_return;
				}
			}
			//以下代码做提交物理页工作
			// now to commit page if need
			if( dwAllocType & MEM_COMMIT )  ////需要提交物理页吗?
			{   //需要提交物理页
				int iAllocPages;

				idxCommitPage = PAGE_INDEX( dwStart );
				DEBUGMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtaulAlloc:To Commit,idxCommit=%d,idxCommitPage=%d,iNeedPages=%d.\r\n", idxCommit, idxCommitPage, iNeedPages ) );
				//检视需要提交的页数并分配相应的块结构
				if( ( iAllocPages = Seg_ReviewRegion( lpSeg, idxFirst, idxCommit, idxCommitPage, iNeedPages, NULL ) ) != -1 )
				{   // 成功,提交物理页。ok , success to commit,now, alloc the physical pages for commit page
					DEBUGMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtaulAlloc: iAllocPages=%d.\r\n", iAllocPages ) );
					if( Seg_MapPhyPages( lpProcessSeg, lpSeg, idxCommit, idxCommitPage, iNeedPages, iAllocPages,  dwAllocType, lpdwPhycialPages, dwProtect ) )
					{
						DEBUGMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtaulAlloc:success to commit=%x.\r\n", dwStart ) );
						dwRetv = dwStart;
						FlushCacheAndClearTLB(); //刷新CACHE
						goto _return;						
					}
					else
					{
						WARNMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtaulAlloc:failuer to MapPhyPages.\r\n" ) );
					}
				}
				else
				{
					WARNMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtaulAlloc:failuer to ReviewRegion.\r\n" ) );
				}
				// 发生了某些错误,做清除工作。some error happen, now clear reserved
				WARNMSG( DEBUG_DOVIRTUALALLOC, ( "Failuer to Commit.\r\n" ) );
				if( bReserved )
				{
					Seg_FreeRegion( lpSeg, idxFirst );
				}
			}
			else //不需要提交物理页,仅仅保留。no commit , only reserve
			{
				DEBUGMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtaulAlloc:success to reserve=%x.\r\n", dwStart ) );
				dwRetv = dwStart;
				goto _return;
			}
		}
		else
		{
		    WARNMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtaulAlloc: not find the segment addr=(0x%x), index=%d, knx=%d.\r\n", dwStart, dwSegIndex, KERNEL_SEGMENT_INDEX ) );
			ASSERT( 0 );
		}
	}
_err_return:
	KL_SetLastError( dwError );
	WARNMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtaulAlloc:failure alloc address(%x).\r\n", dwStart ) );
_return:
	KL_LeaveCriticalSection( &csVirtualMem );
	if( dwRetv )
	    dwRetv = dwRetv | ( dwSegIndex << SEGMENT_SHIFT );
	RETAILMSG( DEBUG_DOVIRTUALALLOC, ( "DoVirtaulAlloc:dwRetv(0x%x).\r\n", dwRetv ) );
	return (LPVOID)dwRetv;
}

// ********************************************************************
// 声明:LPVOID WINAPI KL_VirtualAlloc( 
//							LPVOID lpvAddress, 
//							DWORD dwSize, 
//							DWORD dwAllocType, 
//							DWORD dwProtect )
// 参数:
//		IN lpvAddress - 虚地址
//		IN dwSize - 需要分配的大小(以byte为单位)
//		IN dwAllocType - 分配类型,为以下值的组合:
//					MEM_RESERVE - 保留虚地址
//					MEM_COMMIT - 提交物理页
//		IN dwProtect - 保护属性
// 返回值:
//		假如成功,返回非NULL指针;否则返回NULL
// 功能描述:
//		分配用户虚地址,假如uiAllocType有MEM_COMMIT但没有MEM_RESERVE,则该地址范围必须是之前已经被保留的
// 引用:
//		系统API		
// ********************************************************************
#define DEBUG_KL_VirtualAlloc 0
LPVOID WINAPI KL_VirtualAlloc( 
							LPVOID lpvAddress, 
							DWORD dwSize, 
							DWORD dwAllocType, 
							DWORD dwProtect )
{
	DEBUGMSG( DEBUG_KL_VirtualAlloc, ( "KL_VirtualAlloc entry,lpvAddress=0x%x,dwSize=%d,dwAllocType=0x%x.\r\n", lpvAddress, dwSize, dwAllocType ) );
	if( (DWORD)lpvAddress < 0x80000000 )
		return DoVirtualAlloc( lpvAddress, dwSize, dwAllocType, dwProtect, NULL );
	else
		return NULL;
}

// ********************************************************************
// 声明:LPVOID WINAPI KC_VirtualAlloc( 
//							LPVOID lpvAddress, 
//							DWORD dwSize, 
//							DWORD dwAllocType, 
//							DWORD dwProtect )
// 参数:
//		IN lpvAddress - 虚地址
//		IN dwSize - 需要分配的大小(以byte为单位)
//		IN dwAllocType - 分配类型,为以下值的组合:
//					MEM_RESERVE - 保留虚地址
//					MEM_COMMIT - 提交物理页
//		IN dwProtect - 保护属性
// 返回值:
//		假如成功,返回非NULL指针;否则返回NULL
// 功能描述:
//		内核版,分配用户虚地址,假如uiAllocType有MEM_COMMIT但没有MEM_RESERVE,则该地址范围必须是之前已经被保留的
// 引用:
//		内核版
// ********************************************************************
#define DEBUG_KC_VirtualAlloc 0
LPVOID WINAPI KC_VirtualAlloc( 
							LPVOID lpvAddress, 
							DWORD dwSize, 
							DWORD dwAllocType, 
							DWORD dwProtect )
{
	DEBUGMSG( DEBUG_KC_VirtualAlloc, ( "KC_VirtualAlloc entry,lpvAddress=0x%x,dwSize=%d.\r\n", lpvAddress, dwSize ) );
	return DoVirtualAlloc( lpvAddress, dwSize, dwAllocType, dwProtect, NULL );
}


// ********************************************************************
// 声明:BOOL DoVirtualCopy( 
//						DWORD dwDstAddress, 
//						DWORD dwSrcAddress,
//						DWORD dwSize, 
//						DWORD dwProtect
//						)
// 参数:
//		IN dwDstAddress - 目标地址
//		IN dwSrcAddress - 源地址
//		IN dwSize - 需要拷贝的大小
//		IN dwProtect - 保护属性
// 返回值:
//		假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
//		将源地址的物理页映射到目标地址
// 引用:
//		
// ********************************************************************

#define DEBUG_VIRTUALCOPY 0
static BOOL DoVirtualCopy( 
						DWORD dwDstAddress, 
						DWORD dwSrcAddress,
						DWORD dwSize, 
						DWORD dwProtect
						)
{
	DWORD dwDstStart = dwDstAddress;
	DWORD dwDstEnd = dwDstStart + dwSize;
	DWORD dwSegIndex = GET_SEGMENT_INDEX( dwDstStart );
	LPSEGMENT lpSegDst;
	LPPROCESS_SEGMENTS lpProcessSegDst;
	DWORD dwError = 0;
	DWORD dwRetv = NULL;
	DWORD dwPhyAdr = 0;
	UINT uiNeedPages;
	
	BOOL bVirtualAdr = FALSE;
	BOOL bRetv = FALSE;

	if( dwSize == 0 || dwDstStart == 0 || dwSrcAddress == 0 || dwSegIndex >= MAX_SEGMENTS )
		goto _RET_INVALID;

	uiNeedPages = ( ( dwDstEnd + PAGE_SIZE - 1 ) / PAGE_SIZE ) - ( dwDstStart / PAGE_SIZE );

	if( dwProtect & PAGE_PHYSICAL ) // dwSrcAddress是物理地址吗 ?
	{	//是
		dwPhyAdr = (dwSrcAddress << 8) & ~(PAGE_SIZE-1); // align to page
	    if( ( dwPhyAdr & PAGE_MASK ) != ( dwDstStart & PAGE_MASK ) )  // 源与目标应该对齐页边界
			goto _RET_INVALID;

		dwProtect &= ~PAGE_PHYSICAL;
	}
	else if( IsKernelVirtualAddress( dwSrcAddress ) )  // 源是内核地址吗 ?
	{	//是
		dwPhyAdr = _GetPhysicalPageAdr( dwSrcAddress ); // 得到对应的物理地址
	    if( ( dwPhyAdr & PAGE_MASK ) != ( dwDstStart & PAGE_MASK ) ) // 源与目标应该对齐页边界
			goto _RET_INVALID;
	}
	else
	{   // 源在用户地址空间。from other virtual address
		bVirtualAdr = TRUE;
	}

	KL_EnterCriticalSection( &csVirtualMem );  // 进入冲突段

	//lpSegDst = Seg_FindSegment( dwDstStart );  // 发现目标段
	lpProcessSegDst = Seg_FindProcessSegment( dwDstStart );
	if( lpProcessSegDst )
		lpSegDst = lpProcessSegDst->lpSeg;
	else
		lpSegDst = NULL;

	if( lpSegDst )
	{	//
		UINT idxDstStartBlk;
		UINT idxDstStartPage;
		UINT idxFirstBlk;
		UINT uiNeedAllocPages;

        idxDstStartBlk = BLOCK_INDEX( dwDstAddress );
       	idxDstStartPage = PAGE_INDEX( dwDstAddress );

 	    idxFirstBlk = Seg_SearchFirstBlock( lpSegDst, idxDstStartBlk );		

		if( idxFirstBlk == NOT_FIND_FIRST )
			goto _RET_INVALID_LEAVE;

		// 检查目标区域,保证所用需要拷贝的page已被保留。	
	    uiNeedAllocPages = Seg_ReviewRegion( lpSegDst, idxFirstBlk, idxDstStartBlk, idxDstStartPage, uiNeedPages, NULL );
		if( uiNeedAllocPages != uiNeedPages )
			goto _RET_INVALID_LEAVE;
		if( bVirtualAdr )
		{   // 源在用户地址空间,from other virtual address
			LPSEGMENT lpSegSrc;
			UINT idxSrcStartBlk;
			UINT idxSrcStartPage;
			UINT idxFirstBlk;
			UINT uiAllocPages;
			UINT uiCountPages;
			
			idxSrcStartPage = PAGE_INDEX( dwSrcAddress );
			if( idxSrcStartPage != idxDstStartPage )
				goto _RET_INVALID_LEAVE;

⌨️ 快捷键说明

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