From 611745170eb9ab9e571ea913d195d9d4ef2f6919 Mon Sep 17 00:00:00 2001 From: raphaelthegreat <47210458+raphaelthegreat@users.noreply.github.com> Date: Tue, 4 Jun 2024 00:59:35 +0300 Subject: [PATCH] memory: Implement VirtualQuery --- src/core/libraries/kernel/libkernel.cpp | 25 ++++++++++++++++++ .../libraries/kernel/memory_management.cpp | 10 +++++++ src/core/libraries/kernel/memory_management.h | 20 ++++++++++++++ .../libraries/kernel/thread_management.cpp | 2 ++ src/core/memory.cpp | 26 +++++++++++++++++-- src/core/memory.h | 5 +++- src/main.cpp | 2 +- .../spirv/emit_spirv_context_get_set.cpp | 9 +++++-- .../ir/passes/resource_tracking_pass.cpp | 6 ++--- .../renderer_vulkan/liverpool_to_vk.cpp | 2 ++ 10 files changed, 98 insertions(+), 9 deletions(-) diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/libkernel.cpp index d4ff41c6..8e4bf3d1 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/libkernel.cpp @@ -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 @@ -220,7 +221,28 @@ s64 PS4_SYSV_ABI ps4__read(int d, void* buf, u64 nbytes) { strlen(std::fgets(static_cast(buf), static_cast(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::Instance(); + auto& file = h->GetFile(fd)->f; + file.Seek(offset); + return file.ReadRaw(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); diff --git a/src/core/libraries/kernel/memory_management.cpp b/src/core/libraries/kernel/memory_management.cpp index b369c2ed..cb7f2077 100644 --- a/src/core/libraries/kernel/memory_management.cpp +++ b/src/core/libraries/kernel/memory_management.cpp @@ -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(addr), flags, info); +} + void PS4_SYSV_ABI _sceKernelRtldSetApplicationHeapAPI(void* func) { auto* linker = Common::Singleton::Instance(); linker->SetHeapApiFunc(func); diff --git a/src/core/libraries/kernel/memory_management.h b/src/core/libraries/kernel/memory_management.h index 7108b7b3..aa8cb45e 100644 --- a/src/core/libraries/kernel/memory_management.h +++ b/src/core/libraries/kernel/memory_management.h @@ -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 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 diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index a828094c..c3e022e6 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -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); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 735c8ee4..a0438fa9 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -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) { diff --git a/src/core/memory.h b/src/core/memory.h index 7a623db7..e6937f92 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -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 GetVulkanBuffer(VAddr addr); diff --git a/src/main.cpp b/src/main.cpp index dc3225c8..a373a9a7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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()); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index f653c2dd..49ea7033 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -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); } diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index 41da28aa..24138f0e 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -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::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) { diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index ccbb400d..a1362c56 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -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: