DeAllocateContiguous

This commit is contained in:
ergo720 2018-03-03 23:11:36 +01:00
parent bc0e0734ae
commit 2597e88ea4
6 changed files with 80 additions and 24 deletions

View File

@ -93,14 +93,12 @@ extern "C" {
#define CHIHIRO_INSTANCE_PHYSICAL_PAGE 0x07FF0
#define XBOX_PFN_DATABASE_PHYSICAL_PAGE 0x03FF0
#define CHIHIRO_PFN_DATABASE_PHYSICAL_PAGE 0x07FD0
#define PAGE_DIRECTORY_PHYSICAL_ADDRESS 0x0F000
#define D3D_PHYSICAL_PAGE 0x00000
#define DEBUGKIT_FIRST_UPPER_HALF_PAGE 0x04000
#define NV2A_INSTANCE_PAGE_COUNT 16
#define XBOX_CONTIGUOUS_MEMORY_LIMIT 0x03FDF
#define CHIHIRO_CONTIGUOUS_MEMORY_LIMIT 0x07FCF
#define ZERO_PAGE_ADDR 0
#define FIRST_PAGE_ADDR PAGE_SIZE
#define PAGE_DIRECTORY_PHYSICAL_ADDRESS 0x0F000
#define D3D_PHYSICAL_PAGE 0x00000
#define DEBUGKIT_FIRST_UPPER_HALF_PAGE X64M_PHYSICAL_PAGE // = 0x4000
#define NV2A_INSTANCE_PAGE_COUNT 16
#define CONTIGUOUS_MEMORY_BASE SYSTEM_PHYSICAL_MAP // = 0x80000000
#define CONTIGUOUS_MEMORY_XBOX_SIZE (64 * ONE_MB)
#define CONTIGUOUS_MEMORY_CHIHIRO_SIZE (128 * ONE_MB)

View File

@ -236,7 +236,7 @@ XBSYSAPI EXPORTNUM(171) xboxkrnl::VOID NTAPI xboxkrnl::MmFreeContiguousMemory
{
LOG_FUNC_ONE_ARG(BaseAddress);
g_VMManager.Deallocate((VAddr)BaseAddress);
g_VMManager.DeAllocateContiguous((VAddr)BaseAddress);
// TODO -oDxbx: Sokoban crashes after this, at reset time (press Black + White to hit this).
// Tracing in assembly shows the crash takes place quite a while further, so it's probably

View File

@ -186,9 +186,9 @@ void PhysicalMemory::WritePte(PMMPTE pPteStart, PMMPTE pPteEnd, MMPTE Pte, PFN p
WRITE_ZERO_PTE(pPteStart);
pPteStart++;
}
return;
}
else
{
while (pPteStart <= pPteEnd)
{
Pte.Hardware.PFN = pfn;
@ -196,6 +196,7 @@ void PhysicalMemory::WritePte(PMMPTE pPteStart, PMMPTE pPteEnd, MMPTE Pte, PFN p
pPteStart++;
pfn++;
}
}
}
bool PhysicalMemory::RemoveFree(PFN_COUNT NumberOfPages, PFN* result, PFN_COUNT PfnAlignment, PFN start, PFN end)
@ -626,3 +627,12 @@ PFN PhysicalMemory::RemoveAndZeroAnyFreePage(PageType BusyType, PMMPTE pPte)
return pfn;
}
bool PhysicalMemory::IsMappable(PFN_COUNT PagesRequested)
{
if (m_PhysicalPagesAvailable >= PagesRequested) { return true; }
else
{
EmuWarning("Out of physical memory!");
return false;
}
}

View File

@ -267,6 +267,8 @@ class PhysicalMemory
bool AllocatePT(PFN_COUNT PteNumber, VAddr addr);
// commit whatever free page is available and zero it
PFN RemoveAndZeroAnyFreePage(PageType BusyType, PMMPTE pte);
// checks if enough free page are available for the allocation (doesn't account for fragmentation)
bool IsMappable(PFN_COUNT PagesRequested);
};
#endif

View File

