mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-23 09:03:22 -05:00
A shared mapping is a view of a file section created on the descriptor's handle, read-write when the descriptor is, otherwise read-only. A private mapping is a copy of the file read at mmap, as POSIX allows. Anonymous shm_open objects and JIT shared memory descriptors are temporary files on Windows, so mmap now maps them too (it failed with EOPNOTSUPP before). mprotect of a mapped view above the view's protection fails with EACCES before any bookkeeping changes. The cases Windows cannot represent are listed in the libkernel debt. Dusklight (PPSA99305) uses SQLite in WAL mode, which maps its -shm file. On Windows mainf0634088bevery start logged "Failed to start transaction: disk I/O error" for its Dawn and pipeline caches (3 of 3 runs); with this change the caches initialise and their WAL files fill (4 of 4 runs). The title reaches its menu either way. A shared mapping may end inside the 16 KiB page that holds the end of the file, as POSIX mmap allows: the view ends with the file's last 4 KiB host page, which Windows zero-fills past the end, the rest of the guest page is private zero pages, and the file never grows. A mapping that reaches a whole page past the end still fails with EOPNOTSUPP. PS5LM Plus (PPSA99581) loads its model with llama.cpp, which maps the whole GGUF file shared and read-only. With a 491,400,032-byte model, Windows main5de7a46e0and this change without the last page logged "llama_model_load: error loading model: mmap failed: Operation not supported" (3 of 3 runs); now the model loads and the completion of "The capital of France is" starts with " Paris" (3 of 3 runs). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
84 lines
4.8 KiB
C++
84 lines
4.8 KiB
C++
#ifndef CORE_LIBS_PRX_LIBC_INCLUDE_GUESTARENA_HPP
|
|
#define CORE_LIBS_PRX_LIBC_INCLUDE_GUESTARENA_HPP
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
|
|
// Guest virtual memory is placed inside one reserved arena below the PS5 application map limit
|
|
// absolute address and breaks on host addresses outside that range.
|
|
namespace GuestArena {
|
|
|
|
#ifndef _WIN32
|
|
using SharedBackingResolver = bool (*)(std::uintptr_t address, std::size_t bytes, int* file, std::uint64_t* offset);
|
|
using SharedBackingWriter = bool (*)(std::uintptr_t address, const void* source, std::size_t bytes);
|
|
#endif
|
|
|
|
extern "C" {
|
|
|
|
bool GuestArenaAvailable_nid_postfix();
|
|
bool GuestArenaContains_nid_postfix(const void* pointer, std::size_t bytes);
|
|
void* GuestArenaAllocate_nid_postfix(std::size_t bytes, std::size_t alignment);
|
|
void* GuestArenaAllocateAtOrAbove_nid_postfix(std::uintptr_t hint, std::size_t bytes, std::size_t alignment);
|
|
void* GuestArenaAllocateFromHint_nid_postfix(std::uintptr_t hint, std::size_t bytes, std::size_t alignment);
|
|
std::uintptr_t GuestArenaHighestFree_nid_no_patch(std::size_t bytes, std::size_t alignment);
|
|
void GuestArenaMarkUsed_nid_postfix(const void* pointer, std::size_t bytes);
|
|
void GuestArenaRelease_nid_postfix(const void* pointer, std::size_t bytes);
|
|
// The reserved range, and whether it was reserved with page write watching (Windows MEM_WRITE_WATCH).
|
|
void GuestArenaRange_nid_postfix(std::uintptr_t* base, std::size_t* bytes);
|
|
bool GuestArenaWriteWatched_nid_postfix();
|
|
void GuestArenaSetProtection_nid_postfix(std::uintptr_t address, std::size_t bytes, std::uint32_t protection);
|
|
void GuestArenaCommit_nid_postfix(void* pointer, std::size_t bytes, std::uint32_t protection, std::size_t granule);
|
|
void GuestArenaReset_nid_postfix(void* pointer, std::size_t bytes);
|
|
void GuestArenaSetAccessObserver_nid_postfix(void (*callback)(std::uintptr_t address, std::size_t bytes));
|
|
#ifdef _WIN32
|
|
bool GuestArenaHandleWrite_nid_postfix(std::uintptr_t address);
|
|
bool GuestArenaHandleRead_nid_postfix(std::uintptr_t address);
|
|
void GuestArenaPinWritable_nid_postfix(const void* pointer, std::size_t bytes);
|
|
void GuestArenaUnpinWritable_nid_postfix(const void* pointer, std::size_t bytes);
|
|
bool GuestArenaProtection_nid_postfix(std::uintptr_t address, std::uint32_t* protection);
|
|
bool GuestArenaCollectWrites_nid_postfix(std::uintptr_t address, std::size_t bytes, void** pages, std::size_t* count, bool clear);
|
|
bool GuestArenaCollectArmedWrites_nid_postfix(std::uintptr_t address, std::size_t bytes, void** pages, std::size_t* count, bool clear);
|
|
bool GuestArenaCollectFreshWrites_nid_postfix(std::uintptr_t address, std::size_t bytes, void** pages, std::size_t* count, bool clear);
|
|
bool GuestArenaHostRegionOverlaps_nid_postfix(std::uintptr_t address, std::size_t bytes);
|
|
std::uint64_t GuestArenaCommitGeneration_nid_postfix();
|
|
void GuestArenaSetPrivateMappingObserver_nid_postfix(void (*callback)(std::uintptr_t address, std::size_t bytes, std::uint64_t generation));
|
|
void GuestArenaMap_nid_postfix(void* pointer, std::size_t bytes, void* section, std::uint64_t offset, std::uint32_t protection);
|
|
void GuestArenaMapDirect_nid_postfix(void* pointer, std::size_t bytes, void* section, std::uint64_t offset, std::uint32_t protection);
|
|
void GuestArenaMapFile_nid_postfix(void* pointer, std::size_t bytes, void* section, std::uint64_t offset, std::uint32_t protection, std::uint32_t viewProtection, std::size_t sectionBytes);
|
|
void* GuestArenaMapAlias_nid_postfix(std::uintptr_t address, std::size_t bytes);
|
|
void GuestArenaUnmapAlias_nid_postfix(void* alias);
|
|
bool GuestArenaResidentSpan_nid_postfix(std::uintptr_t address, std::size_t bytes, std::uintptr_t* start, std::uintptr_t* end);
|
|
void GuestArenaForgetSection_nid_postfix(void* section);
|
|
#else
|
|
void GuestArenaSetSharedBacking_nid_postfix(SharedBackingResolver resolver);
|
|
void GuestArenaSetSharedBackingWriter_nid_no_patch(SharedBackingWriter writer);
|
|
bool GuestArenaWriteSharedBacking_nid_no_patch(std::uintptr_t address, const void* source, std::size_t bytes);
|
|
bool GuestArenaSharedBacking_nid_postfix(std::uintptr_t address, std::size_t bytes, int* file, std::uint64_t* offset);
|
|
#endif
|
|
bool GuestArenaBeginHostWrite_nid_postfix(void* pointer, std::size_t bytes);
|
|
void GuestArenaEndHostWrite_nid_postfix(void* pointer, std::size_t bytes);
|
|
void GuestArenaSetHostReadHook_nid_no_patch(void (*hook)(std::uintptr_t address, std::size_t bytes));
|
|
void GuestArenaPrepareHostRead_nid_no_patch(const void* pointer, std::size_t bytes);
|
|
|
|
}
|
|
|
|
class HostWrite {
|
|
public:
|
|
HostWrite(void* pointer, std::size_t bytes) : pointer(pointer), bytes(bytes), open(GuestArenaBeginHostWrite_nid_postfix(pointer, bytes)) {}
|
|
~HostWrite() {
|
|
if (open) GuestArenaEndHostWrite_nid_postfix(pointer, bytes);
|
|
}
|
|
HostWrite(const HostWrite&) = delete;
|
|
HostWrite& operator=(const HostWrite&) = delete;
|
|
bool Open() const { return open; }
|
|
|
|
private:
|
|
void* pointer;
|
|
std::size_t bytes;
|
|
bool open;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|