Bug fixes

This commit is contained in:
ergo720 2017-12-30 17:12:11 +01:00
parent a3f5a4ce74
commit eed9fc75f2
4 changed files with 44 additions and 36 deletions

View File

@ -160,7 +160,7 @@ XBSYSAPI EXPORTNUM(167) xboxkrnl::PVOID NTAPI xboxkrnl::MmAllocateSystemMemory
LOG_FUNC_END;
// TODO: this should probably allocate the memory at a specific system virtual address region...
PVOID pRet = (PVOID)g_VMManager.Allocate(NumberOfBytes, 0, MAXULONG_PTR, NULL, PAGE_SIZE, Protect);
PVOID pRet = (PVOID)g_VMManager.Allocate(NumberOfBytes, 0, MAXULONG_PTR, PAGE_SIZE, Protect);
RETURN(pRet);
}
@ -408,7 +408,7 @@ XBSYSAPI EXPORTNUM(177) xboxkrnl::PVOID NTAPI xboxkrnl::MmMapIoSpace
pRet = (PVOID)PhysicalAddress;
}
else {
g_VMManager.Allocate(NumberOfBytes, 0, MAXULONG_PTR, NULL, PAGE_SIZE, ProtectionType);
g_VMManager.Allocate(NumberOfBytes, 0, MAXULONG_PTR, PAGE_SIZE, ProtectionType);
LOG_INCOMPLETE();
}

View File

@ -104,10 +104,24 @@ XBSYSAPI EXPORTNUM(327) xboxkrnl::NTSTATUS NTAPI xboxkrnl::XeLoadSection
// note that the manager physical allocation routines check the free memory left before attempting a new allocation and bail out
// immediately if not enough is available, this prevents exceeding the max memory on the Xbox
VAddr CapturedAddress = (VAddr)Section->VirtualAddress;
size_t CapturedSize = Section->VirtualSize;
VAddr BaseAddress = (VAddr)Section->VirtualAddress;
VAddr EndingAddress = (VAddr)Section->VirtualAddress + Section->VirtualSize;
ret = XbAllocateVirtualMemoryStub(&CapturedAddress, 0, &CapturedSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if ((*Section->TailReferenceCount) != 0)
{
EndingAddress &= ~PAGE_MASK;
}
if ((*Section->HeadReferenceCount) != 0)
{
BaseAddress = (BaseAddress + PAGE_SIZE) & ~PAGE_MASK;
}
if (EndingAddress > BaseAddress)
{
size_t RegionSize = EndingAddress - BaseAddress;
ret = XbAllocateVirtualMemoryStub(&BaseAddress, 0, &RegionSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
}
// Increment the head/tail page reference counters
(*Section->HeadReferenceCount)++;

View File

@ -286,16 +286,12 @@ VAddr VMManager::Allocate(size_t size, PAddr low_addr, PAddr high_addr, ULONG Al
LOG_FUNC_ARG(bNonContiguous);
LOG_FUNC_END;
// PAGE_WRITECOMBINE/PAGE_NOCACHE are not allowed for shared memory, unless SEC_WRITECOMBINE/SEC_NOCACHE flag
// was specified when calling the CreateFileMapping function. Considering that Cxbx doesn't emulate the caches,
// it's probably safe to ignore these flags
Lock();
size_t ReturnedSize = size;
VAddr v_addr = MapMemoryBlock(&ReturnedSize, low_addr, high_addr, Alignment, bNonContiguous);
if (v_addr)
{
ReprotectVMARange(v_addr, ReturnedSize, protect & ~(PAGE_WRITECOMBINE | PAGE_NOCACHE));
ReprotectVMARange(v_addr, ReturnedSize, protect);
protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY) ?
m_ImageMemoryInUse += ReturnedSize : m_NonImageMemoryInUse += ReturnedSize;
}
@ -342,7 +338,7 @@ VAddr VMManager::AllocateStack(size_t size)
RETURN(v_addr);
}
void VMManager::Deallocate(VAddr addr, size_t size)
void VMManager::Deallocate(VAddr addr)
{
LOG_FUNC_ONE_ARG(addr);
@ -369,12 +365,8 @@ void VMManager::Protect(VAddr target, size_t size, DWORD new_perms)
LOG_FUNC_ARG(new_perms);
LOG_FUNC_END;
// PAGE_WRITECOMBINE/PAGE_NOCACHE are not allowed for shared memory, unless SEC_WRITECOMBINE/SEC_NOCACHE flag
// was specified when calling the CreateFileMapping function. Considering that Cxbx doesn't emulate the caches,
// it's probably safe to ignore these flags
Lock();
ReprotectVMARange(target, size, new_perms & ~(PAGE_WRITECOMBINE | PAGE_NOCACHE));
ReprotectVMARange(target, size, new_perms);
Unlock();
}
@ -476,10 +468,14 @@ xboxkrnl::NTSTATUS VMManager::XbAllocateVirtualMemory(VAddr* addr, ULONG zero_bi
if (bStub)
{
// The stub doesn't allocate anything, but the following is useful as reference
// WARNING: because there are no allocations being done, it can't know if there is overlap and so the memory statistics
// can be wrong in that case (this doesn't happen in XeLoadSection since it checks for the overlap with the head/tail counters)
// REMARK: the following assumes that there is only one VMAType::Free between VAddr and VAddr + size. This is fine for XeUnloadSection,
// not so for NtAllocateVirtualMemory. For that, an approch similar to UnmapRange (in particular VMAType::Lock) should be used.
VMAIter vma_handle = GetVMAIterator(AlignedCapturedBase);
/*VMAIter vma_handle = GetVMAIterator(AlignedCapturedBase);
// base address is outside the range managed by the kernel
assert(vma_handle != m_Vma_map.end());
@ -508,7 +504,7 @@ xboxkrnl::NTSTATUS VMManager::XbAllocateVirtualMemory(VAddr* addr, ULONG zero_bi
{
AlignedCapturedSize -= overlapped_size;
}
}
}*/
// Update the memory manager statistics
if (AlignedCapturedSize > m_MaxContiguousAddress - m_PhysicalMemoryInUse)
@ -520,12 +516,8 @@ xboxkrnl::NTSTATUS VMManager::XbAllocateVirtualMemory(VAddr* addr, ULONG zero_bi
RETURN(ret);
}
m_PhysicalMemoryInUse += AlignedCapturedSize;
if (vma_handle->second.type != VMAType::Stack)
{
vma_handle->second.permissions & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY) ?
protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY) ?
m_ImageMemoryInUse += AlignedCapturedSize : m_NonImageMemoryInUse += AlignedCapturedSize;
}
else { m_StackMemoryInUse += AlignedCapturedSize; }
*addr = AlignedCapturedBase;
*size = AlignedCapturedSize;
@ -579,12 +571,9 @@ xboxkrnl::NTSTATUS VMManager::XbFreeVirtualMemory(VAddr* addr, size_t* size, DWO
if (bStub)
{
*addr = AlignedCapturedBase;
*size = AlignedCapturedSize;
// This was an allocation that didn't actually allocate anything, so just update the memory usage
m_PhysicalMemoryInUse -= AlignedCapturedSize;
m_ImageMemoryInUse -= AlignedCapturedSize;
Unlock();
RETURN(ret);
m_ImageMemoryInUse -= AlignedCapturedSize; // this should check the permissions of the region but for XeLoadSection it's always PAGE_EXECUTE_READWRITE
}
else
{
@ -633,12 +622,13 @@ xboxkrnl::NTSTATUS VMManager::XbFreeVirtualMemory(VAddr* addr, size_t* size, DWO
start_it->second.type = end_vma.type; // restore previously saved vma type
MergeAdjacentVMA(std::prev(start_it));
}
}
*addr = AlignedCapturedBase;
*size = AlignedCapturedSize;
Unlock();
RETURN(ret);
}
}
VAddr VMManager::MapMemoryBlock(size_t* size, PAddr low_addr, PAddr high_addr, ULONG Alignment, bool bNonContiguous)
{
@ -927,10 +917,14 @@ VMManager::VMAIter VMManager::MergeAdjacentVMA(VMAIter vma_handle)
VMManager::VMAIter VMManager::ReprotectVMA(VMAIter vma_handle, DWORD new_perms)
{
// PAGE_WRITECOMBINE/PAGE_NOCACHE are not allowed for shared memory, unless SEC_WRITECOMBINE/SEC_NOCACHE flag
// was specified when calling the CreateFileMapping function. Considering that Cxbx doesn't emulate the caches,
// it's probably safe to ignore these flags
VirtualMemoryArea& vma = vma_handle->second;
DWORD dummy;
vma.permissions = new_perms;
if (!VirtualProtect((void*)vma.base, vma.size, new_perms, &dummy))
vma.permissions = new_perms & ~(PAGE_WRITECOMBINE | PAGE_NOCACHE);
if (!VirtualProtect((void*)vma.base, vma.size, vma.permissions, &dummy))
{
CxbxKrnlCleanup("ReprotectVMA: VirtualProtect could not protect the vma! The error code was %d", GetLastError());
}

View File

@ -138,7 +138,7 @@ class VMManager : public PhysicalMemory
// allocates stack memory
VAddr AllocateStack(size_t size);
// deallocate a block of memory
void Deallocate(VAddr addr, size_t size = 0);
void Deallocate(VAddr addr);
// deallocate stack memory
void DeallocateStack(VAddr addr);
// changes the protections of a memory region