[rpcsx-os] Use orbis::File instead of IoDeviceInstance

This commit is contained in:
DH 2023-07-29 19:53:34 +03:00
parent c29aada46a
commit 84b2419241
43 changed files with 1626 additions and 1161 deletions

View file

@ -4,6 +4,7 @@
#include <deque>
#include <map>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
@ -46,7 +47,9 @@ using kunmap =
std::unordered_map<K, T, Hash, Pred, kallocator<std::pair<const K, T>>>;
} // namespace utils
template <typename T, typename... Args> T *knew(Args &&...args) {
template <typename T, typename... Args>
requires(std::is_constructible_v<T, Args...>)
T *knew(Args &&...args) {
auto loc = static_cast<T *>(utils::kalloc(sizeof(T), alignof(T)));
auto res = std::construct_at(loc, std::forward<Args>(args)...);
if constexpr (requires(T *t) { t->_total_size = sizeof(T); })

View file

@ -1,8 +1,8 @@
#pragma once
#include "KernelAllocator.hpp"
#include "error/ErrorCode.hpp"
#include <atomic>
#include "utils/Rc.hpp"
#include "utils/SharedMutex.hpp"
#include <cstdint>
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<RcBase> device;
std::atomic<unsigned> 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

View file

@ -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<orbis::timeval> tp,
SysResult sys_getrusage(Thread *thread, sint who, ptr<struct rusage> rusage);
SysResult sys_getsockopt(Thread *thread, sint s, sint level, sint name,
caddr_t val, ptr<sint> avalsize);
SysResult sys_readv(Thread *thread, sint fd, ptr<struct iovec> iovp,
uint iovcnt);
SysResult sys_writev(Thread *thread, sint fd, ptr<struct iovec> iovp,
uint iovcnt);
SysResult sys_readv(Thread *thread, sint fd, ptr<IoVec> iovp, uint iovcnt);
SysResult sys_writev(Thread *thread, sint fd, ptr<IoVec> iovp, uint iovcnt);
SysResult sys_settimeofday(Thread *thread, ptr<struct timeval> tp,
ptr<orbis::timezone> tzp);
SysResult sys_fchown(Thread *thread, sint fd, sint uid, sint gid);
@ -249,10 +248,10 @@ SysResult sys_lutimes(Thread *thread, ptr<char> path, ptr<struct timeval> tptr);
SysResult sys_nstat(Thread *thread, ptr<char> path, ptr<struct nstat> ub);
SysResult sys_nfstat(Thread *thread, sint fd, ptr<struct nstat> sb);
SysResult sys_nlstat(Thread *thread, ptr<char> path, ptr<struct nstat> ub);
SysResult sys_preadv(Thread *thread, sint fd, ptr<struct iovec> iovp,
uint iovcnt, off_t offset);
SysResult sys_pwritev(Thread *thread, sint fd, ptr<struct iovec> iovp,
uint iovcnt, off_t offset);
SysResult sys_preadv(Thread *thread, sint fd, ptr<IoVec> iovp, uint iovcnt,
off_t offset);
SysResult sys_pwritev(Thread *thread, sint fd, ptr<IoVec> iovp, uint iovcnt,
off_t offset);
SysResult sys_fhopen(Thread *thread, ptr<const struct fhandle> u_fhp,
sint flags);
SysResult sys_fhstat(Thread *thread, ptr<const struct fhandle> u_fhp,
@ -361,8 +360,7 @@ SysResult sys_eaccess(Thread *thread, ptr<char> 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<struct iovec> iovp, uint iovcnt,
sint flags);
SysResult sys_nmount(Thread *thread, ptr<IoVec> iovp, uint iovcnt, sint flags);
SysResult sys___mac_get_proc(Thread *thread, ptr<struct mac> mac_p);
SysResult sys___mac_set_proc(Thread *thread, ptr<struct mac> mac_p);
SysResult sys___mac_get_fd(Thread *thread, sint fd, ptr<struct mac> 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<struct sctp_sndrcvinfo> sinfo,
sint flags);
SysResult sys_sctp_generic_sendmsg_iov(Thread *thread, sint sd,
ptr<struct iovec> iov, sint iovlen,
caddr_t to, __socklen_t tolen,
SysResult sys_sctp_generic_sendmsg_iov(Thread *thread, sint sd, ptr<IoVec> iov,
sint iovlen, caddr_t to,
__socklen_t tolen,
ptr<struct sctp_sndrcvinfo> sinfo,
sint flags);
SysResult sys_sctp_generic_recvmsg(Thread *thread, sint sd,
ptr<struct iovec> iov, sint iovlen,
caddr_t from, __socklen_t fromlen,
SysResult sys_sctp_generic_recvmsg(Thread *thread, sint sd, ptr<IoVec> iov,
sint iovlen, caddr_t from,
__socklen_t fromlen,
ptr<struct sctp_sndrcvinfo> sinfo,
sint flags);
SysResult sys_pread(Thread *thread, sint fd, ptr<void> buf, size_t nbyte,
@ -557,9 +555,9 @@ SysResult sys_symlinkat(Thread *thread, ptr<char> path1, sint fd,
SysResult sys_unlinkat(Thread *thread, sint fd, ptr<char> path, sint flag);
SysResult sys_posix_openpt(Thread *thread, sint flags);
SysResult sys_gssd_syscall(Thread *thread, ptr<char> path);
SysResult sys_jail_get(Thread *thread, ptr<struct iovec> iovp, uint iovcnt,
SysResult sys_jail_get(Thread *thread, ptr<IoVec> iovp, uint iovcnt,
sint flags);
SysResult sys_jail_set(Thread *thread, ptr<struct iovec> iovp, uint iovcnt,
SysResult sys_jail_set(Thread *thread, ptr<IoVec> iovp, uint iovcnt,
sint flags);
SysResult sys_jail_remove(Thread *thread, sint jid);
SysResult sys_closefrom(Thread *thread, sint lowfd);

View file

@ -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 <mutex>
namespace orbis {
class KernelContext;
struct Thread;
@ -61,7 +60,7 @@ struct Process final {
utils::RcIdMap<Semaphore, sint, 4097, 1> semMap;
utils::RcIdMap<Module, ModuleHandle> modulesMap;
utils::OwningIdMap<Thread, lwpid_t> threadsMap;
utils::RcIdMap<utils::RcBase, sint> fileDescriptors;
utils::RcIdMap<orbis::File, sint> fileDescriptors;
// Named objects for debugging
utils::shared_mutex namedObjMutex;

View file

@ -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<const void> addr, sint flags,
ptr<void> info, ulong infoSize);
SysResult (*open)(Thread *thread, ptr<const char> path, sint flags,
sint mode);
SysResult (*open)(Thread *thread, ptr<const char> path, sint flags, sint mode,
Ref<File> *file);
SysResult (*socket)(Thread *thread, ptr<const char> 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<const void> data, ulong size);
SysResult (*read)(Thread *thread, sint fd, ptr<void> data, ulong size);
SysResult (*pread)(Thread *thread, sint fd, ptr<void> data, ulong size,
ulong offset);
SysResult (*pwrite)(Thread *thread, sint fd, ptr<const void> 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<const char> path, off_t length);
sint type, sint protocol, Ref<File> *file);
SysResult (*dynlib_get_obj_member)(Thread *thread, ModuleHandle handle,
uint64_t index, ptr<ptr<void>> addrp);
SysResult (*dynlib_dlsym)(Thread *thread, ModuleHandle handle,

View file

@ -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;

View file

@ -1,6 +1,5 @@
#pragma once
#include <atomic>
#include <span>
#include <string>
namespace orbis {

View file

@ -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<Stat> ub) {
ORBIS_LOG_WARNING(__FUNCTION__, fd, ub);
thread->where();
if (fd == 0) {
return ErrorCode::PERM;
Ref<File> 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<struct nstat> sb) {

View file

@ -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__);

View file

@ -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<void> 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> 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<void> 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> 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<std::uint64_t>(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<void> 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<struct iovec> iovp, uint iovcnt) {
return ErrorCode::NOSYS;
orbis::SysResult orbis::sys_readv(Thread *thread, sint fd, ptr<IoVec> iovp,
uint iovcnt) {
Ref<File> 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<struct iovec> iovp, uint iovcnt,
off_t offset) {
return ErrorCode::NOSYS;
orbis::SysResult orbis::sys_preadv(Thread *thread, sint fd, ptr<IoVec> iovp,
uint iovcnt, off_t offset) {
Ref<File> 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<std::uint64_t>(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<const void> 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> 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<const void> buf,
size_t nbyte, off_t offset) {
if (auto pwrite = thread->tproc->ops->pwrite) {
return pwrite(thread, fd, buf, nbyte, offset);
Ref<File> 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<std::uint64_t>(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<const void> 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<struct iovec> iovp, uint iovcnt) {
return ErrorCode::NOSYS;
orbis::SysResult orbis::sys_writev(Thread *thread, sint fd, ptr<IoVec> iovp,
uint iovcnt) {
Ref<File> 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<struct iovec> iovp, uint iovcnt,
off_t offset) {
return ErrorCode::NOSYS;
orbis::SysResult orbis::sys_pwritev(Thread *thread, sint fd, ptr<IoVec> iovp,
uint iovcnt, off_t offset) {
Ref<File> 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<std::uint64_t>(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> 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> 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<fd_set> in,
ptr<fd_set> ou, ptr<fd_set> ex,
@ -117,12 +347,12 @@ orbis::SysResult orbis::sys_sysarch(Thread *thread, sint op, ptr<char> parms) {
uint64_t fs;
if (auto error = uread(fs, (ptr<uint64_t>)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,

View file

@ -3,11 +3,11 @@
orbis::SysResult orbis::sys_jail(Thread *thread, ptr<struct jail> jail) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_jail_set(Thread *thread, ptr<struct iovec> iovp,
orbis::SysResult orbis::sys_jail_set(Thread *thread, ptr<IoVec> iovp,
uint iovcnt, sint flags) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_jail_get(Thread *thread, ptr<struct iovec> iovp,
orbis::SysResult orbis::sys_jail_get(Thread *thread, ptr<IoVec> iovp,
uint iovcnt, sint flags) {
return ErrorCode::NOSYS;
}

View file

@ -8,7 +8,6 @@
#include "osem.hpp"
#include "sys/sysproto.hpp"
#include "utils/Logs.hpp"
#include <chrono>
orbis::SysResult orbis::sys_netcontrol(Thread *thread, sint fd, uint op,
ptr<void> buf, uint nbuf) {
@ -24,18 +23,28 @@ orbis::SysResult orbis::sys_socketex(Thread *thread, ptr<const char> 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> 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;

View file

@ -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<struct iovec> iov, sint iovlen, caddr_t to,
Thread *thread, sint sd, ptr<IoVec> iov, sint iovlen, caddr_t to,
__socklen_t tolen, ptr<struct sctp_sndrcvinfo> sinfo, sint flags) {
return ErrorCode::NOSYS;
}
orbis::SysResult
orbis::sys_sctp_generic_recvmsg(Thread *thread, sint sd, ptr<struct iovec> iov,
orbis::sys_sctp_generic_recvmsg(Thread *thread, sint sd, ptr<IoVec> iov,
sint iovlen, caddr_t from, __socklen_t fromlen,
ptr<struct sctp_sndrcvinfo> sinfo, sint flags) {
return ErrorCode::NOSYS;

View file

@ -32,7 +32,14 @@ orbis::SysResult orbis::sys_open(Thread *thread, ptr<char> 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> 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<char> 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> 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<char> path,
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_stat(Thread *thread, ptr<char> path, ptr<Stat> ub) {
ORBIS_LOG_WARNING(__FUNCTION__, path, ub);
auto result = sys_open(thread, path, 0, 0);
Ref<File> 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<char> path,
ptr<Stat> buf, sint flag) {
@ -226,18 +264,25 @@ orbis::SysResult orbis::sys_futimes(Thread *thread, sint fd,
}
orbis::SysResult orbis::sys_truncate(Thread *thread, ptr<char> path,
off_t length) {
if (auto truncate = thread->tproc->ops->truncate) {
return truncate(thread, path, length);
Ref<File> 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<char> 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<char> from,
ptr<char> to) {
return ErrorCode::NOSYS;

View file

@ -8,7 +8,7 @@ orbis::SysResult orbis::sys_unmount(Thread *thread, ptr<char> path,
sint flags) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_nmount(Thread *thread, ptr<struct iovec> iovp,
uint iovcnt, sint flags) {
orbis::SysResult orbis::sys_nmount(Thread *thread, ptr<IoVec> iovp, uint iovcnt,
sint flags) {
return ErrorCode::NOSYS;
}

View file

@ -1,4 +1,5 @@
#include "utils/Logs.hpp"
#include "error/ErrorCode.hpp"
#include <cstdarg>
#include <cstdint>
#include <sstream>
@ -168,6 +169,298 @@ void log_class_string<bool>::format(std::string &out, const void *arg) {
out += get_object(arg) ? "1" : "0";
}
template <>
void log_class_string<orbis::ErrorCode>::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 += "<unknown " + std::to_string((int)errorCode) + ">";
}
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)) {

View file

@ -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

View file

@ -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 <cerrno>
#include <fcntl.h>
#include <span>
#include <string>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <unistd.h>
#include <vector>
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<HostIoDeviceInstance *>(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<orbis::File> *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<HostIoDeviceInstance *>(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<HostFile *>(file);
std::vector<iovec> 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<HostIoDeviceInstance *>(instance);
static orbis::ErrorCode host_write(orbis::File *file, orbis::Uio *uio,
orbis::Thread *) {
auto hostFile = static_cast<HostFile *>(file);
std::vector<iovec> 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<HostIoDeviceInstance *>(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<HostFile *>(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<uint64_t>(hostStat.st_atim.tv_sec),
.nsec = static_cast<uint64_t>(hostStat.st_atim.tv_nsec),
};
sb->mtim = {
.sec = static_cast<uint64_t>(hostStat.st_mtim.tv_sec),
.nsec = static_cast<uint64_t>(hostStat.st_mtim.tv_nsec),
};
sb->ctim = {
.sec = static_cast<uint64_t>(hostStat.st_mtim.tv_sec),
.nsec = static_cast<uint64_t>(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<uint64_t>(hostStat.st_mtim.tv_sec),
.nsec = static_cast<uint64_t>(hostStat.st_mtim.tv_nsec),
};
return {};
}
static std::int32_t host_io_open(IoDevice *device,
orbis::Ref<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto hostDevice = static_cast<HostIoDevice *>(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<HostFile *>(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<SocketFile *>(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<HostFsDevice>(std::move(hostPath));
}
orbis::ErrorCode createSocket(orbis::Ref<orbis::File> *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<SocketFile>();
s->name = std::move(name);
s->hostFd = fd;
s->ops = &socketOps;
*file = s;
return {};
}
orbis::ErrorCode HostFsDevice::open(orbis::Ref<orbis::File> *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<HostIoDeviceInstance>();
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<HostIoDevice>();
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<SocketDeviceInstance *>(instance)->hostFd);
return 0;
}
orbis::ErrorCode createSocket(const char *name, int dom, int type, int prot,
orbis::Ref<IoDeviceInstance> *instance) {
auto s = orbis::knew<SocketDeviceInstance>();
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<HostFile>();
newFile->hostFd = hostFd;
newFile->ops = &hostOps;
newFile->device = this;
*file = newFile;
return {};
}
orbis::File *createHostFile(int hostFd, orbis::Ref<IoDevice> device) {
auto newFile = orbis::knew<HostFile>();
newFile->hostFd = hostFd;
newFile->ops = &hostOps;
newFile->device = device;
return newFile;
}
struct FdWrapDevice : public IoDevice {
int fd;
orbis::ErrorCode open(orbis::Ref<orbis::File> *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<FdWrapDevice>();
result->fd = fd;
return result;
}

View file

@ -1,13 +1,10 @@
#pragma once
#include "orbis/KernelAllocator.hpp"
#include "orbis/file.hpp"
#include "orbis/utils/Rc.hpp"
#include <cstdint>
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<IoDevice> 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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) = nullptr;
virtual orbis::ErrorCode open(orbis::Ref<orbis::File> *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<IoDeviceInstance> *instance);
IoDevice *createHostIoDevice(orbis::kstring hostPath);
orbis::ErrorCode createSocket(orbis::Ref<orbis::File> *file,
orbis::kstring name, int dom, int type, int prot);
orbis::File *createHostFile(int hostFd, orbis::Ref<IoDevice> device);
IoDevice *createFdWrapDevice(int fd);

View file

@ -12,9 +12,6 @@ IoDevice *createHmdCmdCharacterDevice();
IoDevice *createHmdMmapCharacterDevice();
IoDevice *createHmdSnsrCharacterDevice();
IoDevice *createNullCharacterDevice();
IoDevice *createStderrCharacterDevice();
IoDevice *createStdinCharacterDevice();
IoDevice *createStdoutCharacterDevice();
IoDevice *createZeroCharacterDevice();
IoDevice *createRngCharacterDevice();
IoDevice *createAjmCharacterDevice();

View file

@ -1,33 +1,31 @@
#include "io-device.hpp"
#include "orbis/KernelAllocator.hpp"
#include "orbis/file.hpp"
#include "orbis/utils/Logs.hpp"
#include <cstdio>
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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<AjmInstance>();
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<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override {
auto newFile = orbis::knew<AjmFile>();
newFile->ops = &fileOps;
newFile->device = this;
IoDevice *createAjmCharacterDevice() {
auto *newDevice = orbis::knew<AjmDevice>();
newDevice->open = ajm_device_open;
return newDevice;
}
*file = newFile;
return {};
}
};
IoDevice *createAjmCharacterDevice() { return orbis::knew<AjmDevice>(); }

View file

@ -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 <cinttypes>
#include <cstddef>
#include <cstdio>
#include <cstring>
#include <mutex>
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<DceInstance *>(instance);
struct DceFile : public orbis::File {};
struct DceDevice : IoDevice {
orbis::shared_mutex mtx;
VideoOutBuffer bufferAttributes{}; // TODO
orbis::ErrorCode open(orbis::Ref<orbis::File> *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<DceDevice *>(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<std::uint64_t *>(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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<DceInstance>();
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<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto newFile = orbis::knew<DceFile>();
newFile->device = this;
newFile->ops = &ops;
*file = newFile;
return {};
}
IoDevice *createDceCharacterDevice() {
auto *newDevice = orbis::knew<DceDevice>();
newDevice->open = dce_device_open;
return newDevice;
}
IoDevice *createDceCharacterDevice() { return orbis::knew<DceDevice>(); }

View file

@ -1,19 +1,17 @@
#include "io-device.hpp"
#include "orbis/KernelAllocator.hpp"
#include "orbis/file.hpp"
#include "orbis/utils/Logs.hpp"
#include <cstdio>
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<std::uint32_t *>(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<std::uint32_t *>(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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<DipswInstance>();
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<DipswDevice>();
newDevice->open = dipsw_device_open;
return newDevice;
}
struct DipswDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) override {
auto newFile = orbis::knew<DipswFile>();
newFile->device = this;
newFile->ops = &ops;
*file = newFile;
return {};
}
};
IoDevice *createDipswCharacterDevice() { return orbis::knew<DipswDevice>(); }

View file

@ -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 <cinttypes>
#include <cstdio>
#include <mutex>
struct DmemDevice : public IoDevice {
orbis::shared_mutex mtx;
int index;
std::uint64_t nextOffset;
std::uint64_t memBeginAddress;
orbis::ErrorCode open(orbis::Ref<orbis::File> *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<DmemDevice *>(file->device.get());
auto device = static_cast<DmemDevice *>(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<AllocateDirectMemoryArgs *>(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<DmemDevice *>(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<DmemDevice *>(file->device.get());
auto target = device->memBeginAddress + offset;
ORBIS_LOG_WARNING("dmem mmap", device->index, offset, target);
auto addr = rx::vm::map(reinterpret_cast<void *>(target), size, prot, flags);
return addr;
auto result =
rx::vm::map(reinterpret_cast<void *>(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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<DmemInstance>();
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<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto newFile = orbis::knew<DmemFile>();
newFile->device = this;
newFile->ops = &ops;
*file = newFile;
return {};
}
IoDevice *createDmemCharacterDevice(int index) {
auto *newDevice = orbis::knew<DmemDevice>();
newDevice->open = dmem_device_open;
newDevice->index = index;
newDevice->nextOffset = 0;
newDevice->memBeginAddress = 0xf'e000'0000 + dmemSize * index;

View file

@ -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 <atomic>
#include <cinttypes>
#include <cstdio>
#include <cstring>
// #include <rpcs4/bridge.hpp>
#include "vm.hpp"
#include <string>
#include <cstdio>
#include <sys/mman.h>
#include <thread>
#include <type_traits>
#include <utility>
struct GcDevice : public IoDevice {};
struct GcInstance : public IoDeviceInstance {};
struct GcDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *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<void **>(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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<GcInstance>();
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<orbis::File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode) {
auto newFile = orbis::knew<GcFile>();
newFile->device = this;
newFile->ops = &ops;
*file = newFile;
return {};
}
IoDevice *createGcCharacterDevice() {
auto *newDevice = orbis::knew<GcDevice>();
newDevice->open = gc_device_open;
return newDevice;
}
IoDevice *createGcCharacterDevice() { return orbis::knew<GcDevice>(); }

View file

@ -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 <cinttypes>
#include <cstdio>
struct HidDevice : public IoDevice {};
struct HidInstance : public IoDeviceInstance {};
struct HidDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *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<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto newFile = orbis::knew<HidFile>();
newFile->device = this;
newFile->ops = &ops;
*file = newFile;
return {};
}
static std::int32_t hid_device_open(IoDevice *device,
orbis::Ref<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<HidInstance>();
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<HidDevice>();
newDevice->open = hid_device_open;
return newDevice;
}
IoDevice *createHidCharacterDevice() { return orbis::knew<HidDevice>(); }

View file

@ -1,33 +1,34 @@
#include "io-device.hpp"
#include "orbis/KernelAllocator.hpp"
#include "orbis/file.hpp"
#include "orbis/utils/Logs.hpp"
#include <cstdio>
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<orbis::File> *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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<Hmd3daInstance>();
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<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto newFile = orbis::knew<Hmd3daFile>();
newFile->device = this;
newFile->ops = &ops;
*file = newFile;
return {};
}
IoDevice *createHmd3daCharacterDevice() {
auto *newDevice = orbis::knew<Hmd3daDevice>();
newDevice->open = hmd_3da_device_open;
return newDevice;
}
IoDevice *createHmd3daCharacterDevice() { return orbis::knew<Hmd3daDevice>(); }

View file

@ -1,34 +1,33 @@
#include "io-device.hpp"
#include "orbis/KernelAllocator.hpp"
#include "orbis/utils/Logs.hpp"
#include <cstdio>
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<orbis::File> *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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<HmdCmdInstance>();
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<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto newFile = orbis::knew<HmdCmdFile>();
newFile->device = this;
newFile->ops = &ops;
*file = newFile;
return {};
}
IoDevice *createHmdCmdCharacterDevice() {
auto *newDevice = orbis::knew<HmdCmdDevice>();
newDevice->open = hmd_cmd_device_open;
return newDevice;
}
IoDevice *createHmdCmdCharacterDevice() { return orbis::knew<HmdCmdDevice>(); }

View file

@ -2,44 +2,51 @@
#include "orbis/KernelAllocator.hpp"
#include "orbis/utils/Logs.hpp"
#include "vm.hpp"
#include <cinttypes>
#include <cstdio>
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<orbis::File> *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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<HmdMmapInstance>();
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<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto newFile = orbis::knew<HmdMmapFile>();
newFile->device = this;
newFile->ops = &ops;
*file = newFile;
return {};
}
IoDevice *createHmdMmapCharacterDevice() {
auto *newDevice = orbis::knew<HmdMmapDevice>();
newDevice->open = hmd_mmap_device_open;
return newDevice;
return orbis::knew<HmdMmapDevice>();
}

View file

@ -1,31 +1,36 @@
#include "io-device.hpp"
#include "orbis/KernelAllocator.hpp"
#include "orbis/file.hpp"
#include "orbis/utils/Logs.hpp"
#include <cstdio>
struct HmdSnsrDevice : public IoDevice {};
struct HmdSnsrDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<HmdSnsrInstance>();
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<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto newFile = orbis::knew<HmdSnsrFile>();
newFile->device = this;
newFile->ops = &ops;
*file = newFile;
return {};
}
IoDevice *createHmdSnsrCharacterDevice() {
auto *newDevice = orbis::knew<HmdSnsrDevice>();
newDevice->open = smd_snr_device_open;
return newDevice;
return orbis::knew<HmdSnsrDevice>();
}

View file

@ -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<orbis::File> *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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<NullInstance>();
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<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto newFile = orbis::knew<NullFile>();
newFile->device = this;
newFile->ops = &ops;
*file = newFile;
return {};
}
IoDevice *createNullCharacterDevice() {
auto *newDevice = orbis::knew<NullDevice>();
newDevice->open = null_device_open;
return newDevice;
}
IoDevice *createNullCharacterDevice() { return orbis::knew<NullDevice>(); }

View file

@ -2,40 +2,49 @@
#include "orbis/KernelAllocator.hpp"
#include "orbis/utils/Logs.hpp"
#include "vm.hpp"
#include <cinttypes>
#include <cstdio>
struct RngDevice : public IoDevice {};
struct RngInstance : public IoDeviceInstance {};
struct RngDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<RngInstance>();
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<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto newFile = orbis::knew<RngFile>();
newFile->device = this;
newFile->ops = &ops;
*file = newFile;
return {};
}
IoDevice *createRngCharacterDevice() {
auto *newDevice = orbis::knew<RngDevice>();
newDevice->open = rng_device_open;
return newDevice;
}
IoDevice *createRngCharacterDevice() { return orbis::knew<RngDevice>(); }

View file

@ -1,56 +0,0 @@
#include "io-device.hpp"
#include "orbis/KernelAllocator.hpp"
#include <fstream>
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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto stderrDevice = static_cast<StderrDevice *>(device);
if (stderrDevice->instance == nullptr) {
auto *newInstance = orbis::knew<StderrInstance>();
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<StderrDevice>();
newDevice->open = stderr_device_open;
return newDevice;
}

View file

@ -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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<StdinInstance>();
newInstance->read = stdin_instance_read;
io_device_instance_init(device, newInstance);
*instance = newInstance;
return 0;
}
IoDevice *createStdinCharacterDevice() {
auto *newDevice = orbis::knew<StdinDevice>();
newDevice->open = open;
return newDevice;
}

View file

@ -1,54 +0,0 @@
#include "io-device.hpp"
#include "orbis/KernelAllocator.hpp"
#include <cstdio>
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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto stdoutDevice = static_cast<StdoutDevice *>(device);
if (stdoutDevice->instance == nullptr) {
auto *newInstance = orbis::knew<StdoutInstance>();
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<StdoutDevice>();
newDevice->open = stdout_device_open;
return newDevice;
}

View file

@ -1,31 +1,37 @@
#include "io-device.hpp"
#include "orbis/KernelAllocator.hpp"
#include "orbis/uio.hpp"
#include <cstring>
#include <span>
struct ZeroDevice : public IoDevice {};
struct ZeroDevice : public IoDevice {
orbis::ErrorCode open(orbis::Ref<orbis::File> *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<IoDeviceInstance> *instance,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto *newInstance = orbis::knew<ZeroInstance>();
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<orbis::File> *file,
const char *path, std::uint32_t flags,
std::uint32_t mode) {
auto newFile = orbis::knew<ZeroFile>();
newFile->device = this;
newFile->ops = &ops;
*file = newFile;
return {};
}
IoDevice *createZeroCharacterDevice() {
auto *newDevice = orbis::knew<ZeroDevice>();
newDevice->open = zero_device_open;
return newDevice;
}
IoDevice *createZeroCharacterDevice() { return orbis::knew<ZeroDevice>(); }

View file

@ -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 <crypto/sha1.h>
@ -838,38 +840,56 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
}
Ref<orbis::Module> 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<IoDeviceInstance> instance;
orbis::Ref<orbis::File> 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<std::byte> image(len);
auto ptr = image.data();
auto endPtr = ptr + image.size();
orbis::IoVec ioVec{
.base = ptr,
.len = static_cast<std::uint64_t>(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<orbis::Module> createSceFreeTypeFull(orbis::Process *process) {
static Ref<orbis::Module> createSceFreeTypeFull(orbis::Thread *thread) {
auto result = orbis::knew<orbis::Module>();
std::strncpy(result->soName, "libSceFreeTypeFull.prx",
@ -888,7 +908,7 @@ static Ref<orbis::Module> 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<orbis::Module> createSceFreeTypeFull(orbis::Process *process) {
result->initProc = reinterpret_cast<void *>(+[] {});
result->finiProc = reinterpret_cast<void *>(+[] {});
result->proc = process;
result->proc = thread->tproc;
return result;
}
Ref<orbis::Module> 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<orbis::Module> 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<orbis::Module> 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;
}
}

View file

@ -78,7 +78,7 @@ void override(std::string originalModuleName,
orbis::Ref<orbis::Module> loadModule(std::span<std::byte> image,
orbis::Process *process);
orbis::Ref<orbis::Module> loadModuleFile(std::string_view path,
orbis::Process *process);
orbis::Thread *thread);
orbis::Ref<orbis::Module> loadModuleByName(std::string_view name,
orbis::Process *process);
orbis::Thread *thread);
} // namespace rx::linker

View file

@ -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<orbis::Module> executableModule,
std::span<const char *> argv, std::span<const char *> 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<orbis::File> stdinFile;
orbis::Ref<orbis::File> stdoutFile;
orbis::Ref<orbis::File> 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<std::uint64_t> argvOffsets;
std::vector<std::uint64_t> 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<std::uint32_t *>(
// reinterpret_cast<std::byte *>(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<const char *>());
} else {

View file

@ -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<IoDeviceInstance> handle =
static_cast<IoDeviceInstance *>(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<std::uint64_t>(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<std::uint64_t>(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<std::uint64_t>(maddr);
return {};
}
@ -225,281 +230,15 @@ orbis::SysResult virtual_query(orbis::Thread *thread,
}
orbis::SysResult open(orbis::Thread *thread, orbis::ptr<const char> path,
orbis::sint flags, orbis::sint mode) {
orbis::Ref<IoDeviceInstance> 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<orbis::File> *file) {
return rx::vfs::open(path, flags, mode, file);
}
orbis::SysResult socket(orbis::Thread *thread, orbis::ptr<const char> name,
orbis::sint domain, orbis::sint type,
orbis::sint protocol) {
orbis::Ref<IoDeviceInstance> 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<IoDeviceInstance> handle =
static_cast<IoDeviceInstance *>(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<const void> data, orbis::ulong size) {
Ref<IoDeviceInstance> handle =
static_cast<IoDeviceInstance *>(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<void> data, orbis::ulong size) {
Ref<IoDeviceInstance> handle =
static_cast<IoDeviceInstance *>(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<void> data, orbis::ulong size,
orbis::ulong offset) {
Ref<IoDeviceInstance> handle =
static_cast<IoDeviceInstance *>(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<const void> 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<IoDeviceInstance> handle =
static_cast<IoDeviceInstance *>(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<const char> path,
orbis::off_t length) {
return ErrorCode::NOTSUP;
orbis::sint protocol, Ref<File> *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,

152
rpcsx-os/scheduler.hpp Normal file
View file

@ -0,0 +1,152 @@
#pragma once
#include <condition_variable>
#include <forward_list>
#include <functional>
#include <map>
#include <mutex>
#include <orbis/thread/Thread.hpp>
#include <sys/ucontext.h>
#include <thread>
#include <ucontext.h>
#include <utility>
#include <vector>
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<bool()> wakeupCondFn;
};
std::mutex taskMtx;
std::condition_variable taskCond;
std::mutex queueMtx;
std::multimap<int, Task, std::greater<>> mQueue;
std::forward_list<CpuState> mCpuStates;
std::vector<std::thread> mCpus;
std::thread mThread;
std::atomic<bool> 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<bool()> wakeupCondFn = nullptr) {
auto cpuContext = static_cast<CpuState *>(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<ucontext_t *>(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

View file

@ -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<IoDeviceInstance> *instance) {
orbis::Ref<orbis::File> *file) {
orbis::Ref<IoDevice> 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) {

View file

@ -1,16 +1,16 @@
#pragma once
#include "orbis/error/SysResult.hpp"
#include "orbis/file.hpp"
#include "orbis/utils/Rc.hpp"
#include <filesystem>
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<IoDeviceInstance> *instance);
orbis::Ref<orbis::File> *file);
} // namespace rx::vfs