From 21982db6a756791e52277203d23880a390ec331d Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Mon, 21 Apr 2025 15:00:33 -0500 Subject: [PATCH 01/12] Load libSceGnmDriver LLE Adds libSceGnmDriver to LoadSystemModules, --- src/core/libraries/libs.cpp | 1 - src/emulator.cpp | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 3f5baf640..075a9e90a 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -66,7 +66,6 @@ namespace Libraries { void InitHLELibs(Core::Loader::SymbolsResolver* sym) { LOG_INFO(Lib_Kernel, "Initializing HLE libraries"); Libraries::Kernel::RegisterKernel(sym); - Libraries::GnmDriver::RegisterlibSceGnmDriver(sym); Libraries::VideoOut::RegisterLib(sym); Libraries::UserService::RegisterlibSceUserService(sym); Libraries::SystemService::RegisterlibSceSystemService(sym); diff --git a/src/emulator.cpp b/src/emulator.cpp index 1a71b99cb..45e93dc22 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -26,6 +26,7 @@ #include "core/file_format/trp.h" #include "core/file_sys/fs.h" #include "core/libraries/disc_map/disc_map.h" +#include "core/libraries/gnmdriver/gnmdriver.h" #include "core/libraries/libc_internal/libc_internal.h" #include "core/libraries/libs.h" #include "core/libraries/ngs2/ngs2.h" @@ -288,7 +289,7 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector ModulesToLoad{ + constexpr std::array ModulesToLoad{ {{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2}, {"libSceUlt.sprx", nullptr}, {"libSceJson.sprx", nullptr}, @@ -298,7 +299,8 @@ void Emulator::LoadSystemModules(const std::string& game_serial) { {"libSceCesCs.sprx", nullptr}, {"libSceFont.sprx", nullptr}, {"libSceFontFt.sprx", nullptr}, - {"libSceFreeTypeOt.sprx", nullptr}}}; + {"libSceFreeTypeOt.sprx", nullptr}, + {"libSceGnmDriver.sprx", &Libraries::GnmDriver::RegisterlibSceGnmDriver}}}; std::vector found_modules; const auto& sys_module_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir); From c547ab8901faa0c498319e514bdcd2554dde16fb Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Mon, 21 Apr 2025 15:01:33 -0500 Subject: [PATCH 02/12] Separate presenter initialization from libSceGnmDriver HLE init Without this, our GPU side never inits when LLE. --- src/core/libraries/gnmdriver/gnmdriver.cpp | 4 +++- src/core/libraries/gnmdriver/gnmdriver.h | 2 ++ src/core/libraries/libs.cpp | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index 25ac4921c..02d888bd1 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -2799,7 +2799,7 @@ int PS4_SYSV_ABI Func_F916890425496553() { return ORBIS_OK; } -void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { +void InitializePresenter() { LOG_INFO(Lib_GnmDriver, "Initializing presenter"); liverpool = std::make_unique(); presenter = std::make_unique(*g_window, liverpool.get()); @@ -2815,7 +2815,9 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { Platform::IrqC::Instance()->Register(Platform::InterruptId::GpuIdle, ResetSubmissionLock, nullptr); +} +void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("b0xyllnVY-I", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAddEqEvent); LIB_FUNCTION("b08AgtPlHPg", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAreSubmitsAllowed); diff --git a/src/core/libraries/gnmdriver/gnmdriver.h b/src/core/libraries/gnmdriver/gnmdriver.h index 94d06c85f..94f1392d8 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.h +++ b/src/core/libraries/gnmdriver/gnmdriver.h @@ -14,6 +14,8 @@ namespace Libraries::GnmDriver { using namespace Kernel; +void InitializePresenter(); + s32 PS4_SYSV_ABI sceGnmAddEqEvent(SceKernelEqueue eq, u64 id, void* udata); int PS4_SYSV_ABI sceGnmAreSubmitsAllowed(); int PS4_SYSV_ABI sceGnmBeginWorkload(u32 workload_stream, u64* workload); diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 075a9e90a..658e36bad 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -66,6 +66,7 @@ namespace Libraries { void InitHLELibs(Core::Loader::SymbolsResolver* sym) { LOG_INFO(Lib_Kernel, "Initializing HLE libraries"); Libraries::Kernel::RegisterKernel(sym); + Libraries::GnmDriver::InitializePresenter(); Libraries::VideoOut::RegisterLib(sym); Libraries::UserService::RegisterlibSceUserService(sym); Libraries::SystemService::RegisterlibSceSystemService(sym); From 3dac1a2c6aed7542cdc7a7be5c1556407b2f419c Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Mon, 21 Apr 2025 15:02:15 -0500 Subject: [PATCH 03/12] Add a graphics card device stub libSceGnmDriver LLE requires implementing the "/dev/gc" device --- CMakeLists.txt | 2 + src/core/devices/gc_device.cpp | 74 +++++++++++++++++++++++ src/core/devices/gc_device.h | 33 ++++++++++ src/core/libraries/kernel/file_system.cpp | 4 +- 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/core/devices/gc_device.cpp create mode 100644 src/core/devices/gc_device.h diff --git a/CMakeLists.txt b/CMakeLists.txt index beea8a1e0..abb09c97e 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -701,6 +701,8 @@ set(CORE src/core/aerolib/stubs.cpp src/core/address_space.h src/core/devices/base_device.cpp src/core/devices/base_device.h + src/core/devices/gc_device.cpp + src/core/devices/gc_device.h src/core/devices/ioccom.h src/core/devices/logger.cpp src/core/devices/logger.h diff --git a/src/core/devices/gc_device.cpp b/src/core/devices/gc_device.cpp new file mode 100644 index 000000000..3f4079fa9 --- /dev/null +++ b/src/core/devices/gc_device.cpp @@ -0,0 +1,74 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "gc_device.h" + +namespace Core::Devices { + +std::shared_ptr GcDevice::Create(u32 handle, const char*, int, u16) { + return std::shared_ptr( + reinterpret_cast(new GcDevice(handle))); +} + +int GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { + LOG_ERROR(Kernel_Pthread, "(STUBBED) called"); + return 0; +} + +s64 GcDevice::write(const void* buf, size_t nbytes) { + LOG_ERROR(Kernel_Pthread, "(STUBBED) called"); + return 0; +} + +size_t GcDevice::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) { + LOG_ERROR(Kernel_Pthread, "(STUBBED) called"); + return 0; +} + +size_t GcDevice::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) { + LOG_ERROR(Kernel_Pthread, "(STUBBED) called"); + return 0; +} + +s64 GcDevice::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) { + LOG_ERROR(Kernel_Pthread, "(STUBBED) called"); + return 0; +} + +s64 GcDevice::lseek(s64 offset, int whence) { + LOG_ERROR(Kernel_Pthread, "(STUBBED) called"); + return 0; +} + +s64 GcDevice::read(void* buf, size_t nbytes) { + LOG_ERROR(Kernel_Pthread, "(STUBBED) called"); + return 0; +} + +int GcDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) { + LOG_ERROR(Kernel_Pthread, "(STUBBED) called"); + return 0; +} + +s32 GcDevice::fsync() { + LOG_ERROR(Kernel_Pthread, "(STUBBED) called"); + return 0; +} + +int GcDevice::ftruncate(s64 length) { + LOG_ERROR(Kernel_Pthread, "(STUBBED) called"); + return 0; +} + +int GcDevice::getdents(void* buf, u32 nbytes, s64* basep) { + LOG_ERROR(Kernel_Pthread, "(STUBBED) called"); + return 0; +} + +s64 GcDevice::pwrite(const void* buf, size_t nbytes, u64 offset) { + LOG_ERROR(Kernel_Pthread, "(STUBBED) called"); + return 0; +} + +} // namespace Core::Devices \ No newline at end of file diff --git a/src/core/devices/gc_device.h b/src/core/devices/gc_device.h new file mode 100644 index 000000000..93ac04fde --- /dev/null +++ b/src/core/devices/gc_device.h @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once +#include +#include "base_device.h" + +namespace Core::Devices { + +class GcDevice final : BaseDevice { + u32 handle; + +public: + static std::shared_ptr Create(u32 handle, const char*, int, u16); + explicit GcDevice(u32 handle) : handle(handle) {} + + ~GcDevice() override = default; + + int ioctl(u64 cmd, Common::VaCtx* args) override; + s64 write(const void* buf, size_t nbytes) override; + size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override; + size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override; + s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override; + s64 lseek(s64 offset, int whence) override; + s64 read(void* buf, size_t nbytes) override; + int fstat(Libraries::Kernel::OrbisKernelStat* sb) override; + s32 fsync() override; + int ftruncate(s64 length) override; + int getdents(void* buf, u32 nbytes, s64* basep) override; + s64 pwrite(const void* buf, size_t nbytes, u64 offset) override; +}; + +} // namespace Core::Devices \ No newline at end of file diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index bc34dff98..8ef63641f 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -10,6 +10,7 @@ #include "common/singleton.h" #include "core/devices/console_device.h" #include "core/devices/deci_tty6_device.h" +#include "core/devices/gc_device.h" #include "core/devices/logger.h" #include "core/devices/nop_device.h" #include "core/devices/random_device.h" @@ -52,7 +53,8 @@ static std::map available_device = { {"/dev/random", &D::RandomDevice::Create }, {"/dev/srandom", &D::SRandomDevice::Create }, {"/dev/console", &D::ConsoleDevice::Create }, - {"/dev/deci_tty6",&D::DeciTty6Device::Create } + {"/dev/deci_tty6",&D::DeciTty6Device::Create }, + {"/dev/gc", &D::GcDevice::Create } // clang-format on }; From 8b5b34fdba80f8902538d7d0f05e7402f6a2fd50 Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Mon, 21 Apr 2025 15:21:12 -0500 Subject: [PATCH 04/12] Support mapping memory to device files --- src/common/path_util.cpp | 1 + src/common/path_util.h | 2 ++ src/core/libraries/kernel/file_system.cpp | 9 +++++++++ src/emulator.cpp | 6 ++++++ 4 files changed, 18 insertions(+) diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index 702d0fabc..0f71dcb2f 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -136,6 +136,7 @@ static auto UserPaths = [] { create_path(PathType::PatchesDir, user_dir / PATCHES_DIR); create_path(PathType::MetaDataDir, user_dir / METADATA_DIR); create_path(PathType::CustomTrophy, user_dir / CUSTOM_TROPHY); + create_path(PathType::DevicesDir, user_dir / DEVICES_DIR); std::ofstream notice_file(user_dir / CUSTOM_TROPHY / "Notice.txt"); if (notice_file.is_open()) { diff --git a/src/common/path_util.h b/src/common/path_util.h index 2fd9b1588..848bf27f7 100644 --- a/src/common/path_util.h +++ b/src/common/path_util.h @@ -28,6 +28,7 @@ enum class PathType { PatchesDir, // Where patches are stored. MetaDataDir, // Where game metadata (e.g. trophies and menu backgrounds) is stored. CustomTrophy, // Where custom files for trophies are stored. + DevicesDir, // Where temporary device files are located. }; constexpr auto PORTABLE_DIR = "user"; @@ -46,6 +47,7 @@ constexpr auto CHEATS_DIR = "cheats"; constexpr auto PATCHES_DIR = "patches"; constexpr auto METADATA_DIR = "game_data"; constexpr auto CUSTOM_TROPHY = "custom_trophy"; +constexpr auto DEVICES_DIR = "device"; // Filenames constexpr auto LOG_FILE = "shad_log.txt"; diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 8ef63641f..845aa294a 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -91,6 +91,15 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) { file->type = Core::FileSys::FileType::Device; file->m_guest_name = path; file->device = factory(handle, path.data(), flags, mode); + + // Some libraries map memory to their file. We need a host file to support this. + file->m_host_name = mnt->GetHostPath(file->m_guest_name); + bool exists = std::filesystem::exists(file->m_host_name); + if (!exists) { + Common::FS::IOFile out(file->m_host_name, Common::FS::FileAccessMode::Write); + } + auto e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::ReadWrite); + ASSERT(e == 0); return handle; } } diff --git a/src/emulator.cpp b/src/emulator.cpp index 45e93dc22..efc3480dc 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -245,6 +245,12 @@ void Emulator::Run(const std::filesystem::path& file, const std::vectorMount(devices_dir, "/dev"); + // Initialize kernel and library facilities. Libraries::InitHLELibs(&linker->GetHLESymbols()); From f3a3df90e25cc521c622df2ab838bff75d89202e Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Mon, 21 Apr 2025 15:22:50 -0500 Subject: [PATCH 05/12] Log ioctls --- src/core/devices/gc_device.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/devices/gc_device.cpp b/src/core/devices/gc_device.cpp index 3f4079fa9..684f414b1 100644 --- a/src/core/devices/gc_device.cpp +++ b/src/core/devices/gc_device.cpp @@ -12,7 +12,7 @@ std::shared_ptr GcDevice::Create(u32 handle, const char*, int, u16) } int GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { - LOG_ERROR(Kernel_Pthread, "(STUBBED) called"); + LOG_ERROR(Kernel_Pthread, "(STUBBED) cmd = {:#x} called", cmd); return 0; } From 27b7c1dc14a993765644a7ca1b0f07bfa4eec219 Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Mon, 21 Apr 2025 15:30:25 -0500 Subject: [PATCH 06/12] Implement sceKernelMapNamedSystemFlexibleMemory Needed for libSceGnmDriver init --- src/core/libraries/kernel/memory.cpp | 32 ++++++++++++++++++++++++++++ src/core/memory.cpp | 11 ++++++++++ src/core/memory.h | 3 +++ 3 files changed, 46 insertions(+) diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index 8a0c91479..3a5a9a703 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -234,6 +234,37 @@ s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, std::size_t Core::VMAType::Flexible, name); } +s32 PS4_SYSV_ABI sceKernelMapNamedSystemFlexibleMemory(void** addr_in_out, std::size_t len, int prot, + int flags, const char* name) { + if (len == 0 || !Common::Is16KBAligned(len)) { + LOG_ERROR(Kernel_Vmm, "len is 0 or not 16kb multiple"); + return ORBIS_KERNEL_ERROR_EINVAL; + } + + static constexpr size_t MaxNameSize = 32; + if (std::strlen(name) > MaxNameSize) { + LOG_ERROR(Kernel_Vmm, "name exceeds 32 bytes!"); + return ORBIS_KERNEL_ERROR_ENAMETOOLONG; + } + + if (name == nullptr) { + LOG_ERROR(Kernel_Vmm, "name is invalid!"); + return ORBIS_KERNEL_ERROR_EFAULT; + } + + const VAddr in_addr = reinterpret_cast(*addr_in_out); + const auto mem_prot = static_cast(prot); + const auto map_flags = static_cast(flags); + SCOPE_EXIT { + LOG_INFO(Kernel_Vmm, + "in_addr = {:#x}, out_addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}", + in_addr, fmt::ptr(*addr_in_out), len, prot, flags); + }; + auto* memory = Core::Memory::Instance(); + return memory->MapSystemMemory(addr_in_out, in_addr, len, mem_prot, map_flags, + Core::VMAType::Flexible, name); +} + s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot, int flags) { return sceKernelMapNamedFlexibleMemory(addr_in_out, len, prot, flags, ""); @@ -578,6 +609,7 @@ void RegisterMemory(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("PGhQHd-dzv8", "libkernel", 1, "libkernel", 1, 1, sceKernelMmap); LIB_FUNCTION("cQke9UuBQOk", "libkernel", 1, "libkernel", 1, 1, sceKernelMunmap); LIB_FUNCTION("mL8NDH86iQI", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedFlexibleMemory); + LIB_FUNCTION("kc+LEEIYakc", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedSystemFlexibleMemory); LIB_FUNCTION("aNz11fnnzi4", "libkernel", 1, "libkernel", 1, 1, sceKernelAvailableFlexibleMemorySize); LIB_FUNCTION("aNz11fnnzi4", "libkernel_avlfmem", 1, "libkernel", 1, 1, diff --git a/src/core/memory.cpp b/src/core/memory.cpp index cb80d6be4..fe52abff7 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -360,6 +360,17 @@ int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, M return ORBIS_OK; } +int MemoryManager::MapSystemMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, + MemoryMapFlags flags, VMAType type, std::string_view name) { + // If address is 0, this maps to System Reserved memory instead, which starts at address 0x880000000 + VAddr in_addr = virtual_addr; + if (in_addr == 0) { + static constexpr VAddr KernelAllocBase = 0x880000000ULL; + in_addr = SearchFree(KernelAllocBase, size, 1); + } + return MapMemory(out_addr, in_addr, size, prot, flags, type, name); +} + int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, MemoryMapFlags flags, uintptr_t fd, size_t offset) { VAddr mapped_addr = (virtual_addr == 0) ? impl.SystemManagedVirtualBase() : virtual_addr; diff --git a/src/core/memory.h b/src/core/memory.h index a6a55e288..f8ab7efd7 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -189,6 +189,9 @@ public: MemoryMapFlags flags, VMAType type, std::string_view name = "", bool is_exec = false, PAddr phys_addr = -1, u64 alignment = 0); + int MapSystemMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, + MemoryMapFlags flags, VMAType type, std::string_view name = ""); + int MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, MemoryMapFlags flags, uintptr_t fd, size_t offset); From ad7c41ba5c0729de45626b549e79df697f46ae24 Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Mon, 21 Apr 2025 15:50:19 -0500 Subject: [PATCH 07/12] Stub some ioctl commands properly --- src/core/devices/gc_device.cpp | 30 ++++++++++++++++++++++++++++-- src/core/devices/gc_device.h | 8 ++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/core/devices/gc_device.cpp b/src/core/devices/gc_device.cpp index 684f414b1..866a72675 100644 --- a/src/core/devices/gc_device.cpp +++ b/src/core/devices/gc_device.cpp @@ -11,8 +11,34 @@ std::shared_ptr GcDevice::Create(u32 handle, const char*, int, u16) reinterpret_cast(new GcDevice(handle))); } -int GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { - LOG_ERROR(Kernel_Pthread, "(STUBBED) cmd = {:#x} called", cmd); +s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { + auto command = GcCommands(cmd); + switch(command) { + case GcCommands::AreSubmitsAllowed: { + LOG_ERROR(Lib_GnmDriver, "unhandled ioctl sceGnmAreSubmitsAllowed", cmd); + break; + } + case GcCommands::GetCuMask: { + LOG_ERROR(Lib_GnmDriver, "unhandled ioctl get cu mask", cmd); + break; + } + case GcCommands::GetNumTcaUnits: { + LOG_ERROR(Lib_GnmDriver, "unhandled ioctl sceGnmGetNumTcaUnits", cmd); + break; + } + case GcCommands::MipStatsReport: { + LOG_ERROR(Lib_GnmDriver, "unhandled ioctl sceGnmMipStatsReport", cmd); + break; + } + case GcCommands::SetGsRingSizes: { + LOG_ERROR(Lib_GnmDriver, "unhandled ioctl sceGnmSetGsRingSizes", cmd); + break; + } + default: { + LOG_ERROR(Lib_GnmDriver, "unhandled ioctl cmd = {:#x} called", cmd); + break; + } + } return 0; } diff --git a/src/core/devices/gc_device.h b/src/core/devices/gc_device.h index 93ac04fde..2541b7c45 100644 --- a/src/core/devices/gc_device.h +++ b/src/core/devices/gc_device.h @@ -28,6 +28,14 @@ public: int ftruncate(s64 length) override; int getdents(void* buf, u32 nbytes, s64* basep) override; s64 pwrite(const void* buf, size_t nbytes, u64 offset) override; +private: + enum class GcCommands : u64 { + GetNumTcaUnits = 0xc004811f, + SetGsRingSizes = 0xc00c8110, + MipStatsReport = 0xc0848119, + AreSubmitsAllowed = 0xc008811b, + GetCuMask = 0xc010810b, + }; }; } // namespace Core::Devices \ No newline at end of file From dc277394c52008d39da432ce0558d60fd5e5c297 Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Mon, 21 Apr 2025 22:22:28 -0500 Subject: [PATCH 08/12] Some ioctls Handle submits, dingdongs, and compute queue mapping HLE for now. --- src/core/devices/gc_device.cpp | 96 +++++++++++++++++++--- src/core/devices/gc_device.h | 55 ++++++++++++- src/core/libraries/gnmdriver/gnmdriver.cpp | 51 ++++++------ src/core/libraries/gnmdriver/gnmdriver.h | 1 + src/core/libraries/kernel/memory.h | 2 + src/core/libraries/libs.cpp | 1 + src/core/memory.h | 4 +- 7 files changed, 170 insertions(+), 40 deletions(-) diff --git a/src/core/devices/gc_device.cpp b/src/core/devices/gc_device.cpp index 866a72675..94a4a585a 100644 --- a/src/core/devices/gc_device.cpp +++ b/src/core/devices/gc_device.cpp @@ -2,7 +2,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" -#include "gc_device.h" +#include "core/devices/gc_device.h" +#include "core/libraries/kernel/posix_error.h" +#include "core/libraries/gnmdriver/gnmdriver.h" +#include "core/memory.h" +#include "common/assert.h" namespace Core::Devices { @@ -11,27 +15,93 @@ std::shared_ptr GcDevice::Create(u32 handle, const char*, int, u16) reinterpret_cast(new GcDevice(handle))); } + + +s32* submits_addr = 0; + s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { auto command = GcCommands(cmd); switch(command) { - case GcCommands::AreSubmitsAllowed: { - LOG_ERROR(Lib_GnmDriver, "unhandled ioctl sceGnmAreSubmitsAllowed", cmd); - break; - } - case GcCommands::GetCuMask: { - LOG_ERROR(Lib_GnmDriver, "unhandled ioctl get cu mask", cmd); - break; - } case GcCommands::GetNumTcaUnits: { - LOG_ERROR(Lib_GnmDriver, "unhandled ioctl sceGnmGetNumTcaUnits", cmd); + auto data = vaArgPtr(&args->va_list); + *data = 0; break; } - case GcCommands::MipStatsReport: { - LOG_ERROR(Lib_GnmDriver, "unhandled ioctl sceGnmMipStatsReport", cmd); + case GcCommands::AreSubmitsAllowed: { + LOG_INFO(Lib_GnmDriver, "ioctl AreSubmitsAllowed"); + if (submits_addr == nullptr) { + auto* memory = Core::Memory::Instance(); + s32* out_addr; + VAddr in_addr{0xfe0100000}; + auto prot = Core::MemoryProt::CpuRead; + auto flags = Core::MemoryMapFlags::Shared | Core::MemoryMapFlags::Anon | Core::MemoryMapFlags::System; + auto type = Core::VMAType::Direct; + s32 result = memory->MapMemory(reinterpret_cast(&out_addr), in_addr, 0x4000, prot, flags, type); + if (result != 0) { + return POSIX_ENOMEM; + } + submits_addr = out_addr; + } + auto data = vaArgPtr(&args->va_list); + *data = submits_addr; + + *submits_addr = 0; break; } case GcCommands::SetGsRingSizes: { - LOG_ERROR(Lib_GnmDriver, "unhandled ioctl sceGnmSetGsRingSizes", cmd); + auto data = vaArgPtr(&args->va_list); + LOG_ERROR(Lib_GnmDriver, "unhandled ioctl SetGsRingSizes, esgs size = {:#x}, gsvs size = {:#x}", data->esgs_ring_size, data->gsvs_ring_size); + break; + } + case GcCommands::Submit: { + ASSERT(true); + LOG_ERROR(Lib_GnmDriver, "ioctl Submit"); + auto data = vaArgPtr(&args->va_list); + auto commands = std::span{data->cmds, data->count}; + // Submit ioctl receives an indirect buffer packet + break; + } + case GcCommands::GetCuMask: { + auto data = vaArgPtr(&args->va_list); + data[0] = 0x10; + data[1] = 0x10; + data[2] = 0; + data[3] = 0; + break; + } + case GcCommands::SubmitEop: { + ASSERT(true); + LOG_ERROR(Lib_GnmDriver, "ioctl SubmitEop"); + auto data = vaArgPtr(&args->va_list); + auto commands = std::span{data->cmds, data->count}; + // Submit ioctl receives an indirect buffer packet + break; + } + case GcCommands::MapComputeQueue: { + ASSERT(true); + auto data = vaArgPtr(&args->va_list); + auto pipe_id = data->pipe_lo - 1; + auto ring_size = pow(2, data->ring_size_dw); + LOG_ERROR(Lib_GnmDriver, "ioctl MapComputeQueue, pipe_id = {}", pipe_id); + Libraries::GnmDriver::sceGnmMapComputeQueueWithPriority(pipe_id, data->queue_id, data->ring_base_addr, ring_size, data->read_ptr_addr, data->pipe_priority); + break; + } + case GcCommands::SetWaveLimitMultipliers: { + LOG_ERROR(Lib_GnmDriver, "ioctl SetWaveLimitMultipliers"); + auto data = vaArgPtr(&args->va_list); + break; + } + case GcCommands::MipStatsReport: { + auto data = vaArgPtr(&args->va_list); + switch(data->type) { + case 0x10001: + case 0x18001: { + break; + } + default: { + return POSIX_EINVAL; + } + } break; } default: { diff --git a/src/core/devices/gc_device.h b/src/core/devices/gc_device.h index 2541b7c45..9e7e01490 100644 --- a/src/core/devices/gc_device.h +++ b/src/core/devices/gc_device.h @@ -31,10 +31,61 @@ public: private: enum class GcCommands : u64 { GetNumTcaUnits = 0xc004811f, - SetGsRingSizes = 0xc00c8110, - MipStatsReport = 0xc0848119, AreSubmitsAllowed = 0xc008811b, + SetGsRingSizes = 0xc00c8110, + Submit = 0xc0108102, GetCuMask = 0xc010810b, + SubmitEop = 0xc020810c, + MapComputeQueue = 0xc030810d, + SetWaveLimitMultipliers = 0xc030811e, + MipStatsReport = 0xc0848119, + }; + + struct SetGsRingSizesArgs { + u32 esgs_ring_size; + u32 gsvs_ring_size; + u32 unk; + }; + + struct SubmitArgs { + u32 pid; + u32 count; + u64* cmds; + }; + + struct SubmitEopArgs { + u32 pid; + u32 count; + u64* cmds; + u64 eop_v; + s32 wait; + }; + + struct MapComputeQueueArgs { + u32 pipe_hi; + u32 pipe_lo; + u32 queue_id; + u32 g_queue_id; + VAddr ring_base_addr; + u32* read_ptr_addr; + VAddr ding_dong_ptr; + u32 ring_size_dw; + u32 pipe_priority; + }; + + struct SetWaveLimitMultipliersArgs { + s32 bitset; + s32 values[8]; + s32 unk0; + s32 unk1; + s32 unk2; + }; + + struct SetMipStatsReportArgs { + u32 type; + u32 unk0; + u32 unk1; + u32 unk2; }; }; diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index 02d888bd1..108b48186 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -2817,10 +2817,35 @@ void InitializePresenter() { nullptr); } -void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { - LIB_FUNCTION("b0xyllnVY-I", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAddEqEvent); +void RegisterRequiredGnmDriver(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("29oKvKXzEZo", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, + sceGnmMapComputeQueue); + LIB_FUNCTION("A+uGq+3KFtQ", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, + sceGnmMapComputeQueueWithPriority); + LIB_FUNCTION("gObODli-OH8", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, + sceGnmRequestFlipAndSubmitDone); + LIB_FUNCTION("6YRHhh5mHCs", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, + sceGnmRequestFlipAndSubmitDoneForWorkload); + LIB_FUNCTION("xbxNatawohc", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, + sceGnmSubmitAndFlipCommandBuffers); + LIB_FUNCTION("Ga6r7H6Y0RI", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, + sceGnmSubmitAndFlipCommandBuffersForWorkload); + LIB_FUNCTION("zwY0YV91TTI", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, + sceGnmSubmitCommandBuffers); + LIB_FUNCTION("jRcI8VcgTz4", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, + sceGnmSubmitCommandBuffersForWorkload); + LIB_FUNCTION("yvZ73uQUqrk", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmSubmitDone); + LIB_FUNCTION("ArSg-TGinhk", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, + sceGnmUnmapComputeQueue); + LIB_FUNCTION("bX5IbRvECXk", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmDingDong); + LIB_FUNCTION("byXlqupd8cE", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, + sceGnmDingDongForWorkload); LIB_FUNCTION("b08AgtPlHPg", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAreSubmitsAllowed); +} + +void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("b0xyllnVY-I", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAddEqEvent); LIB_FUNCTION("ihxrbsoSKWc", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmBeginWorkload); LIB_FUNCTION("ffrNQOshows", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmComputeWaitOnAddress); @@ -2851,9 +2876,6 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("PVT+fuoS9gU", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmDeleteEqEvent); LIB_FUNCTION("UtObDRQiGbs", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmDestroyWorkloadStream); - LIB_FUNCTION("bX5IbRvECXk", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmDingDong); - LIB_FUNCTION("byXlqupd8cE", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, - sceGnmDingDongForWorkload); LIB_FUNCTION("HHo1BAljZO8", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmDisableMipStatsReport); LIB_FUNCTION("0BzLGljcwBo", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, @@ -2998,10 +3020,6 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { sceGnmLogicalCuMaskToPhysicalCuMask); LIB_FUNCTION("Kl0Z3LH07QI", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmLogicalTcaUnitToPhysical); - LIB_FUNCTION("29oKvKXzEZo", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, - sceGnmMapComputeQueue); - LIB_FUNCTION("A+uGq+3KFtQ", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, - sceGnmMapComputeQueueWithPriority); LIB_FUNCTION("+N+wrSYBLIw", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmPaDisableFlipCallbacks); LIB_FUNCTION("8WDA9RiXLaw", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, @@ -3018,10 +3036,6 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("ZFqKFl23aMc", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmRegisterOwner); LIB_FUNCTION("nvEwfYAImTs", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmRegisterResource); - LIB_FUNCTION("gObODli-OH8", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, - sceGnmRequestFlipAndSubmitDone); - LIB_FUNCTION("6YRHhh5mHCs", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, - sceGnmRequestFlipAndSubmitDoneForWorkload); LIB_FUNCTION("f85orjx7qts", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmRequestMipStatsReportAndReset); LIB_FUNCTION("MYRtYhojKdA", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, @@ -3131,17 +3145,6 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { sceGnmSqttSwitchTraceBuffer2); LIB_FUNCTION("QLzOwOF0t+A", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmSqttWaitForEvent); - LIB_FUNCTION("xbxNatawohc", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, - sceGnmSubmitAndFlipCommandBuffers); - LIB_FUNCTION("Ga6r7H6Y0RI", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, - sceGnmSubmitAndFlipCommandBuffersForWorkload); - LIB_FUNCTION("zwY0YV91TTI", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, - sceGnmSubmitCommandBuffers); - LIB_FUNCTION("jRcI8VcgTz4", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, - sceGnmSubmitCommandBuffersForWorkload); - LIB_FUNCTION("yvZ73uQUqrk", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmSubmitDone); - LIB_FUNCTION("ArSg-TGinhk", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, - sceGnmUnmapComputeQueue); LIB_FUNCTION("yhFCnaz5daw", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmUnregisterAllResourcesForOwner); LIB_FUNCTION("fhKwCVVj9nk", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, diff --git a/src/core/libraries/gnmdriver/gnmdriver.h b/src/core/libraries/gnmdriver/gnmdriver.h index 94f1392d8..94167cef1 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.h +++ b/src/core/libraries/gnmdriver/gnmdriver.h @@ -297,5 +297,6 @@ int PS4_SYSV_ABI Func_BFB41C057478F0BF(); int PS4_SYSV_ABI Func_E51D44DB8151238C(); int PS4_SYSV_ABI Func_F916890425496553(); +void RegisterRequiredGnmDriver(Core::Loader::SymbolsResolver* sym); void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::GnmDriver diff --git a/src/core/libraries/kernel/memory.h b/src/core/libraries/kernel/memory.h index 400b6c3fc..2a86f3843 100644 --- a/src/core/libraries/kernel/memory.h +++ b/src/core/libraries/kernel/memory.h @@ -129,6 +129,8 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolReserve(void* addrIn, size_t len, size_t ali s32 PS4_SYSV_ABI sceKernelMemoryPoolCommit(void* addr, size_t len, int type, int prot, int flags); s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, size_t len, int flags); +int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, size_t offset, void** res); + int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len); void RegisterMemory(Core::Loader::SymbolsResolver* sym); diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 658e36bad..8d8d755cf 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -67,6 +67,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) { LOG_INFO(Lib_Kernel, "Initializing HLE libraries"); Libraries::Kernel::RegisterKernel(sym); Libraries::GnmDriver::InitializePresenter(); + Libraries::GnmDriver::RegisterRequiredGnmDriver(sym); Libraries::VideoOut::RegisterLib(sym); Libraries::UserService::RegisterlibSceUserService(sym); Libraries::SystemService::RegisterlibSceSystemService(sym); diff --git a/src/core/memory.h b/src/core/memory.h index f8ab7efd7..13dfb8d3d 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -41,8 +41,10 @@ enum class MemoryMapFlags : u32 { Shared = 1, Private = 2, Fixed = 0x10, - NoOverwrite = 0x0080, + NoOverwrite = 0x80, NoSync = 0x800, + Anon = 0x1000, + System = 0x2000, NoCore = 0x20000, NoCoalesce = 0x400000, }; From 23883bd42b55e086d616680979194387cefaa488 Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Mon, 21 Apr 2025 22:28:20 -0500 Subject: [PATCH 09/12] GnmEq HLE These use kevent/kqueue, so they need to be HLE for now. --- src/core/libraries/gnmdriver/gnmdriver.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index 108b48186..f0363ba39 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -2842,10 +2842,15 @@ void RegisterRequiredGnmDriver(Core::Loader::SymbolsResolver* sym) { sceGnmDingDongForWorkload); LIB_FUNCTION("b08AgtPlHPg", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAreSubmitsAllowed); + LIB_FUNCTION("b0xyllnVY-I", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAddEqEvent); + LIB_FUNCTION("UoYY0DWMC0U", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, + sceGnmGetEqEventType); + LIB_FUNCTION("H7-fgvEutM0", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, + sceGnmGetEqTimeStamp); + LIB_FUNCTION("PVT+fuoS9gU", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmDeleteEqEvent); } void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { - LIB_FUNCTION("b0xyllnVY-I", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAddEqEvent); LIB_FUNCTION("ihxrbsoSKWc", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmBeginWorkload); LIB_FUNCTION("ffrNQOshows", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmComputeWaitOnAddress); @@ -2873,7 +2878,6 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { sceGnmDebuggerWriteSqIndirectRegister); LIB_FUNCTION("qpGITzPE+Zc", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmDebugHardwareStatus); - LIB_FUNCTION("PVT+fuoS9gU", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmDeleteEqEvent); LIB_FUNCTION("UtObDRQiGbs", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmDestroyWorkloadStream); LIB_FUNCTION("HHo1BAljZO8", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, @@ -2953,10 +2957,6 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { sceGnmGetDbgGcHandle); LIB_FUNCTION("pd4C7da6sEg", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmGetDebugTimestamp); - LIB_FUNCTION("UoYY0DWMC0U", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, - sceGnmGetEqEventType); - LIB_FUNCTION("H7-fgvEutM0", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, - sceGnmGetEqTimeStamp); LIB_FUNCTION("oL4hGI1PMpw", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmGetGpuBlockStatus); LIB_FUNCTION("Fwvh++m9IQI", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, From 4abc2dea494660449fbecdf95ed1154fbfe12a20 Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Mon, 21 Apr 2025 23:27:16 -0500 Subject: [PATCH 10/12] Define remaining ioctls --- src/core/devices/gc_device.cpp | 53 ++++++++++++++++++++++++++++++++-- src/core/devices/gc_device.h | 12 +++++++- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/core/devices/gc_device.cpp b/src/core/devices/gc_device.cpp index 94a4a585a..73d486ff8 100644 --- a/src/core/devices/gc_device.cpp +++ b/src/core/devices/gc_device.cpp @@ -22,13 +22,40 @@ s32* submits_addr = 0; s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { auto command = GcCommands(cmd); switch(command) { + case GcCommands::FlushGarlic: { + LOG_ERROR(Lib_GnmDriver, "ioctl FlushGarlic"); + break; + } + case GcCommands::SubmitDone: { + ASSERT(true); + LOG_ERROR(Lib_GnmDriver, "ioctl SubmitDone"); + break; + } + case GcCommands::WaitIdle: { + ASSERT(true); + LOG_ERROR(Lib_GnmDriver, "ioctl WaitIdle"); + break; + } + case GcCommands::WaitFree: { + ASSERT(true); + LOG_ERROR(Lib_GnmDriver, "ioctl WaitFree"); + break; + } case GcCommands::GetNumTcaUnits: { auto data = vaArgPtr(&args->va_list); *data = 0; break; } - case GcCommands::AreSubmitsAllowed: { - LOG_INFO(Lib_GnmDriver, "ioctl AreSubmitsAllowed"); + case GcCommands::SwitchBuffer: { + ASSERT(true); + LOG_ERROR(Lib_GnmDriver, "ioctl SwitchBuffer"); + break; + } + case GcCommands::DebugHardwareStatus: { + break; + } + case GcCommands::InitializeSubmits: { + LOG_INFO(Lib_GnmDriver, "ioctl InitializeSubmits"); if (submits_addr == nullptr) { auto* memory = Core::Memory::Instance(); s32* out_addr; @@ -48,6 +75,10 @@ s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { *submits_addr = 0; break; } + case GcCommands::UnmapComputeQueue: { + LOG_ERROR(Lib_GnmDriver, "ioctl UnmapComputeQueue"); + break; + } case GcCommands::SetGsRingSizes: { auto data = vaArgPtr(&args->va_list); LOG_ERROR(Lib_GnmDriver, "unhandled ioctl SetGsRingSizes, esgs size = {:#x}, gsvs size = {:#x}", data->esgs_ring_size, data->gsvs_ring_size); @@ -69,6 +100,14 @@ s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { data[3] = 0; break; } + case GcCommands::DingDong: { + ASSERT(true); + LOG_ERROR(Lib_GnmDriver, "ioctl DingDong"); + break; + } + case GcCommands::RequiresNeoCompat: { + return POSIX_ENODEV; + } case GcCommands::SubmitEop: { ASSERT(true); LOG_ERROR(Lib_GnmDriver, "ioctl SubmitEop"); @@ -82,7 +121,17 @@ s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { auto data = vaArgPtr(&args->va_list); auto pipe_id = data->pipe_lo - 1; auto ring_size = pow(2, data->ring_size_dw); + data->pipe_priority = 0; LOG_ERROR(Lib_GnmDriver, "ioctl MapComputeQueue, pipe_id = {}", pipe_id); + Libraries::GnmDriver::sceGnmMapComputeQueue(pipe_id, data->queue_id, data->ring_base_addr, ring_size, data->read_ptr_addr); + break; + } + case GcCommands::MapComputeQueueWithPriority: { + ASSERT(true); + auto data = vaArgPtr(&args->va_list); + auto pipe_id = data->pipe_lo - 1; + auto ring_size = pow(2, data->ring_size_dw); + LOG_ERROR(Lib_GnmDriver, "ioctl MapComputeQueueWithPriority, pipe_id = {}", pipe_id); Libraries::GnmDriver::sceGnmMapComputeQueueWithPriority(pipe_id, data->queue_id, data->ring_base_addr, ring_size, data->read_ptr_addr, data->pipe_priority); break; } diff --git a/src/core/devices/gc_device.h b/src/core/devices/gc_device.h index 9e7e01490..4d4dd6a00 100644 --- a/src/core/devices/gc_device.h +++ b/src/core/devices/gc_device.h @@ -30,13 +30,23 @@ public: s64 pwrite(const void* buf, size_t nbytes, u64 offset) override; private: enum class GcCommands : u64 { + FlushGarlic = 0xc0048114, + SubmitDone = 0xc0048116, + WaitIdle = 0xc0048117, + WaitFree = 0xc004811d, GetNumTcaUnits = 0xc004811f, - AreSubmitsAllowed = 0xc008811b, + SwitchBuffer = 0xc0088101, + DebugHardwareStatus = 0xc0088111, + InitializeSubmits = 0xc008811b, + UnmapComputeQueue = 0xc00c810e, SetGsRingSizes = 0xc00c8110, Submit = 0xc0108102, GetCuMask = 0xc010810b, + DingDong = 0xc010811c, + RequiresNeoCompat = 0xc0108120, SubmitEop = 0xc020810c, MapComputeQueue = 0xc030810d, + MapComputeQueueWithPriority = 0xc030811a, SetWaveLimitMultipliers = 0xc030811e, MipStatsReport = 0xc0848119, }; From 5bf4d093442fa2e2c53da081403afaf8d4fa34ac Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Tue, 22 Apr 2025 08:37:27 -0500 Subject: [PATCH 11/12] Fix compile For now, just remove this stuff. --- src/core/devices/gc_device.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/devices/gc_device.cpp b/src/core/devices/gc_device.cpp index 73d486ff8..b8d0569fd 100644 --- a/src/core/devices/gc_device.cpp +++ b/src/core/devices/gc_device.cpp @@ -88,7 +88,6 @@ s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { ASSERT(true); LOG_ERROR(Lib_GnmDriver, "ioctl Submit"); auto data = vaArgPtr(&args->va_list); - auto commands = std::span{data->cmds, data->count}; // Submit ioctl receives an indirect buffer packet break; } @@ -112,7 +111,6 @@ s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { ASSERT(true); LOG_ERROR(Lib_GnmDriver, "ioctl SubmitEop"); auto data = vaArgPtr(&args->va_list); - auto commands = std::span{data->cmds, data->count}; // Submit ioctl receives an indirect buffer packet break; } From de729835d651e71d9113b40993946d42b3332a0c Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Tue, 22 Apr 2025 08:49:55 -0500 Subject: [PATCH 12/12] Clang --- src/core/devices/gc_device.cpp | 27 ++++++++++++++++----------- src/core/devices/gc_device.h | 3 ++- src/core/libraries/kernel/memory.cpp | 7 ++++--- src/core/libraries/kernel/memory.h | 3 ++- src/core/memory.cpp | 8 +++++--- 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/core/devices/gc_device.cpp b/src/core/devices/gc_device.cpp index b8d0569fd..ccaad9b16 100644 --- a/src/core/devices/gc_device.cpp +++ b/src/core/devices/gc_device.cpp @@ -1,12 +1,12 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/assert.h" #include "common/logging/log.h" #include "core/devices/gc_device.h" -#include "core/libraries/kernel/posix_error.h" #include "core/libraries/gnmdriver/gnmdriver.h" +#include "core/libraries/kernel/posix_error.h" #include "core/memory.h" -#include "common/assert.h" namespace Core::Devices { @@ -15,13 +15,11 @@ std::shared_ptr GcDevice::Create(u32 handle, const char*, int, u16) reinterpret_cast(new GcDevice(handle))); } - - s32* submits_addr = 0; s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { auto command = GcCommands(cmd); - switch(command) { + switch (command) { case GcCommands::FlushGarlic: { LOG_ERROR(Lib_GnmDriver, "ioctl FlushGarlic"); break; @@ -61,9 +59,11 @@ s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { s32* out_addr; VAddr in_addr{0xfe0100000}; auto prot = Core::MemoryProt::CpuRead; - auto flags = Core::MemoryMapFlags::Shared | Core::MemoryMapFlags::Anon | Core::MemoryMapFlags::System; + auto flags = Core::MemoryMapFlags::Shared | Core::MemoryMapFlags::Anon | + Core::MemoryMapFlags::System; auto type = Core::VMAType::Direct; - s32 result = memory->MapMemory(reinterpret_cast(&out_addr), in_addr, 0x4000, prot, flags, type); + s32 result = memory->MapMemory(reinterpret_cast(&out_addr), in_addr, 0x4000, + prot, flags, type); if (result != 0) { return POSIX_ENOMEM; } @@ -81,7 +81,9 @@ s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { } case GcCommands::SetGsRingSizes: { auto data = vaArgPtr(&args->va_list); - LOG_ERROR(Lib_GnmDriver, "unhandled ioctl SetGsRingSizes, esgs size = {:#x}, gsvs size = {:#x}", data->esgs_ring_size, data->gsvs_ring_size); + LOG_ERROR(Lib_GnmDriver, + "unhandled ioctl SetGsRingSizes, esgs size = {:#x}, gsvs size = {:#x}", + data->esgs_ring_size, data->gsvs_ring_size); break; } case GcCommands::Submit: { @@ -121,7 +123,8 @@ s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { auto ring_size = pow(2, data->ring_size_dw); data->pipe_priority = 0; LOG_ERROR(Lib_GnmDriver, "ioctl MapComputeQueue, pipe_id = {}", pipe_id); - Libraries::GnmDriver::sceGnmMapComputeQueue(pipe_id, data->queue_id, data->ring_base_addr, ring_size, data->read_ptr_addr); + Libraries::GnmDriver::sceGnmMapComputeQueue(pipe_id, data->queue_id, data->ring_base_addr, + ring_size, data->read_ptr_addr); break; } case GcCommands::MapComputeQueueWithPriority: { @@ -130,7 +133,9 @@ s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { auto pipe_id = data->pipe_lo - 1; auto ring_size = pow(2, data->ring_size_dw); LOG_ERROR(Lib_GnmDriver, "ioctl MapComputeQueueWithPriority, pipe_id = {}", pipe_id); - Libraries::GnmDriver::sceGnmMapComputeQueueWithPriority(pipe_id, data->queue_id, data->ring_base_addr, ring_size, data->read_ptr_addr, data->pipe_priority); + Libraries::GnmDriver::sceGnmMapComputeQueueWithPriority( + pipe_id, data->queue_id, data->ring_base_addr, ring_size, data->read_ptr_addr, + data->pipe_priority); break; } case GcCommands::SetWaveLimitMultipliers: { @@ -140,7 +145,7 @@ s32 GcDevice::ioctl(u64 cmd, Common::VaCtx* args) { } case GcCommands::MipStatsReport: { auto data = vaArgPtr(&args->va_list); - switch(data->type) { + switch (data->type) { case 0x10001: case 0x18001: { break; diff --git a/src/core/devices/gc_device.h b/src/core/devices/gc_device.h index 4d4dd6a00..c95001eb1 100644 --- a/src/core/devices/gc_device.h +++ b/src/core/devices/gc_device.h @@ -28,6 +28,7 @@ public: int ftruncate(s64 length) override; int getdents(void* buf, u32 nbytes, s64* basep) override; s64 pwrite(const void* buf, size_t nbytes, u64 offset) override; + private: enum class GcCommands : u64 { FlushGarlic = 0xc0048114, @@ -62,7 +63,7 @@ private: u32 count; u64* cmds; }; - + struct SubmitEopArgs { u32 pid; u32 count; diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index 3a5a9a703..dfcadaf8e 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -234,8 +234,8 @@ s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, std::size_t Core::VMAType::Flexible, name); } -s32 PS4_SYSV_ABI sceKernelMapNamedSystemFlexibleMemory(void** addr_in_out, std::size_t len, int prot, - int flags, const char* name) { +s32 PS4_SYSV_ABI sceKernelMapNamedSystemFlexibleMemory(void** addr_in_out, std::size_t len, + int prot, int flags, const char* name) { if (len == 0 || !Common::Is16KBAligned(len)) { LOG_ERROR(Kernel_Vmm, "len is 0 or not 16kb multiple"); return ORBIS_KERNEL_ERROR_EINVAL; @@ -609,7 +609,8 @@ void RegisterMemory(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("PGhQHd-dzv8", "libkernel", 1, "libkernel", 1, 1, sceKernelMmap); LIB_FUNCTION("cQke9UuBQOk", "libkernel", 1, "libkernel", 1, 1, sceKernelMunmap); LIB_FUNCTION("mL8NDH86iQI", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedFlexibleMemory); - LIB_FUNCTION("kc+LEEIYakc", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedSystemFlexibleMemory); + LIB_FUNCTION("kc+LEEIYakc", "libkernel", 1, "libkernel", 1, 1, + sceKernelMapNamedSystemFlexibleMemory); LIB_FUNCTION("aNz11fnnzi4", "libkernel", 1, "libkernel", 1, 1, sceKernelAvailableFlexibleMemorySize); LIB_FUNCTION("aNz11fnnzi4", "libkernel_avlfmem", 1, "libkernel", 1, 1, diff --git a/src/core/libraries/kernel/memory.h b/src/core/libraries/kernel/memory.h index 2a86f3843..517c1c1c8 100644 --- a/src/core/libraries/kernel/memory.h +++ b/src/core/libraries/kernel/memory.h @@ -129,7 +129,8 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolReserve(void* addrIn, size_t len, size_t ali s32 PS4_SYSV_ABI sceKernelMemoryPoolCommit(void* addr, size_t len, int type, int prot, int flags); s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, size_t len, int flags); -int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, size_t offset, void** res); +int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, size_t offset, + void** res); int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index fe52abff7..fae0b4376 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -360,9 +360,11 @@ int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, M return ORBIS_OK; } -int MemoryManager::MapSystemMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, - MemoryMapFlags flags, VMAType type, std::string_view name) { - // If address is 0, this maps to System Reserved memory instead, which starts at address 0x880000000 +int MemoryManager::MapSystemMemory(void** out_addr, VAddr virtual_addr, size_t size, + MemoryProt prot, MemoryMapFlags flags, VMAType type, + std::string_view name) { + // If address is 0, this maps to System Reserved memory. + // System Reserved memory starts at address 0x880000000. VAddr in_addr = virtual_addr; if (in_addr == 0) { static constexpr VAddr KernelAllocBase = 0x880000000ULL;