diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index ea3998ddd..114a096ca 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -23,8 +23,8 @@ u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() { return memory->GetTotalDirectSize(); } -int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, - u64 alignment, int memoryType, s64* physAddrOut) { +s32 PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, + u64 alignment, s32 memoryType, s64* physAddrOut) { if (searchStart < 0 || searchEnd < 0) { LOG_ERROR(Kernel_Vmm, "Invalid parameters!"); return ORBIS_KERNEL_ERROR_EINVAL; @@ -71,13 +71,13 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u return ORBIS_OK; } -s32 PS4_SYSV_ABI sceKernelAllocateMainDirectMemory(size_t len, size_t alignment, int memoryType, +s32 PS4_SYSV_ABI sceKernelAllocateMainDirectMemory(u64 len, u64 alignment, s32 memoryType, s64* physAddrOut) { const auto searchEnd = static_cast(sceKernelGetDirectMemorySize()); return sceKernelAllocateDirectMemory(0, searchEnd, len, alignment, memoryType, physAddrOut); } -s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, size_t len) { +s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, u64 len) { if (len == 0) { return ORBIS_OK; } @@ -87,7 +87,7 @@ s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, size_t len) { return ORBIS_OK; } -s32 PS4_SYSV_ABI sceKernelReleaseDirectMemory(u64 start, size_t len) { +s32 PS4_SYSV_ABI sceKernelReleaseDirectMemory(u64 start, u64 len) { if (len == 0) { return ORBIS_OK; } @@ -96,9 +96,8 @@ s32 PS4_SYSV_ABI sceKernelReleaseDirectMemory(u64 start, size_t len) { return ORBIS_OK; } -s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchEnd, - size_t alignment, u64* physAddrOut, - size_t* sizeOut) { +s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchEnd, u64 alignment, + u64* physAddrOut, u64* sizeOut) { LOG_INFO(Kernel_Vmm, "called searchStart = {:#x}, searchEnd = {:#x}, alignment = {:#x}", searchStart, searchEnd, alignment); @@ -109,7 +108,7 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE auto* memory = Core::Memory::Instance(); PAddr physAddr{}; - size_t size{}; + u64 size{}; s32 result = memory->DirectQueryAvailable(searchStart, searchEnd, alignment, &physAddr, &size); if (size == 0) { @@ -122,14 +121,14 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE return result; } -s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void* addr, int flags, OrbisVirtualQueryInfo* info, - size_t infoSize) { +s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void* addr, s32 flags, OrbisVirtualQueryInfo* info, + u64 infoSize) { LOG_INFO(Kernel_Vmm, "called addr = {}, flags = {:#x}", fmt::ptr(addr), flags); auto* memory = Core::Memory::Instance(); return memory->VirtualQuery(std::bit_cast(addr), flags, info); } -s32 PS4_SYSV_ABI sceKernelReserveVirtualRange(void** addr, u64 len, int flags, u64 alignment) { +s32 PS4_SYSV_ABI sceKernelReserveVirtualRange(void** addr, u64 len, s32 flags, u64 alignment) { LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}, flags = {:#x}, alignment = {:#x}", fmt::ptr(*addr), len, flags, alignment); if (addr == nullptr) { @@ -159,7 +158,7 @@ s32 PS4_SYSV_ABI sceKernelReserveVirtualRange(void** addr, u64 len, int flags, u return result; } -int PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, int prot, int flags, +s32 PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, s32 prot, s32 flags, s64 directMemoryStart, u64 alignment, const char* name) { LOG_INFO(Kernel_Vmm, @@ -202,7 +201,7 @@ int PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, int prot, i return ret; } -int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags, +s32 PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, s32 prot, s32 flags, s64 directMemoryStart, u64 alignment) { LOG_INFO(Kernel_Vmm, "called, redirected to sceKernelMapNamedDirectMemory"); return sceKernelMapNamedDirectMemory(addr, len, prot, flags, directMemoryStart, alignment, @@ -255,7 +254,7 @@ s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, u64 len, s32 pro return sceKernelMapNamedFlexibleMemory(addr_in_out, len, prot, flags, "anon"); } -int PS4_SYSV_ABI sceKernelQueryMemoryProtection(void* addr, void** start, void** end, u32* prot) { +s32 PS4_SYSV_ABI sceKernelQueryMemoryProtection(void* addr, void** start, void** end, u32* prot) { auto* memory = Core::Memory::Instance(); return memory->QueryProtection(std::bit_cast(addr), start, end, prot); } @@ -285,14 +284,14 @@ s32 PS4_SYSV_ABI sceKernelMtypeprotect(const void* addr, u64 size, s32 mtype, s3 return memory_manager->Protect(std::bit_cast(addr), size, protection_flags); } -int PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, int flags, OrbisQueryInfo* query_info, - size_t infoSize) { +s32 PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, s32 flags, OrbisQueryInfo* query_info, + u64 infoSize) { LOG_INFO(Kernel_Vmm, "called offset = {:#x}, flags = {:#x}", offset, flags); auto* memory = Core::Memory::Instance(); return memory->DirectMemoryQuery(offset, flags == 1, query_info); } -s32 PS4_SYSV_ABI sceKernelAvailableFlexibleMemorySize(size_t* out_size) { +s32 PS4_SYSV_ABI sceKernelAvailableFlexibleMemorySize(u64* out_size) { auto* memory = Core::Memory::Instance(); *out_size = memory->GetAvailableFlexibleSize(); LOG_INFO(Kernel_Vmm, "called size = {:#x}", *out_size); @@ -304,7 +303,7 @@ void PS4_SYSV_ABI _sceKernelRtldSetApplicationHeapAPI(void* func[]) { linker->SetHeapAPI(func); } -int PS4_SYSV_ABI sceKernelGetDirectMemoryType(u64 addr, int* directMemoryTypeOut, +s32 PS4_SYSV_ABI sceKernelGetDirectMemoryType(u64 addr, s32* directMemoryTypeOut, void** directMemoryStartOut, void** directMemoryEndOut) { LOG_WARNING(Kernel_Vmm, "called, direct memory addr = {:#x}", addr); @@ -313,23 +312,23 @@ int PS4_SYSV_ABI sceKernelGetDirectMemoryType(u64 addr, int* directMemoryTypeOut directMemoryEndOut); } -int PS4_SYSV_ABI sceKernelIsStack(void* addr, void** start, void** end) { +s32 PS4_SYSV_ABI sceKernelIsStack(void* addr, void** start, void** end) { LOG_DEBUG(Kernel_Vmm, "called, addr = {}", fmt::ptr(addr)); auto* memory = Core::Memory::Instance(); return memory->IsStack(std::bit_cast(addr), start, end); } -s32 PS4_SYSV_ABI sceKernelBatchMap(OrbisKernelBatchMapEntry* entries, int numEntries, - int* numEntriesOut) { +s32 PS4_SYSV_ABI sceKernelBatchMap(OrbisKernelBatchMapEntry* entries, s32 numEntries, + s32* numEntriesOut) { return sceKernelBatchMap2(entries, numEntries, numEntriesOut, MemoryFlags::SCE_KERNEL_MAP_FIXED); // 0x10, 0x410? } -s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEntries, - int* numEntriesOut, int flags) { - int result = ORBIS_OK; - int processed = 0; - for (int i = 0; i < numEntries; i++, processed++) { +s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, s32 numEntries, + s32* numEntriesOut, s32 flags) { + s32 result = ORBIS_OK; + s32 processed = 0; + for (s32 i = 0; i < numEntries; i++, processed++) { if (entries == nullptr || entries[i].length == 0 || entries[i].operation > 4) { result = ORBIS_KERNEL_ERROR_EINVAL; break; // break and assign a value to numEntriesOut. @@ -619,7 +618,7 @@ s32 PS4_SYSV_ABI sceKernelConfiguredFlexibleMemorySize(u64* sizeOut) { return ORBIS_OK; } -int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len) { +s32 PS4_SYSV_ABI sceKernelMunmap(void* addr, u64 len) { LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}", fmt::ptr(addr), len); if (len == 0) { return ORBIS_KERNEL_ERROR_EINVAL; @@ -628,8 +627,8 @@ int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len) { return memory->UnmapMemory(std::bit_cast(addr), len); } -int PS4_SYSV_ABI posix_munmap(void* addr, size_t len) { - int result = sceKernelMunmap(addr, len); +s32 PS4_SYSV_ABI posix_munmap(void* addr, u64 len) { + s32 result = sceKernelMunmap(addr, len); if (result < 0) { LOG_ERROR(Kernel_Pthread, "posix_munmap: error = {}", result); ErrSceToPosix(result); @@ -638,12 +637,12 @@ int PS4_SYSV_ABI posix_munmap(void* addr, size_t len) { return result; } -static constexpr int MAX_PRT_APERTURES = 3; +static constexpr s32 MAX_PRT_APERTURES = 3; static constexpr VAddr PRT_AREA_START_ADDR = 0x1000000000; -static constexpr size_t PRT_AREA_SIZE = 0xec00000000; -static std::array, MAX_PRT_APERTURES> PrtApertures{}; +static constexpr u64 PRT_AREA_SIZE = 0xec00000000; +static std::array, MAX_PRT_APERTURES> PrtApertures{}; -int PS4_SYSV_ABI sceKernelSetPrtAperture(int id, VAddr address, size_t size) { +s32 PS4_SYSV_ABI sceKernelSetPrtAperture(s32 id, VAddr address, u64 size) { if (id < 0 || id >= MAX_PRT_APERTURES) { return ORBIS_KERNEL_ERROR_EINVAL; } @@ -667,7 +666,7 @@ int PS4_SYSV_ABI sceKernelSetPrtAperture(int id, VAddr address, size_t size) { return ORBIS_OK; } -int PS4_SYSV_ABI sceKernelGetPrtAperture(int id, VAddr* address, size_t* size) { +s32 PS4_SYSV_ABI sceKernelGetPrtAperture(s32 id, VAddr* address, u64* size) { if (id < 0 || id >= MAX_PRT_APERTURES) { return ORBIS_KERNEL_ERROR_EINVAL; } diff --git a/src/core/libraries/kernel/memory.h b/src/core/libraries/kernel/memory.h index ea42e7546..ce4ec64fe 100644 --- a/src/core/libraries/kernel/memory.h +++ b/src/core/libraries/kernel/memory.h @@ -52,13 +52,13 @@ constexpr u32 ORBIS_KERNEL_MAXIMUM_NAME_LENGTH = 32; struct OrbisQueryInfo { uintptr_t start; uintptr_t end; - int memoryType; + s32 memoryType; }; struct OrbisVirtualQueryInfo { uintptr_t start; uintptr_t end; - size_t offset; + u64 offset; s32 protection; s32 memory_type; u8 is_flexible : 1; @@ -73,12 +73,12 @@ static_assert(sizeof(OrbisVirtualQueryInfo) == 72, struct OrbisKernelBatchMapEntry { void* start; - size_t offset; - size_t length; + u64 offset; + u64 length; char protection; char type; - short reserved; - int operation; + s16 reserved; + s32 operation; }; enum class OrbisKernelMemoryPoolOpcode : u32 { @@ -124,45 +124,44 @@ struct OrbisKernelMemoryPoolBatchEntry { }; u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize(); -int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, - u64 alignment, int memoryType, s64* physAddrOut); -int PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, int prot, int flags, +s32 PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, + u64 alignment, s32 memoryType, s64* physAddrOut); +s32 PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, s32 prot, s32 flags, s64 directMemoryStart, u64 alignment, const char* name); -int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags, +s32 PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, s32 prot, s32 flags, s64 directMemoryStart, u64 alignment); -s32 PS4_SYSV_ABI sceKernelAllocateMainDirectMemory(size_t len, size_t alignment, int memoryType, +s32 PS4_SYSV_ABI sceKernelAllocateMainDirectMemory(u64 len, u64 alignment, s32 memoryType, s64* physAddrOut); -s32 PS4_SYSV_ABI sceKernelReleaseDirectMemory(u64 start, size_t len); -s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, size_t len); -s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchEnd, - size_t alignment, u64* physAddrOut, - size_t* sizeOut); -s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void* addr, int flags, OrbisVirtualQueryInfo* info, - size_t infoSize); -s32 PS4_SYSV_ABI sceKernelReserveVirtualRange(void** addr, u64 len, int flags, u64 alignment); +s32 PS4_SYSV_ABI sceKernelReleaseDirectMemory(u64 start, u64 len); +s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, u64 len); +s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchEnd, u64 alignment, + u64* physAddrOut, u64* sizeOut); +s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void* addr, s32 flags, OrbisVirtualQueryInfo* info, + u64 infoSize); +s32 PS4_SYSV_ABI sceKernelReserveVirtualRange(void** addr, u64 len, s32 flags, u64 alignment); s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, u64 len, s32 prot, s32 flags, const char* name); s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, u64 len, s32 prot, s32 flags); -int PS4_SYSV_ABI sceKernelQueryMemoryProtection(void* addr, void** start, void** end, u32* prot); +s32 PS4_SYSV_ABI sceKernelQueryMemoryProtection(void* addr, void** start, void** end, u32* prot); s32 PS4_SYSV_ABI sceKernelMprotect(const void* addr, u64 size, s32 prot); s32 PS4_SYSV_ABI sceKernelMtypeprotect(const void* addr, u64 size, s32 mtype, s32 prot); -int PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, int flags, OrbisQueryInfo* query_info, - size_t infoSize); -s32 PS4_SYSV_ABI sceKernelAvailableFlexibleMemorySize(size_t* sizeOut); +s32 PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, s32 flags, OrbisQueryInfo* query_info, + u64 infoSize); +s32 PS4_SYSV_ABI sceKernelAvailableFlexibleMemorySize(u64* sizeOut); void PS4_SYSV_ABI _sceKernelRtldSetApplicationHeapAPI(void* func[]); -int PS4_SYSV_ABI sceKernelGetDirectMemoryType(u64 addr, int* directMemoryTypeOut, +s32 PS4_SYSV_ABI sceKernelGetDirectMemoryType(u64 addr, s32* directMemoryTypeOut, void** directMemoryStartOut, void** directMemoryEndOut); -int PS4_SYSV_ABI sceKernelIsStack(void* addr, void** start, void** end); +s32 PS4_SYSV_ABI sceKernelIsStack(void* addr, void** start, void** end); -s32 PS4_SYSV_ABI sceKernelBatchMap(OrbisKernelBatchMapEntry* entries, int numEntries, - int* numEntriesOut); -s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEntries, - int* numEntriesOut, int flags); +s32 PS4_SYSV_ABI sceKernelBatchMap(OrbisKernelBatchMapEntry* entries, s32 numEntries, + s32* numEntriesOut); +s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, s32 numEntries, + s32* numEntriesOut, s32 flags); s32 PS4_SYSV_ABI sceKernelSetVirtualRangeName(const void* addr, u64 len, const char* name); @@ -175,7 +174,7 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, u64 len, s32 flags); s32 PS4_SYSV_ABI sceKernelMemoryPoolBatch(const OrbisKernelMemoryPoolBatchEntry* entries, s32 count, s32* num_processed, s32 flags); -int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len); +s32 PS4_SYSV_ABI sceKernelMunmap(void* addr, u64 len); void RegisterMemory(Core::Loader::SymbolsResolver* sym); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index dad42347a..f70751f3a 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -17,11 +17,11 @@ namespace Core { MemoryManager::MemoryManager() { // Insert a virtual memory area that covers the entire area we manage. const VAddr system_managed_base = impl.SystemManagedVirtualBase(); - const size_t system_managed_size = impl.SystemManagedVirtualSize(); + const u64 system_managed_size = impl.SystemManagedVirtualSize(); const VAddr system_reserved_base = impl.SystemReservedVirtualBase(); - const size_t system_reserved_size = impl.SystemReservedVirtualSize(); + const u64 system_reserved_size = impl.SystemReservedVirtualSize(); const VAddr user_base = impl.UserVirtualBase(); - const size_t user_size = impl.UserVirtualSize(); + const u64 user_size = impl.UserVirtualSize(); vma_map.emplace(system_managed_base, VirtualMemoryArea{system_managed_base, system_managed_size}); vma_map.emplace(system_reserved_base, @@ -148,7 +148,7 @@ bool MemoryManager::TryWriteBacking(void* address, const void* data, u32 num_byt return true; } -PAddr MemoryManager::PoolExpand(PAddr search_start, PAddr search_end, size_t size, u64 alignment) { +PAddr MemoryManager::PoolExpand(PAddr search_start, PAddr search_end, u64 size, u64 alignment) { std::scoped_lock lk{mutex}; alignment = alignment > 0 ? alignment : 64_KB; @@ -188,8 +188,8 @@ PAddr MemoryManager::PoolExpand(PAddr search_start, PAddr search_end, size_t siz return mapping_start; } -PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, u64 alignment, - int memory_type) { +PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, u64 size, u64 alignment, + s32 memory_type) { std::scoped_lock lk{mutex}; alignment = alignment > 0 ? alignment : 16_KB; @@ -226,7 +226,7 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, return mapping_start; } -void MemoryManager::Free(PAddr phys_addr, size_t size) { +void MemoryManager::Free(PAddr phys_addr, u64 size) { std::scoped_lock lk{mutex}; auto dmem_area = CarveDmemArea(phys_addr, size); @@ -256,7 +256,7 @@ void MemoryManager::Free(PAddr phys_addr, size_t size) { MergeAdjacent(dmem_map, dmem_area); } -int MemoryManager::PoolCommit(VAddr virtual_addr, size_t size, MemoryProt prot) { +s32 MemoryManager::PoolCommit(VAddr virtual_addr, u64 size, MemoryProt prot) { std::scoped_lock lk{mutex}; const u64 alignment = 64_KB; @@ -320,6 +320,28 @@ s32 MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, u64 size, Memo return ORBIS_KERNEL_ERROR_ENOMEM; } + // Validate the requested physical address range + if (phys_addr != -1) { + u64 validated_size = 0; + do { + auto dmem_area = FindDmemArea(phys_addr + validated_size)->second; + // If any requested dmem area is not allocated, return an error. + if (dmem_area.is_free) { + LOG_ERROR(Kernel_Vmm, "Unable to map {:#x} bytes at physical address {:#x}", size, + phys_addr); + return ORBIS_KERNEL_ERROR_ENOMEM; + } + // Track how much we've validated. + validated_size += dmem_area.size - (phys_addr + validated_size - dmem_area.base); + } while (validated_size < size && phys_addr + validated_size < GetTotalDirectSize()); + // If the requested range goes outside the dmem map, return an error. + if (validated_size < size) { + LOG_ERROR(Kernel_Vmm, "Unable to map {:#x} bytes at physical address {:#x}", size, + phys_addr); + return ORBIS_KERNEL_ERROR_ENOMEM; + } + } + // Limit the minumum address to SystemManagedVirtualBase to prevent hardware-specific issues. VAddr mapped_addr = (virtual_addr == 0) ? impl.SystemManagedVirtualBase() : virtual_addr; @@ -403,7 +425,7 @@ s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, Memory auto* h = Common::Singleton::Instance(); VAddr mapped_addr = (virtual_addr == 0) ? impl.SystemManagedVirtualBase() : virtual_addr; - const size_t size_aligned = Common::AlignUp(size, 16_KB); + const u64 size_aligned = Common::AlignUp(size, 16_KB); // Find first free area to map the file. if (False(flags & MemoryMapFlags::Fixed)) { @@ -416,7 +438,7 @@ s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, Memory if (True(flags & MemoryMapFlags::Fixed)) { const auto& vma = FindVMA(virtual_addr)->second; - const size_t remaining_size = vma.base + vma.size - virtual_addr; + const u64 remaining_size = vma.base + vma.size - virtual_addr; ASSERT_MSG(!vma.IsMapped() && remaining_size >= size, "Memory region {:#x} to {:#x} isn't free enough to map region {:#x} to {:#x}", vma.base, vma.base + vma.size, virtual_addr, virtual_addr + size); @@ -448,7 +470,7 @@ s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, Memory return ORBIS_OK; } -s32 MemoryManager::PoolDecommit(VAddr virtual_addr, size_t size) { +s32 MemoryManager::PoolDecommit(VAddr virtual_addr, u64 size) { std::scoped_lock lk{mutex}; const auto it = FindVMA(virtual_addr); @@ -498,7 +520,7 @@ s32 MemoryManager::PoolDecommit(VAddr virtual_addr, size_t size) { return ORBIS_OK; } -s32 MemoryManager::UnmapMemory(VAddr virtual_addr, size_t size) { +s32 MemoryManager::UnmapMemory(VAddr virtual_addr, u64 size) { std::scoped_lock lk{mutex}; return UnmapMemoryImpl(virtual_addr, size); } @@ -564,7 +586,7 @@ s32 MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, u64 size) { return ORBIS_OK; } -int MemoryManager::QueryProtection(VAddr addr, void** start, void** end, u32* prot) { +s32 MemoryManager::QueryProtection(VAddr addr, void** start, void** end, u32* prot) { std::scoped_lock lk{mutex}; const auto it = FindVMA(addr); @@ -586,8 +608,7 @@ int MemoryManager::QueryProtection(VAddr addr, void** start, void** end, u32* pr return ORBIS_OK; } -s64 MemoryManager::ProtectBytes(VAddr addr, VirtualMemoryArea vma_base, size_t size, - MemoryProt prot) { +s64 MemoryManager::ProtectBytes(VAddr addr, VirtualMemoryArea vma_base, u64 size, MemoryProt prot) { const auto start_in_vma = addr - vma_base.base; const auto adjusted_size = vma_base.size - start_in_vma < size ? vma_base.size - start_in_vma : size; @@ -624,7 +645,7 @@ s64 MemoryManager::ProtectBytes(VAddr addr, VirtualMemoryArea vma_base, size_t s return adjusted_size; } -s32 MemoryManager::Protect(VAddr addr, size_t size, MemoryProt prot) { +s32 MemoryManager::Protect(VAddr addr, u64 size, MemoryProt prot) { std::scoped_lock lk{mutex}; // Validate protection flags @@ -649,9 +670,8 @@ s32 MemoryManager::Protect(VAddr addr, size_t size, MemoryProt prot) { auto& vma_base = it->second; ASSERT_MSG(vma_base.Contains(addr + protected_bytes, 0), "Address {:#x} is out of bounds", addr + protected_bytes); - auto result = 0; - result = ProtectBytes(aligned_addr + protected_bytes, vma_base, - aligned_size - protected_bytes, prot); + auto result = ProtectBytes(aligned_addr + protected_bytes, vma_base, + aligned_size - protected_bytes, prot); if (result < 0) { // ProtectBytes returned an error, return it return result; @@ -662,7 +682,7 @@ s32 MemoryManager::Protect(VAddr addr, size_t size, MemoryProt prot) { return ORBIS_OK; } -int MemoryManager::VirtualQuery(VAddr addr, int flags, +s32 MemoryManager::VirtualQuery(VAddr addr, s32 flags, ::Libraries::Kernel::OrbisVirtualQueryInfo* info) { std::scoped_lock lk{mutex}; @@ -707,7 +727,7 @@ int MemoryManager::VirtualQuery(VAddr addr, int flags, return ORBIS_OK; } -int MemoryManager::DirectMemoryQuery(PAddr addr, bool find_next, +s32 MemoryManager::DirectMemoryQuery(PAddr addr, bool find_next, ::Libraries::Kernel::OrbisQueryInfo* out_info) { std::scoped_lock lk{mutex}; @@ -728,13 +748,13 @@ int MemoryManager::DirectMemoryQuery(PAddr addr, bool find_next, return ORBIS_OK; } -int MemoryManager::DirectQueryAvailable(PAddr search_start, PAddr search_end, size_t alignment, - PAddr* phys_addr_out, size_t* size_out) { +s32 MemoryManager::DirectQueryAvailable(PAddr search_start, PAddr search_end, u64 alignment, + PAddr* phys_addr_out, u64* size_out) { std::scoped_lock lk{mutex}; auto dmem_area = FindDmemArea(search_start); PAddr paddr{}; - size_t max_size{}; + u64 max_size{}; while (dmem_area != dmem_map.end()) { if (!dmem_area->second.is_free) { @@ -815,13 +835,60 @@ void MemoryManager::NameVirtualRange(VAddr virtual_addr, u64 size, std::string_v } } +s32 MemoryManager::GetDirectMemoryType(PAddr addr, s32* directMemoryTypeOut, + void** directMemoryStartOut, void** directMemoryEndOut) { + std::scoped_lock lk{mutex}; + + auto dmem_area = FindDmemArea(addr); + + if (addr > dmem_area->second.GetEnd() || dmem_area->second.is_free) { + LOG_ERROR(Core, "Unable to find allocated direct memory region to check type!"); + return ORBIS_KERNEL_ERROR_ENOENT; + } + + const auto& area = dmem_area->second; + *directMemoryStartOut = reinterpret_cast(area.base); + *directMemoryEndOut = reinterpret_cast(area.GetEnd()); + *directMemoryTypeOut = area.memory_type; + return ORBIS_OK; +} + +s32 MemoryManager::IsStack(VAddr addr, void** start, void** end) { + auto vma_handle = FindVMA(addr); + if (vma_handle == vma_map.end()) { + return ORBIS_KERNEL_ERROR_EINVAL; + } + + const VirtualMemoryArea& vma = vma_handle->second; + if (!vma.Contains(addr, 0) || vma.IsFree()) { + return ORBIS_KERNEL_ERROR_EACCES; + } + + u64 stack_start = 0; + u64 stack_end = 0; + if (vma.type == VMAType::Stack) { + stack_start = vma.base; + stack_end = vma.base + vma.size; + } + + if (start != nullptr) { + *start = reinterpret_cast(stack_start); + } + + if (end != nullptr) { + *end = reinterpret_cast(stack_end); + } + + return ORBIS_OK; +} + void MemoryManager::InvalidateMemory(const VAddr addr, const u64 size) const { if (rasterizer) { rasterizer->InvalidateMemory(addr, size); } } -VAddr MemoryManager::SearchFree(VAddr virtual_addr, size_t size, u32 alignment) { +VAddr MemoryManager::SearchFree(VAddr virtual_addr, u64 size, u32 alignment) { // If the requested address is below the mapped range, start search from the lowest address auto min_search_address = impl.SystemManagedVirtualBase(); if (virtual_addr < min_search_address) { @@ -864,7 +931,7 @@ VAddr MemoryManager::SearchFree(VAddr virtual_addr, size_t size, u32 alignment) } // If there's enough space in the VMA, return the address. - const size_t remaining_size = vma.base + vma.size - virtual_addr; + const u64 remaining_size = vma.base + vma.size - virtual_addr; if (remaining_size >= size) { return virtual_addr; } @@ -877,7 +944,7 @@ VAddr MemoryManager::SearchFree(VAddr virtual_addr, size_t size, u32 alignment) return -1; } -MemoryManager::VMAHandle MemoryManager::CarveVMA(VAddr virtual_addr, size_t size) { +MemoryManager::VMAHandle MemoryManager::CarveVMA(VAddr virtual_addr, u64 size) { auto vma_handle = FindVMA(virtual_addr); ASSERT_MSG(vma_handle->second.Contains(virtual_addr, 0), "Virtual address not in vm_map"); @@ -906,7 +973,7 @@ MemoryManager::VMAHandle MemoryManager::CarveVMA(VAddr virtual_addr, size_t size return vma_handle; } -MemoryManager::DMemHandle MemoryManager::CarveDmemArea(PAddr addr, size_t size) { +MemoryManager::DMemHandle MemoryManager::CarveDmemArea(PAddr addr, u64 size) { auto dmem_handle = FindDmemArea(addr); ASSERT_MSG(addr <= dmem_handle->second.GetEnd(), "Physical address not in dmem_map"); @@ -930,7 +997,7 @@ MemoryManager::DMemHandle MemoryManager::CarveDmemArea(PAddr addr, size_t size) return dmem_handle; } -MemoryManager::VMAHandle MemoryManager::Split(VMAHandle vma_handle, size_t offset_in_vma) { +MemoryManager::VMAHandle MemoryManager::Split(VMAHandle vma_handle, u64 offset_in_vma) { auto& old_vma = vma_handle->second; ASSERT(offset_in_vma < old_vma.size && offset_in_vma > 0); @@ -945,7 +1012,7 @@ MemoryManager::VMAHandle MemoryManager::Split(VMAHandle vma_handle, size_t offse return vma_map.emplace_hint(std::next(vma_handle), new_vma.base, new_vma); } -MemoryManager::DMemHandle MemoryManager::Split(DMemHandle dmem_handle, size_t offset_in_area) { +MemoryManager::DMemHandle MemoryManager::Split(DMemHandle dmem_handle, u64 offset_in_area) { auto& old_area = dmem_handle->second; ASSERT(offset_in_area < old_area.size && offset_in_area > 0); @@ -957,51 +1024,4 @@ MemoryManager::DMemHandle MemoryManager::Split(DMemHandle dmem_handle, size_t of return dmem_map.emplace_hint(std::next(dmem_handle), new_area.base, new_area); } -int MemoryManager::GetDirectMemoryType(PAddr addr, int* directMemoryTypeOut, - void** directMemoryStartOut, void** directMemoryEndOut) { - std::scoped_lock lk{mutex}; - - auto dmem_area = FindDmemArea(addr); - - if (addr > dmem_area->second.GetEnd() || dmem_area->second.is_free) { - LOG_ERROR(Core, "Unable to find allocated direct memory region to check type!"); - return ORBIS_KERNEL_ERROR_ENOENT; - } - - const auto& area = dmem_area->second; - *directMemoryStartOut = reinterpret_cast(area.base); - *directMemoryEndOut = reinterpret_cast(area.GetEnd()); - *directMemoryTypeOut = area.memory_type; - return ORBIS_OK; -} - -int MemoryManager::IsStack(VAddr addr, void** start, void** end) { - auto vma_handle = FindVMA(addr); - if (vma_handle == vma_map.end()) { - return ORBIS_KERNEL_ERROR_EINVAL; - } - - const VirtualMemoryArea& vma = vma_handle->second; - if (!vma.Contains(addr, 0) || vma.IsFree()) { - return ORBIS_KERNEL_ERROR_EACCES; - } - - auto stack_start = 0ul; - auto stack_end = 0ul; - if (vma.type == VMAType::Stack) { - stack_start = vma.base; - stack_end = vma.base + vma.size; - } - - if (start != nullptr) { - *start = reinterpret_cast(stack_start); - } - - if (end != nullptr) { - *end = reinterpret_cast(stack_end); - } - - return ORBIS_OK; -} - } // namespace Core diff --git a/src/core/memory.h b/src/core/memory.h index d0a2a09b4..c800ef763 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -63,8 +63,8 @@ enum class VMAType : u32 { struct DirectMemoryArea { PAddr base = 0; - size_t size = 0; - int memory_type = 0; + u64 size = 0; + s32 memory_type = 0; bool is_pooled = false; bool is_free = true; @@ -88,7 +88,7 @@ struct DirectMemoryArea { struct VirtualMemoryArea { VAddr base = 0; - size_t size = 0; + u64 size = 0; PAddr phys_base = 0; VMAType type = VMAType::Free; MemoryProt prot = MemoryProt::NoAccess; @@ -97,7 +97,7 @@ struct VirtualMemoryArea { uintptr_t fd = 0; bool is_exec = false; - bool Contains(VAddr addr, size_t size) const { + bool Contains(VAddr addr, u64 size) const { return addr >= base && (addr + size) <= (base + this->size); } @@ -184,14 +184,13 @@ public: void SetupMemoryRegions(u64 flexible_size, bool use_extended_mem1, bool use_extended_mem2); - PAddr PoolExpand(PAddr search_start, PAddr search_end, size_t size, u64 alignment); + PAddr PoolExpand(PAddr search_start, PAddr search_end, u64 size, u64 alignment); - PAddr Allocate(PAddr search_start, PAddr search_end, size_t size, u64 alignment, - int memory_type); + PAddr Allocate(PAddr search_start, PAddr search_end, u64 size, u64 alignment, s32 memory_type); - void Free(PAddr phys_addr, size_t size); + void Free(PAddr phys_addr, u64 size); - int PoolCommit(VAddr virtual_addr, size_t size, MemoryProt prot); + s32 PoolCommit(VAddr virtual_addr, u64 size, MemoryProt prot); s32 MapMemory(void** out_addr, VAddr virtual_addr, u64 size, MemoryProt prot, MemoryMapFlags flags, VMAType type, std::string_view name = "anon", @@ -200,35 +199,35 @@ public: s32 MapFile(void** out_addr, VAddr virtual_addr, u64 size, MemoryProt prot, MemoryMapFlags flags, s32 fd, s64 phys_addr); - s32 PoolDecommit(VAddr virtual_addr, size_t size); + s32 PoolDecommit(VAddr virtual_addr, u64 size); - s32 UnmapMemory(VAddr virtual_addr, size_t size); + s32 UnmapMemory(VAddr virtual_addr, u64 size); - int QueryProtection(VAddr addr, void** start, void** end, u32* prot); + s32 QueryProtection(VAddr addr, void** start, void** end, u32* prot); - s32 Protect(VAddr addr, size_t size, MemoryProt prot); + s32 Protect(VAddr addr, u64 size, MemoryProt prot); - s64 ProtectBytes(VAddr addr, VirtualMemoryArea vma_base, size_t size, MemoryProt prot); + s64 ProtectBytes(VAddr addr, VirtualMemoryArea vma_base, u64 size, MemoryProt prot); - int VirtualQuery(VAddr addr, int flags, ::Libraries::Kernel::OrbisVirtualQueryInfo* info); + s32 VirtualQuery(VAddr addr, s32 flags, ::Libraries::Kernel::OrbisVirtualQueryInfo* info); - int DirectMemoryQuery(PAddr addr, bool find_next, + s32 DirectMemoryQuery(PAddr addr, bool find_next, ::Libraries::Kernel::OrbisQueryInfo* out_info); - int DirectQueryAvailable(PAddr search_start, PAddr search_end, size_t alignment, - PAddr* phys_addr_out, size_t* size_out); + s32 DirectQueryAvailable(PAddr search_start, PAddr search_end, u64 alignment, + PAddr* phys_addr_out, u64* size_out); - int GetDirectMemoryType(PAddr addr, int* directMemoryTypeOut, void** directMemoryStartOut, + s32 GetDirectMemoryType(PAddr addr, s32* directMemoryTypeOut, void** directMemoryStartOut, void** directMemoryEndOut); + s32 IsStack(VAddr addr, void** start, void** end); + s32 SetDirectMemoryType(s64 phys_addr, s32 memory_type); void NameVirtualRange(VAddr virtual_addr, u64 size, std::string_view name); void InvalidateMemory(VAddr addr, u64 size) const; - int IsStack(VAddr addr, void** start, void** end); - private: VMAHandle FindVMA(VAddr target) { return std::prev(vma_map.upper_bound(target)); @@ -258,15 +257,15 @@ private: return iter; } - VAddr SearchFree(VAddr virtual_addr, size_t size, u32 alignment = 0); + VAddr SearchFree(VAddr virtual_addr, u64 size, u32 alignment = 0); - VMAHandle CarveVMA(VAddr virtual_addr, size_t size); + VMAHandle CarveVMA(VAddr virtual_addr, u64 size); - DMemHandle CarveDmemArea(PAddr addr, size_t size); + DMemHandle CarveDmemArea(PAddr addr, u64 size); - VMAHandle Split(VMAHandle vma_handle, size_t offset_in_vma); + VMAHandle Split(VMAHandle vma_handle, u64 offset_in_vma); - DMemHandle Split(DMemHandle dmem_handle, size_t offset_in_area); + DMemHandle Split(DMemHandle dmem_handle, u64 offset_in_area); u64 UnmapBytesFromEntry(VAddr virtual_addr, VirtualMemoryArea vma_base, u64 size); @@ -277,10 +276,10 @@ private: DMemMap dmem_map; VMAMap vma_map; std::mutex mutex; - size_t total_direct_size{}; - size_t total_flexible_size{}; - size_t flexible_usage{}; - size_t pool_budget{}; + u64 total_direct_size{}; + u64 total_flexible_size{}; + u64 flexible_usage{}; + u64 pool_budget{}; Vulkan::Rasterizer* rasterizer{}; struct PrtArea {