📄 vmm.cpp
字号:
(((DWORD)lpEndAddr & ~(PAGE_FRAME_SIZE - 1)) + PAGE_FRAME_SIZE - 1)
: ((DWORD)lpEndAddr - 1)); //Round down to page.
dwSize = (DWORD)lpEndAddr - (DWORD)lpStartAddr + 1; //Get the actually size.
lpVad = (__VIRTUAL_AREA_DESCRIPTOR*)KMemAlloc(sizeof(__VIRTUAL_AREA_DESCRIPTOR),
KMEM_SIZE_TYPE_ANY); //In order to avoid calling KMemAlloc routine in the
//critical section,we first call it here.
if(NULL == lpVad) //Can not allocate memory.
goto __TERMINAL;
lpVad->lpManager = lpMemMgr;
lpVad->lpStartAddr = NULL;
lpVad->lpEndAddr = NULL;
lpVad->lpNext = NULL;
lpVad->dwAccessFlags = dwAccessFlags;
lpVad->dwAllocFlags = dwAllocFlags;
__INIT_ATOMIC(lpVad->Reference);
lpVad->lpLeft = NULL;
lpVad->lpRight = NULL;
if(lpVaName)
{
if(StrLen((LPSTR)lpVaName) > MAX_VA_NAME_LEN)
lpVaName[MAX_VA_NAME_LEN - 1] = 0;
StrCpy((LPSTR)lpVad->strName[0],(LPSTR)lpVaName); //Set the virtual area's name.
}
else
lpVad->strName[0] = 0;
lpVad->dwCacheFlags = VIRTUAL_AREA_CACHE_IO;
//
//The following code searchs virtual area list or AVL tree,to check if the lpDesiredAddr
//is occupied,if so,then find a new one.
//
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
if(lpMemMgr->dwVirtualAreaNum < SWITCH_VA_NUM) //Should search in the list.
lpStartAddr = SearchVirtualArea_l((__COMMON_OBJECT*)lpMemMgr,lpStartAddr,dwSize);
else //Should search in the AVL tree.
lpStartAddr = SearchVirtualArea_t((__COMMON_OBJECT*)lpMemMgr,lpStartAddr,dwSize);
if(NULL == lpStartAddr) //Can not find proper virtual area.
{
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
goto __TERMINAL;
}
lpVad->lpStartAddr = lpStartAddr;
lpVad->lpEndAddr = (LPVOID)((DWORD)lpStartAddr + dwSize -1);
lpDesiredAddr = lpStartAddr;
if(lpMemMgr->dwVirtualAreaNum < SWITCH_VA_NUM)
InsertIntoList((__COMMON_OBJECT*)lpMemMgr,lpVad); //Insert into list or tree.
else
InsertIntoTree((__COMMON_OBJECT*)lpMemMgr,lpVad);
//
//The following code reserves page table entries for the committed memory.
//
dwPteFlags = PTE_FLAGS_FOR_IOMAP; //IO map flags,that is,this memory range will not
//use hardware cache.
lpPhysical = lpStartAddr;
while(dwSize)
{
if(!lpIndexMgr->ReservePage((__COMMON_OBJECT*)lpIndexMgr,
lpStartAddr,lpPhysical,dwPteFlags))
{
PrintLine("Fatal Error : Internal data structure is not consist.");
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
goto __TERMINAL;
}
dwSize -= PAGE_FRAME_SIZE;
lpStartAddr = (LPVOID)((DWORD)lpStartAddr + PAGE_FRAME_SIZE);
lpPhysical = (LPVOID)((DWORD)lpPhysical + PAGE_FRAME_SIZE);
}
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
bResult = TRUE; //Indicate that the whole operation is successfully.
__TERMINAL:
if(!bResult) //Process failed.
{
if(lpVad)
KMemFree((LPVOID)lpVad,KMEM_SIZE_TYPE_ANY,0L);
if(lpPhysical)
PageFrameManager.FrameFree((__COMMON_OBJECT*)&PageFrameManager,
lpPhysical,
dwSize);
return NULL;
}
return lpDesiredAddr;
}
//
//The implementation of VirtualAlloc routine.
//
static LPVOID VirtualAlloc(__COMMON_OBJECT* lpThis,
LPVOID lpDesiredAddr,
DWORD dwSize,
DWORD dwAllocFlags,
DWORD dwAccessFlags,
UCHAR* lpVaName,
LPVOID lpReserved)
{
switch(dwAllocFlags)
{
case VIRTUAL_AREA_ALLOCATE_IO: //Call DoIoMap only.
return DoIoMap(lpThis,
lpDesiredAddr,
dwSize,
dwAllocFlags,
dwAccessFlags,
lpVaName,
lpReserved);
break;
case VIRTUAL_AREA_ALLOCATE_RESERVE:
return DoReserve(lpThis,
lpDesiredAddr,
dwSize,
dwAllocFlags,
dwAccessFlags,
lpVaName,
lpReserved);
break;
case VIRTUAL_AREA_ALLOCATE_ALL:
return DoReserveAndCommit(lpThis,
lpDesiredAddr,
dwSize,
dwAllocFlags,
dwAccessFlags,
lpVaName,
lpReserved);
break;
case VIRTUAL_AREA_ALLOCATE_COMMIT:
DoCommit(lpThis,
lpDesiredAddr,
dwSize,
dwAllocFlags,
dwAccessFlags,
lpVaName,
lpReserved);
break;
default:
return NULL;
}
return NULL;
}
//
//A helper routine,used to delete a virtual area descriptor object from list.
//
static VOID DelVaFromList(__COMMON_OBJECT* lpThis,__VIRTUAL_AREA_DESCRIPTOR* lpVad)
{
__VIRTUAL_MEMORY_MANAGER* lpMemMgr = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
__VIRTUAL_AREA_DESCRIPTOR* lpNext = NULL;
__VIRTUAL_AREA_DESCRIPTOR* lpPrev = NULL;
if((NULL == lpThis) || (NULL == lpVad)) //Invalidate parameters.
return;
lpPrev = lpMemMgr->lpListHdr;
lpNext = lpMemMgr->lpListHdr;
if(NULL == lpPrev) //There is not any VAD in list.
{
//__POTENTIAL_BUT();
return;
}
if(lpPrev == lpVad) //The vad to be deleted is the first one.
{
lpMemMgr->lpListHdr = lpPrev->lpNext;
lpMemMgr->dwVirtualAreaNum --;
return;
}
while(lpPrev)
{
if(lpVad == lpPrev)
break;
lpNext = lpPrev;
lpPrev = lpPrev->lpNext;
}
if(NULL == lpPrev) //Can not find the virtual area descriptor object in list.
return;
lpNext->lpNext = lpPrev->lpNext; //Delete the VAD object.
lpMemMgr->dwVirtualAreaNum --;
return;
}
//
//A helper routine,used to delete a virtual area descriptor object from AVL
//tree.
//
static VOID DelVaFromTree(__COMMON_OBJECT* lpThis,__VIRTUAL_AREA_DESCRIPTOR* lpVad)
{
return; //We will complete this routine in the future.
}
//
//A helper routine,used to release virtual area that committed and with physical memory
//pages allocated.
//
static VOID ReleaseCommit(__COMMON_OBJECT* lpThis,__VIRTUAL_AREA_DESCRIPTOR* lpVad)
{
__VIRTUAL_MEMORY_MANAGER* lpMemMgr = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
LPVOID lpStartAddr = NULL;
LPVOID lpEndAddr = NULL;
__PAGE_INDEX_MANAGER* lpIndexMgr = NULL;
DWORD dwSize = 0L;
if((NULL == lpThis) || (NULL == lpVad)) //Invalidate parameters.
return;
lpIndexMgr = lpMemMgr->lpPageIndexMgr;
if(NULL == lpIndexMgr) //Fatal error.
return;
lpStartAddr = lpVad->lpStartAddr;
lpEndAddr = lpVad->lpEndAddr;
dwSize = (DWORD)lpEndAddr - (DWORD)lpStartAddr + 1;
lpEndAddr = lpIndexMgr->GetPhysicalAddress((__COMMON_OBJECT*)lpIndexMgr,
lpStartAddr); //Get the physical memory address.
PageFrameManager.FrameFree((__COMMON_OBJECT*)&PageFrameManager,
lpEndAddr,
dwSize); //Release the physical page.
while(dwSize)
{
lpIndexMgr->ReleasePage((__COMMON_OBJECT*)lpIndexMgr,
lpStartAddr); //Release the page table entry that this area occupies.
lpStartAddr = (LPVOID)((DWORD)lpStartAddr + PAGE_FRAME_SIZE);
dwSize -= PAGE_FRAME_SIZE;
}
}
//
//A helper routine,used to release virtual area that committed,but without physical
//memory pages allocated,such as IO map zone.
//This routine only release the page table entry that this virtual area occupies.
//
static VOID ReleaseIoMap(__COMMON_OBJECT* lpThis,__VIRTUAL_AREA_DESCRIPTOR* lpVad)
{
__VIRTUAL_MEMORY_MANAGER* lpMemMgr = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
LPVOID lpStartAddr = NULL;
LPVOID lpEndAddr = NULL;
__PAGE_INDEX_MANAGER* lpIndexMgr = NULL;
DWORD dwSize = 0L;
if((NULL == lpThis) || (NULL == lpVad)) //Invalidate parameters.
return;
lpIndexMgr = lpMemMgr->lpPageIndexMgr;
if(NULL == lpIndexMgr) //Fatal error.
return;
lpStartAddr = lpVad->lpStartAddr;
lpEndAddr = lpVad->lpEndAddr;
dwSize = (DWORD)lpEndAddr - (DWORD)lpStartAddr + 1;
while(dwSize)
{
lpIndexMgr->ReleasePage((__COMMON_OBJECT*)lpIndexMgr,
lpStartAddr); //Release the page table entry that this area occupies.
lpStartAddr = (LPVOID)((DWORD)lpStartAddr + PAGE_FRAME_SIZE);
dwSize -= PAGE_FRAME_SIZE;
}
}
//
//The implementation of VirtualFree routine.
//This routine frees the virtual area allocated by VirtualAlloc,and
//frees any resource,such as physical memory page,page table entries,
//and virtual area descriptor objects,associated with the virtual
//area object.
//
static VOID VirtualFree(__COMMON_OBJECT* lpThis,LPVOID lpVirtualAddr)
{
__VIRTUAL_MEMORY_MANAGER* lpMemMgr = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
__VIRTUAL_AREA_DESCRIPTOR* lpVad = NULL;
__PAGE_INDEX_MANAGER* lpIndexMgr = NULL;
BOOL bResult = FALSE;
DWORD dwFlags = 0L;
if((NULL == lpThis) || (NULL == lpVirtualAddr)) //Invalidate parameters.
return;
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
if(lpMemMgr->dwVirtualAreaNum < SWITCH_VA_NUM) //Should search in the list.
lpVad = GetVaByAddr_l(lpThis,lpVirtualAddr); //Get the virtual area descriptor.
else
lpVad = GetVaByAddr_t(lpThis,lpVirtualAddr);
if(NULL == lpVad) //This virtual address is not allocated yet.
{
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
goto __TERMINAL;
}
//
//Now,we have got the virtual area descriptor object,so,
//first delete it from list or tree.
//
if(lpMemMgr->dwVirtualAreaNum < SWITCH_VA_NUM) //Delete from list.
DelVaFromList(lpThis,lpVad);
else //Delete from tree.
DelVaFromTree(lpThis,lpVad);
//
//According to different allocating type,to do the different actions.
//
switch(lpVad->dwAllocFlags)
{
case VIRTUAL_AREA_ALLOCATE_COMMIT: //The virtual memory area is committed.
ReleaseCommit(lpThis,lpVad);
KMemFree((LPVOID)lpVad,KMEM_SIZE_TYPE_ANY,0L); //Release the memory occupied by
//virtual area descriptor.
break;
case VIRTUAL_AREA_ALLOCATE_RESERVE: //Only reserved.
KMemFree((LPVOID)lpVad,KMEM_SIZE_TYPE_ANY,0L); //Only release the memory.
break;
case VIRTUAL_AREA_ALLOCATE_IO: //Committed,but without physical memory pages.
ReleaseIoMap(lpThis,lpVad);
KMemFree((LPVOID)lpVad,KMEM_SIZE_TYPE_ANY,0L);
break;
default:
break;
}
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
bResult = TRUE; //Set the completing flags.
__TERMINAL:
return;
}
//
//The implementation of GetPdAddress routine.
//This routine returns the physical address of page directory.
//
static LPVOID GetPdAddress(__COMMON_OBJECT* lpThis)
{
__VIRTUAL_MEMORY_MANAGER* lpManager = NULL;
if(NULL == lpThis) //Parameter check.
return NULL;
lpManager = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
return (LPVOID)lpManager->lpPageIndexMgr->lpPdAddress;
}
/***********************************************************************************
************************************************************************************
************************************************************************************
************************************************************************************
***********************************************************************************/
//
//The definition of object Virtual Memory Manager.
//This is one of the global objects,but it is created by CreateObject routine of
//ObjectManager.
//
__VIRTUAL_MEMORY_MANAGER* lpVirtualMemoryMgr = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -