mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-22 16:43:05 -05:00
A mapping without MAP_FIXED treated its address as the lowest place it could go, and a hint at or above the end of the guest arena threw on the host. FreeBSD 11.4's vm_mmap_object places such mappings with vm_map_find_min, which takes the address as a hint only: it tries at or above it, then again from its minimum address. GuestArenaAllocateFromHint does the same in the arena: at or above the hint when it lies below the arena's end and a range fits there, otherwise from the arena's start. MapPlaced and the Windows mmap_aligned use it for hinted mappings; GuestArenaAllocateAtOrAbove keeps its meaning for the callers that need a range above an address. PS5CEMU-HAR (PPSA99360) reserves its JIT range with sceKernelReserveVirtualRange and a hint near its own code, a host address above the arena here, and aborted with "mapping address hint is above the guest address space arena" when launching a 3DS title.
80 lines
4.4 KiB
C++
80 lines
4.4 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);
|
|
#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* 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);
|
|
|
|
}
|
|
|
|
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
|