@ -135,6 +135,8 @@ void VMManager::DestroyMemoryRegions()
for (int i = 0; i < MemoryRegionType::COUNT - 1; ++i)
{
for (auto it = m_MemoryRegionArray[i].RegionMap.begin(); it != m_MemoryRegionArray[i].RegionMap.end(); ++it)
{
if (it->second.type != VMAType::Free)
{
if (it->second.bFragmented)
{
@ -146,6 +148,7 @@ void VMManager::DestroyMemoryRegions()
}
}
}
}
}
void VMManager::InitializePfnDatabase()
@ -404,7 +407,7 @@ VAddr VMManager::AllocateSystemMemory(PageType BusyType, DWORD Perms, size_t Siz
PteNumber = ROUND_UP_4K(Size) >> PAGE_SHIFT;
if (bAddGuardPage) { PteNumber++; Size += PAGE_SIZE; }
if (m_PhysicalPagesAvailable < PteNumber) { goto Fail; }
if (!IsMappable(PteNumber)) { goto Fail; }
if (RemoveFree(PteNumber, &pfn, 0, 0, m_HighestPage)) // MapViewOfFileEx path
{
@ -469,7 +472,7 @@ VAddr VMManager::AllocateSystemMemory(PageType BusyType, DWORD Perms, size_t Siz
PointerPte++;
}
EndingPte = PointerPte + PteNumber - 1;
EndingPfn = pfn + PteNumber;
EndingPfn = pfn + PteNumber - 1;
WritePte(PointerPte, EndingPte, TempPte, pfn);
EndingPte->Hardware.GuardOrEnd = 1;
@ -534,6 +537,7 @@ VAddr VMManager::AllocateContiguous(size_t Size, PAddr LowerAddress, PAddr Highe
HigherPfn = HigherAddress >> PAGE_SHIFT;
PfnAlignment = Alignment >> PAGE_SHIFT;
if (!IsMappable(PteNumber)) { goto Fail; }
if (HigherPfn > m_MaxContiguousPfn) { HigherPfn = m_MaxContiguousPfn; }
if (LowerPfn > HigherPfn) { LowerPfn = HigherPfn; }
if (!PfnAlignment) { PfnAlignment = 1; }
@ -545,17 +549,18 @@ VAddr VMManager::AllocateContiguous(size_t Size, PAddr LowerAddress, PAddr Highe
assert(CHECK_ALIGNMENT(pfn, PfnAlignment)); // check if the page alignment is correct
EndingPfn = pfn + PteNumber - 1;
// check if we have to construct the PT's for this allocation
if (!AllocatePT(PteNumber, addr))
{
InsertFree(pfn, pfn + PteNumber - 1);
InsertFree(pfn, EndingPfn);
goto Fail;
}
// Finally, write the pte's and the pfn's
PointerPte = GetPteAddress(addr);
EndingPte = PointerPte + PteNumber - 1;
EndingPfn = pfn + PteNumber;
WritePte(PointerPte, EndingPte, TempPte, pfn);
WritePfn(pfn, EndingPfn, PointerPte, PageType::Contiguous, true);
@ -647,6 +652,45 @@ void VMManager::Deallocate(VAddr addr)
Unlock();
}
void VMManager::DeAllocateContiguous(VAddr addr)
{
LOG_FUNC_BEGIN
LOG_FUNC_ARG(addr);
LOG_FUNC_END;
MMPTE TempPte;
PMMPTE StartingPte;
PMMPTE EndingPte;
PFN pfn;
PFN EndingPfn;
VMAIter it;
assert(CHECK_ALIGNMENT(addr, PAGE_SIZE)); // all starting addresses from the contiguous region are page aligned
Lock();
it = CheckExistenceVMA(addr, MemoryRegionType::Contiguous);
if (it == m_MemoryRegionArray[MemoryRegionType::Contiguous].RegionMap.end() || it->second.type == VMAType::Free)
{
Unlock();
return;
}
StartingPte = GetPteAddress(addr);
EndingPte = StartingPte + (it->second.size >> PAGE_SHIFT) - 1;
pfn = StartingPte->Hardware.PFN;
EndingPfn = pfn + (EndingPte - StartingPte);
InsertFree(pfn, EndingPfn);
WritePfn(pfn, EndingPfn, StartingPte, PageType::Contiguous, true, true);
WritePte(StartingPte, EndingPte, TempPte, 0, true);
DestructVMA(it, MemoryRegionType::Contiguous);
Unlock();
}
PFN_COUNT VMManager::DeAllocateSystemMemory(PageType BusyType, VAddr addr, size_t Size /*MemoryRegionType Type*/)
{
LOG_FUNC_BEGIN

View File

@ -140,6 +140,8 @@ class VMManager : public PhysicalMemory
VAddr MapDeviceMemory(PAddr Paddr, size_t Size, DWORD Perms);
// deallocates memory in the system region
PFN_COUNT DeAllocateSystemMemory(PageType BusyType, VAddr addr, size_t Size /*MemoryRegionType Type*/);
// deallocates memory in the contiguous region
void DeAllocateContiguous(VAddr addr);
// deallocate a block of memory
void Deallocate(VAddr addr);
// changes the protections of a memory region