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

📄 virtual.c

📁 深圳市微逻辑电子有限公司 巨果&#8226 Kingmos&reg 系统核心
💻 C
📖 第 1 页 / 共 5 页
字号:
			idxSrcStartBlk = BLOCK_INDEX( dwSrcAddress );


			lpSegSrc = Seg_FindSegment( dwSrcAddress );
			if( lpSegSrc == NULL )
				goto _RET_INVALID_LEAVE;
			
			idxFirstBlk = Seg_SearchFirstBlock( lpSegSrc, idxSrcStartBlk );
		    if( idxFirstBlk == NOT_FIND_FIRST )
			    goto _RET_INVALID_LEAVE;
			
			// 保证所用需要的page已被提交。
			
			uiAllocPages = Seg_ReviewRegion( lpSegSrc, idxFirstBlk, idxSrcStartBlk, idxSrcStartPage, uiNeedPages, &uiCountPages );
			if( uiAllocPages || uiCountPages != uiNeedPages )
				goto _RET_INVALID_LEAVE;
			bRetv = Seg_Copy( lpProcessSegDst, lpSegDst, idxDstStartBlk, idxDstStartPage, uiNeedPages, lpSegSrc, idxSrcStartBlk, dwProtect );
		}
		else
		{   // 源是物理地址,直接映射。phy address
			bRetv = Seg_MapPhyPages( lpProcessSegDst, lpSegDst, idxDstStartBlk, idxDstStartPage, uiNeedPages, uiNeedAllocPages, MEM_PHYSICAL | MEM_CONTIGUOUS, (DWORD*)dwPhyAdr, dwProtect );
		}
	}

	if( bRetv )
		FlushCacheAndClearTLB(); // 因为有重新映射,必须刷新CACHE

	KL_LeaveCriticalSection( &csVirtualMem );//离开冲突段
	return bRetv;

_RET_INVALID_LEAVE:
	KL_LeaveCriticalSection( &csVirtualMem );
_RET_INVALID:
	KL_SetLastError( ERROR_INVALID_PARAMETER );
	WARNMSG( DEBUG_VIRTUALCOPY, ( "DoVirtaulCopy:failure alloc.\r\n" ) );
	return bRetv;
}

// ********************************************************************
// 声明:BOOL WINAPI KL_VirtualCopy( 
//							 LPVOID lpvDest,
//							 LPVOID lpvSrc,
//							 DWORD cbSize,
//							 DWORD fdwProtect )
// 参数:
//		IN dwDstAddress - 目标地址
//		IN dwSrcAddress - 源地址
//		IN dwSize - 需要拷贝的大小
//		IN dwProtect - 保护属性
// 返回值:
//		假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
//		将源地址的物理页映射到目标地址
// 引用:
//		系统API	
// ********************************************************************
#define DEBUG_KL_VirtualCopy 0
BOOL WINAPI KL_VirtualCopy( 
							 LPVOID lpvDest,
							 LPVOID lpvSrc,
							 DWORD cbSize,
							 DWORD fdwProtect )
{
	DEBUGMSG( DEBUG_KL_VirtualCopy, ( "KL_VirtualAlloc entry,lpvDest=0x%x,lpvSrc=0x%x,cbSize=%d.\r\n", lpvDest, lpvSrc, cbSize ) );
	return DoVirtualCopy( (DWORD)lpvDest, (DWORD)lpvSrc, cbSize, fdwProtect ) ? TRUE : FALSE;
}

// ********************************************************************
// 声明:static BOOL DoVirtualFree( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType )
// 参数:
//		IN lpAddress - 虚地址
//		IN dwSize - 虚内存大小
//		IN dwFreeType - 释放类型,可以为:
//				MEM_DECOMMIT - 释放一段区域的物理页
//				MEM_RELEASE - 释放整个域,dwSize必须为0
// 返回值:
//		假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
//		释放虚内存域/地址
// 引用:
//		
// ********************************************************************
static BOOL DoVirtualFree( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType )
{
	DWORD dwStart = (DWORD)lpAddress;
	DWORD dwSegIndex;
	int idxFirstBlk, idxStartBlk, idxPage;
	int iPages;
	LPSEGMENT lpSeg;
	LPPROCESS_SEGMENTS lpProcessSeg;
	BOOL bRetv = FALSE;
	BOOL bFlush = FALSE;

	// check param
	// 检查参数是否有效
	if( lpAddress == NULL || 
		( (dwFreeType & MEM_RELEASE) && dwSize ) )
	{
		KL_SetLastError( ERROR_INVALID_PARAMETER );
		return FALSE;
	}

	KL_EnterCriticalSection( &csVirtualMem );

	dwSegIndex = GET_SEGMENT_INDEX( dwStart );

	if( ( lpProcessSeg = Seg_FindProcessSegment( dwStart ) ) &&
		( lpSeg = lpProcessSeg->lpSeg ) )  // 得到地址对应的段指针
	{
		idxStartBlk = BLOCK_INDEX( dwStart );
		idxFirstBlk = Seg_SearchFirstBlock( lpSeg, idxStartBlk ); // 得到该域的第一个块
		idxPage = PAGE_INDEX( dwStart );
		if( idxFirstBlk != NOT_FIND_FIRST )  // 块有效吗 ?
		{	// 有效
			int iReserved;
			int iCountPages = 0;
			if( dwFreeType == MEM_DECOMMIT && dwSize )
			{	// 释放一段区域
                iPages = ( ( dwStart + dwSize + PAGE_SIZE - 1 ) >> PAGE_SHIFT ) - ( dwStart >> PAGE_SHIFT );
				// 统计保留的页数 和 已分配的页数
				iReserved = Seg_ReviewRegion( lpSeg, idxFirstBlk, idxStartBlk, idxPage, iPages, &iCountPages );
				if( iCountPages >= iPages )
				{
					if( iReserved != iPages )
					{   //先刷新CACHE 
						FlushCacheAndClearTLB();
						bFlush |= Seg_DecommitPages( lpProcessSeg, lpSeg, idxStartBlk, idxPage, iPages );
						bRetv = TRUE;
						goto _return;
					}
				}
				else
				{   //error
					ASSERT( 0 );
				}
			}
			else if( dwFreeType & MEM_RELEASE )
			{	//释放整个域
                if( idxPage == 0 && idxFirstBlk == idxStartBlk )
                {	// 统计保留的页数 和 已分配的页数
					iReserved = Seg_ReviewRegion( lpSeg, idxFirstBlk, idxStartBlk, 0, -1, &iCountPages );
				    if( iReserved != iCountPages )
					{
						FlushCacheAndClearTLB();
						bFlush |= Seg_DecommitPages( lpProcessSeg, lpSeg, idxStartBlk, 0, iCountPages );
					}
					// 释放该域已定位的块
					Seg_FreeRegion( lpSeg, idxStartBlk );
					bRetv = TRUE;
					goto _return;
				}
			}
		}
	}
_return:
	//调用Seg_DecommitPages之前已经调用了FlushCacheAndClearTLB,这里必要吗 ?
	if( bFlush )
        FlushCacheAndClearTLB();
	KL_LeaveCriticalSection( &csVirtualMem );
	return bRetv;
}

// ********************************************************************
// 声明:BOOL WINAPI KL_VirtualFree( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType )
//		IN lpAddress - 虚地址
//		IN dwSize - 虚内存大小
//		IN dwFreeType - 释放类型,可以为:
//				MEM_DECOMMIT - 释放一段区域的物理页
//				MEM_RELEASE - 释放整个域,dwSize必须为0
// 返回值:
//		假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
//		释放虚内存域/地址
// 引用:
//		系统API	
// ********************************************************************
#define DEBUG_KL_VirtualFree 0
BOOL WINAPI KL_VirtualFree( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType )
{
	DEBUGMSG( DEBUG_KL_VirtualFree, ( "KL_VirtualFree entry,lpAddress=0x%x,dwSize=0x%x.\r\n", lpAddress, dwSize ) );
	if( (DWORD)lpAddress < 0x80000000 )
		return DoVirtualFree( lpAddress, dwSize, dwFreeType );
	else
		return FALSE;
}

// ********************************************************************
// 声明:BOOL WINAPI KC_VirtualFree( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType )
//		IN lpAddress - 虚地址
//		IN dwSize - 虚内存大小
//		IN dwFreeType - 释放类型,可以为:
//				MEM_DECOMMIT - 释放一段区域的物理页
//				MEM_RELEASE - 释放整个域,dwSize必须为0
// 返回值:
//		假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
//		释放虚内存域/地址
// 引用:
//		内核版
// ********************************************************************
#define DEBUG_KC_VirtualFree 0
BOOL WINAPI KC_VirtualFree( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType )
{
	DEBUGMSG( DEBUG_KC_VirtualFree, ( "KC_VirtualFree entry,lpAddress=0x%x,dwSize=0x%x.\r\n", lpAddress, dwSize ) );
	return DoVirtualFree( lpAddress, dwSize, dwFreeType );
}


// ********************************************************************
// 声明:BOOL WINAPI KL_VirtualProtect( LPVOID lpvAddress, DWORD dwSize, DWORD flNewProtect, PDWORD lpflOldProtect )
// 参数:
//		IN lpAddress - 虚地址
//		IN dwSize - 虚内存大小
//		IN flNewProtect - 新的保护属性
//		IN lpfOldProtect - 之前的保护属性
// 返回值:
//		假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
//		重新设置内存域的页属性
// 引用:
//		系统API
// ********************************************************************
#define DEBUG_KL_VirtualProtect 0
BOOL WINAPI KL_VirtualProtect( LPVOID lpvAddress, DWORD dwSize, DWORD flNewProtect, PDWORD lpflOldProtect )
{
	DWORD dwStart;// = (DWORD)lpvAddress;
	DWORD dwSegIndex;// = GET_SEGMENT_INDEX( (DWORD)dwStart );
	LPSEGMENT lpSeg;
	DWORD dwError = 0;
	LPPROCESS_SEGMENTS lpProcessSeg;

	DEBUGMSG( DEBUG_KL_VirtualProtect, ( "KL_VirtualProtect entry,lpvAddress=0x%x,dwSize=0x%x.\r\n", lpvAddress, dwSize ) );

	// 检查参数
	if( dwSize == 0 || 
		lpflOldProtect == NULL ||
		lpvAddress == NULL )
	{
        KL_SetLastError(  ERROR_INVALID_PARAMETER );
		return FALSE;
	}

	dwStart = (DWORD)lpvAddress;
	dwSegIndex = GET_SEGMENT_INDEX( (DWORD)dwStart );

	KL_EnterCriticalSection( &csVirtualMem );

	if( dwSegIndex < MAX_SEGMENTS )
	{
		if( ( lpProcessSeg = Seg_FindProcessSegment( dwStart ) ) &&
			( lpSeg = lpProcessSeg->lpSeg ) )  // 得到虚地址对应的段指针
		//if( ( lpSeg = Seg_FindSegment( dwStart ) ) ) // 得到虚地址所在的段
		{
			DWORD idxFirstBlk, idxStartBlk = BLOCK_INDEX( dwStart );
			DWORD idxStartPage;
			DWORD dwPages;
			// 2004-01-28, this is a error, i will test it
			//idxStartBlk = Seg_SearchFirstBlock( lpSeg, idxFirstBlk );
			idxFirstBlk = Seg_SearchFirstBlock( lpSeg, idxStartBlk ); // 得到该内存域的第一个块
			//if( idxStartBlk != NOT_FIND_FIRST )
			if( idxFirstBlk != NOT_FIND_FIRST )
			// 2004-01-28
			{
				idxStartPage = PAGE_INDEX( dwStart );
				dwPages = ( ( dwStart + dwSize + PAGE_SIZE - 1 ) / PAGE_SIZE ) - ( dwStart / PAGE_SIZE );
				// 扫描需要的页是否都已经提交
				if( Seg_ScanCommitRegion( lpSeg, idxFirstBlk, idxStartBlk, idxStartPage, dwPages ) )
				{	//是
					DWORD dwNewAttrib;
					//得到当前的属性
					*lpflOldProtect = GetProtectFromAttrib( lpSeg->lpBlks[idxStartBlk]->uiPages[idxStartPage] );
					dwNewAttrib = GetAttribFromProtect( flNewProtect );
					if( dwNewAttrib )
					{	//设置新的属性
					    Seg_ResetPageAttrib( lpProcessSeg, lpSeg, idxFirstBlk, idxStartBlk, idxStartPage, dwPages, dwNewAttrib );
						FlushCacheAndClearTLB(); //刷新CACHE
					}
				}
			}
			else
			{   // 虚地址无效
				//ASSERT( 0 );
				dwError = ERROR_INVALID_PARAMETER;
				WARNMSG( DEBUG_KL_VirtualProtect, ( "KL_VirtualProtect: invalid address=0x%x,dwSize=0x%x.\r\n", lpvAddress, dwSize ) );
				goto _err_return;
			}
		}
	}
_err_return:
	if( dwError )
		KL_SetLastError( dwError );
	KL_LeaveCriticalSection( &csVirtualMem );
	return dwError ? FALSE : TRUE;
}

// ********************************************************************
// 声明:LPVOID WINAPI KL_AllocPhysMem( 
//						   DWORD dwSize,
//						   DWORD fdwProtect,
//						   DWORD dwAlignmentMask,
//						   DWORD dwFlags,
//						   ULONG * pPhysicalAddress
//						   )
// 参数:
//		IN dwSize - 需要分配的大小
//		IN fdwProtect - 保护属性
//		IN dwAlignmentMask - 开始地址对齐模式
//		IN dwFlags - 标志
//		OUT pPhysicalAddress - 用于接受分配的物理地址
// 返回值:
//		假如成功,返回非NULL的虚地址,pPhysicalAddress返回对应的物理地址;否则,返回NULL
// 功能描述:
//		分配连续的物理页
// 引用:
//		系统API
// ********************************************************************
#define DEBUG_KL_AllocPhysMem 0
LPVOID WINAPI KL_AllocPhysMem( 
						   DWORD dwSize,
						   DWORD fdwProtect,
						   DWORD dwAlignmentMask,
						   DWORD dwFlags,
						   ULONG * pPhysicalAddress
						   )
{
   	void * p;
	DWORD dwPageSize = ALIGN_PAGE_UP( dwSize );
    LPVOID lpVAdr = NULL;

	DEBUGMSG( DEBUG_KL_AllocPhysMem, ( "KL_AllocPhysMem entry,dwSize=0x%x.\r\n", dwSize ) );

	KL_EnterCriticalSection( &csVirtualMem );
	// 得到连续的页
	p = Page_GetContiguous( dwPageSize / PAGE_SIZE, dwAlignmentMask );
	if( p )
	{	//
	    DWORD dwPhysicalAddress = _GetPhysicalPageAdr( (DWORD)p ); // 得到p对应的物理地址
		//将p映射到用户空间
		lpVAdr = DoVirtualAlloc( NULL, 
								dwPageSize, 
								MEM_COMMIT | MEM_RESERVE | MEM_PHYSICAL | MEM_CONTIGUOUS, 
								fdwProtect | PAGE_NOCACHE, 
								(LPVOID)dwPhysicalAddress );
        if( lpVAdr )
		{
			*pPhysicalAddress = dwPhysicalAddress;
		}
		else
		{	//失败。
			Page_ReleaseContiguous( p, dwPageSize / PAGE_SIZE );
		}
	}

	KL_LeaveCriticalSection( &csVirtualMem );
	return lpVAdr; 
}

// ********************************************************************
// 声明:BOOL WINAPI KL_FreePhysMem( LPVOID lpvAddress )
// 参数:
//		IN lpvAddress - 虚地址(用KL_AllocPhysMem分配的虚地址)
// 返回值:
//		假如成功,返回TRUE; 否则,返回FALSE
// 功能描述:
//		释放之前用 KL_AllocPhysMem 分配的地址
// 引用:
//		系统API
// ********************************************************************
#define DEBUG_KL_FreePhysMem 0
BOOL WINAPI KL_FreePhysMem( LPVOID lpvAddress )
{
	DEBUGMSG( DEBUG_KL_FreePhysMem, ( "KL_FreePhysMem entry,lpvAddress=0x%x.\r\n", lpvAddress ) );
	return DoVirtualFree( lpvAddress, 0, MEM_RELEASE );
}



⌨️ 快捷键说明

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