mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-20 15:40:30 +01:00
[orbis-kernel] do not use linker for exec
implement hdd device stub implement /dev/console rw remove dup2 hack fix altstack after execve
This commit is contained in:
parent
3464f50eb9
commit
3cb4baed51
|
|
@ -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 {};
|
||||
|
|
|
|||
|
|
@ -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<void> result,
|
||||
ptr<void> value, uint64_t type) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, op, id, type);
|
||||
thread->where();
|
||||
|
||||
if (op == 2) {
|
||||
if (id == 0x2010000) {
|
||||
return uwrite((ptr<uint>)value, 0u);
|
||||
}
|
||||
}
|
||||
if (op == 25) {
|
||||
struct nonsys_int {
|
||||
union {
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> 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<sint> name,
|
|||
|
||||
auto result = uread(thread->tproc->appInfo, (ptr<AppInfo>)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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 <span>
|
||||
#include <unistd.h>
|
||||
|
||||
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<orbis::File> *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<ConsoleDevice *>(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<ConsoleDevice *>(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<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override {
|
||||
auto newFile = orbis::knew<ConsoleFile>();
|
||||
newFile->ops = &fileOps;
|
||||
newFile->device = this;
|
||||
orbis::ErrorCode ConsoleDevice::open(orbis::Ref<orbis::File> *file,
|
||||
const char *path, std::uint32_t flags,
|
||||
std::uint32_t mode,
|
||||
orbis::Thread *thread) {
|
||||
auto newFile = orbis::knew<ConsoleFile>();
|
||||
newFile->ops = &fileOps;
|
||||
newFile->device = this;
|
||||
|
||||
*file = newFile;
|
||||
return {};
|
||||
}
|
||||
};
|
||||
*file = newFile;
|
||||
return {};
|
||||
}
|
||||
|
||||
IoDevice *createConsoleCharacterDevice() { return orbis::knew<ConsoleDevice>(); }
|
||||
IoDevice *createConsoleCharacterDevice(int inputFd, int outputFd) {
|
||||
return orbis::knew<ConsoleDevice>(inputFd, outputFd);
|
||||
}
|
||||
|
|
|
|||
70
rpcsx-os/iodev/hdd.cpp
Normal file
70
rpcsx-os/iodev/hdd.cpp
Normal file
|
|
@ -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 <span>
|
||||
|
||||
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<orbis::uint>(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<orbis::File> *fs, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override {
|
||||
auto newFile = orbis::knew<HddFile>();
|
||||
newFile->ops = &fsOps;
|
||||
newFile->device = this;
|
||||
|
||||
*fs = newFile;
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
IoDevice *createHddCharacterDevice() { return orbis::knew<HddDevice>(); }
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
#include <atomic>
|
||||
#include <elf.h>
|
||||
#include <filesystem>
|
||||
#include <linux/prctl.h>
|
||||
#include <orbis/KernelContext.hpp>
|
||||
#include <orbis/module.hpp>
|
||||
#include <orbis/module/Module.hpp>
|
||||
|
|
@ -25,6 +26,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#include <csignal>
|
||||
|
|
@ -160,23 +162,29 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) {
|
|||
}
|
||||
|
||||
void setupSigHandlers() {
|
||||
auto sigStackSize = std::max<std::size_t>(
|
||||
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<std::size_t>(
|
||||
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<orbis::Module> executableModule,
|
||||
std::span<std::string> argv, std::span<std::string> 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<void *>(stackStartAddress), stackSize,
|
||||
|
|
@ -388,33 +409,40 @@ int ps4Exec(orbis::Thread *mainThread,
|
|||
std::vector<std::uint64_t> argvOffsets;
|
||||
std::vector<std::uint64_t> 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);
|
||||
|
||||
if (libSceLibcInternal == nullptr) {
|
||||
std::fprintf(stderr, "libSceLibcInternal not found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
libSceLibcInternal->id =
|
||||
mainThread->tproc->modulesMap.insert(libSceLibcInternal);
|
||||
|
||||
auto libkernel = rx::linker::loadModuleFile(
|
||||
"/system/common/lib/libkernel_sys.sprx", mainThread);
|
||||
|
||||
if (libkernel == nullptr) {
|
||||
std::fprintf(stderr, "libkernel not found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
libkernel->id = mainThread->tproc->modulesMap.insert(libkernel);
|
||||
interpBase = reinterpret_cast<std::uint64_t>(libkernel->base);
|
||||
entryPoint = libkernel->entryPoint;
|
||||
|
||||
// *reinterpret_cast<std::uint32_t *>(
|
||||
// reinterpret_cast<std::byte *>(libkernel->base) + 0x6c2e4) = ~0;
|
||||
|
||||
// *reinterpret_cast<std::uint32_t *>(
|
||||
// reinterpret_cast<std::byte *>(libkernel->base) + 0x71300) = ~0;
|
||||
}
|
||||
|
||||
libSceLibcInternal->id =
|
||||
mainThread->tproc->modulesMap.insert(libSceLibcInternal);
|
||||
|
||||
auto libkernel = rx::linker::loadModuleFile(
|
||||
"/system/common/lib/libkernel_sys.sprx", mainThread);
|
||||
|
||||
if (libkernel == nullptr) {
|
||||
std::fprintf(stderr, "libkernel not found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
libkernel->id = mainThread->tproc->modulesMap.insert(libkernel);
|
||||
|
||||
// *reinterpret_cast<std::uint32_t *>(
|
||||
// reinterpret_cast<std::byte *>(libkernel->base) + 0x6c2e4) = ~0;
|
||||
|
||||
// *reinterpret_cast<std::uint32_t *>(
|
||||
// reinterpret_cast<std::byte *>(libkernel->base) + 0x71300) = ~0;
|
||||
|
||||
StackWriter stack{reinterpret_cast<std::uint64_t>(mainThread->stackEnd)};
|
||||
|
||||
for (auto &elem : argv) {
|
||||
|
|
@ -432,7 +460,7 @@ int ps4Exec(orbis::Thread *mainThread,
|
|||
// clang-format off
|
||||
std::uint64_t auxv[] = {
|
||||
AT_ENTRY, executableModule->entryPoint,
|
||||
AT_BASE, reinterpret_cast<std::uint64_t>(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::uint64_t>(+[] { 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) {
|
||||
|
|
|
|||
|
|
@ -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 <map>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <sys/prctl.h>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
|
|
@ -500,25 +502,6 @@ SysResult thr_new(orbis::Thread *thread, orbis::ptr<thr_param> param,
|
|||
childThread->stackStart);
|
||||
|
||||
auto stdthr = std::thread{[=, childThread = Ref<Thread>(childThread)] {
|
||||
stack_t ss{};
|
||||
|
||||
auto sigStackSize = std::max<std::size_t>(
|
||||
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<void>(
|
||||
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<thr_param> 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<shared_mutex>();
|
||||
auto cv = knew<shared_cv>();
|
||||
mtx->lock();
|
||||
auto flag = knew<std::atomic<bool>>();
|
||||
*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<char> fname, ptr<ptr<char>> 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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<std::size_t>(
|
||||
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<ucontext_t *>(thread->context);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
namespace rx::thread {
|
||||
void initialize();
|
||||
void deinitialize();
|
||||
void setupSignalStack();
|
||||
void setupThisThread();
|
||||
|
||||
void invoke(orbis::Thread *thread);
|
||||
} // namespace rx::thread
|
||||
|
|
|
|||
Loading…
Reference in a new issue