mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-27 00:28:14 +00:00
75 lines
2.7 KiB
C++
75 lines
2.7 KiB
C++
#include "prx/libkernel/include/Api.hpp"
|
|
#include "prx/libc/include/Api.hpp"
|
|
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <limits>
|
|
#include <source_location>
|
|
|
|
namespace {
|
|
constexpr std::size_t Page = 0x4000;
|
|
constexpr int ReadWrite = 3;
|
|
constexpr int PrivateAnonymous = 0x1002;
|
|
constexpr int Sync = 0x0;
|
|
constexpr int Async = 0x1;
|
|
constexpr int Invalidate = 0x2;
|
|
constexpr int Invalid = 22;
|
|
constexpr int NoMemory = 12;
|
|
constexpr int Busy = 16;
|
|
|
|
void Require(bool condition, std::source_location location = std::source_location::current()) {
|
|
if (condition) return;
|
|
std::fprintf(stderr, "msync check failed at line %u\n", static_cast<unsigned>(location.line()));
|
|
std::abort();
|
|
}
|
|
|
|
bool Succeeds(void* address, std::size_t length, int flags) {
|
|
*__error_nid_postfix() = 77;
|
|
return msync_nid_postfix(address, length, flags) == 0 && *__error_nid_postfix() == 77;
|
|
}
|
|
|
|
bool Fails(void* address, std::size_t length, int flags, int error) {
|
|
*__error_nid_postfix() = 0;
|
|
return msync_nid_postfix(address, length, flags) == -1 && *__error_nid_postfix() == error;
|
|
}
|
|
|
|
char* Map(std::size_t pages) {
|
|
void* mapped = mmap_nid_postfix(nullptr, pages * Page, ReadWrite, PrivateAnonymous, -1, 0);
|
|
Require(mapped != reinterpret_cast<void*>(static_cast<std::uintptr_t>(-1)));
|
|
return static_cast<char*>(mapped);
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
char* mapped = Map(3);
|
|
mapped[0] = 1;
|
|
Require(Succeeds(mapped, 3 * Page, Sync));
|
|
Require(Succeeds(mapped, 3 * Page, Async));
|
|
Require(Succeeds(mapped + 100, 10, Sync));
|
|
Require(Succeeds(mapped + Page - 1, 2, Sync));
|
|
Require(Succeeds(mapped + Page, 0, Sync));
|
|
Require(Succeeds(mapped, Page, 0x4));
|
|
|
|
Require(Fails(mapped, Page, Async | Invalidate, Invalid));
|
|
const auto top = std::numeric_limits<std::uintptr_t>::max() & ~(Page - 1);
|
|
Require(Fails(reinterpret_cast<void*>(top), 2 * Page, Sync, Invalid));
|
|
Require(Fails(mapped, Page, Invalidate, Busy));
|
|
Require(Fails(mapped, 3 * Page, Sync | Invalidate, Busy));
|
|
Require(Fails(mapped + 1, 16, Invalidate, Busy));
|
|
Require(Fails(mapped, 0, Invalidate, Busy));
|
|
Require(Succeeds(mapped, Page, 0x8));
|
|
|
|
Require(munmap_nid_postfix(mapped, 3 * Page) == 0);
|
|
Require(Fails(mapped, Page, Sync, NoMemory));
|
|
Require(Fails(mapped + Page, 3 * Page, Async, NoMemory));
|
|
Require(Fails(mapped + Page, 0, Sync, NoMemory));
|
|
Require(Fails(mapped, Page, Invalidate, NoMemory));
|
|
|
|
void* reserved = nullptr;
|
|
Require(sceKernelReserveVirtualRange(&reserved, 2 * Page, 0, 0) == 0);
|
|
Require(Succeeds(reserved, 2 * Page, Sync));
|
|
Require(Succeeds(reserved, 0, Async));
|
|
return 0;
|
|
}
|