memory: Implement VirtualQuery

This commit is contained in:
raphaelthegreat 2024-06-04 00:59:35 +03:00
parent 1dd815d07d
commit 611745170e
10 changed files with 98 additions and 9 deletions

View File

@ -18,6 +18,7 @@
#include "core/libraries/kernel/time_management.h"
#include "core/libraries/libs.h"
#include "core/linker.h"
#include "core/file_sys/fs.h"
#include "core/memory.h"
#ifdef _WIN64
#include <io.h>
@ -220,7 +221,28 @@ s64 PS4_SYSV_ABI ps4__read(int d, void* buf, u64 nbytes) {
strlen(std::fgets(static_cast<char*>(buf), static_cast<int>(nbytes), stdin)));
}
size_t PS4_SYSV_ABI sceKernelPread(int fd, void *buf, size_t count, uint64_t offset) {
long unsigned int read_bytes = 0;
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(OVERLAPPED));
overlapped.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 32);
overlapped.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
auto& file = h->GetFile(fd)->f;
file.Seek(offset);
return file.ReadRaw<u8>(buf, count);
}
int PS4_SYSV_ABI Unknown1() {
return 0x81100004;
}
void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("fJgP+wqifno", "libSceDiscMap", 1, "libSceDiscMap", 1, 1, Unknown1);
// obj
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
// memory
@ -232,9 +254,11 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("WFcfL2lzido", "libkernel", 1, "libkernel", 1, 1, sceKernelQueryMemoryProtection);
LIB_FUNCTION("BHouLQzh0X0", "libkernel", 1, "libkernel", 1, 1, sceKernelDirectMemoryQuery);
LIB_FUNCTION("MBuItvba6z8", "libkernel", 1, "libkernel", 1, 1, sceKernelReleaseDirectMemory);
LIB_FUNCTION("hwVSPCmp5tM", "libkernel", 1, "libkernel", 1, 1, sceKernelCheckedReleaseDirectMemory);
LIB_FUNCTION("cQke9UuBQOk", "libkernel", 1, "libkernel", 1, 1, sceKernelMunmap);
LIB_FUNCTION("mL8NDH86iQI", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedFlexibleMemory);
LIB_FUNCTION("IWIBBdTHit4", "libkernel", 1, "libkernel", 1, 1, sceKernelMapFlexibleMemory);
LIB_FUNCTION("rVjRvHJ0X6c", "libkernel", 1, "libkernel", 1, 1, sceKernelVirtualQuery);
LIB_FUNCTION("p5EcQeEeJAE", "libkernel", 1, "libkernel", 1, 1, _sceKernelRtldSetApplicationHeapAPI);
// equeue
@ -254,6 +278,7 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertUtcToLocaltime);
LIB_FUNCTION("WB66evu8bsU", "libkernel", 1, "libkernel", 1, 1, sceKernelGetCompiledSdkVersion);
LIB_FUNCTION("DRuBt2pvICk", "libkernel", 1, "libkernel", 1, 1, ps4__read);
LIB_FUNCTION("+r3rMFwItV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPread);
Libraries::Kernel::fileSystemSymbolsRegister(sym);
Libraries::Kernel::timeSymbolsRegister(sym);

View File

@ -17,6 +17,11 @@ u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() {
return SCE_KERNEL_MAIN_DMEM_SIZE;
}
s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, size_t len) {
auto* memory = Core::Memory::Instance();
return memory->Free(start, len);
}
int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len,
u64 alignment, int memoryType, s64* physAddrOut) {
if (searchStart < 0 || searchEnd <= searchStart) {
@ -134,6 +139,11 @@ int PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, int flags, OrbisQueryInf
return memory->DirectMemoryQuery(offset, flags == 1, query_info);
}
s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void *addr, int flags, OrbisVirtualQueryInfo *info, size_t infoSize) {
auto* memory = Core::Memory::Instance();
return memory->VirtualQuery(std::bit_cast<VAddr>(addr), flags, info);
}
void PS4_SYSV_ABI _sceKernelRtldSetApplicationHeapAPI(void* func) {
auto* linker = Common::Singleton<Core::Linker>::Instance();
linker->SetHeapApiFunc(func);

View File

@ -3,6 +3,7 @@
#pragma once
#include "common/bit_field.h"
#include "common/types.h"
constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5376_MB; // ~ 6GB
@ -36,7 +37,24 @@ struct OrbisQueryInfo {
int memoryType;
};
struct OrbisVirtualQueryInfo {
uintptr_t start;
uintptr_t end;
size_t offset;
s32 protection;
s32 memory_type;
union {
BitField<0, 1, u32> is_flexible;
BitField<1, 1, u32> is_direct;
BitField<2, 1, u32> is_stack;
BitField<3, 1, u32> is_pooled;
BitField<4, 1, u32> is_commited;
};
std::array<char, 32> name;
};
u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize();
s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, size_t len);
int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len,
u64 alignment, int memoryType, s64* physAddrOut);
s32 PS4_SYSV_ABI sceKernelAllocateMainDirectMemory(size_t len, size_t alignment, int memoryType,
@ -52,6 +70,8 @@ int PS4_SYSV_ABI sceKernelQueryMemoryProtection(void* addr, void** start, void**
int PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, int flags, OrbisQueryInfo* query_info,
size_t infoSize);
s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void *addr, int flags, OrbisVirtualQueryInfo *info, size_t infoSize);
void PS4_SYSV_ABI _sceKernelRtldSetApplicationHeapAPI(void* func);
} // namespace Libraries::Kernel

