From 84b24192411422b58d3b60d66304ffa2038edeaa Mon Sep 17 00:00:00 2001 From: DH Date: Sat, 29 Jul 2023 19:53:34 +0300 Subject: [PATCH] [rpcsx-os] Use orbis::File instead of IoDeviceInstance --- .../include/orbis/KernelAllocator.hpp | 5 +- orbis-kernel/include/orbis/file.hpp | 25 +- orbis-kernel/include/orbis/sys/sysproto.hpp | 34 +- orbis-kernel/include/orbis/thread/Process.hpp | 5 +- .../include/orbis/thread/ProcessOps.hpp | 20 +- orbis-kernel/include/orbis/uio.hpp | 4 +- orbis-kernel/include/orbis/utils/Logs.hpp | 1 - orbis-kernel/src/sys/sys_descrip.cpp | 54 ++- orbis-kernel/src/sys/sys_event.cpp | 2 +- orbis-kernel/src/sys/sys_generic.cpp | 304 ++++++++++++++-- orbis-kernel/src/sys/sys_jail.cpp | 4 +- orbis-kernel/src/sys/sys_sce.cpp | 19 +- orbis-kernel/src/sys/sys_uipc.cpp | 4 +- orbis-kernel/src/sys/sys_vfs.cpp | 111 ++++-- orbis-kernel/src/sys/sys_vfs_mount.cpp | 4 +- orbis-kernel/src/utils/Logs.cpp | 293 ++++++++++++++++ rpcsx-os/CMakeLists.txt | 3 - rpcsx-os/io-device.cpp | 321 ++++++++++++----- rpcsx-os/io-device.hpp | 44 +-- rpcsx-os/io-devices.hpp | 3 - rpcsx-os/iodev/ajm.cpp | 42 ++- rpcsx-os/iodev/dce.cpp | 113 +++--- rpcsx-os/iodev/dipsw.cpp | 49 ++- rpcsx-os/iodev/dmem.cpp | 79 +++-- rpcsx-os/iodev/gc.cpp | 77 ++--- rpcsx-os/iodev/hid.cpp | 53 ++- rpcsx-os/iodev/hmd_3da.cpp | 45 +-- rpcsx-os/iodev/hmd_cmd.cpp | 45 ++- rpcsx-os/iodev/hmd_mmap.cpp | 65 ++-- rpcsx-os/iodev/hmd_snsr.cpp | 43 ++- rpcsx-os/iodev/null.cpp | 42 +-- rpcsx-os/iodev/rng.cpp | 63 ++-- rpcsx-os/iodev/stderr.cpp | 56 --- rpcsx-os/iodev/stdin.cpp | 28 -- rpcsx-os/iodev/stdout.cpp | 54 --- rpcsx-os/iodev/zero.cpp | 48 +-- rpcsx-os/linker.cpp | 62 ++-- rpcsx-os/linker.hpp | 4 +- rpcsx-os/main.cpp | 71 ++-- rpcsx-os/ops.cpp | 326 ++---------------- rpcsx-os/scheduler.hpp | 152 ++++++++ rpcsx-os/vfs.cpp | 6 +- rpcsx-os/vfs.hpp | 4 +- 43 files changed, 1626 insertions(+), 1161 deletions(-) delete mode 100644 rpcsx-os/iodev/stderr.cpp delete mode 100644 rpcsx-os/iodev/stdin.cpp delete mode 100644 rpcsx-os/iodev/stdout.cpp create mode 100644 rpcsx-os/scheduler.hpp diff --git a/orbis-kernel/include/orbis/KernelAllocator.hpp b/orbis-kernel/include/orbis/KernelAllocator.hpp index bc6a641c7..a43713248 100644 --- a/orbis-kernel/include/orbis/KernelAllocator.hpp +++ b/orbis-kernel/include/orbis/KernelAllocator.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -46,7 +47,9 @@ using kunmap = std::unordered_map>>; } // namespace utils -template T *knew(Args &&...args) { +template + requires(std::is_constructible_v) +T *knew(Args &&...args) { auto loc = static_cast(utils::kalloc(sizeof(T), alignof(T))); auto res = std::construct_at(loc, std::forward(args)...); if constexpr (requires(T *t) { t->_total_size = sizeof(T); }) diff --git a/orbis-kernel/include/orbis/file.hpp b/orbis-kernel/include/orbis/file.hpp index b58cf0428..a12e985e0 100644 --- a/orbis-kernel/include/orbis/file.hpp +++ b/orbis-kernel/include/orbis/file.hpp @@ -1,8 +1,8 @@ #pragma once -#include "KernelAllocator.hpp" #include "error/ErrorCode.hpp" -#include +#include "utils/Rc.hpp" +#include "utils/SharedMutex.hpp" #include namespace orbis { @@ -16,10 +16,8 @@ struct FileOps { std::int32_t flags; ErrorCode (*ioctl)(File *file, std::uint64_t request, void *argp, Thread *thread) = nullptr; - ErrorCode (*rdwr)(File *file, Uio *uio, Thread *thread) = nullptr; - ErrorCode (*close)(File *file, Thread *thread) = nullptr; - ErrorCode (*lseek)(File *file, std::uint64_t *offset, std::uint32_t whence, - Thread *thread) = nullptr; + ErrorCode (*read)(File *file, Uio *uio, Thread *thread) = nullptr; + ErrorCode (*write)(File *file, Uio *uio, Thread *thread) = nullptr; ErrorCode (*truncate)(File *file, std::uint64_t len, Thread *thread) = nullptr; @@ -40,17 +38,10 @@ struct FileOps { Thread *thread) = nullptr; }; -struct File final { - FileOps *ops; +struct File : RcBase { + shared_mutex mtx; + const FileOps *ops = nullptr; Ref device; - std::atomic refs{0}; - - void incRef() { refs.fetch_add(1, std::memory_order::acquire); } - - void decRef() { - if (refs.fetch_sub(1, std::memory_order::release) == 1) { - kdelete(this); - } - } + std::uint64_t nextOff = 0; }; } // namespace orbis diff --git a/orbis-kernel/include/orbis/sys/sysproto.hpp b/orbis-kernel/include/orbis/sys/sysproto.hpp index 7b9075677..ec95ced58 100644 --- a/orbis-kernel/include/orbis/sys/sysproto.hpp +++ b/orbis-kernel/include/orbis/sys/sysproto.hpp @@ -18,6 +18,7 @@ struct KEvent; struct timespec; struct Stat; struct stack_t; +struct IoVec; SysResult nosys(Thread *thread); @@ -126,10 +127,8 @@ SysResult sys_gettimeofday(Thread *thread, ptr tp, SysResult sys_getrusage(Thread *thread, sint who, ptr rusage); SysResult sys_getsockopt(Thread *thread, sint s, sint level, sint name, caddr_t val, ptr avalsize); -SysResult sys_readv(Thread *thread, sint fd, ptr iovp, - uint iovcnt); -SysResult sys_writev(Thread *thread, sint fd, ptr iovp, - uint iovcnt); +SysResult sys_readv(Thread *thread, sint fd, ptr iovp, uint iovcnt); +SysResult sys_writev(Thread *thread, sint fd, ptr iovp, uint iovcnt); SysResult sys_settimeofday(Thread *thread, ptr tp, ptr tzp); SysResult sys_fchown(Thread *thread, sint fd, sint uid, sint gid); @@ -249,10 +248,10 @@ SysResult sys_lutimes(Thread *thread, ptr path, ptr tptr); SysResult sys_nstat(Thread *thread, ptr path, ptr ub); SysResult sys_nfstat(Thread *thread, sint fd, ptr sb); SysResult sys_nlstat(Thread *thread, ptr path, ptr ub); -SysResult sys_preadv(Thread *thread, sint fd, ptr iovp, - uint iovcnt, off_t offset); -SysResult sys_pwritev(Thread *thread, sint fd, ptr iovp, - uint iovcnt, off_t offset); +SysResult sys_preadv(Thread *thread, sint fd, ptr iovp, uint iovcnt, + off_t offset); +SysResult sys_pwritev(Thread *thread, sint fd, ptr iovp, uint iovcnt, + off_t offset); SysResult sys_fhopen(Thread *thread, ptr u_fhp, sint flags); SysResult sys_fhstat(Thread *thread, ptr u_fhp, @@ -361,8 +360,7 @@ SysResult sys_eaccess(Thread *thread, ptr path, sint flags); SysResult sys_afs3_syscall(Thread *thread, slong syscall, slong param1, slong param2, slong param3, slong param4, slong param5, slong param6); -SysResult sys_nmount(Thread *thread, ptr iovp, uint iovcnt, - sint flags); +SysResult sys_nmount(Thread *thread, ptr iovp, uint iovcnt, sint flags); SysResult sys___mac_get_proc(Thread *thread, ptr mac_p); SysResult sys___mac_set_proc(Thread *thread, ptr mac_p); SysResult sys___mac_get_fd(Thread *thread, sint fd, ptr mac_p); @@ -494,14 +492,14 @@ SysResult sys_sctp_generic_sendmsg(Thread *thread, sint sd, caddr_t msg, sint mlen, caddr_t to, __socklen_t tolen, ptr sinfo, sint flags); -SysResult sys_sctp_generic_sendmsg_iov(Thread *thread, sint sd, - ptr iov, sint iovlen, - caddr_t to, __socklen_t tolen, +SysResult sys_sctp_generic_sendmsg_iov(Thread *thread, sint sd, ptr iov, + sint iovlen, caddr_t to, + __socklen_t tolen, ptr sinfo, sint flags); -SysResult sys_sctp_generic_recvmsg(Thread *thread, sint sd, - ptr iov, sint iovlen, - caddr_t from, __socklen_t fromlen, +SysResult sys_sctp_generic_recvmsg(Thread *thread, sint sd, ptr iov, + sint iovlen, caddr_t from, + __socklen_t fromlen, ptr sinfo, sint flags); SysResult sys_pread(Thread *thread, sint fd, ptr buf, size_t nbyte, @@ -557,9 +555,9 @@ SysResult sys_symlinkat(Thread *thread, ptr path1, sint fd, SysResult sys_unlinkat(Thread *thread, sint fd, ptr path, sint flag); SysResult sys_posix_openpt(Thread *thread, sint flags); SysResult sys_gssd_syscall(Thread *thread, ptr path); -SysResult sys_jail_get(Thread *thread, ptr iovp, uint iovcnt, +SysResult sys_jail_get(Thread *thread, ptr iovp, uint iovcnt, sint flags); -SysResult sys_jail_set(Thread *thread, ptr iovp, uint iovcnt, +SysResult sys_jail_set(Thread *thread, ptr iovp, uint iovcnt, sint flags); SysResult sys_jail_remove(Thread *thread, sint jid); SysResult sys_closefrom(Thread *thread, sint lowfd); diff --git a/orbis-kernel/include/orbis/thread/Process.hpp b/orbis-kernel/include/orbis/thread/Process.hpp index fdfdd601a..6599bc390 100644 --- a/orbis-kernel/include/orbis/thread/Process.hpp +++ b/orbis-kernel/include/orbis/thread/Process.hpp @@ -6,12 +6,11 @@ #include "../thread/Thread.hpp" #include "../thread/types.hpp" #include "ProcessState.hpp" +#include "orbis/file.hpp" #include "orbis/module/Module.hpp" #include "orbis/utils/IdMap.hpp" #include "orbis/utils/SharedMutex.hpp" -#include - namespace orbis { class KernelContext; struct Thread; @@ -61,7 +60,7 @@ struct Process final { utils::RcIdMap semMap; utils::RcIdMap modulesMap; utils::OwningIdMap threadsMap; - utils::RcIdMap fileDescriptors; + utils::RcIdMap fileDescriptors; // Named objects for debugging utils::shared_mutex namedObjMutex; diff --git a/orbis-kernel/include/orbis/thread/ProcessOps.hpp b/orbis-kernel/include/orbis/thread/ProcessOps.hpp index 85fa0f17f..1086756cd 100644 --- a/orbis-kernel/include/orbis/thread/ProcessOps.hpp +++ b/orbis-kernel/include/orbis/thread/ProcessOps.hpp @@ -3,11 +3,13 @@ #include "../module/ModuleHandle.hpp" #include "../thread/types.hpp" #include "orbis-config.hpp" +#include "orbis/utils/Rc.hpp" namespace orbis { struct Thread; struct Module; struct timespec; +struct File; struct ProcessOps { SysResult (*mmap)(Thread *thread, caddr_t addr, size_t len, sint prot, @@ -28,22 +30,10 @@ struct ProcessOps { SysResult (*virtual_query)(Thread *thread, ptr addr, sint flags, ptr info, ulong infoSize); - SysResult (*open)(Thread *thread, ptr path, sint flags, - sint mode); + SysResult (*open)(Thread *thread, ptr path, sint flags, sint mode, + Ref *file); SysResult (*socket)(Thread *thread, ptr name, sint domain, - sint type, sint protocol); - SysResult (*close)(Thread *thread, sint fd); - SysResult (*ioctl)(Thread *thread, sint fd, ulong com, caddr_t argp); - SysResult (*write)(Thread *thread, sint fd, ptr data, ulong size); - SysResult (*read)(Thread *thread, sint fd, ptr data, ulong size); - SysResult (*pread)(Thread *thread, sint fd, ptr data, ulong size, - ulong offset); - SysResult (*pwrite)(Thread *thread, sint fd, ptr data, ulong size, - ulong offset); - SysResult (*lseek)(Thread *thread, sint fd, ulong offset, sint whence); - SysResult (*ftruncate)(Thread *thread, sint fd, off_t length); - SysResult (*truncate)(Thread *thread, ptr path, off_t length); - + sint type, sint protocol, Ref *file); SysResult (*dynlib_get_obj_member)(Thread *thread, ModuleHandle handle, uint64_t index, ptr> addrp); SysResult (*dynlib_dlsym)(Thread *thread, ModuleHandle handle, diff --git a/orbis-kernel/include/orbis/uio.hpp b/orbis-kernel/include/orbis/uio.hpp index 9ebbe5d16..f1f8c4768 100644 --- a/orbis-kernel/include/orbis/uio.hpp +++ b/orbis-kernel/include/orbis/uio.hpp @@ -20,8 +20,8 @@ enum class UioSeg : std::uint8_t { struct Uio { std::uint64_t offset; IoVec *iov; - std::int32_t iovcnt; - std::int32_t resid; + std::uint32_t iovcnt; + std::int64_t resid; UioSeg segflg; UioRw rw; void *td; diff --git a/orbis-kernel/include/orbis/utils/Logs.hpp b/orbis-kernel/include/orbis/utils/Logs.hpp index deca579fe..94217c9ad 100644 --- a/orbis-kernel/include/orbis/utils/Logs.hpp +++ b/orbis-kernel/include/orbis/utils/Logs.hpp @@ -1,6 +1,5 @@ #pragma once #include -#include #include namespace orbis { diff --git a/orbis-kernel/src/sys/sys_descrip.cpp b/orbis-kernel/src/sys/sys_descrip.cpp index ff9893c20..888d5d82b 100644 --- a/orbis-kernel/src/sys/sys_descrip.cpp +++ b/orbis-kernel/src/sys/sys_descrip.cpp @@ -17,53 +17,43 @@ orbis::SysResult orbis::sys_fcntl(Thread *thread, sint fd, sint cmd, } orbis::SysResult orbis::sys_close(Thread *thread, sint fd) { ORBIS_LOG_NOTICE(__FUNCTION__, fd); - if (auto close = thread->tproc->ops->close) { - return close(thread, fd); + if (fd == 0) { + return {}; // FIXME: remove when shm would be implemented } - return ErrorCode::NOSYS; + if (thread->tproc->fileDescriptors.close(fd)) { + return {}; + } + + return ErrorCode::BADF; } orbis::SysResult orbis::sys_closefrom(Thread *thread, sint lowfd) { return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_fstat(Thread *thread, sint fd, ptr ub) { - ORBIS_LOG_WARNING(__FUNCTION__, fd, ub); - thread->where(); - if (fd == 0) { - return ErrorCode::PERM; + Ref file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; } - auto result = sys_lseek(thread, fd, 0, SEEK_CUR); - auto oldpos = thread->retval[0]; - if (result.isError()) { + auto stat = file->ops->stat; + if (stat == nullptr) { + return ErrorCode::NOTSUP; + } + + std::lock_guard lock(file->mtx); + Stat _ub; + auto result = uread(_ub, ub); + if (result != ErrorCode{}) { return result; } - result = sys_lseek(thread, fd, 0, SEEK_END); - auto len = thread->retval[0]; - if (result.isError()) { + result = stat(file.get(), &_ub, thread); + if (result != ErrorCode{}) { return result; } - result = sys_read(thread, fd, ub, 1); - if (result.isError()) { - *ub = {}; - ub->mode = 0777 | 0x4000; - } else { - *ub = {}; - ub->size = len; - ub->blksize = 1; - ub->blocks = len; - ub->mode = 0777 | 0x8000; - } - - result = sys_lseek(thread, fd, oldpos, SEEK_SET); - if (result.isError()) { - return result; - } - - thread->retval[0] = 0; - return {}; + return uwrite(ub, _ub); } orbis::SysResult orbis::sys_nfstat(Thread *thread, sint fd, ptr sb) { diff --git a/orbis-kernel/src/sys/sys_event.cpp b/orbis-kernel/src/sys/sys_event.cpp index 62e6858c2..a53df8f8c 100644 --- a/orbis-kernel/src/sys/sys_event.cpp +++ b/orbis-kernel/src/sys/sys_event.cpp @@ -3,7 +3,7 @@ #include "thread/Process.hpp" #include "utils/Logs.hpp" -struct KQueue : orbis::RcBase {}; +struct KQueue : orbis::File {}; orbis::SysResult orbis::sys_kqueue(Thread *thread) { ORBIS_LOG_TODO(__FUNCTION__); diff --git a/orbis-kernel/src/sys/sys_generic.cpp b/orbis-kernel/src/sys/sys_generic.cpp index ceb909cad..41d7a1f5c 100644 --- a/orbis-kernel/src/sys/sys_generic.cpp +++ b/orbis-kernel/src/sys/sys_generic.cpp @@ -1,74 +1,296 @@ #include "orbis/utils/Logs.hpp" #include "sys/sysproto.hpp" +#include "uio.hpp" orbis::SysResult orbis::sys_read(Thread *thread, sint fd, ptr buf, size_t nbyte) { - ORBIS_LOG_TRACE(__FUNCTION__, fd, buf, nbyte); - if (auto read = thread->tproc->ops->read) { - return read(thread, fd, buf, nbyte); + Ref file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; } - return ErrorCode::NOSYS; + auto read = file->ops->read; + if (read == nullptr) { + return ErrorCode::NOTSUP; + } + + std::lock_guard lock(file->mtx); + IoVec vec{.base = (void *)buf, .len = nbyte}; + + Uio io{ + .offset = file->nextOff, + .iov = &vec, + .iovcnt = 1, + .segflg = UioSeg::UserSpace, + .rw = UioRw::Read, + .td = thread, + }; + + auto error = read(file.get(), &io, thread); + if (error != ErrorCode{} && error != ErrorCode::AGAIN) { + return error; + } + + auto cnt = io.offset - file->nextOff; + file->nextOff = io.offset; + + thread->retval[0] = cnt; + return {}; } orbis::SysResult orbis::sys_pread(Thread *thread, sint fd, ptr buf, size_t nbyte, off_t offset) { - ORBIS_LOG_TRACE(__FUNCTION__, fd, buf, nbyte, offset); - if (auto pread = thread->tproc->ops->pread) { - return pread(thread, fd, buf, nbyte, offset); + Ref file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; } - return ErrorCode::NOSYS; + auto read = file->ops->read; + if (read == nullptr) { + return ErrorCode::NOTSUP; + } + + std::lock_guard lock(file->mtx); + IoVec vec{.base = (void *)buf, .len = nbyte}; + + Uio io{ + .offset = static_cast(offset), + .iov = &vec, + .iovcnt = 1, + .segflg = UioSeg::UserSpace, + .rw = UioRw::Read, + .td = thread, + }; + + auto error = read(file.get(), &io, thread); + if (error != ErrorCode{} && error != ErrorCode::AGAIN) { + return error; + } + + thread->retval[0] = io.offset - offset; + return {}; } orbis::SysResult orbis::sys_freebsd6_pread(Thread *thread, sint fd, ptr buf, size_t nbyte, sint, off_t offset) { return sys_pread(thread, fd, buf, nbyte, offset); } -orbis::SysResult orbis::sys_readv(Thread *thread, sint fd, - ptr iovp, uint iovcnt) { - return ErrorCode::NOSYS; +orbis::SysResult orbis::sys_readv(Thread *thread, sint fd, ptr iovp, + uint iovcnt) { + Ref file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; + } + + auto read = file->ops->read; + if (read == nullptr) { + return ErrorCode::NOTSUP; + } + + std::lock_guard lock(file->mtx); + + Uio io{ + .offset = file->nextOff, + .iov = iovp, + .iovcnt = iovcnt, + .segflg = UioSeg::UserSpace, + .rw = UioRw::Read, + .td = thread, + }; + + auto error = read(file.get(), &io, thread); + if (error != ErrorCode{} && error != ErrorCode::AGAIN) { + return error; + } + + auto cnt = io.offset - file->nextOff; + file->nextOff = io.offset; + thread->retval[0] = cnt; + return {}; } -orbis::SysResult orbis::sys_preadv(Thread *thread, sint fd, - ptr iovp, uint iovcnt, - off_t offset) { - return ErrorCode::NOSYS; +orbis::SysResult orbis::sys_preadv(Thread *thread, sint fd, ptr iovp, + uint iovcnt, off_t offset) { + Ref file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; + } + + auto read = file->ops->read; + if (read == nullptr) { + return ErrorCode::NOTSUP; + } + + std::lock_guard lock(file->mtx); + + Uio io{ + .offset = static_cast(offset), + .iov = iovp, + .iovcnt = iovcnt, + .segflg = UioSeg::UserSpace, + .rw = UioRw::Read, + .td = thread, + }; + + auto error = read(file.get(), &io, thread); + if (error != ErrorCode{} && error != ErrorCode::AGAIN) { + return error; + } + + thread->retval[0] = io.offset - offset; + return {}; } orbis::SysResult orbis::sys_write(Thread *thread, sint fd, ptr buf, size_t nbyte) { - ORBIS_LOG_NOTICE(__FUNCTION__, fd, buf, nbyte); - if (auto write = thread->tproc->ops->write) { - return write(thread, fd, buf, nbyte); + Ref file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; } - return ErrorCode::NOSYS; + auto write = file->ops->write; + if (write == nullptr) { + return ErrorCode::NOTSUP; + } + + std::lock_guard lock(file->mtx); + IoVec vec{.base = (void *)buf, .len = nbyte}; + + Uio io{ + .offset = file->nextOff, + .iov = &vec, + .iovcnt = 1, + .segflg = UioSeg::UserSpace, + .rw = UioRw::Write, + .td = thread, + }; + + auto error = write(file.get(), &io, thread); + if (error != ErrorCode{} && error != ErrorCode::AGAIN) { + return error; + } + + auto cnt = io.offset - file->nextOff; + file->nextOff = io.offset; + + thread->retval[0] = cnt; + return {}; } orbis::SysResult orbis::sys_pwrite(Thread *thread, sint fd, ptr buf, size_t nbyte, off_t offset) { - if (auto pwrite = thread->tproc->ops->pwrite) { - return pwrite(thread, fd, buf, nbyte, offset); + Ref file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; } - return ErrorCode::NOSYS; + + auto write = file->ops->write; + if (write == nullptr) { + return ErrorCode::NOTSUP; + } + + std::lock_guard lock(file->mtx); + IoVec vec{.base = (void *)buf, .len = nbyte}; + + Uio io{ + .offset = static_cast(offset), + .iov = &vec, + .iovcnt = 1, + .segflg = UioSeg::UserSpace, + .rw = UioRw::Write, + .td = thread, + }; + + auto error = write(file.get(), &io, thread); + if (error != ErrorCode{} && error != ErrorCode::AGAIN) { + return error; + } + + thread->retval[0] = io.offset - offset; + return {}; } orbis::SysResult orbis::sys_freebsd6_pwrite(Thread *thread, sint fd, ptr buf, size_t nbyte, sint, off_t offset) { return sys_pwrite(thread, fd, buf, nbyte, offset); } -orbis::SysResult orbis::sys_writev(Thread *thread, sint fd, - ptr iovp, uint iovcnt) { - return ErrorCode::NOSYS; +orbis::SysResult orbis::sys_writev(Thread *thread, sint fd, ptr iovp, + uint iovcnt) { + Ref file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; + } + + auto write = file->ops->write; + if (write == nullptr) { + return ErrorCode::NOTSUP; + } + + std::lock_guard lock(file->mtx); + + Uio io{ + .offset = file->nextOff, + .iov = iovp, + .iovcnt = iovcnt, + .segflg = UioSeg::UserSpace, + .rw = UioRw::Write, + .td = thread, + }; + + auto error = write(file.get(), &io, thread); + if (error != ErrorCode{} && error != ErrorCode::AGAIN) { + return error; + } + + auto cnt = io.offset - file->nextOff; + file->nextOff = io.offset; + + thread->retval[0] = cnt; + return {}; } -orbis::SysResult orbis::sys_pwritev(Thread *thread, sint fd, - ptr iovp, uint iovcnt, - off_t offset) { - return ErrorCode::NOSYS; +orbis::SysResult orbis::sys_pwritev(Thread *thread, sint fd, ptr iovp, + uint iovcnt, off_t offset) { + Ref file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; + } + + auto write = file->ops->write; + if (write == nullptr) { + return ErrorCode::NOTSUP; + } + + std::lock_guard lock(file->mtx); + + Uio io{ + .offset = static_cast(offset), + .iov = iovp, + .iovcnt = iovcnt, + .segflg = UioSeg::UserSpace, + .rw = UioRw::Write, + .td = thread, + }; + auto error = write(file.get(), &io, thread); + if (error != ErrorCode{} && error != ErrorCode::AGAIN) { + return error; + } + + thread->retval[0] = io.offset - offset; + return {}; } orbis::SysResult orbis::sys_ftruncate(Thread *thread, sint fd, off_t length) { ORBIS_LOG_WARNING(__FUNCTION__, fd, length); - if (auto ftruncate = thread->tproc->ops->ftruncate) { - return ftruncate(thread, fd, length); + if (fd == 0) { + return {}; // FIXME: remove when shm implemented } - return ErrorCode::NOSYS; + Ref file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; + } + + auto truncate = file->ops->truncate; + if (truncate == nullptr) { + return ErrorCode::NOTSUP; + } + + std::lock_guard lock(file->mtx); + return truncate(file.get(), length, thread); } orbis::SysResult orbis::sys_freebsd6_ftruncate(Thread *thread, sint fd, sint, off_t length) { @@ -77,10 +299,18 @@ orbis::SysResult orbis::sys_freebsd6_ftruncate(Thread *thread, sint fd, sint, orbis::SysResult orbis::sys_ioctl(Thread *thread, sint fd, ulong com, caddr_t data) { ORBIS_LOG_WARNING(__FUNCTION__, fd, com); - if (auto ioctl = thread->tproc->ops->ioctl) { - return ioctl(thread, fd, com, data); + Ref file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; } - return ErrorCode::NOSYS; + + auto ioctl = file->ops->ioctl; + if (ioctl == nullptr) { + return ErrorCode::NOTSUP; + } + + std::lock_guard lock(file->mtx); + return ioctl(file.get(), com, data, thread); } orbis::SysResult orbis::sys_pselect(Thread *thread, sint nd, ptr in, ptr ou, ptr ex, @@ -117,12 +347,12 @@ orbis::SysResult orbis::sys_sysarch(Thread *thread, sint op, ptr parms) { uint64_t fs; if (auto error = uread(fs, (ptr)parms); error != ErrorCode{}) return error; - std::printf("sys_sysarch: set FS to 0x%zx\n", (std::size_t)fs); + ORBIS_LOG_WARNING("sys_sysarch: set FS", (std::size_t)fs); thread->fsBase = fs; return {}; } - std::printf("sys_sysarch(op = %d, parms = %p): unknown op\n", op, parms); + ORBIS_LOG_WARNING(__FUNCTION__, op, parms); return {}; } orbis::SysResult orbis::sys_nnpfs_syscall(Thread *thread, sint operation, diff --git a/orbis-kernel/src/sys/sys_jail.cpp b/orbis-kernel/src/sys/sys_jail.cpp index 323284a2a..74261d630 100644 --- a/orbis-kernel/src/sys/sys_jail.cpp +++ b/orbis-kernel/src/sys/sys_jail.cpp @@ -3,11 +3,11 @@ orbis::SysResult orbis::sys_jail(Thread *thread, ptr jail) { return ErrorCode::NOSYS; } -orbis::SysResult orbis::sys_jail_set(Thread *thread, ptr iovp, +orbis::SysResult orbis::sys_jail_set(Thread *thread, ptr iovp, uint iovcnt, sint flags) { return ErrorCode::NOSYS; } -orbis::SysResult orbis::sys_jail_get(Thread *thread, ptr iovp, +orbis::SysResult orbis::sys_jail_get(Thread *thread, ptr iovp, uint iovcnt, sint flags) { return ErrorCode::NOSYS; } diff --git a/orbis-kernel/src/sys/sys_sce.cpp b/orbis-kernel/src/sys/sys_sce.cpp index 88c9cc77d..4066200a2 100644 --- a/orbis-kernel/src/sys/sys_sce.cpp +++ b/orbis-kernel/src/sys/sys_sce.cpp @@ -8,7 +8,6 @@ #include "osem.hpp" #include "sys/sysproto.hpp" #include "utils/Logs.hpp" -#include orbis::SysResult orbis::sys_netcontrol(Thread *thread, sint fd, uint op, ptr buf, uint nbuf) { @@ -24,18 +23,28 @@ orbis::SysResult orbis::sys_socketex(Thread *thread, ptr name, sint domain, sint type, sint protocol) { ORBIS_LOG_TODO(__FUNCTION__, name, domain, type, protocol); if (auto socket = thread->tproc->ops->socket) { - return socket(thread, name, domain, type, protocol); + Ref file; + auto result = socket(thread, name, domain, type, protocol, &file); + + if (result.isError()) { + return result; + } + + auto fd = thread->tproc->fileDescriptors.insert(file); + ORBIS_LOG_WARNING("Socket opened", name, fd); + thread->retval[0] = fd; + return {}; } return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_socketclose(Thread *thread, sint fd) { // This syscall is identical to sys_close ORBIS_LOG_NOTICE(__FUNCTION__, fd); - if (auto close = thread->tproc->ops->close) { - return close(thread, fd); + if (thread->tproc->fileDescriptors.close(fd)) { + return {}; } - return ErrorCode::NOSYS; + return ErrorCode::BADF; } orbis::SysResult orbis::sys_netgetiflist(Thread *thread /* TODO */) { return ErrorCode::NOSYS; diff --git a/orbis-kernel/src/sys/sys_uipc.cpp b/orbis-kernel/src/sys/sys_uipc.cpp index 244c1944a..a87c04d9a 100644 --- a/orbis-kernel/src/sys/sys_uipc.cpp +++ b/orbis-kernel/src/sys/sys_uipc.cpp @@ -82,12 +82,12 @@ orbis::sys_sctp_generic_sendmsg(Thread *thread, sint sd, caddr_t msg, sint mlen, return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_sctp_generic_sendmsg_iov( - Thread *thread, sint sd, ptr iov, sint iovlen, caddr_t to, + Thread *thread, sint sd, ptr iov, sint iovlen, caddr_t to, __socklen_t tolen, ptr sinfo, sint flags) { return ErrorCode::NOSYS; } orbis::SysResult -orbis::sys_sctp_generic_recvmsg(Thread *thread, sint sd, ptr iov, +orbis::sys_sctp_generic_recvmsg(Thread *thread, sint sd, ptr iov, sint iovlen, caddr_t from, __socklen_t fromlen, ptr sinfo, sint flags) { return ErrorCode::NOSYS; diff --git a/orbis-kernel/src/sys/sys_vfs.cpp b/orbis-kernel/src/sys/sys_vfs.cpp index 134087816..061baa7b6 100644 --- a/orbis-kernel/src/sys/sys_vfs.cpp +++ b/orbis-kernel/src/sys/sys_vfs.cpp @@ -32,7 +32,14 @@ orbis::SysResult orbis::sys_open(Thread *thread, ptr path, sint flags, sint mode) { ORBIS_LOG_NOTICE("sys_open", path, flags, mode); if (auto open = thread->tproc->ops->open) { - return open(thread, path, flags, mode); + Ref file; + auto result = open(thread, path, flags, mode, &file); + if (result.isError()) { + return result; + } + + thread->retval[0] = thread->tproc->fileDescriptors.insert(file); + return {}; } return ErrorCode::NOSYS; @@ -84,10 +91,46 @@ orbis::SysResult orbis::sys_unlinkat(Thread *thread, sint fd, ptr path, } orbis::SysResult orbis::sys_lseek(Thread *thread, sint fd, off_t offset, sint whence) { - if (auto lseek = thread->tproc->ops->lseek) { - return lseek(thread, fd, offset, whence); + Ref file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; } - return ErrorCode::NOSYS; + + std::lock_guard lock(file->mtx); + + // TODO: use ioctl? + switch (whence) { + case SEEK_SET: + file->nextOff = offset; + break; + + case SEEK_CUR: + file->nextOff += offset; + break; + + case SEEK_END: { + if (file->ops->stat == nullptr) { + ORBIS_LOG_ERROR("seek with end whence: unimplemented stat"); + return ErrorCode::NOTSUP; + } + + orbis::Stat stat; + auto result = file->ops->stat(file.get(), &stat, thread); + if (result != ErrorCode{}) { + return result; + } + + file->nextOff = stat.size + offset; + break; + } + + default: + ORBIS_LOG_ERROR("sys_lseek: unimplemented whence", whence); + return ErrorCode::NOSYS; + } + + thread->retval[0] = file->nextOff; + return {}; } orbis::SysResult orbis::sys_freebsd6_lseek(Thread *thread, sint fd, sint, off_t offset, sint whence) { @@ -105,35 +148,30 @@ orbis::SysResult orbis::sys_eaccess(Thread *thread, ptr path, return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_stat(Thread *thread, ptr path, ptr ub) { - ORBIS_LOG_WARNING(__FUNCTION__, path, ub); - auto result = sys_open(thread, path, 0, 0); + Ref file; + auto result = thread->tproc->ops->open(thread, path, 0, 0, &file); if (result.isError()) { - return ErrorCode::NOENT; - } - - auto fd = thread->retval[0]; - result = sys_lseek(thread, fd, 0, SEEK_END); - if (result.isError()) { - sys_close(thread, fd); return result; } - auto len = thread->retval[0]; - result = sys_pread(thread, fd, ub, 1, 0); - if (result.isError()) { - *ub = {}; - ub->mode = 0777 | 0x4000; - } else { - *ub = {}; - ub->size = len; - ub->blksize = 1; - ub->blocks = len; - ub->mode = 0777 | 0x8000; + auto stat = file->ops->stat; + if (stat == nullptr) { + return ErrorCode::NOTSUP; } - sys_close(thread, fd); - thread->retval[0] = 0; - return {}; + std::lock_guard lock(file->mtx); + Stat _ub; + result = uread(_ub, ub); + if (result.isError()) { + return result; + } + + result = stat(file.get(), &_ub, thread); + if (result.isError()) { + return result; + } + + return uwrite(ub, _ub); } orbis::SysResult orbis::sys_fstatat(Thread *thread, sint fd, ptr path, ptr buf, sint flag) { @@ -226,18 +264,25 @@ orbis::SysResult orbis::sys_futimes(Thread *thread, sint fd, } orbis::SysResult orbis::sys_truncate(Thread *thread, ptr path, off_t length) { - if (auto truncate = thread->tproc->ops->truncate) { - return truncate(thread, path, length); + Ref file; + auto result = thread->tproc->ops->open(thread, path, 0, 0, &file); + if (result.isError()) { + return result; } - return ErrorCode::NOSYS; + + auto truncate = file->ops->truncate; + if (truncate == nullptr) { + return ErrorCode::NOTSUP; + } + + std::lock_guard lock(file->mtx); + return truncate(file.get(), length, thread); } orbis::SysResult orbis::sys_freebsd6_truncate(Thread *thread, ptr path, sint, off_t length) { return sys_truncate(thread, path, length); } -orbis::SysResult orbis::sys_fsync(Thread *thread, sint fd) { - return ErrorCode::NOSYS; -} +orbis::SysResult orbis::sys_fsync(Thread *thread, sint fd) { return {}; } orbis::SysResult orbis::sys_rename(Thread *thread, ptr from, ptr to) { return ErrorCode::NOSYS; diff --git a/orbis-kernel/src/sys/sys_vfs_mount.cpp b/orbis-kernel/src/sys/sys_vfs_mount.cpp index fdfe684ff..3f80cc105 100644 --- a/orbis-kernel/src/sys/sys_vfs_mount.cpp +++ b/orbis-kernel/src/sys/sys_vfs_mount.cpp @@ -8,7 +8,7 @@ orbis::SysResult orbis::sys_unmount(Thread *thread, ptr path, sint flags) { return ErrorCode::NOSYS; } -orbis::SysResult orbis::sys_nmount(Thread *thread, ptr iovp, - uint iovcnt, sint flags) { +orbis::SysResult orbis::sys_nmount(Thread *thread, ptr iovp, uint iovcnt, + sint flags) { return ErrorCode::NOSYS; } diff --git a/orbis-kernel/src/utils/Logs.cpp b/orbis-kernel/src/utils/Logs.cpp index 9fcea48c3..d3b08ffde 100644 --- a/orbis-kernel/src/utils/Logs.cpp +++ b/orbis-kernel/src/utils/Logs.cpp @@ -1,4 +1,5 @@ #include "utils/Logs.hpp" +#include "error/ErrorCode.hpp" #include #include #include @@ -168,6 +169,298 @@ void log_class_string::format(std::string &out, const void *arg) { out += get_object(arg) ? "1" : "0"; } +template <> +void log_class_string::format(std::string &out, + const void *arg) { + auto errorCode = get_object(arg); + switch (errorCode) { + case ErrorCode::PERM: + out += "PERM"; + return; + case ErrorCode::NOENT: + out += "NOENT"; + return; + case ErrorCode::SRCH: + out += "SRCH"; + return; + case ErrorCode::INTR: + out += "INTR"; + return; + case ErrorCode::IO: + out += "IO"; + return; + case ErrorCode::NXIO: + out += "NXIO"; + return; + case ErrorCode::TOOBIG: + out += "TOOBIG"; + return; + case ErrorCode::NOEXEC: + out += "NOEXEC"; + return; + case ErrorCode::BADF: + out += "BADF"; + return; + case ErrorCode::CHILD: + out += "CHILD"; + return; + case ErrorCode::DEADLK: + out += "DEADLK"; + return; + case ErrorCode::NOMEM: + out += "NOMEM"; + return; + case ErrorCode::ACCES: + out += "ACCES"; + return; + case ErrorCode::FAULT: + out += "FAULT"; + return; + case ErrorCode::NOTBLK: + out += "NOTBLK"; + return; + case ErrorCode::BUSY: + out += "BUSY"; + return; + case ErrorCode::EXIST: + out += "EXIST"; + return; + case ErrorCode::XDEV: + out += "XDEV"; + return; + case ErrorCode::NODEV: + out += "NODEV"; + return; + case ErrorCode::NOTDIR: + out += "NOTDIR"; + return; + case ErrorCode::ISDIR: + out += "ISDIR"; + return; + case ErrorCode::INVAL: + out += "INVAL"; + return; + case ErrorCode::NFILE: + out += "NFILE"; + return; + case ErrorCode::MFILE: + out += "MFILE"; + return; + case ErrorCode::NOTTY: + out += "NOTTY"; + return; + case ErrorCode::TXTBSY: + out += "TXTBSY"; + return; + case ErrorCode::FBIG: + out += "FBIG"; + return; + case ErrorCode::NOSPC: + out += "NOSPC"; + return; + case ErrorCode::SPIPE: + out += "SPIPE"; + return; + case ErrorCode::ROFS: + out += "ROFS"; + return; + case ErrorCode::MLINK: + out += "MLINK"; + return; + case ErrorCode::PIPE: + out += "PIPE"; + return; + case ErrorCode::DOM: + out += "DOM"; + return; + case ErrorCode::RANGE: + out += "RANGE"; + return; + case ErrorCode::AGAIN: + out += "AGAIN"; + return; + case ErrorCode::INPROGRESS: + out += "INPROGRESS"; + return; + case ErrorCode::ALREADY: + out += "ALREADY"; + return; + case ErrorCode::NOTSOCK: + out += "NOTSOCK"; + return; + case ErrorCode::DESTADDRREQ: + out += "DESTADDRREQ"; + return; + case ErrorCode::MSGSIZE: + out += "MSGSIZE"; + return; + case ErrorCode::PROTOTYPE: + out += "PROTOTYPE"; + return; + case ErrorCode::NOPROTOOPT: + out += "NOPROTOOPT"; + return; + case ErrorCode::PROTONOSUPPORT: + out += "PROTONOSUPPORT"; + return; + case ErrorCode::SOCKTNOSUPPORT: + out += "SOCKTNOSUPPORT"; + return; + case ErrorCode::OPNOTSUPP: + out += "OPNOTSUPP"; + return; + case ErrorCode::PFNOSUPPORT: + out += "PFNOSUPPORT"; + return; + case ErrorCode::AFNOSUPPORT: + out += "AFNOSUPPORT"; + return; + case ErrorCode::ADDRINUSE: + out += "ADDRINUSE"; + return; + case ErrorCode::ADDRNOTAVAIL: + out += "ADDRNOTAVAIL"; + return; + case ErrorCode::NETDOWN: + out += "NETDOWN"; + return; + case ErrorCode::NETUNREACH: + out += "NETUNREACH"; + return; + case ErrorCode::NETRESET: + out += "NETRESET"; + return; + case ErrorCode::CONNABORTED: + out += "CONNABORTED"; + return; + case ErrorCode::CONNRESET: + out += "CONNRESET"; + return; + case ErrorCode::NOBUFS: + out += "NOBUFS"; + return; + case ErrorCode::ISCONN: + out += "ISCONN"; + return; + case ErrorCode::NOTCONN: + out += "NOTCONN"; + return; + case ErrorCode::SHUTDOWN: + out += "SHUTDOWN"; + return; + case ErrorCode::TOOMANYREFS: + out += "TOOMANYREFS"; + return; + case ErrorCode::TIMEDOUT: + out += "TIMEDOUT"; + return; + case ErrorCode::CONNREFUSED: + out += "CONNREFUSED"; + return; + case ErrorCode::LOOP: + out += "LOOP"; + return; + case ErrorCode::NAMETOOLONG: + out += "NAMETOOLONG"; + return; + case ErrorCode::HOSTDOWN: + out += "HOSTDOWN"; + return; + case ErrorCode::HOSTUNREACH: + out += "HOSTUNREACH"; + return; + case ErrorCode::NOTEMPTY: + out += "NOTEMPTY"; + return; + case ErrorCode::PROCLIM: + out += "PROCLIM"; + return; + case ErrorCode::USERS: + out += "USERS"; + return; + case ErrorCode::DQUOT: + out += "DQUOT"; + return; + case ErrorCode::STALE: + out += "STALE"; + return; + case ErrorCode::REMOTE: + out += "REMOTE"; + return; + case ErrorCode::BADRPC: + out += "BADRPC"; + return; + case ErrorCode::RPCMISMATCH: + out += "RPCMISMATCH"; + return; + case ErrorCode::PROGUNAVAIL: + out += "PROGUNAVAIL"; + return; + case ErrorCode::PROGMISMATCH: + out += "PROGMISMATCH"; + return; + case ErrorCode::PROCUNAVAIL: + out += "PROCUNAVAIL"; + return; + case ErrorCode::NOLCK: + out += "NOLCK"; + return; + case ErrorCode::NOSYS: + out += "NOSYS"; + return; + case ErrorCode::FTYPE: + out += "FTYPE"; + return; + case ErrorCode::AUTH: + out += "AUTH"; + return; + case ErrorCode::NEEDAUTH: + out += "NEEDAUTH"; + return; + case ErrorCode::IDRM: + out += "IDRM"; + return; + case ErrorCode::NOMSG: + out += "NOMSG"; + return; + case ErrorCode::OVERFLOW: + out += "OVERFLOW"; + return; + case ErrorCode::CANCELED: + out += "CANCELED"; + return; + case ErrorCode::ILSEQ: + out += "ILSEQ"; + return; + case ErrorCode::NOATTR: + out += "NOATTR"; + return; + case ErrorCode::DOOFUS: + out += "DOOFUS"; + return; + case ErrorCode::BADMSG: + out += "BADMSG"; + return; + case ErrorCode::MULTIHOP: + out += "MULTIHOP"; + return; + case ErrorCode::NOLINK: + out += "NOLINK"; + return; + case ErrorCode::PROTO: + out += "PROTO"; + return; + case ErrorCode::NOTCAPABLE: + out += "NOTCAPABLE"; + return; + case ErrorCode::CAPMODE: + out += "CAPMODE"; + return; + } + + out += ""; +} + void _orbis_log_print(LogLevel lvl, std::string_view msg, std::string_view names, const log_type_info *sup, ...) { if (lvl > logs_level.load(std::memory_order::relaxed)) { diff --git a/rpcsx-os/CMakeLists.txt b/rpcsx-os/CMakeLists.txt index 977e1f1fe..d26045059 100644 --- a/rpcsx-os/CMakeLists.txt +++ b/rpcsx-os/CMakeLists.txt @@ -15,9 +15,6 @@ add_executable(rpcsx-os iodev/hmd_snsr.cpp iodev/null.cpp iodev/rng.cpp - iodev/stderr.cpp - iodev/stdin.cpp - iodev/stdout.cpp iodev/zero.cpp main.cpp diff --git a/rpcsx-os/io-device.cpp b/rpcsx-os/io-device.cpp index a017f6c7b..5a534ec1e 100644 --- a/rpcsx-os/io-device.cpp +++ b/rpcsx-os/io-device.cpp @@ -1,70 +1,221 @@ #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" +#include "orbis/file.hpp" +#include "orbis/stat.hpp" +#include "orbis/uio.hpp" #include "orbis/utils/Logs.hpp" +#include #include +#include #include #include +#include +#include #include +#include -std::int64_t io_device_instance_close(IoDeviceInstance *instance) { return 0; } +struct HostFile : orbis::File { + int hostFd = -1; -void io_device_instance_init(IoDevice *device, IoDeviceInstance *instance) { - if (instance->device == nullptr) { - instance->device = device; + ~HostFile() { + if (hostFd > 0) { + ::close(hostFd); + } } - - if (instance->close == nullptr) { - instance->close = io_device_instance_close; - } -} - -struct HostIoDevice : IoDevice { - orbis::utils::kstring hostPath; }; -struct HostIoDeviceInstance : IoDeviceInstance { - int hostFd; -}; - -struct SocketDeviceInstance : IoDeviceInstance { +struct SocketFile : orbis::File { orbis::utils::kstring name; - int hostFd; + int hostFd = -1; + + ~SocketFile() { + if (hostFd > 0) { + ::close(hostFd); + } + } }; -static std::int64_t host_io_device_instance_read(IoDeviceInstance *instance, - void *data, - std::uint64_t size) { - auto hostIoInstance = static_cast(instance); - return ::read(hostIoInstance->hostFd, data, size); // TODO: convert errno +struct HostFsDevice : IoDevice { + orbis::kstring hostPath; + + explicit HostFsDevice(orbis::kstring path) : hostPath(std::move(path)) {} + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override; +}; + +static orbis::ErrorCode convertErrno() { + switch (auto error = errno) { + case EPERM: + return orbis::ErrorCode::PERM; + case ENOENT: + return orbis::ErrorCode::NOENT; + case EBADF: + return orbis::ErrorCode::BADF; + case EIO: + return orbis::ErrorCode::IO; + case EACCES: + return orbis::ErrorCode::ACCES; + case EEXIST: + return orbis::ErrorCode::EXIST; + case EBUSY: + return orbis::ErrorCode::BUSY; + case ENOTDIR: + return orbis::ErrorCode::NOTDIR; + case EISDIR: + return orbis::ErrorCode::ISDIR; + case EFBIG: + return orbis::ErrorCode::FBIG; + case ENOSPC: + return orbis::ErrorCode::NOSPC; + case ESPIPE: + return orbis::ErrorCode::SPIPE; + case EPIPE: + return orbis::ErrorCode::PIPE; + + default: + ORBIS_LOG_ERROR("Unconverted errno", error); + } + + return orbis::ErrorCode::IO; } -static std::int64_t host_io_device_instance_write(IoDeviceInstance *instance, - const void *data, - std::uint64_t size) { - auto hostIoInstance = static_cast(instance); - return ::write(hostIoInstance->hostFd, data, size); // TODO: convert errno +static orbis::ErrorCode host_read(orbis::File *file, orbis::Uio *uio, + orbis::Thread *) { + auto hostFile = static_cast(file); + std::vector vec; + for (auto entry : std::span(uio->iov, uio->iovcnt)) { + vec.push_back({.iov_base = entry.base, .iov_len = entry.len}); + } + + ssize_t cnt; + if (hostFile->hostFd == 0) { + cnt = ::read(hostFile->hostFd, vec.data(), vec.size()); + } else { + cnt = ::preadv(hostFile->hostFd, vec.data(), vec.size(), uio->offset); + } + if (cnt < 0) { + return convertErrno(); + } + + uio->resid -= cnt; + uio->offset += cnt; + return {}; } -static std::int64_t host_io_device_instance_lseek(IoDeviceInstance *instance, - std::uint64_t offset, - std::uint32_t whence) { - auto hostIoInstance = static_cast(instance); +static orbis::ErrorCode host_write(orbis::File *file, orbis::Uio *uio, + orbis::Thread *) { + auto hostFile = static_cast(file); + std::vector vec; + for (auto entry : std::span(uio->iov, uio->iovcnt)) { + vec.push_back({.iov_base = entry.base, .iov_len = entry.len}); + } - return ::lseek(hostIoInstance->hostFd, offset, whence); // TODO: convert errno + ssize_t cnt; + if (hostFile->hostFd == 1 || hostFile->hostFd == 2) { + cnt = ::write(hostFile->hostFd, vec.data(), vec.size()); + } else { + cnt = ::pwritev(hostFile->hostFd, vec.data(), vec.size(), uio->offset); + } + if (cnt < 0) { + return convertErrno(); + } + + uio->resid -= cnt; + uio->offset += cnt; + return {}; } -static std::int64_t host_io_device_instance_close(IoDeviceInstance *instance) { - auto hostIoInstance = static_cast(instance); - ::close(hostIoInstance->hostFd); - return io_device_instance_close(instance); +static orbis::ErrorCode host_stat(orbis::File *file, orbis::Stat *sb, + orbis::Thread *thread) { + auto hostFile = static_cast(file); + struct stat hostStat; + ::fstat(hostFile->hostFd, &hostStat); + sb->dev = hostStat.st_dev; // TODO + sb->ino = hostStat.st_ino; + sb->mode = hostStat.st_mode; + sb->nlink = hostStat.st_nlink; + sb->uid = hostStat.st_uid; + sb->gid = hostStat.st_gid; + sb->rdev = hostStat.st_rdev; + sb->atim = { + .sec = static_cast(hostStat.st_atim.tv_sec), + .nsec = static_cast(hostStat.st_atim.tv_nsec), + }; + sb->mtim = { + .sec = static_cast(hostStat.st_mtim.tv_sec), + .nsec = static_cast(hostStat.st_mtim.tv_nsec), + }; + sb->ctim = { + .sec = static_cast(hostStat.st_mtim.tv_sec), + .nsec = static_cast(hostStat.st_mtim.tv_nsec), + }; + sb->size = hostStat.st_size; + sb->blocks = hostStat.st_blocks; + sb->blksize = hostStat.st_blksize; + // TODO + sb->flags = 0; + sb->gen = 0; + sb->lspare = 0; + sb->birthtim = { + .sec = static_cast(hostStat.st_mtim.tv_sec), + .nsec = static_cast(hostStat.st_mtim.tv_nsec), + }; + + return {}; } -static std::int32_t host_io_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto hostDevice = static_cast(device); - auto realPath = hostDevice->hostPath + "/" + path; +static orbis::ErrorCode host_truncate(orbis::File *file, std::uint64_t len, + orbis::Thread *thread) { + auto hostFile = static_cast(file); + if (::ftruncate(hostFile->hostFd, len)) { + return convertErrno(); + } + + return {}; +} + +static orbis::ErrorCode socket_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { + auto soc = static_cast(file); + ORBIS_LOG_FATAL("Unhandled socket ioctl", request, soc->name); + return {}; +} + +static const orbis::FileOps hostOps = { + .read = host_read, + .write = host_write, + .truncate = host_truncate, + .stat = host_stat, +}; + +static const orbis::FileOps socketOps = { + .ioctl = socket_ioctl, +}; + +IoDevice *createHostIoDevice(orbis::kstring hostPath) { + return orbis::knew(std::move(hostPath)); +} + +orbis::ErrorCode createSocket(orbis::Ref *file, + orbis::kstring name, int dom, int type, + int prot) { + auto fd = ::socket(dom, type, prot); + if (fd < 0) { + return convertErrno(); + } + + auto s = orbis::knew(); + s->name = std::move(name); + s->hostFd = fd; + s->ops = &socketOps; + *file = s; + return {}; +} + +orbis::ErrorCode HostFsDevice::open(orbis::Ref *file, + const char *path, std::uint32_t flags, + std::uint32_t mode) { + auto realPath = hostPath + "/" + path; int realFlags = flags & O_ACCMODE; flags &= ~O_ACCMODE; @@ -104,59 +255,51 @@ static std::int32_t host_io_open(IoDevice *device, flags &= ~kOpenFlagExcl; } + if ((flags & kOpenFlagDirectory) != 0) { + realFlags |= O_DIRECTORY; + flags &= ~kOpenFlagDirectory; + } + if (flags != 0) { - std::fprintf(stderr, "host_io_open: ***ERROR*** Unhandled open flags %x\n", - flags); + ORBIS_LOG_ERROR("host_open: ***ERROR*** Unhandled open flags", flags); } int hostFd = ::open(realPath.c_str(), realFlags, 0777); if (hostFd < 0) { - std::fprintf(stderr, "host_io_open: '%s' not found.\n", realPath.c_str()); - return 1; // TODO: convert errno + auto error = convertErrno(); + ORBIS_LOG_ERROR("host_open failed", realPath, error); + return error; } - auto newInstance = orbis::knew(); - - newInstance->hostFd = hostFd; - - newInstance->read = host_io_device_instance_read; - newInstance->write = host_io_device_instance_write; - newInstance->lseek = host_io_device_instance_lseek; - newInstance->close = host_io_device_instance_close; - - io_device_instance_init(device, newInstance); - - *instance = newInstance; - return 0; -} - -IoDevice *createHostIoDevice(const char *hostPath) { - auto result = orbis::knew(); - result->open = host_io_open; - result->hostPath = hostPath; - return result; -} - -static std::int64_t socket_instance_ioctl(IoDeviceInstance *instance, - std::uint64_t request, void *argp) { - - ORBIS_LOG_FATAL("Unhandled socket ioctl", request); - return 0; -} - -static std::int64_t socket_instance_close(IoDeviceInstance *instance) { - ::close(static_cast(instance)->hostFd); - return 0; -} - -orbis::ErrorCode createSocket(const char *name, int dom, int type, int prot, - orbis::Ref *instance) { - auto s = orbis::knew(); - s->ioctl = socket_instance_ioctl; - s->close = socket_instance_close; - s->name = name; - s->hostFd = ::socket(dom, type, prot); - *instance = s; + auto newFile = orbis::knew(); + newFile->hostFd = hostFd; + newFile->ops = &hostOps; + newFile->device = this; + *file = newFile; return {}; } + +orbis::File *createHostFile(int hostFd, orbis::Ref device) { + auto newFile = orbis::knew(); + newFile->hostFd = hostFd; + newFile->ops = &hostOps; + newFile->device = device; + return newFile; +} + +struct FdWrapDevice : public IoDevice { + int fd; + + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override { + *file = createHostFile(fd, this); + return {}; + } +}; + +IoDevice *createFdWrapDevice(int fd) { + auto result = orbis::knew(); + result->fd = fd; + return result; +} diff --git a/rpcsx-os/io-device.hpp b/rpcsx-os/io-device.hpp index 5e7111829..acc63afc0 100644 --- a/rpcsx-os/io-device.hpp +++ b/rpcsx-os/io-device.hpp @@ -1,13 +1,10 @@ #pragma once +#include "orbis/KernelAllocator.hpp" +#include "orbis/file.hpp" #include "orbis/utils/Rc.hpp" #include -struct IoDevice; -namespace orbis { -enum class ErrorCode : int; -} - enum OpenFlags { kOpenFlagReadOnly = 0x0, kOpenFlagWriteOnly = 0x1, @@ -26,36 +23,13 @@ enum OpenFlags { kOpenFlagDirectory = 0x20000, }; -struct IoDeviceInstance : orbis::RcBase { - orbis::Ref device; - - std::int64_t (*ioctl)(IoDeviceInstance *instance, std::uint64_t request, - void *argp) = nullptr; - - std::int64_t (*write)(IoDeviceInstance *instance, const void *data, - std::uint64_t size) = nullptr; - std::int64_t (*read)(IoDeviceInstance *instance, void *data, - std::uint64_t size) = nullptr; - std::int64_t (*close)(IoDeviceInstance *instance) = nullptr; - std::int64_t (*lseek)(IoDeviceInstance *instance, std::uint64_t offset, - std::uint32_t whence) = nullptr; - - void *(*mmap)(IoDeviceInstance *instance, void *address, std::uint64_t size, - std::int32_t prot, std::int32_t flags, - std::int64_t offset) = nullptr; - void *(*munmap)(IoDeviceInstance *instance, void *address, - std::uint64_t size) = nullptr; -}; - struct IoDevice : orbis::RcBase { - std::int32_t (*open)(IoDevice *device, orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) = nullptr; + virtual orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) = 0; }; -std::int64_t io_device_instance_close(IoDeviceInstance *instance); -void io_device_instance_init(IoDevice *device, IoDeviceInstance *instance); - -IoDevice *createHostIoDevice(const char *hostPath); -orbis::ErrorCode createSocket(const char *name, int dom, int type, int prot, - orbis::Ref *instance); +IoDevice *createHostIoDevice(orbis::kstring hostPath); +orbis::ErrorCode createSocket(orbis::Ref *file, + orbis::kstring name, int dom, int type, int prot); +orbis::File *createHostFile(int hostFd, orbis::Ref device); +IoDevice *createFdWrapDevice(int fd); diff --git a/rpcsx-os/io-devices.hpp b/rpcsx-os/io-devices.hpp index 92621df6c..b537db6de 100644 --- a/rpcsx-os/io-devices.hpp +++ b/rpcsx-os/io-devices.hpp @@ -12,9 +12,6 @@ IoDevice *createHmdCmdCharacterDevice(); IoDevice *createHmdMmapCharacterDevice(); IoDevice *createHmdSnsrCharacterDevice(); IoDevice *createNullCharacterDevice(); -IoDevice *createStderrCharacterDevice(); -IoDevice *createStdinCharacterDevice(); -IoDevice *createStdoutCharacterDevice(); IoDevice *createZeroCharacterDevice(); IoDevice *createRngCharacterDevice(); IoDevice *createAjmCharacterDevice(); diff --git a/rpcsx-os/iodev/ajm.cpp b/rpcsx-os/iodev/ajm.cpp index 3e4f895ff..af9529677 100644 --- a/rpcsx-os/iodev/ajm.cpp +++ b/rpcsx-os/iodev/ajm.cpp @@ -1,33 +1,31 @@ #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" +#include "orbis/file.hpp" #include "orbis/utils/Logs.hpp" -#include -struct AjmDevice : public IoDevice {}; +struct AjmFile : orbis::File {}; -struct AjmInstance : public IoDeviceInstance {}; - -static std::int64_t ajm_instance_ioctl(IoDeviceInstance *instance, - std::uint64_t request, void *argp) { +static orbis::ErrorCode ajm_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { ORBIS_LOG_FATAL("Unhandled AJM ioctl", request); - return -1; + return orbis::ErrorCode::PERM; } -static std::int32_t ajm_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->ioctl = ajm_instance_ioctl; +static const orbis::FileOps fileOps = { + .ioctl = ajm_ioctl, +}; - io_device_instance_init(device, newInstance); - *instance = newInstance; - return 0; -} +struct AjmDevice : IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override { + auto newFile = orbis::knew(); + newFile->ops = &fileOps; + newFile->device = this; -IoDevice *createAjmCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = ajm_device_open; - return newDevice; -} \ No newline at end of file + *file = newFile; + return {}; + } +}; + +IoDevice *createAjmCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/iodev/dce.cpp b/rpcsx-os/iodev/dce.cpp index 7c0d7a874..9efd78a06 100644 --- a/rpcsx-os/iodev/dce.cpp +++ b/rpcsx-os/iodev/dce.cpp @@ -2,12 +2,13 @@ #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" #include "orbis/error/ErrorCode.hpp" +#include "orbis/file.hpp" #include "orbis/utils/Logs.hpp" +#include "orbis/utils/SharedMutex.hpp" #include "vm.hpp" -#include -#include #include #include +#include struct VideoOutBuffer { std::uint32_t pixelFormat; @@ -17,12 +18,6 @@ struct VideoOutBuffer { std::uint32_t height; }; -struct DceDevice : public IoDevice {}; - -struct DceInstance : public IoDeviceInstance { - VideoOutBuffer bufferAttributes{}; -}; - struct RegisterBuffer { std::uint64_t attributeIndex; std::uint64_t index; @@ -87,9 +82,20 @@ struct ResolutionStatus { std::uint32_t y; }; -static std::int64_t dce_instance_ioctl(IoDeviceInstance *instance, - std::uint64_t request, void *argp) { - auto dceInstance = static_cast(instance); +struct DceFile : public orbis::File {}; + +struct DceDevice : IoDevice { + orbis::shared_mutex mtx; + VideoOutBuffer bufferAttributes{}; // TODO + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override; +}; + +static orbis::ErrorCode dce_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { + auto device = static_cast(file->device.get()); + + std::lock_guard lock(device->mtx); if (request == 0xc0308203) { // returns: @@ -122,7 +128,7 @@ static std::int64_t dce_instance_ioctl(IoDeviceInstance *instance, args->size); } else if (args->id == 10) { if (args->size != sizeof(FlipControlStatus)) { - return 0; + return {}; } FlipControlStatus flipStatus{}; @@ -154,10 +160,10 @@ static std::int64_t dce_instance_ioctl(IoDeviceInstance *instance, *(std::uint64_t *)args->size = 0x100000; // size } else if (args->id == 31) { rx::bridge.header->bufferInUseAddress = args->size; - return 0; + return {}; } else if (args->id == 33) { // adjust color std::printf("adjust color\n"); - return 0; + return {}; } else if (args->id != 0 && args->id != 1) { // used during open/close ORBIS_LOG_NOTICE("dce: UNIMPLEMENTED FlipControl", args->id, args->arg2, args->ptr, args->size); @@ -165,7 +171,7 @@ static std::int64_t dce_instance_ioctl(IoDeviceInstance *instance, std::fflush(stdout); //__builtin_trap(); } - return 0; + return {}; } if (request == 0xc0308206) { @@ -176,18 +182,18 @@ static std::int64_t dce_instance_ioctl(IoDeviceInstance *instance, if (args->index >= std::size(rx::bridge.header->buffers)) { // TODO ORBIS_LOG_FATAL("dce: out of buffers!"); - return -1; + return orbis::ErrorCode::NOMEM; } // TODO: lock bridge header rx::bridge.header->buffers[args->index] = { - .width = dceInstance->bufferAttributes.width, - .height = dceInstance->bufferAttributes.height, - .pitch = dceInstance->bufferAttributes.pitch, + .width = device->bufferAttributes.width, + .height = device->bufferAttributes.height, + .pitch = device->bufferAttributes.pitch, .address = args->address, - .pixelFormat = dceInstance->bufferAttributes.pixelFormat, - .tilingMode = dceInstance->bufferAttributes.tilingMode}; - return 0; + .pixelFormat = device->bufferAttributes.pixelFormat, + .tilingMode = device->bufferAttributes.tilingMode}; + return {}; } if (request == 0xc0308207) { // SCE_SYS_DCE_IOCTL_REGISTER_BUFFER_ATTRIBUTE @@ -199,12 +205,12 @@ static std::int64_t dce_instance_ioctl(IoDeviceInstance *instance, args->unk4_zero, args->unk5_zero, args->unk6, args->unk7, args->unk8); - dceInstance->bufferAttributes.pixelFormat = args->pixelFormat; - dceInstance->bufferAttributes.tilingMode = args->tilingMode; - dceInstance->bufferAttributes.pitch = args->pitch; - dceInstance->bufferAttributes.width = args->width; - dceInstance->bufferAttributes.height = args->height; - return 0; + device->bufferAttributes.pixelFormat = args->pixelFormat; + device->bufferAttributes.tilingMode = args->tilingMode; + device->bufferAttributes.pitch = args->pitch; + device->bufferAttributes.width = args->width; + device->bufferAttributes.height = args->height; + return {}; } if (request == 0xc0488204) { @@ -217,13 +223,13 @@ static std::int64_t dce_instance_ioctl(IoDeviceInstance *instance, rx::bridge.sendFlip(args->displayBufferIndex, /*args->flipMode,*/ args->flipArg); - return 0; + return {}; } if (request == 0x80088209) { // deallocate? auto arg = *reinterpret_cast(argp); ORBIS_LOG_ERROR("dce: 0x80088209", arg); - return 0; + return {}; } ORBIS_LOG_FATAL("Unhandled dce ioctl", request); @@ -231,30 +237,37 @@ static std::int64_t dce_instance_ioctl(IoDeviceInstance *instance, std::fflush(stdout); __builtin_trap(); - return 0; + return {}; } -static void *dce_instance_mmap(IoDeviceInstance *instance, void *address, - std::uint64_t size, std::int32_t prot, - std::int32_t flags, std::int64_t offset) { +static orbis::ErrorCode dce_mmap(orbis::File *file, void **address, + std::uint64_t size, std::int32_t prot, + std::int32_t flags, std::int64_t offset, + orbis::Thread *thread) { ORBIS_LOG_FATAL("dce mmap", address, size, offset); - return rx::vm::map(address, size, prot, flags); + auto result = rx::vm::map(*address, size, prot, flags); + + if (result == (void *)-1) { + return orbis::ErrorCode::INVAL; // TODO + } + + *address = result; + return {}; } -static std::int32_t dce_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->ioctl = dce_instance_ioctl; - newInstance->mmap = dce_instance_mmap; - io_device_instance_init(device, newInstance); - *instance = newInstance; - return 0; +static const orbis::FileOps ops = { + .ioctl = dce_ioctl, + .mmap = dce_mmap, +}; + +orbis::ErrorCode DceDevice::open(orbis::Ref *file, + const char *path, std::uint32_t flags, + std::uint32_t mode) { + auto newFile = orbis::knew(); + newFile->device = this; + newFile->ops = &ops; + *file = newFile; + return {}; } -IoDevice *createDceCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = dce_device_open; - return newDevice; -} +IoDevice *createDceCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/iodev/dipsw.cpp b/rpcsx-os/iodev/dipsw.cpp index dbb77bb83..1b9c34c5e 100644 --- a/rpcsx-os/iodev/dipsw.cpp +++ b/rpcsx-os/iodev/dipsw.cpp @@ -1,19 +1,17 @@ #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" +#include "orbis/file.hpp" #include "orbis/utils/Logs.hpp" -#include -struct DipswDevice : public IoDevice {}; +struct DipswFile : public orbis::File {}; -struct DipswInstance : public IoDeviceInstance {}; - -static std::int64_t dipsw_instance_ioctl(IoDeviceInstance *instance, - std::uint64_t request, void *argp) { +static orbis::ErrorCode dipsw_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { if (request == 0x40048806) { // is connected? ORBIS_LOG_ERROR("dipsw ioctl 0x40048806", argp); *reinterpret_cast(argp) = 0; - return 0; + return {}; } // 0x40088808 @@ -22,7 +20,7 @@ static std::int64_t dipsw_instance_ioctl(IoDeviceInstance *instance, if (request == 0x40088808) { ORBIS_LOG_ERROR("dipsw ioctl 0x40088808", argp); *reinterpret_cast(argp) = 1; - return 0; + return {}; } // 0x8010880a @@ -36,28 +34,27 @@ static std::int64_t dipsw_instance_ioctl(IoDeviceInstance *instance, ORBIS_LOG_ERROR("dipsw ioctl 0x8010880a", args->address, args->size); - return 0; + return {}; } ORBIS_LOG_FATAL("Unhandled dipsw ioctl", request); - std::fflush(stdout); //__builtin_trap(); - return 0; + return {}; } -static std::int32_t dipsw_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->ioctl = dipsw_instance_ioctl; - io_device_instance_init(device, newInstance); - *instance = newInstance; - return 0; -} +static const orbis::FileOps ops = { + .ioctl = dipsw_ioctl, +}; -IoDevice *createDipswCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = dipsw_device_open; - return newDevice; -} +struct DipswDevice : public IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override { + auto newFile = orbis::knew(); + newFile->device = this; + newFile->ops = &ops; + *file = newFile; + return {}; + } +}; + +IoDevice *createDipswCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/iodev/dmem.cpp b/rpcsx-os/iodev/dmem.cpp index ac1bfe37a..429b0c00b 100644 --- a/rpcsx-os/iodev/dmem.cpp +++ b/rpcsx-os/iodev/dmem.cpp @@ -1,17 +1,22 @@ #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" +#include "orbis/file.hpp" #include "orbis/utils/Logs.hpp" +#include "orbis/utils/SharedMutex.hpp" #include "vm.hpp" -#include -#include +#include struct DmemDevice : public IoDevice { + orbis::shared_mutex mtx; int index; std::uint64_t nextOffset; std::uint64_t memBeginAddress; + + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override; }; -struct DmemInstance : public IoDeviceInstance {}; +struct DmemFile : public orbis::File {}; struct AllocateDirectMemoryArgs { std::uint64_t searchStart; @@ -25,20 +30,21 @@ static constexpr auto dmemSize = 4ul * 1024 * 1024 * 1024; // static const std::uint64_t nextOffset = 0; // static const std::uint64_t memBeginAddress = 0xfe0000000; -static std::int64_t dmem_instance_ioctl(IoDeviceInstance *instance, - std::uint64_t request, void *argp) { +static orbis::ErrorCode dmem_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { + auto device = static_cast(file->device.get()); - auto device = static_cast(instance->device.get()); + std::lock_guard lock(device->mtx); switch (request) { case 0x4008800a: // get size ORBIS_LOG_ERROR("dmem getTotalSize", device->index, argp); *(std::uint64_t *)argp = dmemSize; - return 0; + return {}; case 0xc0208016: // get avaiable size ORBIS_LOG_ERROR("dmem getAvaiableSize", device->index, argp); *(std::uint64_t *)argp = dmemSize - device->nextOffset; - return 0; + return {}; case 0xc0288001: { // sceKernelAllocateDirectMemory auto args = reinterpret_cast(argp); @@ -50,12 +56,12 @@ static std::int64_t dmem_instance_ioctl(IoDeviceInstance *instance, args->alignment, args->memoryType, alignedOffset); if (alignedOffset + args->len > dmemSize) { - return -1; + return orbis::ErrorCode::NOMEM; } args->searchStart = alignedOffset; device->nextOffset = alignedOffset + args->len; - return 0; + return {}; } case 0x80108002: { // sceKernelReleaseDirectMemory @@ -70,48 +76,51 @@ static std::int64_t dmem_instance_ioctl(IoDeviceInstance *instance, args->size); // std::fflush(stdout); //__builtin_trap(); - return 0; + return {}; } default: - ORBIS_LOG_FATAL("Unhandled dmem ioctl", device->index, request); - return 0; - - std::fflush(stdout); - __builtin_trap(); + return {}; } - - return -1; } -static void *dmem_instance_mmap(IoDeviceInstance *instance, void *address, - std::uint64_t size, std::int32_t prot, - std::int32_t flags, std::int64_t offset) { - auto device = static_cast(instance->device.get()); +static orbis::ErrorCode dmem_mmap(orbis::File *file, void **address, + std::uint64_t size, std::int32_t prot, + std::int32_t flags, std::int64_t offset, + orbis::Thread *thread) { + auto device = static_cast(file->device.get()); auto target = device->memBeginAddress + offset; ORBIS_LOG_WARNING("dmem mmap", device->index, offset, target); - auto addr = rx::vm::map(reinterpret_cast(target), size, prot, flags); - return addr; + auto result = + rx::vm::map(reinterpret_cast(target), size, prot, flags); + + if (result == (void *)-1) { + return orbis::ErrorCode::INVAL; // TODO + } + + *address = result; + return {}; } -static std::int32_t dmem_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->ioctl = dmem_instance_ioctl; - newInstance->mmap = dmem_instance_mmap; +static const orbis::FileOps ops = { + .ioctl = dmem_ioctl, + .mmap = dmem_mmap, +}; - io_device_instance_init(device, newInstance); - *instance = newInstance; - return 0; +orbis::ErrorCode DmemDevice::open(orbis::Ref *file, + const char *path, std::uint32_t flags, + std::uint32_t mode) { + auto newFile = orbis::knew(); + newFile->device = this; + newFile->ops = &ops; + *file = newFile; + return {}; } IoDevice *createDmemCharacterDevice(int index) { auto *newDevice = orbis::knew(); - newDevice->open = dmem_device_open; newDevice->index = index; newDevice->nextOffset = 0; newDevice->memBeginAddress = 0xf'e000'0000 + dmemSize * index; diff --git a/rpcsx-os/iodev/gc.cpp b/rpcsx-os/iodev/gc.cpp index e7d2964cf..e1c1d7112 100644 --- a/rpcsx-os/iodev/gc.cpp +++ b/rpcsx-os/iodev/gc.cpp @@ -1,27 +1,21 @@ #include "bridge.hpp" #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" +#include "orbis/file.hpp" #include "orbis/utils/Logs.hpp" -#include -#include -#include -#include -// #include #include "vm.hpp" -#include +#include #include -#include -#include -#include - -struct GcDevice : public IoDevice {}; - -struct GcInstance : public IoDeviceInstance {}; +struct GcDevice : public IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override; +}; +struct GcFile : public orbis::File {}; static std::uint64_t g_submitDoneFlag; -static std::int64_t gc_instance_ioctl(IoDeviceInstance *instance, - std::uint64_t request, void *argp) { +static orbis::ErrorCode gc_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { // 0xc00c8110 // 0xc0848119 @@ -30,7 +24,7 @@ static std::int64_t gc_instance_ioctl(IoDeviceInstance *instance, // TODO ORBIS_LOG_ERROR("gc ioctl 0xc008811b", *(std::uint64_t *)argp); *reinterpret_cast(argp) = &g_submitDoneFlag; - return 0; + break; case 0xc0108102: { // submit? struct Args { @@ -44,7 +38,7 @@ static std::int64_t gc_instance_ioctl(IoDeviceInstance *instance, flockfile(stderr); ORBIS_LOG_ERROR("gc ioctl 0xc0108102", args->arg0, args->count, args->cmds); - for (int i = 0; i < args->count; ++i) { + for (unsigned i = 0; i < args->count; ++i) { auto cmd = args->cmds + (i * 2); auto cmdId = cmd[0] & 0xffff'ffff; auto addressLoPart = cmd[0] >> 32; @@ -95,7 +89,7 @@ static std::int64_t gc_instance_ioctl(IoDeviceInstance *instance, ORBIS_LOG_ERROR("gc ioctl 0xc020810c", args->arg0, args->count, args->cmds, args->arg3, args->arg4); - for (int i = 0; i < args->count; ++i) { + for (unsigned i = 0; i < args->count; ++i) { auto cmd = args->cmds + (i * 2); auto cmdId = cmd[0] & 0xffff'ffff; auto addressLoPart = cmd[0] >> 32; @@ -238,31 +232,36 @@ static std::int64_t gc_instance_ioctl(IoDeviceInstance *instance, __builtin_trap(); break; } - return 0; + return {}; } -static void *gc_instance_mmap(IoDeviceInstance *instance, void *address, - std::uint64_t size, std::int32_t prot, - std::int32_t flags, std::int64_t offset) { - ORBIS_LOG_FATAL("Unhandled gc mmap", offset); +static orbis::ErrorCode gc_mmap(orbis::File *file, void **address, + std::uint64_t size, std::int32_t prot, + std::int32_t flags, std::int64_t offset, + orbis::Thread *thread) { + ORBIS_LOG_FATAL("gc mmap", address, size, offset); + auto result = rx::vm::map(*address, size, prot, flags); - return rx::vm::map(address, size, prot, flags); + if (result == (void *)-1) { + return orbis::ErrorCode::INVAL; // TODO + } + + *address = result; + return {}; } -static std::int32_t gc_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->ioctl = gc_instance_ioctl; - newInstance->mmap = gc_instance_mmap; - io_device_instance_init(device, newInstance); - *instance = newInstance; - return 0; +static const orbis::FileOps ops = { + .ioctl = gc_ioctl, + .mmap = gc_mmap, +}; + +orbis::ErrorCode GcDevice::open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) { + auto newFile = orbis::knew(); + newFile->device = this; + newFile->ops = &ops; + *file = newFile; + return {}; } -IoDevice *createGcCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = gc_device_open; - return newDevice; -} +IoDevice *createGcCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/iodev/hid.cpp b/rpcsx-os/iodev/hid.cpp index 8375baf68..be0481032 100644 --- a/rpcsx-os/iodev/hid.cpp +++ b/rpcsx-os/iodev/hid.cpp @@ -1,43 +1,34 @@ #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" +#include "orbis/file.hpp" #include "orbis/utils/Logs.hpp" -#include "vm.hpp" -#include -#include -struct HidDevice : public IoDevice {}; -struct HidInstance : public IoDeviceInstance {}; +struct HidDevice : public IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override; +}; +struct HidFile : public orbis::File {}; -static std::int64_t hid_instance_ioctl(IoDeviceInstance *instance, - std::uint64_t request, void *argp) { +static orbis::ErrorCode hid_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { ORBIS_LOG_FATAL("Unhandled hid ioctl", request); // 0x800c4802 - return 0; + return {}; } -static void *hid_instance_mmap(IoDeviceInstance *instance, void *address, - std::uint64_t size, std::int32_t prot, - std::int32_t flags, std::int64_t offset) { - ORBIS_LOG_FATAL("Unhandled hid mmap", offset); - return rx::vm::map(address, size, prot, flags); +static const orbis::FileOps ops = { + .ioctl = hid_ioctl, +}; + +orbis::ErrorCode HidDevice::open(orbis::Ref *file, + const char *path, std::uint32_t flags, + std::uint32_t mode) { + auto newFile = orbis::knew(); + newFile->device = this; + newFile->ops = &ops; + *file = newFile; + return {}; } -static std::int32_t hid_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->ioctl = hid_instance_ioctl; - newInstance->mmap = hid_instance_mmap; - - io_device_instance_init(device, newInstance); - *instance = newInstance; - return 0; -} - -IoDevice *createHidCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = hid_device_open; - return newDevice; -} +IoDevice *createHidCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/iodev/hmd_3da.cpp b/rpcsx-os/iodev/hmd_3da.cpp index bf03768db..1f7efcaf8 100644 --- a/rpcsx-os/iodev/hmd_3da.cpp +++ b/rpcsx-os/iodev/hmd_3da.cpp @@ -1,33 +1,34 @@ #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" +#include "orbis/file.hpp" #include "orbis/utils/Logs.hpp" -#include -struct Hmd3daDevice : public IoDevice {}; - -struct Hmd3daInstance : public IoDeviceInstance {}; - -static std::int64_t hmd_3da_instance_ioctl(IoDeviceInstance *instance, - std::uint64_t request, void *argp) { +struct Hmd3daDevice : public IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override; +}; +struct Hmd3daFile : public orbis::File {}; +static orbis::ErrorCode hmd_3da_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { ORBIS_LOG_FATAL("Unhandled hmd_3da ioctl", request); - return -1; + + // 0x800c4802 + return {}; } -static std::int32_t hmd_3da_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->ioctl = hmd_3da_instance_ioctl; +static const orbis::FileOps ops = { + .ioctl = hmd_3da_ioctl, +}; - io_device_instance_init(device, newInstance); - *instance = newInstance; - return 0; +orbis::ErrorCode Hmd3daDevice::open(orbis::Ref *file, + const char *path, std::uint32_t flags, + std::uint32_t mode) { + auto newFile = orbis::knew(); + newFile->device = this; + newFile->ops = &ops; + *file = newFile; + return {}; } -IoDevice *createHmd3daCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = hmd_3da_device_open; - return newDevice; -} +IoDevice *createHmd3daCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/iodev/hmd_cmd.cpp b/rpcsx-os/iodev/hmd_cmd.cpp index 05b4e5301..4b3a81c71 100644 --- a/rpcsx-os/iodev/hmd_cmd.cpp +++ b/rpcsx-os/iodev/hmd_cmd.cpp @@ -1,34 +1,33 @@ #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" #include "orbis/utils/Logs.hpp" -#include -struct HmdCmdDevice : public IoDevice {}; - -struct HmdCmdInstance : public IoDeviceInstance {}; - -static std::int64_t hmd_cmd_instance_ioctl(IoDeviceInstance *instance, - std::uint64_t request, void *argp) { +struct HmdCmdDevice : public IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override; +}; +struct HmdCmdFile : public orbis::File {}; +static orbis::ErrorCode hmd_cmd_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { ORBIS_LOG_FATAL("Unhandled hmd_cmd ioctl", request); - return -1; + + // 0x800c4802 + return {}; } -static std::int32_t hmd_cmd_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->ioctl = hmd_cmd_instance_ioctl; +static const orbis::FileOps ops = { + .ioctl = hmd_cmd_ioctl, +}; - io_device_instance_init(device, newInstance); - - *instance = newInstance; - return 0; +orbis::ErrorCode HmdCmdDevice::open(orbis::Ref *file, + const char *path, std::uint32_t flags, + std::uint32_t mode) { + auto newFile = orbis::knew(); + newFile->device = this; + newFile->ops = &ops; + *file = newFile; + return {}; } -IoDevice *createHmdCmdCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = hmd_cmd_device_open; - return newDevice; -} +IoDevice *createHmdCmdCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/iodev/hmd_mmap.cpp b/rpcsx-os/iodev/hmd_mmap.cpp index 1d5f334cf..24b5f98f8 100644 --- a/rpcsx-os/iodev/hmd_mmap.cpp +++ b/rpcsx-os/iodev/hmd_mmap.cpp @@ -2,44 +2,51 @@ #include "orbis/KernelAllocator.hpp" #include "orbis/utils/Logs.hpp" #include "vm.hpp" -#include -#include -struct HmdMmapDevice : public IoDevice {}; - -struct HmdMmapInstance : public IoDeviceInstance {}; - -static std::int64_t hmd_mmap_instance_ioctl(IoDeviceInstance *instance, - std::uint64_t request, void *argp) { +struct HmdMmapDevice : public IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override; +}; +struct HmdMmapFile : public orbis::File {}; +static orbis::ErrorCode hmd_mmap_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { ORBIS_LOG_FATAL("Unhandled hmd_mmap ioctl", request); - std::fflush(stdout); - __builtin_trap(); - return -1; + + // 0x800c4802 + return {}; } -static void *hmd_mmap_instance_mmap(IoDeviceInstance *instance, void *address, - std::uint64_t size, std::int32_t prot, - std::int32_t flags, std::int64_t offset) { - ORBIS_LOG_FATAL("Unhandled hmd_mmap mmap", offset); - return rx::vm::map(address, size, prot, flags); +static orbis::ErrorCode hmd_mmap_mmap(orbis::File *file, void **address, + std::uint64_t size, std::int32_t prot, + std::int32_t flags, std::int64_t offset, + orbis::Thread *thread) { + ORBIS_LOG_FATAL("hmd_mmap mmap", address, size, offset); + auto result = rx::vm::map(*address, size, prot, flags); + + if (result == (void *)-1) { + return orbis::ErrorCode::INVAL; // TODO + } + + *address = result; + return {}; } -static std::int32_t hmd_mmap_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->ioctl = hmd_mmap_instance_ioctl; - newInstance->mmap = hmd_mmap_instance_mmap; +static const orbis::FileOps ops = { + .ioctl = hmd_mmap_ioctl, + .mmap = hmd_mmap_mmap, +}; - io_device_instance_init(device, newInstance); - *instance = newInstance; - return 0; +orbis::ErrorCode HmdMmapDevice::open(orbis::Ref *file, + const char *path, std::uint32_t flags, + std::uint32_t mode) { + auto newFile = orbis::knew(); + newFile->device = this; + newFile->ops = &ops; + *file = newFile; + return {}; } IoDevice *createHmdMmapCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = hmd_mmap_device_open; - return newDevice; + return orbis::knew(); } diff --git a/rpcsx-os/iodev/hmd_snsr.cpp b/rpcsx-os/iodev/hmd_snsr.cpp index 9180659d3..d68aa649c 100644 --- a/rpcsx-os/iodev/hmd_snsr.cpp +++ b/rpcsx-os/iodev/hmd_snsr.cpp @@ -1,31 +1,36 @@ #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" +#include "orbis/file.hpp" #include "orbis/utils/Logs.hpp" -#include -struct HmdSnsrDevice : public IoDevice {}; +struct HmdSnsrDevice : public IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override; +}; +struct HmdSnsrFile : public orbis::File {}; -struct HmdSnsrInstance : public IoDeviceInstance {}; - -static std::int64_t smd_snr_instance_ioctl(IoDeviceInstance *instance, - std::uint64_t request, void *argp) { +static orbis::ErrorCode hmd_snsr_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { ORBIS_LOG_FATAL("Unhandled hmd_snsr ioctl", request); - return -1; + + // 0x800c4802 + return {}; } -static std::int32_t smd_snr_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->ioctl = smd_snr_instance_ioctl; - io_device_instance_init(device, newInstance); - *instance = newInstance; - return 0; +static const orbis::FileOps ops = { + .ioctl = hmd_snsr_ioctl, +}; + +orbis::ErrorCode HmdSnsrDevice::open(orbis::Ref *file, + const char *path, std::uint32_t flags, + std::uint32_t mode) { + auto newFile = orbis::knew(); + newFile->device = this; + newFile->ops = &ops; + *file = newFile; + return {}; } IoDevice *createHmdSnsrCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = smd_snr_device_open; - return newDevice; + return orbis::knew(); } diff --git a/rpcsx-os/iodev/null.cpp b/rpcsx-os/iodev/null.cpp index d55964182..4564c449e 100644 --- a/rpcsx-os/iodev/null.cpp +++ b/rpcsx-os/iodev/null.cpp @@ -1,29 +1,31 @@ #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" +#include "orbis/uio.hpp" -struct NullDevice : public IoDevice {}; +struct NullDevice : public IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override; +}; +struct NullFile : public orbis::File {}; -struct NullInstance : public IoDeviceInstance {}; - -static std::int64_t null_instance_write(IoDeviceInstance *instance, - const void *data, std::uint64_t size) { - return size; +static orbis::ErrorCode null_write(orbis::File *file, orbis::Uio *uio, + orbis::Thread *) { + uio->resid = 0; + return {}; } -static std::int32_t null_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->write = null_instance_write; +static const orbis::FileOps ops = { + .write = null_write, +}; - io_device_instance_init(device, newInstance); - *instance = newInstance; - return 0; +orbis::ErrorCode NullDevice::open(orbis::Ref *file, + const char *path, std::uint32_t flags, + std::uint32_t mode) { + auto newFile = orbis::knew(); + newFile->device = this; + newFile->ops = &ops; + *file = newFile; + return {}; } -IoDevice *createNullCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = null_device_open; - return newDevice; -} +IoDevice *createNullCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/iodev/rng.cpp b/rpcsx-os/iodev/rng.cpp index 071259b15..d302e87b3 100644 --- a/rpcsx-os/iodev/rng.cpp +++ b/rpcsx-os/iodev/rng.cpp @@ -2,40 +2,49 @@ #include "orbis/KernelAllocator.hpp" #include "orbis/utils/Logs.hpp" #include "vm.hpp" -#include -#include -struct RngDevice : public IoDevice {}; -struct RngInstance : public IoDeviceInstance {}; +struct RngDevice : public IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override; +}; +struct RngFile : public orbis::File {}; -static std::int64_t rng_instance_ioctl(IoDeviceInstance *instance, - std::uint64_t request, void *argp) { +static orbis::ErrorCode rng_ioctl(orbis::File *file, std::uint64_t request, + void *argp, orbis::Thread *thread) { ORBIS_LOG_FATAL("Unhandled rng ioctl", request); - return 0; + + // 0x800c4802 + return {}; } -static void *rng_instance_mmap(IoDeviceInstance *instance, void *address, - std::uint64_t size, std::int32_t prot, - std::int32_t flags, std::int64_t offset) { - ORBIS_LOG_FATAL("Unhandled rng mmap", offset); - return rx::vm::map(address, size, prot, flags); +static orbis::ErrorCode rng_mmap(orbis::File *file, void **address, + std::uint64_t size, std::int32_t prot, + std::int32_t flags, std::int64_t offset, + orbis::Thread *thread) { + ORBIS_LOG_FATAL("rng mmap", address, size, offset); + auto result = rx::vm::map(*address, size, prot, flags); + + if (result == (void *)-1) { + return orbis::ErrorCode::INVAL; // TODO + } + + *address = result; + return {}; } -static std::int32_t rng_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->ioctl = rng_instance_ioctl; - newInstance->mmap = rng_instance_mmap; +static const orbis::FileOps ops = { + .ioctl = rng_ioctl, + .mmap = rng_mmap, +}; - io_device_instance_init(device, newInstance); - *instance = newInstance; - return 0; +orbis::ErrorCode RngDevice::open(orbis::Ref *file, + const char *path, std::uint32_t flags, + std::uint32_t mode) { + auto newFile = orbis::knew(); + newFile->device = this; + newFile->ops = &ops; + *file = newFile; + return {}; } -IoDevice *createRngCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = rng_device_open; - return newDevice; -} +IoDevice *createRngCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/iodev/stderr.cpp b/rpcsx-os/iodev/stderr.cpp deleted file mode 100644 index 639548685..000000000 --- a/rpcsx-os/iodev/stderr.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "io-device.hpp" -#include "orbis/KernelAllocator.hpp" -#include - -struct StderrInstance : public IoDeviceInstance {}; - -struct StderrDevice : public IoDevice { - StderrInstance *instance = nullptr; -}; - -static std::int64_t stderr_instance_write(IoDeviceInstance *instance, - const void *data, - std::uint64_t size) { - static const bool istty = isatty(fileno(stderr)); - if (size && istty) - std::fprintf(stderr, "\e[0;35m"); - auto result = std::fwrite(data, 1, size, stderr); - if (size && istty) - std::fprintf(stderr, "\e[0m"); - std::fflush(stderr); - - return result; -} - -static std::int64_t stderr_instance_close(IoDeviceInstance *instance) { - instance->device->decRef(); - return 0; -} - -static std::int32_t stderr_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto stderrDevice = static_cast(device); - if (stderrDevice->instance == nullptr) { - auto *newInstance = orbis::knew(); - newInstance->write = stderr_instance_write; - newInstance->close = stderr_instance_close; - - io_device_instance_init(device, newInstance); - - *instance = newInstance; - } else { - device->incRef(); - - *instance = stderrDevice->instance; - } - - return 0; -} - -IoDevice *createStderrCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = stderr_device_open; - return newDevice; -} diff --git a/rpcsx-os/iodev/stdin.cpp b/rpcsx-os/iodev/stdin.cpp deleted file mode 100644 index c619aa33c..000000000 --- a/rpcsx-os/iodev/stdin.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "io-device.hpp" -#include "orbis/KernelAllocator.hpp" - -struct StdinDevice : public IoDevice {}; - -struct StdinInstance : public IoDeviceInstance {}; - -static std::int64_t stdin_instance_read(IoDeviceInstance *instance, void *data, - std::uint64_t size) { - return -1; -} - -static std::int32_t open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->read = stdin_instance_read; - io_device_instance_init(device, newInstance); - *instance = newInstance; - return 0; -} - -IoDevice *createStdinCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = open; - return newDevice; -} diff --git a/rpcsx-os/iodev/stdout.cpp b/rpcsx-os/iodev/stdout.cpp deleted file mode 100644 index 338f45736..000000000 --- a/rpcsx-os/iodev/stdout.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "io-device.hpp" -#include "orbis/KernelAllocator.hpp" -#include - -struct StdoutInstance : public IoDeviceInstance {}; - -struct StdoutDevice : public IoDevice { - StdoutInstance *instance = nullptr; -}; - -static std::int64_t stdout_instance_write(IoDeviceInstance *instance, - const void *data, - std::uint64_t size) { - static const bool istty = isatty(fileno(stdout)); - if (size && istty) - std::fprintf(stdout, "\e[30;1m"); - auto result = std::fwrite(data, 1, size, stdout); - if (size && istty) - std::fprintf(stdout, "\e[0m"); - std::fflush(stdout); - - return result; -} - -static std::int64_t stdout_instance_close(IoDeviceInstance *instance) { - instance->device->decRef(); - return 0; -} - -static std::int32_t stdout_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto stdoutDevice = static_cast(device); - if (stdoutDevice->instance == nullptr) { - auto *newInstance = orbis::knew(); - newInstance->write = stdout_instance_write; - newInstance->close = stdout_instance_close; - io_device_instance_init(device, newInstance); - - *instance = newInstance; - } else { - device->incRef(); - *instance = stdoutDevice->instance; - } - - return 0; -} - -IoDevice *createStdoutCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = stdout_device_open; - return newDevice; -} diff --git a/rpcsx-os/iodev/zero.cpp b/rpcsx-os/iodev/zero.cpp index fa23769b5..e7d9d7fb2 100644 --- a/rpcsx-os/iodev/zero.cpp +++ b/rpcsx-os/iodev/zero.cpp @@ -1,31 +1,37 @@ #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" +#include "orbis/uio.hpp" #include +#include -struct ZeroDevice : public IoDevice {}; +struct ZeroDevice : public IoDevice { + orbis::ErrorCode open(orbis::Ref *file, const char *path, + std::uint32_t flags, std::uint32_t mode) override; +}; +struct ZeroFile : public orbis::File {}; -struct ZeroInstance : public IoDeviceInstance {}; - -static std::int64_t zero_device_read(IoDeviceInstance *instance, void *data, - std::uint64_t size) { - std::memset(data, 0, size); - return size; +static orbis::ErrorCode zero_read(orbis::File *file, orbis::Uio *uio, + orbis::Thread *) { + for (auto entry : std::span(uio->iov, uio->iovcnt)) { + std::memset(entry.base, 0, entry.len); + uio->offset += entry.len; + } + uio->resid = 0; + return {}; } -static std::int32_t zero_device_open(IoDevice *device, - orbis::Ref *instance, - const char *path, std::uint32_t flags, - std::uint32_t mode) { - auto *newInstance = orbis::knew(); - newInstance->read = zero_device_read; +static const orbis::FileOps ops = { + .read = zero_read, +}; - io_device_instance_init(device, newInstance); - *instance = newInstance; - return 0; +orbis::ErrorCode ZeroDevice::open(orbis::Ref *file, + const char *path, std::uint32_t flags, + std::uint32_t mode) { + auto newFile = orbis::knew(); + newFile->device = this; + newFile->ops = &ops; + *file = newFile; + return {}; } -IoDevice *createZeroCharacterDevice() { - auto *newDevice = orbis::knew(); - newDevice->open = zero_device_open; - return newDevice; -} +IoDevice *createZeroCharacterDevice() { return orbis::knew(); } diff --git a/rpcsx-os/linker.cpp b/rpcsx-os/linker.cpp index aea7c8a7c..6f399844e 100644 --- a/rpcsx-os/linker.cpp +++ b/rpcsx-os/linker.cpp @@ -3,6 +3,8 @@ #include "io-device.hpp" #include "orbis/KernelAllocator.hpp" #include "orbis/module/Module.hpp" +#include "orbis/stat.hpp" +#include "orbis/uio.hpp" #include "vfs.hpp" #include "vm.hpp" #include @@ -838,38 +840,56 @@ Ref rx::linker::loadModule(std::span image, } Ref rx::linker::loadModuleFile(std::string_view path, - orbis::Process *process) { + orbis::Thread *thread) { if (!path.contains('/')) { - return loadModuleByName(path, process); + return loadModuleByName(path, thread); } - orbis::Ref instance; + orbis::Ref instance; if (vfs::open(path, kOpenFlagReadOnly, 0, &instance).isError()) { return {}; } - auto len = instance->lseek(instance.get(), 0, SEEK_END); - instance->lseek(instance.get(), 0, SEEK_SET); + orbis::Stat fileStat; + if (instance->ops->stat(instance.get(), &fileStat, nullptr) != + orbis::ErrorCode{}) { + return {}; + } + + auto len = fileStat.size; std::vector image(len); auto ptr = image.data(); - auto endPtr = ptr + image.size(); + orbis::IoVec ioVec{ + .base = ptr, + .len = static_cast(len), + }; + orbis::Uio io{ + .offset = 0, + .iov = &ioVec, + .iovcnt = 1, + .resid = 0, + .segflg = orbis::UioSeg::SysSpace, + .rw = orbis::UioRw::Read, + .td = thread, + }; - while (ptr != endPtr) { - auto result = instance->read(instance.get(), ptr, endPtr - ptr); - if (result < 0) { + while (io.offset < image.size()) { + ioVec = { + .base = ptr + io.offset, + .len = image.size() - io.offset, + }; + auto result = instance->ops->read(instance.get(), &io, thread); + if (result != orbis::ErrorCode{}) { std::fprintf(stderr, "Module file reading error\n"); std::abort(); } - ptr += result; } - instance->close(instance.get()); - - return loadModule(image, process); + return loadModule(image, thread->tproc); } -static Ref createSceFreeTypeFull(orbis::Process *process) { +static Ref createSceFreeTypeFull(orbis::Thread *thread) { auto result = orbis::knew(); std::strncpy(result->soName, "libSceFreeTypeFull.prx", @@ -888,7 +908,7 @@ static Ref createSceFreeTypeFull(orbis::Process *process) { } for (auto needed : result->needed) { - auto neededMod = rx::linker::loadModuleByName(needed, process); + auto neededMod = rx::linker::loadModuleByName(needed, thread); if (neededMod == nullptr) { std::fprintf(stderr, "Failed to load needed '%s' for FreeType\n", @@ -903,20 +923,20 @@ static Ref createSceFreeTypeFull(orbis::Process *process) { result->initProc = reinterpret_cast(+[] {}); result->finiProc = reinterpret_cast(+[] {}); - result->proc = process; + result->proc = thread->tproc; return result; } Ref rx::linker::loadModuleByName(std::string_view name, - orbis::Process *process) { + orbis::Thread *thread) { if (name.ends_with(".prx")) { name.remove_suffix(4); } if (auto it = g_moduleOverrideTable.find(name); it != g_moduleOverrideTable.end()) { - return loadModuleFile(it->second.c_str(), process); + return loadModuleFile(it->second.c_str(), thread); } if (name == "libSceAbstractTwitch") { @@ -924,14 +944,14 @@ Ref rx::linker::loadModuleByName(std::string_view name, } if (name == "libSceFreeTypeFull") { - return createSceFreeTypeFull(process); + return createSceFreeTypeFull(thread); } { std::string filePath = "/app0/sce_module/"; filePath += name; filePath += ".elf"; - if (auto result = rx::linker::loadModuleFile(filePath.c_str(), process)) { + if (auto result = rx::linker::loadModuleFile(filePath.c_str(), thread)) { return result; } } @@ -941,7 +961,7 @@ Ref rx::linker::loadModuleByName(std::string_view name, filePath += name; filePath += ".sprx"; - if (auto result = rx::linker::loadModuleFile(filePath.c_str(), process)) { + if (auto result = rx::linker::loadModuleFile(filePath.c_str(), thread)) { return result; } } diff --git a/rpcsx-os/linker.hpp b/rpcsx-os/linker.hpp index a051008fc..9a0f798ae 100644 --- a/rpcsx-os/linker.hpp +++ b/rpcsx-os/linker.hpp @@ -78,7 +78,7 @@ void override(std::string originalModuleName, orbis::Ref loadModule(std::span image, orbis::Process *process); orbis::Ref loadModuleFile(std::string_view path, - orbis::Process *process); + orbis::Thread *thread); orbis::Ref loadModuleByName(std::string_view name, - orbis::Process *process); + orbis::Thread *thread); } // namespace rx::linker diff --git a/rpcsx-os/main.cpp b/rpcsx-os/main.cpp index 32cabb06f..d234b9cf9 100644 --- a/rpcsx-os/main.cpp +++ b/rpcsx-os/main.cpp @@ -290,17 +290,9 @@ static void onSysExit(orbis::Thread *thread, int id, uint64_t *args, funlockfile(stderr); } -static int ps4Exec(orbis::Process *mainProcess, +static int ps4Exec(orbis::Thread *mainThread, orbis::utils::Ref executableModule, std::span argv, std::span envp) { - mainProcess->sysent = &orbis::ps4_sysvec; - mainProcess->ops = &rx::procOpsTable; - - auto [baseId, mainThread] = mainProcess->threadsMap.emplace(); - mainThread->tproc = mainProcess; - mainThread->tid = mainProcess->pid + baseId; - mainThread->state = orbis::ThreadState::RUNNING; - const auto stackEndAddress = 0x7'ffff'c000ull; const auto stackSize = 0x40000 * 16; auto stackStartAddress = stackEndAddress - stackSize; @@ -316,9 +308,9 @@ static int ps4Exec(orbis::Process *mainProcess, rx::vfs::mount("/dev/dmem0", createDmemCharacterDevice(0)); rx::vfs::mount("/dev/dmem1", createDmemCharacterDevice(1)); rx::vfs::mount("/dev/dmem2", createDmemCharacterDevice(2)); - rx::vfs::mount("/dev/stdout", createStdoutCharacterDevice()); - rx::vfs::mount("/dev/stderr", createStderrCharacterDevice()); - rx::vfs::mount("/dev/stdin", createStdinCharacterDevice()); + rx::vfs::mount("/dev/stdout", createFdWrapDevice(STDOUT_FILENO)); + rx::vfs::mount("/dev/stderr", createFdWrapDevice(STDERR_FILENO)); + rx::vfs::mount("/dev/stdin", createFdWrapDevice(STDIN_FILENO)); rx::vfs::mount("/dev/zero", createZeroCharacterDevice()); rx::vfs::mount("/dev/null", createNullCharacterDevice()); rx::vfs::mount("/dev/dipsw", createDipswCharacterDevice()); @@ -332,22 +324,29 @@ static int ps4Exec(orbis::Process *mainProcess, rx::vfs::mount("/dev/rng", createRngCharacterDevice()); rx::vfs::mount("/dev/ajm", createAjmCharacterDevice()); - rx::procOpsTable.open(mainThread, "/dev/stdin", 0, 0); - rx::procOpsTable.open(mainThread, "/dev/stdout", 0, 0); - rx::procOpsTable.open(mainThread, "/dev/stderr", 0, 0); + orbis::Ref stdinFile; + orbis::Ref stdoutFile; + orbis::Ref stderrFile; + rx::procOpsTable.open(mainThread, "/dev/stdin", 0, 0, &stdinFile); + rx::procOpsTable.open(mainThread, "/dev/stdout", 0, 0, &stdoutFile); + rx::procOpsTable.open(mainThread, "/dev/stderr", 0, 0, &stderrFile); + + mainThread->tproc->fileDescriptors.insert(stdinFile); + mainThread->tproc->fileDescriptors.insert(stdoutFile); + mainThread->tproc->fileDescriptors.insert(stderrFile); std::vector argvOffsets; std::vector envpOffsets; auto libkernel = rx::linker::loadModuleFile( - "/system/common/lib/libkernel_sys.sprx", mainProcess); + "/system/common/lib/libkernel_sys.sprx", mainThread); if (libkernel == nullptr) { std::fprintf(stderr, "libkernel not found\n"); return 1; } - libkernel->id = mainProcess->modulesMap.insert(libkernel); + libkernel->id = mainThread->tproc->modulesMap.insert(libkernel); // *reinterpret_cast( // reinterpret_cast(libkernel->base) + 0x6c2e4) = ~0; @@ -562,20 +561,6 @@ int main(int argc, const char *argv[]) { // rx::vm::printHostStats(); auto initProcess = orbis::g_context.createProcess(10); pthread_setname_np(pthread_self(), "10.MAINTHREAD"); - initProcess->sysent = &orbis::ps4_sysvec; - initProcess->onSysEnter = onSysEnter; - initProcess->onSysExit = onSysExit; - auto executableModule = - rx::linker::loadModuleFile(argv[argIndex], initProcess); - - if (executableModule == nullptr) { - std::fprintf(stderr, "Failed to open '%s'\n", argv[argIndex]); - std::abort(); - } - - executableModule->id = initProcess->modulesMap.insert(executableModule); - initProcess->processParam = executableModule->processParam; - initProcess->processParamSize = executableModule->processParamSize; std::thread{[] { pthread_setname_np(pthread_self(), "Bridge"); @@ -641,9 +626,31 @@ int main(int argc, const char *argv[]) { int status = 0; + initProcess->sysent = &orbis::ps4_sysvec; + initProcess->onSysEnter = onSysEnter; + initProcess->onSysExit = onSysExit; + initProcess->ops = &rx::procOpsTable; + + auto [baseId, mainThread] = initProcess->threadsMap.emplace(); + mainThread->tproc = initProcess; + mainThread->tid = initProcess->pid + baseId; + mainThread->state = orbis::ThreadState::RUNNING; + + auto executableModule = + rx::linker::loadModuleFile(argv[argIndex], mainThread); + + if (executableModule == nullptr) { + std::fprintf(stderr, "Failed to open '%s'\n", argv[argIndex]); + std::abort(); + } + + executableModule->id = initProcess->modulesMap.insert(executableModule); + initProcess->processParam = executableModule->processParam; + initProcess->processParamSize = executableModule->processParamSize; + if (executableModule->type == rx::linker::kElfTypeSceDynExec || executableModule->type == rx::linker::kElfTypeSceExec) { - status = ps4Exec(initProcess, std::move(executableModule), + status = ps4Exec(mainThread, std::move(executableModule), std::span(argv + argIndex, argc - argIndex), std::span()); } else { diff --git a/rpcsx-os/ops.cpp b/rpcsx-os/ops.cpp index 1c9c1e7ab..fd28661bf 100644 --- a/rpcsx-os/ops.cpp +++ b/rpcsx-os/ops.cpp @@ -40,7 +40,7 @@ loadPrx(orbis::Thread *thread, std::string_view name, bool relocate, return {{}, it->second}; } - auto module = rx::linker::loadModuleFile(name, thread->tproc); + auto module = rx::linker::loadModuleFile(name, thread); if (module == nullptr) { if (!expectedName.empty()) { @@ -138,30 +138,35 @@ loadPrx(orbis::Thread *thread, std::string_view path, bool relocate) { orbis::SysResult mmap(orbis::Thread *thread, orbis::caddr_t addr, orbis::size_t len, orbis::sint prot, orbis::sint flags, orbis::sint fd, orbis::off_t pos) { - auto result = (void *)-1; if (fd == -1) { - result = rx::vm::map(addr, len, prot, flags); - } else { - Ref handle = - static_cast(thread->tproc->fileDescriptors.get(fd)); - if (handle == nullptr) { - return ErrorCode::BADF; + auto result = rx::vm::map(addr, len, prot, flags); + if (result == (void *)-1) { + return ErrorCode::NOMEM; } - if (handle->mmap != nullptr) { - result = handle->mmap(handle.get(), addr, len, prot, flags, pos); - } else { - ORBIS_LOG_FATAL("unimplemented mmap", fd, (void *)addr, len, prot, flags, - pos); - result = rx::vm::map(addr, len, prot, flags); - } + thread->retval[0] = reinterpret_cast(result); + return {}; } - if (result == (void *)-1) { - return ErrorCode::NOMEM; + auto file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; } - thread->retval[0] = reinterpret_cast(result); + if (file->ops->mmap == nullptr) { + ORBIS_LOG_FATAL("unimplemented mmap", fd, (void *)addr, len, prot, flags, + pos); + return mmap(thread, addr, len, prot, flags, -1, 0); + } + + void *maddr = addr; + auto result = file->ops->mmap(file, &maddr, len, prot, flags, pos, thread); + + if (result != ErrorCode{}) { + return result; + } + + thread->retval[0] = reinterpret_cast(maddr); return {}; } @@ -225,281 +230,15 @@ orbis::SysResult virtual_query(orbis::Thread *thread, } orbis::SysResult open(orbis::Thread *thread, orbis::ptr path, - orbis::sint flags, orbis::sint mode) { - orbis::Ref instance; - auto result = rx::vfs::open(path, flags, mode, &instance); - if (result.isError()) { - ORBIS_LOG_WARNING("Failed to open file", path, result.value()); - thread->where(); - return result; - } - - auto fd = thread->tproc->fileDescriptors.insert(instance); - thread->retval[0] = fd; - ORBIS_LOG_WARNING("File opened", path, fd); - return {}; + orbis::sint flags, orbis::sint mode, + orbis::Ref *file) { + return rx::vfs::open(path, flags, mode, file); } orbis::SysResult socket(orbis::Thread *thread, orbis::ptr name, orbis::sint domain, orbis::sint type, - orbis::sint protocol) { - orbis::Ref instance; - auto error = createSocket(name, domain, type, protocol, &instance); - if (error != ErrorCode{}) { - ORBIS_LOG_WARNING("Failed to open socket", name, int(error)); - return error; - } - - auto fd = thread->tproc->fileDescriptors.insert(instance); - thread->retval[0] = fd; - ORBIS_LOG_WARNING("Socket opened", name, fd); - return {}; -} - -orbis::SysResult close(orbis::Thread *thread, orbis::sint fd) { - if (fd == 0) { - return {}; - } - if (!thread->tproc->fileDescriptors.close(fd)) { - return ErrorCode::BADF; - } - - ORBIS_LOG_WARNING("fd closed", fd); - return {}; -} - -// clang-format off -#define IOCPARM_SHIFT 13 /* number of bits for ioctl size */ -#define IOCPARM_MASK ((1 << IOCPARM_SHIFT) - 1) /* parameter length mask */ -#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK) -#define IOCBASECMD(x) ((x) & ~(IOCPARM_MASK << 16)) -#define IOCGROUP(x) (((x) >> 8) & 0xff) - -#define IOCPARM_MAX (1 << IOCPARM_SHIFT) /* max size of ioctl */ -#define IOC_VOID 0x20000000 /* no parameters */ -#define IOC_OUT 0x40000000 /* copy out parameters */ -#define IOC_IN 0x80000000 /* copy in parameters */ -#define IOC_INOUT (IOC_IN | IOC_OUT) -#define IOC_DIRMASK (IOC_VOID | IOC_OUT | IOC_IN) - -#define _IOC(inout, group, num, len) \ - ((unsigned long)((inout) | (((len) & IOCPARM_MASK) << 16) | ((group) << 8) | \ - (num))) -#define _IO(g, n) _IOC(IOC_VOID, (g), (n), 0) -#define _IOWINT(g, n) _IOC(IOC_VOID, (g), (n), sizeof(int)) -#define _IOR(g, n, t) _IOC(IOC_OUT, (g), (n), sizeof(t)) -#define _IOW(g, n, t) _IOC(IOC_IN, (g), (n), sizeof(t)) -/* this should be _IORW, but stdio got there first */ -#define _IOWR(g, n, t) _IOC(IOC_INOUT, (g), (n), sizeof(t)) -// clang-format on - -static std::string iocGroupToString(unsigned iocGroup) { - if (iocGroup >= 128) { - const char *sceGroups[] = { - "DEV", - "DMEM", - "GC", - "DCE", - "UVD", - "VCE", - "DBGGC", - "TWSI", - "MDBG", - "DEVENV", - "AJM", - "TRACE", - "IBS", - "MBUS", - "HDMI", - "CAMERA", - "FAN", - "THERMAL", - "PFS", - "ICC_CONFIG", - "IPC", - "IOSCHED", - "ICC_INDICATOR", - "EXFATFS", - "ICC_NVS", - "DVE", - "ICC_POWER", - "AV_CONTROL", - "ICC_SC_CONFIGURATION", - "ICC_DEVICE_POWER", - "SSHOT", - "DCE_SCANIN", - "FSCTRL", - "HMD", - "SHM", - "PHYSHM", - "HMDDFU", - "BLUETOOTH_HID", - "SBI", - "S3DA", - "SPM", - "BLOCKPOOL", - "SDK_EVENTLOG", - }; - - if (iocGroup - 127 >= std::size(sceGroups)) { - return "'?'"; - } - - return sceGroups[iocGroup - 127]; - } - - if (isprint(iocGroup)) { - return "'" + std::string(1, (char)iocGroup) + "'"; - } - - return "'?'"; -} - -static void printIoctl(unsigned long arg) { - std::printf("0x%lx { IO%s%s %lu(%s), %lu, %lu }\n", arg, - arg & IOC_OUT ? "R" : "", arg & IOC_IN ? "W" : "", IOCGROUP(arg), - iocGroupToString(IOCGROUP(arg)).c_str(), arg & 0xFF, - IOCPARM_LEN(arg)); -} - -static void ioctlToStream(std::ostream &stream, unsigned long arg) { - stream << "0x" << std::hex << arg << " { IO"; - - if ((arg & IOC_OUT) != 0) { - stream << 'R'; - } - - if ((arg & IOC_IN) != 0) { - stream << 'W'; - } - if ((arg & IOC_VOID) != 0) { - stream << 'i'; - } - - stream << " 0x" << IOCGROUP(arg); - stream << "('" << iocGroupToString(IOCGROUP(arg)) << "'), "; - stream << std::dec << (arg & 0xFF) << ", " << IOCPARM_LEN(arg) << " }"; -} - -static std::string ioctlToString(unsigned long arg) { - std::ostringstream stream; - ioctlToStream(stream, arg); - return std::move(stream).str(); -} - -orbis::SysResult ioctl(orbis::Thread *thread, orbis::sint fd, orbis::ulong com, - orbis::caddr_t argp) { - std::printf("ioctl: %d %s\n", (int)fd, ioctlToString(com).c_str()); - - Ref handle = - static_cast(thread->tproc->fileDescriptors.get(fd)); - if (handle == nullptr) { - return ErrorCode::BADF; - } - - if (handle->ioctl == nullptr) { - return ErrorCode::NOTSUP; - } - - auto result = handle->ioctl(handle.get(), com, argp); - - if (result < 0) { - // TODO - thread->where(); - return ErrorCode::IO; - } - - thread->retval[0] = result; - return {}; -} -orbis::SysResult write(orbis::Thread *thread, orbis::sint fd, - orbis::ptr data, orbis::ulong size) { - Ref handle = - static_cast(thread->tproc->fileDescriptors.get(fd)); - if (handle == nullptr) { - return ErrorCode::BADF; - } - - auto result = handle->write(handle.get(), data, size); - - if (result < 0) { - // TODO - return ErrorCode::IO; - } - - thread->retval[0] = result; - return {}; -} -orbis::SysResult read(orbis::Thread *thread, orbis::sint fd, - orbis::ptr data, orbis::ulong size) { - Ref handle = - static_cast(thread->tproc->fileDescriptors.get(fd)); - if (handle == nullptr) { - return ErrorCode::BADF; - } - - auto result = handle->read(handle.get(), data, size); - - if (result < 0) { - // TODO - return ErrorCode::IO; - } - - thread->retval[0] = result; - return {}; -} -orbis::SysResult pread(orbis::Thread *thread, orbis::sint fd, - orbis::ptr data, orbis::ulong size, - orbis::ulong offset) { - Ref handle = - static_cast(thread->tproc->fileDescriptors.get(fd)); - if (handle == nullptr) { - return ErrorCode::BADF; - } - - auto prevPos = handle->lseek(handle.get(), 0, SEEK_CUR); - handle->lseek(handle.get(), offset, SEEK_SET); - auto result = handle->read(handle.get(), data, size); - handle->lseek(handle.get(), prevPos, SEEK_SET); - - if (result < 0) { - // TODO - return ErrorCode::IO; - } - - thread->retval[0] = result; - return {}; -} -orbis::SysResult pwrite(orbis::Thread *thread, orbis::sint fd, - orbis::ptr data, orbis::ulong size, - orbis::ulong offset) { - return ErrorCode::NOTSUP; -} -orbis::SysResult lseek(orbis::Thread *thread, orbis::sint fd, - orbis::ulong offset, orbis::sint whence) { - Ref handle = - static_cast(thread->tproc->fileDescriptors.get(fd)); - if (handle == nullptr) { - return ErrorCode::BADF; - } - - auto result = handle->lseek(handle.get(), offset, whence); - - if (result < 0) { - // TODO - return ErrorCode::IO; - } - - thread->retval[0] = result; - return {}; -} -orbis::SysResult ftruncate(orbis::Thread *thread, orbis::sint fd, - orbis::off_t length) { - return {}; -} -orbis::SysResult truncate(orbis::Thread *thread, orbis::ptr path, - orbis::off_t length) { - return ErrorCode::NOTSUP; + orbis::sint protocol, Ref *file) { + return createSocket(file, name, domain, type, protocol); } orbis::SysResult dynlib_get_obj_member(orbis::Thread *thread, @@ -793,15 +532,6 @@ ProcessOps rx::procOpsTable = { .virtual_query = virtual_query, .open = open, .socket = socket, - .close = close, - .ioctl = ioctl, - .write = write, - .read = read, - .pread = pread, - .pwrite = pwrite, - .lseek = lseek, - .ftruncate = ftruncate, - .truncate = truncate, .dynlib_get_obj_member = dynlib_get_obj_member, .dynlib_dlsym = dynlib_dlsym, .dynlib_do_copy_relocations = dynlib_do_copy_relocations, diff --git a/rpcsx-os/scheduler.hpp b/rpcsx-os/scheduler.hpp new file mode 100644 index 000000000..375c3e0ae --- /dev/null +++ b/rpcsx-os/scheduler.hpp @@ -0,0 +1,152 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rx { +class Scheduler { + struct CpuState { + std::mutex mtx; + std::condition_variable cond; + orbis::Thread *task = nullptr; + ucontext_t cpuContext; + }; + + struct Task { + orbis::Thread *thread; + std::function wakeupCondFn; + }; + + std::mutex taskMtx; + std::condition_variable taskCond; + std::mutex queueMtx; + std::multimap> mQueue; + std::forward_list mCpuStates; + std::vector mCpus; + std::thread mThread; + std::atomic mExit{false}; + +public: + Scheduler(std::size_t smpCount) { + mCpus.resize(smpCount); + + for (std::size_t i = 0; i < smpCount; ++i) { + auto state = &mCpuStates.emplace_front(); + mCpus[i] = std::thread{[=, this] { cpuEntry(i, state); }}; + } + + mThread = std::thread{[this] { schedulerEntry(); }}; + } + + ~Scheduler() { + mExit = true; + taskCond.notify_one(); + + for (auto &cpuState : mCpuStates) { + cpuState.cond.notify_one(); + } + + mThread.join(); + + for (auto &cpu : mCpus) { + cpu.join(); + } + } + + void enqueue(orbis::Thread *thread) { + std::lock_guard lockQueue(queueMtx); + mQueue.emplace(thread->prio, Task{.thread = thread}); + taskCond.notify_one(); + } + + [[noreturn]] void + releaseThisCpu(orbis::Thread *thread, + std::function wakeupCondFn = nullptr) { + auto cpuContext = static_cast(thread->cpuContext); + thread->cpuContext = nullptr; + thread->cpuIndex = -1; + mQueue.emplace(thread->prio, Task{.thread = thread, + .wakeupCondFn = std::move(wakeupCondFn)}); + cpuContext->task = nullptr; + ::setcontext(&cpuContext->cpuContext); + __builtin_unreachable(); + } + +private: + [[noreturn]] void invoke(orbis::Thread *thread) { + auto ctxt = reinterpret_cast(thread->context); + ::setcontext(ctxt); + __builtin_unreachable(); + } + + orbis::Thread *fetchTask() { + std::lock_guard lockQueue(queueMtx); + decltype(mQueue)::iterator foundIt = mQueue.end(); + for (auto it = mQueue.begin(); it != mQueue.end(); ++it) { + auto &[prio, task] = *it; + if (task.wakeupCondFn != nullptr && !task.wakeupCondFn()) { + continue; + } + + if (foundIt == mQueue.end() || foundIt->first < task.thread->prio) { + foundIt = it; + } + } + + if (foundIt != mQueue.end()) { + auto result = foundIt->second.thread; + mQueue.erase(foundIt); + return result; + } + + return nullptr; + } + + void schedulerEntry() { + while (!mExit.load(std::memory_order::relaxed)) { + if (mQueue.empty()) { + continue; + } + + std::unique_lock lock(taskMtx); + taskCond.wait(lock); + + for (auto &cpu : mCpuStates) { + if (cpu.task == nullptr) { + cpu.task = fetchTask(); + } + } + } + } + + void cpuEntry(std::size_t cpuIndex, CpuState *state) { + ::getcontext(&state->cpuContext); + + while (!mExit.load(std::memory_order::relaxed)) { + auto task = std::exchange(state->task, nullptr); + if (task == nullptr) { + taskCond.notify_one(); + + std::unique_lock lock(state->mtx); + state->cond.wait(lock); + task = std::exchange(state->task, nullptr); + } + + if (task != nullptr) { + task->cpuIndex = cpuIndex; + task->cpuContext = state; + invoke(task); + } + } + } +}; +} // namespace rx diff --git a/rpcsx-os/vfs.cpp b/rpcsx-os/vfs.cpp index 00dd94627..c95a93f9a 100644 --- a/rpcsx-os/vfs.cpp +++ b/rpcsx-os/vfs.cpp @@ -26,7 +26,7 @@ orbis::SysResult rx::vfs::mount(const std::filesystem::path &guestPath, } orbis::SysResult rx::vfs::open(std::string_view path, int flags, int mode, - orbis::Ref *instance) { + orbis::Ref *file) { orbis::Ref device; bool isCharacterDevice = path.starts_with("/dev/"); @@ -50,8 +50,8 @@ orbis::SysResult rx::vfs::open(std::string_view path, int flags, int mode, } if (device != nullptr) { - return (orbis::ErrorCode)device->open( - device.get(), instance, std::string(path).c_str(), flags, mode); + return (orbis::ErrorCode)device->open(file, std::string(path).c_str(), + flags, mode); } if (isCharacterDevice) { diff --git a/rpcsx-os/vfs.hpp b/rpcsx-os/vfs.hpp index 277ada361..04d4871ec 100644 --- a/rpcsx-os/vfs.hpp +++ b/rpcsx-os/vfs.hpp @@ -1,16 +1,16 @@ #pragma once #include "orbis/error/SysResult.hpp" +#include "orbis/file.hpp" #include "orbis/utils/Rc.hpp" #include struct IoDevice; -struct IoDeviceInstance; namespace rx::vfs { void initialize(); void deinitialize(); orbis::SysResult mount(const std::filesystem::path &guestPath, IoDevice *dev); orbis::SysResult open(std::string_view path, int flags, int mode, - orbis::Ref *instance); + orbis::Ref *file); } // namespace rx::vfs