From e9897441fec78a6357d524d3c0d74df2a17b158e Mon Sep 17 00:00:00 2001 From: DH Date: Tue, 31 Oct 2023 14:22:22 +0300 Subject: [PATCH] [orbis-kernel] Initial rfork implementation --- orbis-kernel/include/orbis/sys/sysproto.hpp | 2 +- orbis-kernel/include/orbis/thread/Thread.hpp | 2 + orbis-kernel/include/orbis/utils/IdMap.hpp | 56 +++++++++++++++++++- orbis-kernel/src/KernelContext.cpp | 5 +- orbis-kernel/src/sys/sys_fork.cpp | 44 ++++++++++++++- orbis-kernel/src/sys/sys_sce.cpp | 32 +++++------ orbis-kernel/src/sysvec.cpp | 2 + rpcsx-os/CMakeLists.txt | 3 ++ rpcsx-os/io-devices.hpp | 3 ++ rpcsx-os/iodev/bt.cpp | 32 +++++++++++ rpcsx-os/iodev/cd.cpp | 32 +++++++++++ rpcsx-os/iodev/notification.cpp | 9 ++++ rpcsx-os/iodev/xpt.cpp | 38 +++++++++++++ rpcsx-os/main.cpp | 37 +++++++------ rpcsx-os/ops.cpp | 17 +++--- rpcsx-os/thread.cpp | 29 +++++++--- rpcsx-os/thread.hpp | 1 - 17 files changed, 294 insertions(+), 50 deletions(-) create mode 100644 rpcsx-os/iodev/bt.cpp create mode 100644 rpcsx-os/iodev/cd.cpp create mode 100644 rpcsx-os/iodev/xpt.cpp diff --git a/orbis-kernel/include/orbis/sys/sysproto.hpp b/orbis-kernel/include/orbis/sys/sysproto.hpp index d19f150bf..ea368d542 100644 --- a/orbis-kernel/include/orbis/sys/sysproto.hpp +++ b/orbis-kernel/include/orbis/sys/sysproto.hpp @@ -659,7 +659,7 @@ SysResult sys_opmc_get_ctr(Thread *thread /* TODO */); SysResult sys_budget_create(Thread *thread /* TODO */); SysResult sys_budget_delete(Thread *thread /* TODO */); SysResult sys_budget_get(Thread *thread /* TODO */); -SysResult sys_budget_set(Thread *thread /* TODO */); +SysResult sys_budget_set(Thread *thread, slong budget); SysResult sys_virtual_query(Thread *thread, ptr addr, uint64_t unk, ptr info, size_t infosz); SysResult sys_mdbg_call(Thread *thread /* TODO */); diff --git a/orbis-kernel/include/orbis/thread/Thread.hpp b/orbis-kernel/include/orbis/thread/Thread.hpp index 262417575..6e9a8b211 100644 --- a/orbis-kernel/include/orbis/thread/Thread.hpp +++ b/orbis-kernel/include/orbis/thread/Thread.hpp @@ -39,4 +39,6 @@ struct Thread { void incRef() {} void decRef() {} }; + +extern thread_local Thread *g_currentThread; } // namespace orbis diff --git a/orbis-kernel/include/orbis/utils/IdMap.hpp b/orbis-kernel/include/orbis/utils/IdMap.hpp index 416388fd1..b3d420478 100644 --- a/orbis-kernel/include/orbis/utils/IdMap.hpp +++ b/orbis-kernel/include/orbis/utils/IdMap.hpp @@ -33,6 +33,16 @@ class RcIdMap { } } + bool insert(std::size_t index, T *object) { + if (mask.test(index)) { + return false; + } + + mask.set(index); + objects[index] = object; + return true; + } + std::size_t insert(T *object) { std::size_t index = mask.countr_one(); mask.set(index); @@ -117,6 +127,28 @@ public: end_iterator end() const { return {}; } private: + bool insert_impl(IdT id, T *object) { + std::lock_guard lock(mutex); + + auto raw = static_cast(id); + auto page = (raw - MinId) / ChunkSize; + auto index = (raw - MinId) % ChunkSize; + + if (page >= ChunkCount) { + return false; + } + + if (!m_chunks[page].insert(index, object)) { + return false; + } + + if (m_chunks[page].mask.full()) { + m_fullChunks.set(page); + } + + return true; + } + IdT insert_impl(T *object) { std::lock_guard lock(mutex); @@ -159,7 +191,29 @@ public: return result; } - T *get(IdT id) { + bool insert(IdT id, T *object) { + if (insert_impl(id, object)) { + object->incRef(); + return true; + } + + return false; + } + + bool insert(IdT id, const Ref &ref) { return insert(id, ref.get()); } + + bool insert(IdT id, Ref &&ref) { + auto object = ref.release(); + + if (!insert_impl(id, object)) { + object->decRef(); + return false; + } + + return true; + } + + Ref get(IdT id) { const auto rawId = static_cast(id) - MinId; if (rawId >= MaxId - MinId) { diff --git a/orbis-kernel/src/KernelContext.cpp b/orbis-kernel/src/KernelContext.cpp index d90e4a29e..26a2689c2 100644 --- a/orbis-kernel/src/KernelContext.cpp +++ b/orbis-kernel/src/KernelContext.cpp @@ -6,11 +6,14 @@ #include namespace orbis { +thread_local Thread *g_currentThread; + KernelContext &g_context = *[]() -> KernelContext * { // Allocate global shared kernel memory // TODO: randomize for hardening and reduce size auto ptr = mmap(reinterpret_cast(0x200'0000'0000), 0x1'0000'0000, - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0); + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0); if (!ptr) std::abort(); diff --git a/orbis-kernel/src/sys/sys_fork.cpp b/orbis-kernel/src/sys/sys_fork.cpp index 52b0c472d..681d581f9 100644 --- a/orbis-kernel/src/sys/sys_fork.cpp +++ b/orbis-kernel/src/sys/sys_fork.cpp @@ -1,10 +1,52 @@ +#include "KernelContext.hpp" #include "sys/sysproto.hpp" +#include "utils/Logs.hpp" +#include +#include orbis::SysResult orbis::sys_fork(Thread *thread) { return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_pdfork(Thread *thread, ptr fdp, sint flags) { return ErrorCode::NOSYS; } + orbis::SysResult orbis::sys_vfork(Thread *thread) { return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_rfork(Thread *thread, sint flags) { - return ErrorCode::NOSYS; + ORBIS_LOG_TODO(__FUNCTION__, flags); + + int hostPid = ::fork(); + if (hostPid) { + thread->retval[0] = 10001; + thread->retval[1] = 0; + } else { + auto process = g_context.createProcess(10001); + std::lock_guard lock(thread->tproc->fileDescriptors.mutex); + process->sysent = thread->tproc->sysent; + process->onSysEnter = thread->tproc->onSysEnter; + process->onSysExit = thread->tproc->onSysExit; + process->ops = thread->tproc->ops; + process->isSystem = thread->tproc->isSystem; + for (auto [id, mod] : thread->tproc->modulesMap) { + if (!process->modulesMap.insert(id, mod)) { + std::abort(); + } + } + + for (auto [id, mod] : thread->tproc->fileDescriptors) { + if (!process->fileDescriptors.insert(id, mod)) { + std::abort(); + } + } + + auto [baseId, newThread] = process->threadsMap.emplace(); + newThread->tproc = process; + newThread->tid = process->pid + baseId; + newThread->state = orbis::ThreadState::RUNNING; + newThread->context = thread->context; + newThread->fsBase = thread->fsBase; + + orbis::g_currentThread = newThread; + newThread->retval[0] = 0; + newThread->retval[1] = 1; + } + return {}; } diff --git a/orbis-kernel/src/sys/sys_sce.cpp b/orbis-kernel/src/sys/sys_sce.cpp index 39796bf12..94c368ba5 100644 --- a/orbis-kernel/src/sys/sys_sce.cpp +++ b/orbis-kernel/src/sys/sys_sce.cpp @@ -51,7 +51,7 @@ orbis::SysResult orbis::sys_socketclose(Thread *thread, sint fd) { return ErrorCode::BADF; } orbis::SysResult orbis::sys_netgetiflist(Thread *thread /* TODO */) { - return ErrorCode::NOSYS; + return {}; } orbis::SysResult orbis::sys_mtypeprotect(Thread *thread /* TODO */) { @@ -215,8 +215,9 @@ orbis::SysResult orbis::sys_evf_open(Thread *thread, ptr name) { return sys_evf_create(thread, name, kEvfAttrShared, 0x400000); } - if (std::string_view("SceShellCoreUtilAppFocus") == _name) { - return sys_evf_create(thread, name, kEvfAttrShared, 1); + if (std::string_view("SceShellCoreUtilAppFocus") == _name || + std::string_view("SceBootStatusFlags") == _name) { + return sys_evf_create(thread, name, kEvfAttrShared, 0x2408); } return sys_evf_create(thread, name, kEvfAttrShared, 0); return ErrorCode::SRCH; @@ -290,7 +291,7 @@ orbis::SysResult orbis::sys_evf_trywait(Thread *thread, sint id, auto result = evf->tryWait(thread, mode, patternSet); ORBIS_LOG_TRACE(__FUNCTION__, evf->name, thread->tid, id, patternSet, mode, - pPatternSet, result); + pPatternSet, result); if (pPatternSet != nullptr) { uwrite(pPatternSet, thread->evfResultPattern); @@ -332,7 +333,7 @@ orbis::SysResult orbis::sys_evf_cancel(Thread *thread, sint id, uint64_t value, } ORBIS_LOG_TRACE(__FUNCTION__, evf->name, thread->tid, id, value, - pNumWaitThreads); + pNumWaitThreads); auto numWaitThreads = evf->cancel(value); if (pNumWaitThreads != 0) { @@ -403,7 +404,7 @@ orbis::SysResult orbis::sys_osem_create(Thread *thread, return {}; } orbis::SysResult orbis::sys_osem_delete(Thread *thread, sint id) { - ORBIS_LOG_WARNING(__FUNCTION__, id); + ORBIS_LOG_TRACE(__FUNCTION__, id); Ref sem = thread->tproc->semMap.get(id); if (sem == nullptr) { return ErrorCode::SRCH; @@ -444,7 +445,7 @@ orbis::SysResult orbis::sys_osem_open(Thread *thread, return {}; } orbis::SysResult orbis::sys_osem_close(Thread *thread, sint id) { - ORBIS_LOG_WARNING(__FUNCTION__, id); + ORBIS_LOG_TRACE(__FUNCTION__, id); if (!thread->tproc->semMap.close(id)) { return ErrorCode::SRCH; } @@ -473,7 +474,7 @@ orbis::SysResult orbis::sys_osem_wait(Thread *thread, sint id, sint need, return {}; } orbis::SysResult orbis::sys_osem_trywait(Thread *thread, sint id, sint need) { - ORBIS_LOG_NOTICE(__FUNCTION__, thread, id, need); + ORBIS_LOG_TRACE(__FUNCTION__, thread, id, need); Ref sem = thread->tproc->semMap.get(id); if (need < 1 || need > sem->maxValue) return ErrorCode::INVAL; @@ -485,7 +486,7 @@ orbis::SysResult orbis::sys_osem_trywait(Thread *thread, sint id, sint need) { return {}; } orbis::SysResult orbis::sys_osem_post(Thread *thread, sint id, sint count) { - ORBIS_LOG_NOTICE(__FUNCTION__, thread, id, count); + ORBIS_LOG_WARNING(__FUNCTION__, thread, id, count); Ref sem = thread->tproc->semMap.get(id); if (count < 1 || count > sem->maxValue - sem->value) return ErrorCode::INVAL; @@ -500,6 +501,7 @@ orbis::SysResult orbis::sys_osem_post(Thread *thread, sint id, sint count) { orbis::SysResult orbis::sys_osem_cancel(Thread *thread, sint id, sint set, ptr pNumWaitThreads) { ORBIS_LOG_TODO(__FUNCTION__, thread, id, set, pNumWaitThreads); + std::abort(); return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_namedobj_create(Thread *thread, @@ -589,8 +591,9 @@ orbis::SysResult orbis::sys_budget_delete(Thread *thread /* TODO */) { orbis::SysResult orbis::sys_budget_get(Thread *thread /* TODO */) { return ErrorCode::NOSYS; } -orbis::SysResult orbis::sys_budget_set(Thread *thread /* TODO */) { - return ErrorCode::NOSYS; +orbis::SysResult orbis::sys_budget_set(Thread *thread, slong budget) { + ORBIS_LOG_TODO(__FUNCTION__, budget); + return {}; } orbis::SysResult orbis::sys_virtual_query(Thread *thread, ptr addr, uint64_t unk, ptr info, @@ -601,9 +604,7 @@ orbis::SysResult orbis::sys_virtual_query(Thread *thread, ptr addr, return ErrorCode::NOSYS; } -orbis::SysResult orbis::sys_mdbg_call(Thread *thread /* TODO */) { - return ErrorCode::NOSYS; -} +orbis::SysResult orbis::sys_mdbg_call(Thread *thread /* TODO */) { return {}; } orbis::SysResult orbis::sys_obs_sblock_create(Thread *thread /* TODO */) { return ErrorCode::NOSYS; } @@ -942,7 +943,8 @@ orbis::sys_dynlib_get_info_ex(Thread *thread, SceKernelModule handle, return uwrite(destModuleInfoEx, result); } orbis::SysResult orbis::sys_budget_getid(Thread *thread) { - return ErrorCode::NOSYS; + thread->retval[0] = 1; + return {}; } orbis::SysResult orbis::sys_budget_get_ptype(Thread *thread, sint budgetId) { thread->retval[0] = 1; diff --git a/orbis-kernel/src/sysvec.cpp b/orbis-kernel/src/sysvec.cpp index 5bc1a3648..8eb1bfb87 100644 --- a/orbis-kernel/src/sysvec.cpp +++ b/orbis-kernel/src/sysvec.cpp @@ -57,6 +57,8 @@ void orbis::syscall_entry(Thread *thread) { auto result = sysent.call(thread, args); + thread = orbis::g_currentThread; + if (thread->tproc->onSysExit != nullptr) { thread->tproc->onSysExit(thread, syscall_num, args, sysent.narg, result); diff --git a/rpcsx-os/CMakeLists.txt b/rpcsx-os/CMakeLists.txt index b51c0ade5..f64e343d6 100644 --- a/rpcsx-os/CMakeLists.txt +++ b/rpcsx-os/CMakeLists.txt @@ -5,7 +5,9 @@ add_library(orbis::kernel::config ALIAS standalone-config) add_executable(rpcsx-os iodev/ajm.cpp iodev/blockpool.cpp + iodev/bt.cpp iodev/camera.cpp + iodev/cd.cpp iodev/console.cpp iodev/dce.cpp iodev/dipsw.cpp @@ -25,6 +27,7 @@ add_executable(rpcsx-os iodev/sbl_srv.cpp iodev/shm.cpp iodev/urandom.cpp + iodev/xpt.cpp iodev/zero.cpp main.cpp diff --git a/rpcsx-os/io-devices.hpp b/rpcsx-os/io-devices.hpp index 4d5c4989a..4e250f1ad 100644 --- a/rpcsx-os/io-devices.hpp +++ b/rpcsx-os/io-devices.hpp @@ -25,3 +25,6 @@ IoDevice *createUrandomCharacterDevice(); IoDevice *createCameraCharacterDevice(); IoDevice *createNotificationCharacterDevice(int index); IoDevice *createMBusCharacterDevice(); +IoDevice *createBtCharacterDevice(); +IoDevice *createXptCharacterDevice(); +IoDevice *createCdCharacterDevice(); diff --git a/rpcsx-os/iodev/bt.cpp b/rpcsx-os/iodev/bt.cpp new file mode 100644 index 000000000..7b5d1aaf8 --- /dev/null +++ b/rpcsx-os/iodev/bt.cpp @@ -0,0 +1,32 @@ +#include "io-device.hpp" +#include "orbis/KernelAllocator.hpp" +#include "orbis/file.hpp" +#include "orbis/utils/Logs.hpp" + +struct BtFile : orbis::File {}; + +static orbis::ErrorCode bt_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { + + ORBIS_LOG_FATAL("Unhandled bt ioctl", request); + return {}; +} + +static const orbis::FileOps fileOps = { + .ioctl = bt_ioctl, +}; + +struct BtDevice : IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode, + orbis::Thread *thread) override { + auto newFile = orbis::knew(); + newFile->ops = &fileOps; + newFile->device = this; + + *file = newFile; + return {}; + } +}; + +IoDevice *createBtCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/iodev/cd.cpp b/rpcsx-os/iodev/cd.cpp new file mode 100644 index 000000000..77171aeaf --- /dev/null +++ b/rpcsx-os/iodev/cd.cpp @@ -0,0 +1,32 @@ +#include "io-device.hpp" +#include "orbis/KernelAllocator.hpp" +#include "orbis/file.hpp" +#include "orbis/utils/Logs.hpp" + +struct CdFile : orbis::File {}; + +static orbis::ErrorCode cd_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { + + ORBIS_LOG_FATAL("Unhandled cd ioctl", request); + return {}; +} + +static const orbis::FileOps fileOps = { + .ioctl = cd_ioctl, +}; + +struct CdDevice : IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode, + orbis::Thread *thread) override { + auto newFile = orbis::knew(); + newFile->ops = &fileOps; + newFile->device = this; + + *file = newFile; + return {}; + } +}; + +IoDevice *createCdCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/iodev/notification.cpp b/rpcsx-os/iodev/notification.cpp index 1c6d23a81..09a087b3d 100644 --- a/rpcsx-os/iodev/notification.cpp +++ b/rpcsx-os/iodev/notification.cpp @@ -2,6 +2,8 @@ #include "orbis/KernelAllocator.hpp" #include "orbis/file.hpp" #include "orbis/utils/Logs.hpp" +#include +#include struct NotificationFile : orbis::File {}; struct NotificationDevice : IoDevice { @@ -20,8 +22,15 @@ static orbis::ErrorCode notification_ioctl(orbis::File *file, std::uint64_t requ return {}; } +static orbis::ErrorCode notification_read(orbis::File *file, orbis::Uio *uio, orbis::Thread *thread) { + ORBIS_LOG_FATAL("Unhandled notification_read"); + std::this_thread::sleep_for(std::chrono::hours(120)); + return {}; +} + static const orbis::FileOps fileOps = { .ioctl = notification_ioctl, + .read = notification_read, }; orbis::ErrorCode NotificationDevice::open(orbis::Ref *file, const char *path, diff --git a/rpcsx-os/iodev/xpt.cpp b/rpcsx-os/iodev/xpt.cpp new file mode 100644 index 000000000..653131f7a --- /dev/null +++ b/rpcsx-os/iodev/xpt.cpp @@ -0,0 +1,38 @@ +#include "io-device.hpp" +#include "orbis/KernelAllocator.hpp" +#include "orbis/file.hpp" +#include "orbis/utils/Logs.hpp" +#include "orbis/thread/Thread.hpp" +#include + +struct XptFile : orbis::File {}; + +static orbis::ErrorCode xpt_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { + + ORBIS_LOG_FATAL("Unhandled xpt ioctl", request); + if (request == 0xc4a81602) { + thread->where(); + std::this_thread::sleep_for(std::chrono::hours(120)); + } + return {}; +} + +static const orbis::FileOps fileOps = { + .ioctl = xpt_ioctl, +}; + +struct XptDevice : IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode, + orbis::Thread *thread) override { + auto newFile = orbis::knew(); + newFile->ops = &fileOps; + newFile->device = this; + + *file = newFile; + return {}; + } +}; + +IoDevice *createXptCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/main.cpp b/rpcsx-os/main.cpp index 897c7168b..1e7b9231a 100644 --- a/rpcsx-os/main.cpp +++ b/rpcsx-os/main.cpp @@ -41,7 +41,7 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) { auto signalAddress = reinterpret_cast(info->si_addr); - if (rx::thread::g_current != nullptr && sig == SIGSEGV && + if (orbis::g_currentThread != nullptr && sig == SIGSEGV && signalAddress >= 0x40000 && signalAddress < 0x100'0000'0000) { auto ctx = reinterpret_cast(ucontext); bool isWrite = (ctx->uc_mcontext.gregs[REG_ERR] & 0x2) != 0; @@ -103,7 +103,7 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) { std::abort(); } - _writefsbase_u64(rx::thread::g_current->fsBase); + _writefsbase_u64(orbis::g_currentThread->fsBase); return; } @@ -120,22 +120,22 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) { if (sig != SIGINT) { char buf[128] = ""; int len = snprintf(buf, sizeof(buf), " [%s] %u: Signal address=%p\n", - rx::thread::g_current ? "guest" : "host", - rx::thread::g_current ? rx::thread::g_current->tid - : ::gettid(), + orbis::g_currentThread ? "guest" : "host", + orbis::g_currentThread ? orbis::g_currentThread->tid + : ::gettid(), info->si_addr); write(2, buf, len); if (std::size_t printed = - rx::printAddressLocation(buf, sizeof(buf), rx::thread::g_current, + rx::printAddressLocation(buf, sizeof(buf), orbis::g_currentThread, (std::uint64_t)info->si_addr)) { printed += std::snprintf(buf + printed, sizeof(buf) - printed, "\n"); write(2, buf, printed); } - if (rx::thread::g_current) { + if (orbis::g_currentThread) { rx::printStackTrace(reinterpret_cast(ucontext), - rx::thread::g_current, 2); + orbis::g_currentThread, 2); } else { rx::printStackTrace(reinterpret_cast(ucontext), 2); } @@ -159,10 +159,11 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) { } } -static void setupSigHandlers() { - stack_t ss; +void setupSigHandlers() { auto sigStackSize = std::max( SIGSTKSZ, utils::alignUp(8 * 1024 * 1024, sysconf(_SC_PAGE_SIZE))); + + stack_t ss{}; ss.ss_sp = malloc(sigStackSize); if (ss.ss_sp == NULL) { perror("malloc"); @@ -170,7 +171,7 @@ static void setupSigHandlers() { } ss.ss_size = sigStackSize; - ss.ss_flags = 0; + ss.ss_flags = 1 << 31; if (sigaltstack(&ss, NULL) == -1) { perror("sigaltstack"); @@ -250,7 +251,7 @@ static const char *getSyscallName(orbis::Thread *thread, int sysno) { } static void onSysEnter(orbis::Thread *thread, int id, uint64_t *args, int argsCount) { - if (!g_traceSyscalls) { + if (!g_traceSyscalls && thread->tid < 10000) { return; } flockfile(stderr); @@ -276,7 +277,7 @@ static void onSysEnter(orbis::Thread *thread, int id, uint64_t *args, static void onSysExit(orbis::Thread *thread, int id, uint64_t *args, int argsCount, orbis::SysResult result) { - if (!result.isError() && !g_traceSyscalls) { + if (!result.isError() && !g_traceSyscalls && thread->tid < 10000) { return; } @@ -327,7 +328,8 @@ static int ps4Exec(orbis::Thread *mainThread, rx::vfs::addDevice("dmem0", createDmemCharacterDevice(0)); rx::vfs::addDevice("npdrm", createNpdrmCharacterDevice()); - rx::vfs::addDevice("icc_configuration", createIccConfigurationCharacterDevice()); + rx::vfs::addDevice("icc_configuration", + createIccConfigurationCharacterDevice()); rx::vfs::addDevice("console", createConsoleCharacterDevice()); rx::vfs::addDevice("camera", createCameraCharacterDevice()); rx::vfs::addDevice("dmem1", dmem1); @@ -353,6 +355,9 @@ static int ps4Exec(orbis::Thread *mainThread, rx::vfs::addDevice("ajm", createAjmCharacterDevice()); rx::vfs::addDevice("urandom", createUrandomCharacterDevice()); rx::vfs::addDevice("mbus", createMBusCharacterDevice()); + rx::vfs::addDevice("bt", createBtCharacterDevice()); + rx::vfs::addDevice("xpt0", createXptCharacterDevice()); + rx::vfs::addDevice("cd0", createXptCharacterDevice()); rx::vfs::addDevice("notification0", createNotificationCharacterDevice(0)); rx::vfs::addDevice("notification1", createNotificationCharacterDevice(1)); rx::vfs::addDevice("notification2", createNotificationCharacterDevice(2)); @@ -385,7 +390,8 @@ static int ps4Exec(orbis::Thread *mainThread, return 1; } - libSceLibcInternal->id = mainThread->tproc->modulesMap.insert(libSceLibcInternal); + libSceLibcInternal->id = + mainThread->tproc->modulesMap.insert(libSceLibcInternal); auto libkernel = rx::linker::loadModuleFile( "/system/common/lib/libkernel_sys.sprx", mainThread); @@ -403,7 +409,6 @@ static int ps4Exec(orbis::Thread *mainThread, // *reinterpret_cast( // reinterpret_cast(libkernel->base) + 0x71300) = ~0; - StackWriter stack{reinterpret_cast(mainThread->stackEnd)}; for (auto elem : argv) { diff --git a/rpcsx-os/ops.cpp b/rpcsx-os/ops.cpp index 77837a870..720a16ea0 100644 --- a/rpcsx-os/ops.cpp +++ b/rpcsx-os/ops.cpp @@ -167,7 +167,8 @@ orbis::SysResult mmap(orbis::Thread *thread, orbis::caddr_t addr, } void *maddr = addr; - auto result = file->ops->mmap(file, &maddr, len, prot, flags, pos, thread); + auto result = + file->ops->mmap(file.get(), &maddr, len, prot, flags, pos, thread); if (result != ErrorCode{}) { return result; @@ -282,7 +283,8 @@ orbis::SysResult rmdir(Thread *thread, ptr path) { ORBIS_LOG_TODO(__FUNCTION__, path); return rx::vfs::rmdir(path, thread); } -orbis::SysResult rename(Thread *thread, ptr from, ptr to) { +orbis::SysResult rename(Thread *thread, ptr from, + ptr to) { ORBIS_LOG_TODO(__FUNCTION__, from, to); return rx::vfs::rename(from, to, thread); } @@ -317,7 +319,7 @@ orbis::SysResult blockpool_unmap(orbis::Thread *thread, orbis::caddr_t addr, orbis::SysResult socket(orbis::Thread *thread, orbis::ptr name, orbis::sint domain, orbis::sint type, orbis::sint protocol, Ref *file) { - return createSocket(file, name, domain, type, protocol); + return createSocket(file, name ? name : "", domain, type, protocol); } orbis::SysResult shm_unlink(orbis::Thread *thread, const char *path) { @@ -376,7 +378,7 @@ orbis::SysResult dynlib_dlsym(orbis::Thread *thread, orbis::ModuleHandle handle, std::string_view symView(symbol); if (auto nid = rx::linker::decodeNid(symView)) { - if (auto addr = findSymbolById(module, *nid)) { + if (auto addr = findSymbolById(module.get(), *nid)) { *addrp = addr; return {}; } @@ -386,7 +388,8 @@ orbis::SysResult dynlib_dlsym(orbis::Thread *thread, orbis::ModuleHandle handle, module->moduleName, rx::linker::encodeNid(rx::linker::encodeFid(symView)).string); - if (auto addr = findSymbolById(module, rx::linker::encodeFid(symView))) { + if (auto addr = + findSymbolById(module.get(), rx::linker::encodeFid(symView))) { *addrp = addr; return {}; } @@ -486,7 +489,7 @@ SysResult thr_new(orbis::Thread *thread, orbis::ptr param, childThread->stackStart); auto stdthr = std::thread{[=, childThread = Ref(childThread)] { - stack_t ss; + stack_t ss{}; auto sigStackSize = std::max( SIGSTKSZ, ::utils::alignUp(8 * 1024 * 1024, sysconf(_SC_PAGE_SIZE))); @@ -498,7 +501,7 @@ SysResult thr_new(orbis::Thread *thread, orbis::ptr param, } ss.ss_size = sigStackSize; - ss.ss_flags = 0; + ss.ss_flags = 1 << 31; if (sigaltstack(&ss, NULL) == -1) { perror("sigaltstack"); diff --git a/rpcsx-os/thread.cpp b/rpcsx-os/thread.cpp index 5f85c0ee0..a5c59f0c3 100644 --- a/rpcsx-os/thread.cpp +++ b/rpcsx-os/thread.cpp @@ -1,6 +1,7 @@ #include "thread.hpp" #include "backtrace.hpp" #include "orbis/sys/sysentry.hpp" +#include "orbis/thread/Thread.hpp" #include #include #include @@ -12,8 +13,6 @@ #include #include -thread_local orbis::Thread *rx::thread::g_current = nullptr; - static auto setContext = [] { struct SetContext : Xbyak::CodeGenerator { SetContext() { @@ -34,6 +33,8 @@ static auto setContext = [] { return setContextStorage.getCode(); }(); +void setupSigHandlers(); + static __attribute__((no_stack_protector)) void handleSigSys(int sig, siginfo_t *info, void *ucontext) { if (auto hostFs = _readgsbase_u64()) { @@ -42,10 +43,24 @@ handleSigSys(int sig, siginfo_t *info, void *ucontext) { // rx::printStackTrace(reinterpret_cast(ucontext), // rx::thread::g_current, 1); - auto prevContext = std::exchange(rx::thread::g_current->context, ucontext); - orbis::syscall_entry(rx::thread::g_current); - rx::thread::g_current->context = prevContext; - _writefsbase_u64(rx::thread::g_current->fsBase); + auto thread = orbis::g_currentThread; + auto prevContext = std::exchange(thread->context, ucontext); + orbis::syscall_entry(thread); + if (thread != orbis::g_currentThread) { + thread = orbis::g_currentThread; + + setupSigHandlers(); + rx::thread::initialize(); + + if (prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, + (void *)0x100'0000'0000, ~0ull - 0x100'0000'0000, nullptr)) { + perror("prctl failed\n"); + exit(-1); + } + } + + thread->context = prevContext; + _writefsbase_u64(thread->fsBase); } void rx::thread::initialize() { @@ -62,7 +77,7 @@ void rx::thread::initialize() { void rx::thread::deinitialize() {} void rx::thread::invoke(orbis::Thread *thread) { - g_current = thread; + orbis::g_currentThread = thread; sigset_t unblockSigs{}; sigset_t oldSigmask{}; diff --git a/rpcsx-os/thread.hpp b/rpcsx-os/thread.hpp index 74452e9fd..035225eaa 100644 --- a/rpcsx-os/thread.hpp +++ b/rpcsx-os/thread.hpp @@ -6,6 +6,5 @@ namespace rx::thread { void initialize(); void deinitialize(); -extern thread_local orbis::Thread *g_current; void invoke(orbis::Thread *thread); } // namespace rx::thread