View File

@ -1273,6 +1273,7 @@ int PS4_SYSV_ABI posix_pthread_rwlock_rdlock(ScePthreadRw* thread) {
}
return result;
}
int PS4_SYSV_ABI posix_pthread_rwlock_unlock(ScePthreadRw* thread) {
int result = scePthreadRwlockUnlock(thread);
if (result < 0) {
@ -1280,6 +1281,7 @@ int PS4_SYSV_ABI posix_pthread_rwlock_unlock(ScePthreadRw* thread) {
}
return result;
}
void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("4+h9EzwKF4I", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetschedpolicy);
LIB_FUNCTION("-Wreprtu0Qs", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetdetachstate);

View File

@ -26,7 +26,7 @@ MemoryManager::~MemoryManager() = default;
PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, u64 alignment,
int memory_type) {
PAddr free_addr = 0;
PAddr free_addr = search_start;
// Iterate through allocated blocked and find the next free position
for (const auto& block : allocations) {
@ -45,7 +45,7 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size,
return free_addr;
}
void MemoryManager::Free(PAddr phys_addr, size_t size) {
int MemoryManager::Free(PAddr phys_addr, size_t size) {
const auto it = std::ranges::find_if(allocations, [&](const auto& alloc) {
return alloc.base == phys_addr && alloc.size == size;
});
@ -53,6 +53,7 @@ void MemoryManager::Free(PAddr phys_addr, size_t size) {
// Free the ranges.
allocations.erase(it);
return ORBIS_OK;
}
int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
@ -137,6 +138,27 @@ int MemoryManager::QueryProtection(VAddr addr, void** start, void** end, u32* pr
return ORBIS_OK;
}
int MemoryManager::VirtualQuery(VAddr addr, int flags, Libraries::Kernel::OrbisVirtualQueryInfo* info) {
auto it = FindVMA(addr);
while (it->second.type == VMAType::Free && flags == 1) {
it++;
}
const auto& vma = it->second;
info->start = vma.base;
info->end = vma.base + vma.size;
info->is_flexible.Assign(vma.type == VMAType::Flexible);
info->is_direct.Assign(vma.type == VMAType::Direct);
info->is_commited.Assign(vma.type != VMAType::Free);
if (vma.type == VMAType::Direct) {
const auto it = std::ranges::find(allocations, vma.base, &DirectMemoryArea::base);
ASSERT(it != allocations.end());
info->memory_type = it->memory_type;
}
return ORBIS_OK;
}
int MemoryManager::DirectMemoryQuery(PAddr addr, bool find_next,
Libraries::Kernel::OrbisQueryInfo* out_info) {
const auto it = std::ranges::find_if(allocations, [&](const DirectMemoryArea& alloc) {

View File

@ -19,6 +19,7 @@ class Instance;
namespace Libraries::Kernel {
struct OrbisQueryInfo;
struct OrbisVirtualQueryInfo;
}
namespace Core {
@ -103,7 +104,7 @@ public:
PAddr Allocate(PAddr search_start, PAddr search_end, size_t size, u64 alignment,
int memory_type);
void Free(PAddr phys_addr, size_t size);
int Free(PAddr phys_addr, size_t size);
int MapMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
MemoryMapFlags flags, VMAType type, std::string_view name = "",
@ -113,6 +114,8 @@ public:
int QueryProtection(VAddr addr, void** start, void** end, u32* prot);
int VirtualQuery(VAddr addr, int flags, Libraries::Kernel::OrbisVirtualQueryInfo* info);
int DirectMemoryQuery(PAddr addr, bool find_next, Libraries::Kernel::OrbisQueryInfo* out_info);
std::pair<vk::Buffer, size_t> GetVulkanBuffer(VAddr addr);

View File

@ -96,7 +96,7 @@ int main(int argc, char* argv[]) {
for (const auto& entry : std::filesystem::directory_iterator(sce_module_folder)) {
if (entry.path().filename() == "libc.prx" ||
entry.path().filename() == "libSceFios2.prx" ||
entry.path().filename() == "libSceNpToolkit2.prx") {
entry.path().filename() == "libSceNpToolkit.prx") {
found = true;
LOG_INFO(Loader, "Loading {}", entry.path().string().c_str());
linker->LoadModule(entry.path().string().c_str());

View File

@ -95,9 +95,14 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp) {
}
}
switch (attr) {
case IR::Attribute::FragCoord:
return ctx.OpLoad(ctx.F32[1],
case IR::Attribute::FragCoord: {
const Id coord = ctx.OpLoad(ctx.F32[1],
ctx.OpAccessChain(ctx.input_f32, ctx.frag_coord, ctx.ConstU32(comp)));
if (comp == 3) {
return ctx.OpFDiv(ctx.F32[1], ctx.ConstF32(1.f), coord);
}
return coord;
}
default:
throw NotImplementedException("Read attribute {}", attr);
}

View File

@ -185,7 +185,7 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
.stride = buffer.GetStride(),
.num_records = u32(buffer.num_records),
.used_types = BufferDataType(inst),
.is_storage = true || IsBufferStore(inst),
.is_storage = IsBufferStore(inst),
});
const auto inst_info = inst.Flags<IR::BufferInstInfo>();
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
@ -205,8 +205,8 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
const u32 dword_offset = inst_info.inst_offset.Value() / sizeof(u32);
IR::U32 address = ir.Imm32(dword_offset);
if (inst_info.index_enable && inst_info.offset_enable) {
const IR::U32 offset{ir.CompositeExtract(inst.Arg(1), 0)};
const IR::U32 index{ir.CompositeExtract(inst.Arg(1), 1)};
const IR::U32 offset{ir.CompositeExtract(inst.Arg(1), 1)};
const IR::U32 index{ir.CompositeExtract(inst.Arg(1), 0)};
address = ir.IAdd(ir.IMul(index, ir.Imm32(dword_stride)), address);
address = ir.IAdd(address, ir.ShiftRightLogical(offset, ir.Imm32(2)));
} else if (inst_info.index_enable) {

View File

@ -14,6 +14,8 @@ vk::StencilOp StencilOp(Liverpool::StencilFunc op) {
return vk::StencilOp::eKeep;
case Liverpool::StencilFunc::Zero:
return vk::StencilOp::eZero;
case Liverpool::StencilFunc::ReplaceTest:
return vk::StencilOp::eReplace;
case Liverpool::StencilFunc::AddClamp:
return vk::StencilOp::eIncrementAndClamp;
case Liverpool::StencilFunc::SubClamp: