diff --git a/core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp b/core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp index 12b4b4d97..4ebb4d4d5 100644 --- a/core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp +++ b/core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp @@ -1,6 +1,7 @@ #include "DirectMemory.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" +#include "prx/libc/include/General.hpp" #include #include #include @@ -19,6 +20,9 @@ constexpr int GuestPrivate = 0x2; constexpr int GuestAnonymous = 0x1000; constexpr int GuestSyncAsync = 0x1; constexpr int GuestSyncInvalidate = 0x2; +constexpr int GuestAdviceCore = 9; +constexpr int GuestAdviceProtect = 10; +constexpr std::uintptr_t GuestUserAddressEnd = 0x800000000000; bool RoundLength(std::size_t length, std::size_t& rounded) { constexpr auto mask = PS5_PAGE_SIZE - 1; @@ -149,4 +153,14 @@ int APS5_VABI msync_nid_postfix(void* address, std::size_t length, int flags) { return 0; } +int APS5_VABI madvise_nid_postfix(void* address, std::size_t length, int advice) { + if (advice == GuestAdviceProtect) NotImplemented_nid_no_patch("madvise MADV_PROTECT"); + const auto start = reinterpret_cast(address); + if (advice < 0 || advice > GuestAdviceCore || start > GuestUserAddressEnd || length > GuestUserAddressEnd - start) { + SetError(GuestInvalid); + return -1; + } + return 0; +} + } diff --git a/core/libs/tests/GuestMemory.cpp b/core/libs/tests/GuestMemory.cpp index 892cefb40..93e95a3e3 100644 --- a/core/libs/tests/GuestMemory.cpp +++ b/core/libs/tests/GuestMemory.cpp @@ -37,6 +37,7 @@ extern "C" { void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept; int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept; int APS5_VABI mprotect_nid_postfix(void*, std::size_t, int) noexcept; +int APS5_VABI madvise_nid_postfix(void*, std::size_t, int); int* APS5_VABI __error_nid_postfix(); int APS5_VABI sceKernelMapNamedFlexibleMemory(void**, std::size_t, int, int, const char*); int APS5_VABI sceKernelMapNamedFlexibleMemoryInternal(void**, std::size_t, int, int, const char*); @@ -1136,6 +1137,19 @@ int main() { GuestAllocations::Mutation mutation; Require(mutation.Find(memory).writable); } + for (int advice = 0; advice <= 9; ++advice) Require(madvise_nid_postfix(memory, page * 3, advice) == 0); + Require(memory[0] == 42 && memory[page * 2] == 73); + Require(madvise_nid_postfix(memory + 1, 0, 4) == 0); + Require(madvise_nid_postfix(memory, page, 11) == -1 && *__error_nid_postfix() == 22); + *__error_nid_postfix() = 0; + Require(madvise_nid_postfix(memory, page, -1) == -1 && *__error_nid_postfix() == 22); + *__error_nid_postfix() = 0; + Require(madvise_nid_postfix(memory, 0, 11) == -1 && *__error_nid_postfix() == 22); + *__error_nid_postfix() = 0; + Require(madvise_nid_postfix(memory, std::numeric_limits::max(), 0) == -1 && *__error_nid_postfix() == 22); + *__error_nid_postfix() = 0; + Require(madvise_nid_postfix(reinterpret_cast(0x800000000000), 1, 0) == -1 && *__error_nid_postfix() == 22); + Require(madvise_nid_postfix(reinterpret_cast(0x7fffffffc000), 0x4000, 4) == 0); Require(munmap_nid_postfix(memory + 1, page) == -1 && *__error_nid_postfix() == 22); Require(munmap_nid_postfix(memory, 0) == -1 && *__error_nid_postfix() == 22); Require(memory[0] == 42); @@ -1145,6 +1159,7 @@ int main() { Require(memory[page * 2] == 73); Require(munmap_nid_postfix(memory + page * 2, page) == 0); Require(munmap_nid_postfix(memory, page) == -1); + Require(madvise_nid_postfix(memory, page, 4) == 0); *__error_nid_postfix() = 0; Require(mprotect_nid_postfix(memory, page, 1) == -1 && *__error_nid_postfix() == 22); *__error_nid_postfix() = 0;