From 3cb4baed518b3089ebb57675a92cb089b00b8a8a Mon Sep 17 00:00:00 2001 From: DH Date: Thu, 2 Nov 2023 16:26:58 +0300 Subject: [PATCH] [orbis-kernel] do not use linker for exec implement hdd device stub implement /dev/console rw remove dup2 hack fix altstack after execve --- orbis-kernel/src/sys/sys_descrip.cpp | 8 +- orbis-kernel/src/sys/sys_sce.cpp | 8 ++ orbis-kernel/src/sys/sys_sysctl.cpp | 7 +- rpcsx-os/CMakeLists.txt | 1 + rpcsx-os/io-devices.hpp | 3 +- rpcsx-os/iodev/console.cpp | 72 ++++++++++++--- rpcsx-os/iodev/hdd.cpp | 70 +++++++++++++++ rpcsx-os/main.cpp | 127 +++++++++++++++++---------- rpcsx-os/ops.cpp | 73 ++++++--------- rpcsx-os/thread.cpp | 38 ++++++-- rpcsx-os/thread.hpp | 2 + 11 files changed, 284 insertions(+), 125 deletions(-) create mode 100644 rpcsx-os/iodev/hdd.cpp diff --git a/orbis-kernel/src/sys/sys_descrip.cpp b/orbis-kernel/src/sys/sys_descrip.cpp index 6a0d00f0..a64d3bc8 100644 --- a/orbis-kernel/src/sys/sys_descrip.cpp +++ b/orbis-kernel/src/sys/sys_descrip.cpp @@ -6,16 +6,12 @@ orbis::SysResult orbis::sys_getdtablesize(Thread *thread) { return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_dup2(Thread *thread, uint from, uint to) { - if (to == 1 || to == 2) { // HACK: ignore setup /dev/console to stdout/stderr - return {}; - } - - std::lock_guard lock(thread->tproc->fileDescriptors.mutex); - auto file = thread->tproc->fileDescriptors.get(from); + if (file == nullptr) { return ErrorCode::BADF; } + thread->tproc->fileDescriptors.close(to); thread->tproc->fileDescriptors.insert(to, file); return {}; diff --git a/orbis-kernel/src/sys/sys_sce.cpp b/orbis-kernel/src/sys/sys_sce.cpp index 2d377b4b..bca15913 100644 --- a/orbis-kernel/src/sys/sys_sce.cpp +++ b/orbis-kernel/src/sys/sys_sce.cpp @@ -60,6 +60,14 @@ orbis::SysResult orbis::sys_mtypeprotect(Thread *thread /* TODO */) { orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op, uint32_t id, ptr result, ptr value, uint64_t type) { + ORBIS_LOG_ERROR(__FUNCTION__, op, id, type); + thread->where(); + + if (op == 2) { + if (id == 0x2010000) { + return uwrite((ptr)value, 0u); + } + } if (op == 25) { struct nonsys_int { union { diff --git a/orbis-kernel/src/sys/sys_sysctl.cpp b/orbis-kernel/src/sys/sys_sysctl.cpp index efb68f6d..a1d3ab90 100644 --- a/orbis-kernel/src/sys/sys_sysctl.cpp +++ b/orbis-kernel/src/sys/sys_sysctl.cpp @@ -8,8 +8,6 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr name, size_t newlen) { enum sysctl_ctl { unspec, kern, vm, vfs, net, debug, hw, machdep, user }; - // machdep.tsc_freq - enum sysctl_kern { usrstack = 33, kern_14 = 14, @@ -154,11 +152,14 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr name, auto result = uread(thread->tproc->appInfo, (ptr)new_); if (result == ErrorCode{}) { - auto appInfo = thread->tproc->appInfo; + auto &appInfo = thread->tproc->appInfo; ORBIS_LOG_ERROR("set AppInfo", appInfo.appId, appInfo.unk0, appInfo.unk1, appInfo.appType, appInfo.titleId, appInfo.unk2, appInfo.unk3, appInfo.unk5, appInfo.unk6, appInfo.unk7, appInfo.unk8); + + // HACK + appInfo.unk4 = orbis::slong(0x80000000'00000000); } return result; diff --git a/rpcsx-os/CMakeLists.txt b/rpcsx-os/CMakeLists.txt index 242e64ba..194607d6 100644 --- a/rpcsx-os/CMakeLists.txt +++ b/rpcsx-os/CMakeLists.txt @@ -9,6 +9,7 @@ add_executable(rpcsx-os iodev/camera.cpp iodev/cd.cpp iodev/console.cpp + iodev/hdd.cpp iodev/dce.cpp iodev/dipsw.cpp iodev/dmem.cpp diff --git a/rpcsx-os/io-devices.hpp b/rpcsx-os/io-devices.hpp index d7bfd373..a55b6beb 100644 --- a/rpcsx-os/io-devices.hpp +++ b/rpcsx-os/io-devices.hpp @@ -17,7 +17,7 @@ IoDevice *createRngCharacterDevice(); IoDevice *createAjmCharacterDevice(); IoDevice *createIccConfigurationCharacterDevice(); IoDevice *createNpdrmCharacterDevice(); -IoDevice *createConsoleCharacterDevice(); +IoDevice *createConsoleCharacterDevice(int inputFd, int outputFd); IoDevice *createSblSrvCharacterDevice(); IoDevice *createShmDevice(); IoDevice *createBlockPoolDevice(); @@ -29,3 +29,4 @@ IoDevice *createBtCharacterDevice(); IoDevice *createXptCharacterDevice(); IoDevice *createCdCharacterDevice(); IoDevice *createMetaDbgCharacterDevice(); +IoDevice *createHddCharacterDevice(); diff --git a/rpcsx-os/iodev/console.cpp b/rpcsx-os/iodev/console.cpp index ca1f2804..66ac19b9 100644 --- a/rpcsx-os/iodev/console.cpp +++ b/rpcsx-os/iodev/console.cpp @@ -1,32 +1,78 @@ #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" +#include "orbis/error/ErrorCode.hpp" #include "orbis/file.hpp" +#include "orbis/uio.hpp" #include "orbis/utils/Logs.hpp" +#include +#include struct ConsoleFile : orbis::File {}; +struct ConsoleDevice : IoDevice { + int inputFd; + int outputFd; + + ConsoleDevice(int inputFd, int outputFd) + : inputFd(inputFd), outputFd(outputFd) {} + + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode, + orbis::Thread *thread) override; +}; static orbis::ErrorCode console_ioctl(orbis::File *file, std::uint64_t request, - void *argp, orbis::Thread *thread) { + void *argp, orbis::Thread *thread) { ORBIS_LOG_FATAL("Unhandled console ioctl", request); return {}; } +static orbis::ErrorCode console_read(orbis::File *file, orbis::Uio *uio, + orbis::Thread *thread) { + auto dev = dynamic_cast(file->device.get()); + + for (auto vec : std::span(uio->iov, uio->iovcnt)) { + auto result = ::read(dev->inputFd, vec.base, vec.len); + + if (result < 0) { + return orbis::ErrorCode::IO; + } + + uio->offset += result; + break; + } + return {}; +} + +static orbis::ErrorCode console_write(orbis::File *file, orbis::Uio *uio, + orbis::Thread *thread) { + auto dev = dynamic_cast(file->device.get()); + + for (auto vec : std::span(uio->iov, uio->iovcnt)) { + ::write(dev->outputFd, vec.base, vec.len); + } + uio->resid = 0; + return {}; +} + static const orbis::FileOps fileOps = { .ioctl = console_ioctl, + .read = console_read, + .write = console_write, }; -struct ConsoleDevice : 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; +orbis::ErrorCode ConsoleDevice::open(orbis::Ref *file, + const char *path, std::uint32_t flags, + std::uint32_t mode, + orbis::Thread *thread) { + auto newFile = orbis::knew(); + newFile->ops = &fileOps; + newFile->device = this; - *file = newFile; - return {}; - } -}; + *file = newFile; + return {}; +} -IoDevice *createConsoleCharacterDevice() { return orbis::knew(); } +IoDevice *createConsoleCharacterDevice(int inputFd, int outputFd) { + return orbis::knew(inputFd, outputFd); +} diff --git a/rpcsx-os/iodev/hdd.cpp b/rpcsx-os/iodev/hdd.cpp new file mode 100644 index 00000000..5fcb6e81 --- /dev/null +++ b/rpcsx-os/iodev/hdd.cpp @@ -0,0 +1,70 @@ +#include "io-device.hpp" +#include "orbis/KernelAllocator.hpp" +#include "orbis/error/ErrorCode.hpp" +#include "orbis/file.hpp" +#include "orbis/thread/Thread.hpp" +#include "orbis/uio.hpp" +#include "orbis/utils/Logs.hpp" +#include + +struct HddFile : orbis::File {}; + +static orbis::ErrorCode hdd_ioctl(orbis::File *fs, std::uint64_t request, + void *argp, orbis::Thread *thread) { + + if (request == 0x40046480) { // DIOCGSECTORSIZE + return orbis::uwrite(orbis::ptr(argp), 0x1000u); + } + + ORBIS_LOG_FATAL("Unhandled hdd ioctl", request); + thread->where(); + return {}; +} + +static orbis::ErrorCode hdd_read(orbis::File *file, orbis::Uio *uio, + orbis::Thread *thread) { + auto dev = file->device.get(); + + ORBIS_LOG_ERROR(__FUNCTION__, uio->offset); + for (auto vec : std::span(uio->iov, uio->iovcnt)) { + std::memset(vec.base, 0, vec.len); + + // HACK: dummy UFS header + if (uio->offset == 0x10000) { + *(uint32_t *)((char *)vec.base + 0x55c) = 0x19540119; + *(uint64_t *)((char *)vec.base + 0x3e8) = 0x1000; + *(uint8_t *)((char *)vec.base + 0xd3) = 1; + *(uint8_t *)((char *)vec.base + 0xd1) = 1; + } + uio->offset += vec.len; + } + return {}; +} + + +static orbis::ErrorCode hdd_stat(orbis::File *fs, orbis::Stat *sb, + orbis::Thread *thread) { + // TODO + return {}; +} + +static const orbis::FileOps fsOps = { + .ioctl = hdd_ioctl, + .read = hdd_read, + .stat = hdd_stat, +}; + +struct HddDevice : IoDevice { + orbis::ErrorCode open(orbis::Ref *fs, const char *path, + std::uint32_t flags, std::uint32_t mode, + orbis::Thread *thread) override { + auto newFile = orbis::knew(); + newFile->ops = &fsOps; + newFile->device = this; + + *fs = newFile; + return {}; + } +}; + +IoDevice *createHddCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/main.cpp b/rpcsx-os/main.cpp index 402b2d08..f09cf9b9 100644 --- a/rpcsx-os/main.cpp +++ b/rpcsx-os/main.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,7 @@ #include #include #include +#include #include #include @@ -160,23 +162,29 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) { } void setupSigHandlers() { - auto sigStackSize = std::max( - SIGSTKSZ, utils::alignUp(8 * 1024 * 1024, sysconf(_SC_PAGE_SIZE))); + stack_t oss{}; - stack_t ss{}; - ss.ss_sp = malloc(sigStackSize); - if (ss.ss_sp == NULL) { - perror("malloc"); - exit(EXIT_FAILURE); - } + // if (sigaltstack(nullptr, &oss) < 0 || oss.ss_size == 0) { + auto sigStackSize = std::max( + SIGSTKSZ, utils::alignUp(64 * 1024 * 1024, sysconf(_SC_PAGE_SIZE))); - ss.ss_size = sigStackSize; - ss.ss_flags = 1 << 31; + stack_t ss{}; + ss.ss_sp = malloc(sigStackSize); + if (ss.ss_sp == NULL) { + perror("malloc"); + exit(EXIT_FAILURE); + } - if (sigaltstack(&ss, NULL) == -1) { - perror("sigaltstack"); - exit(EXIT_FAILURE); - } + ss.ss_size = sigStackSize; + ss.ss_flags = 1 << 31; + + std::fprintf(stderr, "installing sp [%p, %p]\n", ss.ss_sp, (char *)ss.ss_sp + ss.ss_size); + + if (sigaltstack(&ss, NULL) == -1) { + perror("sigaltstack"); + exit(EXIT_FAILURE); + } + // } struct sigaction act {}; act.sa_sigaction = handle_signal; @@ -309,24 +317,23 @@ static void ps4InitDev() { auto dmem1 = createDmemCharacterDevice(1); orbis::g_context.dmemDevice = dmem1; - auto stdoutDev = createFdWrapDevice(::open("stdout.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666)); - auto stderrDev = createFdWrapDevice(::open("stderr.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666)); - auto stdinDev = createFdWrapDevice(STDIN_FILENO); + auto consoleDev = createConsoleCharacterDevice( + STDIN_FILENO, ::open("tty.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666)); rx::vfs::addDevice("dmem0", createDmemCharacterDevice(0)); rx::vfs::addDevice("npdrm", createNpdrmCharacterDevice()); rx::vfs::addDevice("icc_configuration", createIccConfigurationCharacterDevice()); - rx::vfs::addDevice("console", createConsoleCharacterDevice()); + rx::vfs::addDevice("console", consoleDev); rx::vfs::addDevice("camera", createCameraCharacterDevice()); rx::vfs::addDevice("dmem1", dmem1); rx::vfs::addDevice("dmem2", createDmemCharacterDevice(2)); - rx::vfs::addDevice("stdout", stdoutDev); - rx::vfs::addDevice("stderr", stderrDev); - rx::vfs::addDevice("deci_stdin", stdinDev); - rx::vfs::addDevice("deci_stdout", stdoutDev); - rx::vfs::addDevice("deci_stderr", stderrDev); - rx::vfs::addDevice("stdin", stdinDev); + rx::vfs::addDevice("stdout", consoleDev); + rx::vfs::addDevice("stderr", consoleDev); + rx::vfs::addDevice("deci_stdin", consoleDev); + rx::vfs::addDevice("deci_stdout", consoleDev); + rx::vfs::addDevice("deci_stderr", consoleDev); + rx::vfs::addDevice("stdin", consoleDev); rx::vfs::addDevice("zero", createZeroCharacterDevice()); rx::vfs::addDevice("null", createNullCharacterDevice()); rx::vfs::addDevice("dipsw", createDipswCharacterDevice()); @@ -346,6 +353,20 @@ static void ps4InitDev() { rx::vfs::addDevice("bt", createBtCharacterDevice()); rx::vfs::addDevice("xpt0", createXptCharacterDevice()); rx::vfs::addDevice("cd0", createXptCharacterDevice()); + rx::vfs::addDevice("da0x0.crypt", createHddCharacterDevice()); + rx::vfs::addDevice("da0x1.crypt", createHddCharacterDevice()); + rx::vfs::addDevice("da0x2.crypt", createHddCharacterDevice()); + rx::vfs::addDevice("da0x3.crypt", createHddCharacterDevice()); + rx::vfs::addDevice("da0x4.crypt", createHddCharacterDevice()); + rx::vfs::addDevice("da0x5.crypt", createHddCharacterDevice()); + // rx::vfs::addDevice("da0x6x0", createHddCharacterDevice()); // boot log + rx::vfs::addDevice("da0x6x2.crypt", createHddCharacterDevice()); + rx::vfs::addDevice("da0x8", createHddCharacterDevice()); + rx::vfs::addDevice("da0x9.crypt", createHddCharacterDevice()); + rx::vfs::addDevice("da0x12.crypt", createHddCharacterDevice()); + rx::vfs::addDevice("da0x13.crypt", createHddCharacterDevice()); + rx::vfs::addDevice("da0x14.crypt", createHddCharacterDevice()); + rx::vfs::addDevice("da0x15", createHddCharacterDevice()); rx::vfs::addDevice("notification0", createNotificationCharacterDevice(0)); rx::vfs::addDevice("notification1", createNotificationCharacterDevice(1)); rx::vfs::addDevice("notification2", createNotificationCharacterDevice(2)); @@ -374,7 +395,7 @@ int ps4Exec(orbis::Thread *mainThread, orbis::utils::Ref executableModule, std::span argv, std::span envp) { const auto stackEndAddress = 0x7'ffff'c000ull; - const auto stackSize = 0x40000 * 16; + const auto stackSize = 0x40000 * 32; auto stackStartAddress = stackEndAddress - stackSize; mainThread->stackStart = rx::vm::map(reinterpret_cast(stackStartAddress), stackSize, @@ -388,32 +409,39 @@ int ps4Exec(orbis::Thread *mainThread, std::vector argvOffsets; std::vector envpOffsets; - auto libSceLibcInternal = rx::linker::loadModuleFile( - "/system/common/lib/libSceLibcInternal.sprx", mainThread); + std::uint64_t interpBase = 0; + std::uint64_t entryPoint = executableModule->entryPoint; - if (libSceLibcInternal == nullptr) { - std::fprintf(stderr, "libSceLibcInternal not found\n"); - return 1; - } + if (executableModule->type != rx::linker::kElfTypeExec) { + auto libSceLibcInternal = rx::linker::loadModuleFile( + "/system/common/lib/libSceLibcInternal.sprx", mainThread); - libSceLibcInternal->id = - mainThread->tproc->modulesMap.insert(libSceLibcInternal); + if (libSceLibcInternal == nullptr) { + std::fprintf(stderr, "libSceLibcInternal not found\n"); + return 1; + } - auto libkernel = rx::linker::loadModuleFile( - "/system/common/lib/libkernel_sys.sprx", mainThread); + libSceLibcInternal->id = + mainThread->tproc->modulesMap.insert(libSceLibcInternal); - if (libkernel == nullptr) { - std::fprintf(stderr, "libkernel not found\n"); - return 1; - } + auto libkernel = rx::linker::loadModuleFile( + "/system/common/lib/libkernel_sys.sprx", mainThread); - libkernel->id = mainThread->tproc->modulesMap.insert(libkernel); + if (libkernel == nullptr) { + std::fprintf(stderr, "libkernel not found\n"); + return 1; + } - // *reinterpret_cast( - // reinterpret_cast(libkernel->base) + 0x6c2e4) = ~0; + libkernel->id = mainThread->tproc->modulesMap.insert(libkernel); + interpBase = reinterpret_cast(libkernel->base); + entryPoint = libkernel->entryPoint; - // *reinterpret_cast( - // reinterpret_cast(libkernel->base) + 0x71300) = ~0; + // *reinterpret_cast( + // reinterpret_cast(libkernel->base) + 0x6c2e4) = ~0; + + // *reinterpret_cast( + // reinterpret_cast(libkernel->base) + 0x71300) = ~0; + } StackWriter stack{reinterpret_cast(mainThread->stackEnd)}; @@ -432,7 +460,7 @@ int ps4Exec(orbis::Thread *mainThread, // clang-format off std::uint64_t auxv[] = { AT_ENTRY, executableModule->entryPoint, - AT_BASE, reinterpret_cast(libkernel->base), + AT_BASE, interpBase, AT_NULL, 0 }; // clang-format on @@ -466,8 +494,7 @@ int ps4Exec(orbis::Thread *mainThread, // FIXME: should be at guest user space context->uc_mcontext.gregs[REG_RDX] = reinterpret_cast(+[] { std::printf("At exit\n"); }); - ; - context->uc_mcontext.gregs[REG_RIP] = libkernel->entryPoint; + context->uc_mcontext.gregs[REG_RIP] = entryPoint; mainThread->context = context; rx::thread::invoke(mainThread); @@ -744,6 +771,12 @@ int main(int argc, const char *argv[]) { initProcess->processParam = executableModule->processParam; initProcess->processParamSize = executableModule->processParamSize; + 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); + } + if (executableModule->type == rx::linker::kElfTypeSceDynExec || executableModule->type == rx::linker::kElfTypeSceExec || executableModule->type == rx::linker::kElfTypeExec) { diff --git a/rpcsx-os/ops.cpp b/rpcsx-os/ops.cpp index 199ca710..a4c0172d 100644 --- a/rpcsx-os/ops.cpp +++ b/rpcsx-os/ops.cpp @@ -2,6 +2,7 @@ #include "align.hpp" #include "backtrace.hpp" #include "io-device.hpp" +#include "io-devices.hpp" #include "iodev/blockpool.hpp" #include "iodev/dmem.hpp" #include "linker.hpp" @@ -28,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -500,25 +502,6 @@ SysResult thr_new(orbis::Thread *thread, orbis::ptr param, childThread->stackStart); auto stdthr = std::thread{[=, childThread = Ref(childThread)] { - stack_t ss{}; - - auto sigStackSize = std::max( - SIGSTKSZ, ::utils::alignUp(8 * 1024 * 1024, sysconf(_SC_PAGE_SIZE))); - - ss.ss_sp = malloc(sigStackSize); - if (ss.ss_sp == NULL) { - perror("malloc"); - ::exit(EXIT_FAILURE); - } - - ss.ss_size = sigStackSize; - ss.ss_flags = 1 << 31; - - if (sigaltstack(&ss, NULL) == -1) { - perror("sigaltstack"); - ::exit(EXIT_FAILURE); - } - static_cast( uwrite(_param.child_tid, slong(childThread->tid))); // TODO: verify auto context = new ucontext_t{}; @@ -534,6 +517,9 @@ SysResult thr_new(orbis::Thread *thread, orbis::ptr param, childThread->context = context; childThread->state = orbis::ThreadState::RUNNING; + + rx::thread::setupSignalStack(); + rx::thread::setupThisThread(); rx::thread::invoke(childThread.get()); }}; @@ -632,18 +618,17 @@ SysResult fork(Thread *thread, slong flags) { ORBIS_LOG_TODO(__FUNCTION__, flags); auto childPid = g_context.allocatePid() * 10000 + 1; - auto mtx = knew(); - auto cv = knew(); - mtx->lock(); + auto flag = knew>(); + *flag = false; int hostPid = ::fork(); if (hostPid) { - cv->wait(*mtx); - mtx->unlock(); + while (*flag == false) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } - kdelete(cv); - kdelete(mtx); + kfree(flag, sizeof(*flag)); thread->retval[0] = childPid; thread->retval[1] = 0; @@ -674,7 +659,7 @@ SysResult fork(Thread *thread, slong flags) { rx::vm::fork(thread->tproc->pid); rx::vfs::fork(); - cv->notify_all(*mtx); + *flag = true; auto [baseId, newThread] = process->threadsMap.emplace(); newThread->tproc = process; @@ -691,33 +676,14 @@ SysResult fork(Thread *thread, slong flags) { setupSigHandlers(); rx::thread::initialize(); + rx::thread::setupThisThread(); - if (prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, - (void *)0x100'0000'0000, ~0ull - 0x100'0000'0000, nullptr)) { - perror("prctl failed\n"); - std::exit(-1); - } - - auto stdoutFd = - ::open(("stdout-" + std::to_string(thread->tproc->pid) + ".txt").c_str(), - O_CREAT | O_TRUNC | O_WRONLY, 0666); - auto stderrFd = - ::open(("stderr-" + std::to_string(thread->tproc->pid) + ".txt").c_str(), - O_CREAT | O_TRUNC | O_WRONLY, 0666); auto logFd = ::open(("log-" + std::to_string(thread->tproc->pid) + ".txt").c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0666); dup2(logFd, 1); dup2(logFd, 2); - - auto stdoutDev = createFdWrapDevice(stdoutFd); - auto stderrDev = createFdWrapDevice(stderrFd); - - rx::vfs::addDevice("stdout", stdoutDev); - rx::vfs::addDevice("stderr", stderrDev); - rx::vfs::addDevice("deci_stdout", stdoutDev); - rx::vfs::addDevice("deci_stderr", stderrDev); return {}; } @@ -768,7 +734,18 @@ SysResult execve(Thread *thread, ptr fname, ptr> argv, thread->tproc->processParam = executableModule->processParam; thread->tproc->processParamSize = executableModule->processParamSize; - ps4Exec(thread, executableModule, _argv, _envv); + auto name = path; + if (auto slashP = name.rfind('/'); slashP != std::string::npos) { + name = name.substr(slashP + 1); + } + + pthread_setname_np(pthread_self(), name.c_str()); + + std::thread([&] { + rx::thread::setupSignalStack(); + rx::thread::setupThisThread(); + ps4Exec(thread, executableModule, _argv, _envv); + }).join(); std::abort(); } diff --git a/rpcsx-os/thread.cpp b/rpcsx-os/thread.cpp index fa42f1c2..41bdd40d 100644 --- a/rpcsx-os/thread.cpp +++ b/rpcsx-os/thread.cpp @@ -1,4 +1,5 @@ #include "thread.hpp" +#include "align.hpp" #include "orbis/sys/sysentry.hpp" #include "orbis/thread/Process.hpp" #include "orbis/thread/Thread.hpp" @@ -61,25 +62,48 @@ void rx::thread::initialize() { void rx::thread::deinitialize() {} -void rx::thread::invoke(orbis::Thread *thread) { - orbis::g_currentThread = thread; +void rx::thread::setupSignalStack() { + stack_t ss{}; + + auto sigStackSize = std::max( + SIGSTKSZ, ::utils::alignUp(64 * 1024 * 1024, sysconf(_SC_PAGE_SIZE))); + + ss.ss_sp = malloc(sigStackSize); + if (ss.ss_sp == NULL) { + perror("malloc"); + std::exit(EXIT_FAILURE); + } + + ss.ss_size = sigStackSize; + ss.ss_flags = 1 << 31; + if (sigaltstack(&ss, NULL) == -1) { + perror("sigaltstack"); + std::exit(EXIT_FAILURE); + } +} + +void rx::thread::setupThisThread() { sigset_t unblockSigs{}; sigset_t oldSigmask{}; sigaddset(&unblockSigs, SIGSYS); if (pthread_sigmask(SIG_UNBLOCK, &unblockSigs, &oldSigmask)) { perror("pthread_sigmask failed\n"); - exit(-1); + std::exit(-1); } - std::uint64_t hostFs = _readfsbase_u64(); - _writegsbase_u64(hostFs); - 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); + std::exit(-1); } +} + +void rx::thread::invoke(orbis::Thread *thread) { + orbis::g_currentThread = thread; + + std::uint64_t hostFs = _readfsbase_u64(); + _writegsbase_u64(hostFs); _writefsbase_u64(thread->fsBase); auto context = reinterpret_cast(thread->context); diff --git a/rpcsx-os/thread.hpp b/rpcsx-os/thread.hpp index 035225ea..2794e8b9 100644 --- a/rpcsx-os/thread.hpp +++ b/rpcsx-os/thread.hpp @@ -5,6 +5,8 @@ namespace rx::thread { void initialize(); void deinitialize(); +void setupSignalStack(); +void setupThisThread(); void invoke(orbis::Thread *thread); } // namespace rx::thread