diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index 9fcaa2439..dd0e07302 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -481,6 +481,59 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, size_t len, int flags) return memory->PoolDecommit(pool_addr, len); } +s32 PS4_SYSV_ABI sceKernelMemoryPoolBatch(const OrbisKernelMemoryPoolBatchEntry* entries, s32 count, + s32* num_processed, s32 flags) { + if (entries == nullptr) { + return ORBIS_KERNEL_ERROR_EINVAL; + } + s32 result = ORBIS_OK; + s32 processed = 0; + + for (s32 i = 0; i < count; i++, processed++) { + OrbisKernelMemoryPoolBatchEntry entry = entries[i]; + switch (entry.opcode) { + case OrbisKernelMemoryPoolOpcode::Commit: { + result = sceKernelMemoryPoolCommit(entry.commit_params.addr, entry.commit_params.len, + entry.commit_params.type, entry.commit_params.prot, + entry.flags); + break; + } + case OrbisKernelMemoryPoolOpcode::Decommit: { + result = sceKernelMemoryPoolDecommit(entry.decommit_params.addr, + entry.decommit_params.len, entry.flags); + break; + } + case OrbisKernelMemoryPoolOpcode::Protect: { + result = sceKernelMProtect(entry.protect_params.addr, entry.protect_params.len, + entry.protect_params.prot); + break; + } + case OrbisKernelMemoryPoolOpcode::TypeProtect: { + result = sceKernelMTypeProtect( + entry.type_protect_params.addr, entry.type_protect_params.len, + entry.type_protect_params.type, entry.type_protect_params.prot); + break; + } + case OrbisKernelMemoryPoolOpcode::Move: { + UNREACHABLE_MSG("Unimplemented sceKernelMemoryPoolBatch opcode Move"); + } + default: { + result = ORBIS_KERNEL_ERROR_EINVAL; + break; + } + } + + if (result != ORBIS_OK) { + break; + } + } + + if (num_processed != nullptr) { + *num_processed = processed; + } + return result; +} + int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, size_t offset, void** res) { LOG_INFO(Kernel_Vmm, "called addr = {}, len = {}, prot = {}, flags = {}, fd = {}, offset = {}", @@ -612,6 +665,7 @@ void RegisterMemory(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("pU-QydtGcGY", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolReserve); LIB_FUNCTION("Vzl66WmfLvk", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolCommit); LIB_FUNCTION("LXo1tpFqJGs", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolDecommit); + LIB_FUNCTION("YN878uKRBbE", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolBatch); LIB_FUNCTION("BPE9s9vQQXo", "libkernel", 1, "libkernel", 1, 1, posix_mmap); LIB_FUNCTION("BPE9s9vQQXo", "libScePosix", 1, "libkernel", 1, 1, posix_mmap); diff --git a/src/core/libraries/kernel/memory.h b/src/core/libraries/kernel/memory.h index 2ca7f2931..3e2bf8de5 100644 --- a/src/core/libraries/kernel/memory.h +++ b/src/core/libraries/kernel/memory.h @@ -81,6 +81,48 @@ struct OrbisKernelBatchMapEntry { int operation; }; +enum class OrbisKernelMemoryPoolOpcode : u32 { + Commit = 1, + Decommit = 2, + Protect = 3, + TypeProtect = 4, + Move = 5, +}; + +struct OrbisKernelMemoryPoolBatchEntry { + OrbisKernelMemoryPoolOpcode opcode; + u32 flags; + union { + struct { + void* addr; + u64 len; + u8 prot; + u8 type; + } commit_params; + struct { + void* addr; + u64 len; + } decommit_params; + struct { + void* addr; + u64 len; + u8 prot; + } protect_params; + struct { + void* addr; + u64 len; + u8 prot; + u8 type; + } type_protect_params; + struct { + void* dest_addr; + void* src_addr; + u64 len; + } move_params; + uintptr_t padding[3]; + }; +}; + u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize(); int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, u64 alignment, int memoryType, s64* physAddrOut); @@ -130,6 +172,8 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolReserve(void* addrIn, size_t len, size_t ali void** addrOut); s32 PS4_SYSV_ABI sceKernelMemoryPoolCommit(void* addr, size_t len, int type, int prot, int flags); s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, size_t len, int 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);