📄 virtmem.c
字号:
LockPages (pvAddr, 1, 0, flLock)) // TODO: We should not call this here if VAcs is already hold!!!! Change this (to fail directly or update page table directly if possible)
{ // Query only, do not lock
pvRet = VerifyAccess (pvAddr, flVerify, (ACCESSKEY)-1);
}
}
else
{ // Forced Page-in inactive (less intrusive debugger):
fPageInFailed = TRUE;
DEBUGMSG(ZONE_VIRTMEM, (TEXT(" DebugVerify: VMPage not paged in.\r\n")));
}
}
if (pfPageInFailed) *pfPageInFailed = fPageInFailed;
return pvRet;
}
#if HARDWARE_PT_PER_PROC
ERRFALSE(PAGE_SIZE == 4096);
MEMBLOCK *GetKPagePMB (DWORD dwVMBase)
{
MEMBLOCK *pmb = MDAllocMemBlock (dwVMBase, 0);
if (pmb) {
DEBUGMSG (ZONE_VIRTMEM, (L"pmb = %8.8lx, pmb->aPages = %8.8lx\r\n", pmb, pmb->aPages));
pmb->alk = ~0ul;
pmb->cLocks = 1;
pmb->ixBase = UNKNOWN_BASE;
pmb->aPages[5] = KPAGE_PTE; // KPage is from 0x5000 to 0x5fff
}
return pmb;
}
#else
const MEMBLOCK KPageBlock = {
~0ul, // alk
0, // cUses
0, // flags
UNKNOWN_BASE,// ixBase
0, // hPf
1, // cLocks
{
#if PAGE_SIZE == 4096
0, 0, 0, 0, 0,
#elif PAGE_SIZE == 2048
/* 0x0000: */ 0, 0, 0, 0,
/* 0x2000: */ 0, 0, 0, 0,
/* 0x4000: */ 0, 0, 0,
/* 0x5800: (start of user visible kernel data page) */
#elif PAGE_SIZE == 1024
/* 0x0000: */ 0, 0, 0, 0,
/* 0x1000: */ 0, 0, 0, 0,
/* 0x2000: */ 0, 0, 0, 0,
/* 0x3000: */ 0, 0, 0, 0,
/* 0x4000: */ 0, 0, 0, 0,
/* 0x5000: */ 0, 0,
/* 0x5800: (start of user visible kernel data page) */
#else
#error Unsupported page size.
#endif
KPAGE_PTE
}
};
#define GetKPagePMB(dwVMBase) ((MEMBLOCK*)&KPageBlock)
#endif
SECTION NKSection;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPVOID
InitNKSection(void)
{
NKSection[0] = GetKPagePMB (SECURE_VMBASE);
DEBUGCHK (NKSection[0]);
// save the address of NKSection in KInfo
KInfoTable[KINX_NKSECTION] = (DWORD) &NKSection;
return (LPVOID) SECURE_VMBASE;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
VOID
DeleteSection(
LPVOID lpvSect
)
{
PSECTION pscn;
DWORD dwSect = (DWORD) lpvSect;
int ix;
int ixScn;
LPDWORD pPageList = NULL;
DEBUGMSG(ZONE_VIRTMEM,(TEXT("DeleteSection %8.8lx\r\n"), dwSect));
EnterCriticalSection(&VAcs);
if ((ixScn = dwSect>>VA_SECTION) <= SECTION_MASK
&& ixScn >= RESERVED_SECTIONS
&& (pscn = SectionTable[ixScn]) != NULL_SECTION) {
DEBUGCHK (pscn != &NKSection);
// if this is a mapper section, clear the "filesys owned bit for this section
if ((dwSect >= FIRST_MAPPER_ADDRESS) && (dwSect < LAST_MAPPER_ADDRESS)) {
g_ObjStoreSlotBits &= ~ MapperSlotToBit (ixScn);
}
// For process sections, start freeing at block 1. Otherwise, this
// should be a mapper section which starts freeing at block 0.
#if HARDWARE_PT_PER_PROC
ix = 0;
#else
ix = ((*pscn)[0] != &KPageBlock)? 0 : 1;
#endif
for ( ; ix < BLOCK_MASK+1 ; ++ix) {
if ((*pscn)[ix] != NULL_BLOCK) {
if ((*pscn)[ix] != RESERVED_BLOCK) {
pPageList = DecommitPages(pscn, ix, 0, PAGES_PER_BLOCK, dwSect, TRUE, pPageList);
if ((*pscn)[ix] != RESERVED_BLOCK) {
MDFreeMemBlock ((*pscn)[ix]);
}
}
}
}
SectionTable[ixScn] = NULL_SECTION;
FreeSection(pscn);
if (ixScn < FirstFreeSection)
FirstFreeSection = ixScn;
#if HARDWARE_PT_PER_PROC
{
extern void FreeHardwarePT (DWORD dwVMBase);
FreeHardwarePT (dwSect);
}
#endif
} else
DEBUGMSG(ZONE_VIRTMEM,(TEXT("DeleteSection failed.\r\n")));
// do the zeroing of pages outside VAcs
LeaveCriticalSection(&VAcs);
FreePageList (pPageList);
return;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPVOID CreateSection (LPVOID lpvAddr, BOOL fInitKPage)
{
PSECTION pSect;
uint ixSect;
DEBUGMSG(ZONE_VIRTMEM,(TEXT("CreateSection %8.8lx\r\n"), lpvAddr));
EnterCriticalSection(&VAcs);
if (lpvAddr != 0) {
if ((ixSect = (ulong)lpvAddr>>VA_SECTION) > SECTION_MASK
|| SectionTable[ixSect] != NULL_SECTION) {
DEBUGMSG(1,(TEXT("CreateSection failed (1)\r\n")));
lpvAddr = 0;
goto exitCreate;
}
} else {
/* scan for an available section table entry */
// NOTE: never use slot 1
for (;;) {
for (ixSect = FirstFreeSection ; ixSect < MAX_PROCESSES+RESERVED_SECTIONS
; ++ixSect) {
if (SectionTable[ixSect] == NULL_SECTION)
goto foundSect;
}
if (FirstFreeSection == (RESERVED_SECTIONS+1))
break;
FirstFreeSection = RESERVED_SECTIONS+1;
}
/* no sections available */
DEBUGMSG(1, (TEXT("CreateSection failed (2)\r\n")));
goto exitCreate;
/* found a free section set new first free index */
foundSect:
FirstFreeSection = ixSect+1;
}
/* Allocate a section and initialize it to invalid blocks */
if ((pSect = GetSection()) == 0) {
DEBUGMSG(1, (TEXT("CreateSection failed (3)\r\n")));
lpvAddr = 0;
goto exitCreate;
}
///memcpy(pSect, &NullSection, sizeof(NullSection));
SectionTable[ixSect] = pSect;
lpvAddr = (LPVOID)(ixSect << VA_SECTION);
if (fInitKPage && !((*pSect)[0] = GetKPagePMB (ixSect << VA_SECTION))) {
// failed to create Memblock
DeleteSection (lpvAddr);
lpvAddr = NULL;
}
exitCreate:
LeaveCriticalSection(&VAcs);
DEBUGMSG(ZONE_VIRTMEM, (TEXT("CreateSection done: addr=%8.8lx, pSect=%8.8lx\r\n"), lpvAddr, pSect));
return lpvAddr;
}
// CreateMapperSection - allocate memory section for file mapping
//
// This function will allocate a 32mb section and reserve the entire range for
// use by file mapping.
DWORD g_ObjStoreSlotBits; // bit fields
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL CreateMapperSection (DWORD dwBase, BOOL fAddProtect)
{
BOOL bRet = FALSE;
MEMBLOCK *pmb;
PSECTION pscn;
int ix;
DEBUGMSG(ZONE_VIRTMEM,(TEXT("CreateMapperSection %8.8lx\r\n"), dwBase));
if (dwBase < FIRST_MAPPER_ADDRESS || dwBase >= LAST_MAPPER_ADDRESS) {
DEBUGMSG(1, (TEXT("CreateMapperSection: %8.8lx is out of range.\r\n"), dwBase));
return FALSE;
}
// First, create a normal section. Then convert it into a special section
// for the Mapper.
EnterCriticalSection(&VAcs);
if (CreateSection((LPVOID)dwBase, FALSE) != 0) {
DWORD dwSlot = (dwBase>>VA_SECTION) & SECTION_MASK;
pscn = SectionTable[dwSlot];
if (pmb = MDAllocMemBlock (dwBase, 0)) {
if (fAddProtect) {
LockFromKey(&pmb->alk, &pCurProc->aky);
// 2nd gig section with protection, it's object store
g_ObjStoreSlotBits |= MapperSlotToBit (dwSlot);
} else
LockFromKey(&pmb->alk, &ProcArray[0].aky);
pmb->cUses = 1;
pmb->flags = MB_PAGER_MAPPING;
pmb->ixBase = 0;
(*pscn)[0] = pmb;
for (ix = 1 ; ix < BLOCK_MASK+1 ; ++ix)
(*pscn)[ix] = RESERVED_BLOCK;
bRet = TRUE;
} else {
DeleteSection((LPVOID)dwBase);
DEBUGMSG(1, (TEXT("CreateMapperSection: unable to allocate MEMBLOCK\r\n")));
}
}
LeaveCriticalSection(&VAcs);
return bRet;
}
//------------------------------------------------------------------------------
// DeleteMapperSection - delete a section created by CreateMapperSection()
//
// This function must be used to delete a memory section which is created by
// CreateMapperSection.
//------------------------------------------------------------------------------
void
DeleteMapperSection(
DWORD dwBase
)
{
if ((dwBase >= FIRST_MAPPER_ADDRESS) && (dwBase < LAST_MAPPER_ADDRESS))
DeleteSection((LPVOID)dwBase);
else
DEBUGMSG(1, (TEXT("DeleteMapperSection: %8.8lx is out of range.\r\n"), dwBase));
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPVOID
DoVirtualAlloc(
LPVOID lpvAddress0, /* address of region to reserve or commit */
DWORD cbSize, /* size of the region */
DWORD fdwAllocationType, /* type of allocation */
DWORD fdwProtect, /* type of access protection */
DWORD fdwInternal,
DWORD dwPFNBase
)
{
int ixBlock;
int ixPage;
int ix;
int ixFirB; /* index of first block in region */
PSECTION pscn;
int cPages; /* # of pages to allocate */
int cNeed;
int cpAlloc; /* # of physical pages to allocate */
ulong ulPgMask; /* page permissions */
ulong ulPFN; /* page physical frame number */
MEMBLOCK *pmb;
DWORD err;
DWORD dwEnd;
LPVOID lpvResult = NULL;
DWORD dwAddr = (DWORD) lpvAddress0;
DWORD dwSlot0Addr = ZeroPtrABS(dwAddr);
ACCESSKEY aky = pCurProc->aky;
DWORD dwBase;
BOOL fNeedInvalidate = FALSE;
ixFirB = UNKNOWN_BASE;
DEBUGMSG(ZONE_VIRTMEM, (TEXT("VirtualAlloc(%8.8lx, %lx, %lx, %lx)\r\n"),
lpvAddress0, cbSize, fdwAllocationType, fdwProtect));
// validate parameters
if (IsKernelVa (dwAddr) // invalid address?
|| !cbSize // size == 0?
|| ((cbSize >= (1<<VA_SECTION)) // size too big? (okay to reserver > 32M with specific parameters)
&& (dwSlot0Addr || (fdwAllocationType != MEM_RESERVE) || (fdwProtect != PAGE_NOACCESS)))
|| !(ulPgMask = MakePagePerms(fdwProtect, dwAddr))) { // invalid flag?
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return NULL;
}
dwEnd = dwAddr + cbSize;
//
// Lockout other changes to the virtual memory state.
//
EnterCriticalSection(&VAcs);
if (IsSecureVa(dwAddr)) {
aky = ProcArray[0].aky;
pscn = &NKSection;
dwBase = SECURE_VMBASE;
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -