mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-05 00:00:42 +01:00
[rpcsx-os/orbis-kernel] random bugfixes
ipmi: fixed respond sync, get message, try get message, try send message event: detach event emitter from file signals: basic implementation linker: fixed zero symbol relocation, fixed exec relocation shared_cv/mutex: implement eintr response support shared_cv: fixed possible loop instead of wait ipmi: implement invoke async, respond async, get result, get client app id, client get name rpcsx-os: add safemode flag
This commit is contained in:
parent
8791312d4f
commit
65e653f5ef
|
|
@ -166,23 +166,23 @@ struct BridgePusher {
|
|||
}
|
||||
|
||||
void sendMapDmem(std::uint32_t pid, std::uint32_t dmemIndex, std::uint64_t address, std::uint64_t size, std::uint32_t prot, std::uint64_t offset) {
|
||||
if (pid == expGpuPid) {
|
||||
// if (pid == expGpuPid) {
|
||||
sendCommand(CommandId::MapDmem, {pid, dmemIndex, address, size, prot, offset});
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
void sendCommandBuffer(std::uint32_t pid, std::uint64_t queue,
|
||||
std::uint64_t address, std::uint64_t size) {
|
||||
if (pid == expGpuPid) {
|
||||
// if (pid == expGpuPid) {
|
||||
sendCommand(CommandId::CommandBuffer, {pid, queue, address, size});
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
void sendFlip(std::uint32_t pid, std::uint32_t bufferIndex,
|
||||
std::uint64_t arg) {
|
||||
if (pid == expGpuPid) {
|
||||
// if (pid == expGpuPid) {
|
||||
sendCommand(CommandId::Flip, {pid, bufferIndex, arg});
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
void wait() {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
#pragma once
|
||||
#include "AudioOut.hpp"
|
||||
#include "KernelAllocator.hpp"
|
||||
#include "evf.hpp"
|
||||
#include "ipmi.hpp"
|
||||
#include "orbis/utils/IdMap.hpp"
|
||||
#include "osem.hpp"
|
||||
#include "thread/types.hpp"
|
||||
#include "utils/IdMap.hpp"
|
||||
#include "utils/LinkedNode.hpp"
|
||||
#include "utils/SharedCV.hpp"
|
||||
#include "utils/SharedMutex.hpp"
|
||||
|
||||
#include "AudioOut.hpp"
|
||||
#include "KernelAllocator.hpp"
|
||||
#include "orbis/thread/types.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <pthread.h>
|
||||
|
|
@ -175,6 +174,10 @@ public:
|
|||
AudioOut *audioOut = nullptr;
|
||||
uint sdkVersion{};
|
||||
uint fwSdkVersion{};
|
||||
uint safeMode{};
|
||||
|
||||
shared_mutex regMgrMtx;
|
||||
kmap<std::uint32_t, std::uint32_t> regMgrInt;
|
||||
|
||||
private:
|
||||
mutable pthread_mutex_t m_heap_mtx;
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ struct FileOps {
|
|||
Thread *thread) = nullptr;
|
||||
ErrorCode (*sendmsg)(orbis::File *file, msghdr *msg, sint flags,
|
||||
Thread *thread) = nullptr;
|
||||
ErrorCode (*recvfrom)(orbis::File *file, void *buf, size_t len,
|
||||
sint flags, SocketAddress *from, uint32_t *fromlenaddr,
|
||||
ErrorCode (*recvfrom)(orbis::File *file, void *buf, size_t len, sint flags,
|
||||
SocketAddress *from, uint32_t *fromlenaddr,
|
||||
Thread *thread) = nullptr;
|
||||
ErrorCode (*recvmsg)(orbis::File *file, msghdr *msg, sint flags,
|
||||
Thread *thread) = nullptr;
|
||||
|
|
@ -75,11 +75,15 @@ struct FileOps {
|
|||
|
||||
struct File : RcBase {
|
||||
shared_mutex mtx;
|
||||
EventEmitter event;
|
||||
Ref<EventEmitter> event;
|
||||
const FileOps *ops = nullptr;
|
||||
Ref<RcBase> device;
|
||||
std::uint64_t nextOff = 0;
|
||||
int flags = 0;
|
||||
int mode = 0;
|
||||
int hostFd = -1;
|
||||
utils::kvector<Dirent> dirEntries;
|
||||
|
||||
bool noBlock() const { return (flags & 4) != 0; }
|
||||
};
|
||||
} // namespace orbis
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ struct Thread;
|
|||
|
||||
struct IpmiServer : RcBase {
|
||||
struct IpmiPacketInfo {
|
||||
ptr<void> userData;
|
||||
ulong inputSize;
|
||||
uint type;
|
||||
uint clientKid;
|
||||
ptr<void> eventHandler;
|
||||
|
|
@ -26,6 +26,8 @@ struct IpmiServer : RcBase {
|
|||
|
||||
struct Packet {
|
||||
IpmiPacketInfo info;
|
||||
lwpid_t clientTid;
|
||||
Ref<IpmiSession> session;
|
||||
kvector<std::byte> message;
|
||||
};
|
||||
|
||||
|
|
@ -36,6 +38,7 @@ struct IpmiServer : RcBase {
|
|||
slong serverTid{};
|
||||
};
|
||||
|
||||
kmap<std::uint32_t, std::uint32_t> tidToClientTid;
|
||||
kstring name;
|
||||
ptr<void> serverImpl;
|
||||
ptr<void> eventHandler;
|
||||
|
|
@ -51,24 +54,36 @@ struct IpmiServer : RcBase {
|
|||
};
|
||||
|
||||
struct IpmiClient : RcBase {
|
||||
struct MessageQueue {
|
||||
shared_cv messageCv;
|
||||
kdeque<kvector<std::byte>> messages;
|
||||
};
|
||||
|
||||
struct AsyncResponse {
|
||||
uint methodId;
|
||||
sint errorCode;
|
||||
kvector<kvector<std::byte>> data;
|
||||
};
|
||||
|
||||
kstring name;
|
||||
ptr<void> clientImpl;
|
||||
ptr<void> userData;
|
||||
Ref<IpmiSession> session;
|
||||
shared_mutex mutex;
|
||||
shared_cv sessionCv;
|
||||
sint pid;
|
||||
kdeque<kvector<std::byte>> messages;
|
||||
Process *process;
|
||||
kdeque<MessageQueue> messageQueues;
|
||||
kdeque<EventFlag> eventFlags;
|
||||
shared_cv messageCv;
|
||||
kdeque<AsyncResponse> asyncResponses;
|
||||
|
||||
explicit IpmiClient(kstring name) : name(std::move(name)) {}
|
||||
};
|
||||
|
||||
struct IpmiSession : RcBase {
|
||||
struct MessageResponse {
|
||||
struct SyncResponse {
|
||||
sint errorCode;
|
||||
kvector<std::byte> data;
|
||||
std::uint32_t callerTid;
|
||||
kvector<kvector<std::byte>> data;
|
||||
};
|
||||
|
||||
ptr<void> sessionImpl;
|
||||
|
|
@ -77,9 +92,9 @@ struct IpmiSession : RcBase {
|
|||
Ref<IpmiServer> server;
|
||||
shared_mutex mutex;
|
||||
shared_cv responseCv;
|
||||
kdeque<MessageResponse> messageResponses;
|
||||
kdeque<SyncResponse> syncResponses;
|
||||
shared_cv connectCv;
|
||||
bool expectedOutput = false; // TODO: verify
|
||||
uint expectedOutput{0};
|
||||
sint connectionStatus{0};
|
||||
};
|
||||
|
||||
|
|
@ -108,20 +123,19 @@ static_assert(sizeof(IpmiCreateClientConfig) == 0x150);
|
|||
|
||||
struct IpmiBufferInfo {
|
||||
ptr<void> data;
|
||||
uint64_t capacity;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
|
||||
struct IpmiDataInfo {
|
||||
ptr<void> data;
|
||||
uint64_t size;
|
||||
uint64_t capacity; //?
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiBufferInfo) == 0x10);
|
||||
static_assert(sizeof(IpmiDataInfo) == 0x18);
|
||||
// static_assert(sizeof(IpmiBufferInfo) == 0x18);
|
||||
// static_assert(sizeof(IpmiDataInfo) == 0x10);
|
||||
|
||||
struct IpmiSyncMessageHeader {
|
||||
struct [[gnu::packed]] IpmiSyncMessageHeader {
|
||||
orbis::ptr<void> sessionImpl;
|
||||
orbis::uint pid;
|
||||
orbis::uint methodId;
|
||||
|
|
@ -129,10 +143,18 @@ struct IpmiSyncMessageHeader {
|
|||
orbis::uint numOutData;
|
||||
};
|
||||
|
||||
struct [[gnu::packed]] IpmiAsyncMessageHeader {
|
||||
orbis::ptr<void> sessionImpl;
|
||||
orbis::uint methodId;
|
||||
orbis::uint pid;
|
||||
orbis::uint numInData;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiSyncMessageHeader) == 0x18);
|
||||
|
||||
ErrorCode ipmiCreateClient(Process *proc, void *clientImpl, const char *name,
|
||||
const IpmiCreateClientConfig &config, Ref<IpmiClient> &result);
|
||||
const IpmiCreateClientConfig &config,
|
||||
Ref<IpmiClient> &result);
|
||||
ErrorCode ipmiCreateServer(Process *proc, void *serverImpl, const char *name,
|
||||
const IpmiCreateServerConfig &config,
|
||||
Ref<IpmiServer> &result);
|
||||
|
|
@ -162,9 +184,10 @@ SysResult sysIpmiSessionRespondSync(Thread *thread, ptr<uint> result, uint kid,
|
|||
SysResult sysIpmiClientInvokeAsyncMethod(Thread *thread, ptr<uint> result,
|
||||
uint kid, ptr<void> params,
|
||||
uint64_t paramsSz);
|
||||
SysResult sysIpmiClientTryGetResult(Thread *thread, ptr<uint> result,
|
||||
uint kid, ptr<void> params,
|
||||
uint64_t paramsSz);
|
||||
SysResult sysImpiSessionRespondAsync(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiClientTryGetResult(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiClientGetMessage(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiClientTryGetMessage(Thread *thread, ptr<uint> result, uint kid,
|
||||
|
|
@ -181,10 +204,15 @@ SysResult sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result,
|
|||
uint64_t paramsSz);
|
||||
SysResult sysIpmiClientConnect(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiSessionGetClientAppId(Thread *thread, ptr<uint> result,
|
||||
uint kid, ptr<void> params,
|
||||
uint64_t paramsSz);
|
||||
SysResult sysIpmiSessionGetUserData(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiServerGetName(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiClientGetName(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiClientWaitEventFlag(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiClientPollEventFlag(Thread *thread, ptr<uint> result, uint kid,
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ struct KNote {
|
|||
~KNote();
|
||||
};
|
||||
|
||||
struct EventEmitter {
|
||||
struct EventEmitter : orbis::RcBase {
|
||||
shared_mutex mutex;
|
||||
std::set<KNote *, std::less<>, kallocator<KNote *>> notes;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#include "orbis-config.hpp"
|
||||
#include <orbis/error.hpp>
|
||||
#include <orbis/thread.hpp>
|
||||
#include <orbis/time.hpp>
|
||||
#include <orbis/module/ModuleHandle.hpp>
|
||||
#include <orbis/thread/cpuset.hpp>
|
||||
#include <orbis/thread/types.hpp>
|
||||
|
||||
namespace orbis {
|
||||
using acl_type_t = sint;
|
||||
|
|
@ -11,17 +13,24 @@ using cpuwhich_t = sint;
|
|||
using cpulevel_t = sint;
|
||||
using SceKernelModule = ModuleHandle;
|
||||
|
||||
struct Thread;
|
||||
struct AuthInfo;
|
||||
struct MemoryProtection;
|
||||
struct ModuleInfo;
|
||||
struct ModuleInfoEx;
|
||||
struct KEvent;
|
||||
struct timespec;
|
||||
struct timesec;
|
||||
struct timezone;
|
||||
struct timeval;
|
||||
struct Stat;
|
||||
struct stack_t;
|
||||
struct IoVec;
|
||||
struct BatchMapEntry;
|
||||
struct UContext;
|
||||
struct SigSet;
|
||||
struct SigAction;
|
||||
struct SocketAddress;
|
||||
|
||||
SysResult nosys(Thread *thread);
|
||||
|
||||
|
|
@ -29,7 +38,7 @@ SysResult sys_exit(Thread *thread, sint status);
|
|||
SysResult sys_fork(Thread *thread);
|
||||
SysResult sys_read(Thread *thread, sint fd, ptr<void> buf, size_t nbyte);
|
||||
SysResult sys_write(Thread *thread, sint fd, ptr<const void> buf, size_t nbyte);
|
||||
SysResult sys_open(Thread *thread, ptr<char> path, sint flags, sint mode);
|
||||
SysResult sys_open(Thread *thread, ptr<const char> path, sint flags, sint mode);
|
||||
SysResult sys_close(Thread *thread, sint fd);
|
||||
SysResult sys_wait4(Thread *thread, sint pid, ptr<sint> status, sint options,
|
||||
ptr<struct rusage> rusage);
|
||||
|
|
@ -125,15 +134,14 @@ SysResult sys_bind(Thread *thread, sint s, caddr_t name, sint namelen);
|
|||
SysResult sys_setsockopt(Thread *thread, sint s, sint level, sint name,
|
||||
caddr_t val, sint valsize);
|
||||
SysResult sys_listen(Thread *thread, sint s, sint backlog);
|
||||
SysResult sys_gettimeofday(Thread *thread, ptr<orbis::timeval> tp,
|
||||
ptr<orbis::timezone> tzp);
|
||||
SysResult sys_gettimeofday(Thread *thread, ptr<timeval> tp, ptr<timezone> tzp);
|
||||
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<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);
|
||||
ptr<timezone> tzp);
|
||||
SysResult sys_fchown(Thread *thread, sint fd, sint uid, sint gid);
|
||||
SysResult sys_fchmod(Thread *thread, sint fd, sint mode);
|
||||
SysResult sys_setreuid(Thread *thread, sint ruid, sint euid);
|
||||
|
|
@ -230,8 +238,8 @@ SysResult sys_ktimer_settime(Thread *thread, sint timerid, sint flags,
|
|||
SysResult sys_ktimer_gettime(Thread *thread, sint timerid,
|
||||
ptr<struct itimerspec> value);
|
||||
SysResult sys_ktimer_getoverrun(Thread *thread, sint timerid);
|
||||
SysResult sys_nanosleep(Thread *thread, cptr<orbis::timespec> rqtp,
|
||||
ptr<orbis::timespec> rmtp);
|
||||
SysResult sys_nanosleep(Thread *thread, cptr<timespec> rqtp,
|
||||
ptr<timespec> rmtp);
|
||||
SysResult sys_ntp_gettime(Thread *thread, ptr<struct ntptimeval> ntvp);
|
||||
SysResult sys_minherit(Thread *thread, ptr<void> addr, size_t len,
|
||||
sint inherit);
|
||||
|
|
@ -305,14 +313,14 @@ SysResult sys_jail(Thread *thread, ptr<struct jail> jail);
|
|||
SysResult sys_nnpfs_syscall(Thread *thread, sint operation, ptr<char> a_pathP,
|
||||
sint opcode, ptr<void> a_paramsP,
|
||||
sint a_followSymlinks);
|
||||
SysResult sys_sigprocmask(Thread *thread, sint how, ptr<uint64_t> set,
|
||||
ptr<uint64_t> oset);
|
||||
SysResult sys_sigsuspend(Thread *thread, ptr<const struct sigset> set);
|
||||
SysResult sys_sigpending(Thread *thread, ptr<struct sigset> set);
|
||||
SysResult sys_sigtimedwait(Thread *thread, ptr<const struct sigset> set,
|
||||
SysResult sys_sigprocmask(Thread *thread, sint how, ptr<SigSet> set,
|
||||
ptr<SigSet> oset);
|
||||
SysResult sys_sigsuspend(Thread *thread, ptr<const SigSet> set);
|
||||
SysResult sys_sigpending(Thread *thread, ptr<SigSet> set);
|
||||
SysResult sys_sigtimedwait(Thread *thread, ptr<const SigSet> set,
|
||||
ptr<struct siginfo> info,
|
||||
ptr<const timespec> timeout);
|
||||
SysResult sys_sigwaitinfo(Thread *thread, ptr<const struct sigset> set,
|
||||
SysResult sys_sigwaitinfo(Thread *thread, ptr<const SigSet> set,
|
||||
ptr<struct siginfo> info);
|
||||
SysResult sys___acl_get_file(Thread *thread, ptr<char> path, acl_type_t type,
|
||||
ptr<struct acl> aclp);
|
||||
|
|
@ -412,13 +420,13 @@ SysResult sys_extattr_delete_link(Thread *thread, ptr<const char> path,
|
|||
sint attrnamespace, ptr<const char> attrname);
|
||||
SysResult sys___mac_execve(Thread *thread, ptr<char> fname, ptr<ptr<char>> argv,
|
||||
ptr<ptr<char>> envv, ptr<struct mac> mac_p);
|
||||
SysResult sys_sigaction(Thread *thread, sint sig, ptr<struct sigaction> act,
|
||||
ptr<struct sigaction> oact);
|
||||
SysResult sys_sigreturn(Thread *thread, ptr<struct ucontext> sigcntxp);
|
||||
SysResult sys_getcontext(Thread *thread, ptr<struct ucontext> ucp);
|
||||
SysResult sys_setcontext(Thread *thread, ptr<struct ucontext> ucp);
|
||||
SysResult sys_swapcontext(Thread *thread, ptr<struct ucontext> oucp,
|
||||
ptr<struct ucontext> ucp);
|
||||
SysResult sys_sigaction(Thread *thread, sint sig, ptr<SigAction> act,
|
||||
ptr<SigAction> oact);
|
||||
SysResult sys_sigreturn(Thread *thread, ptr<UContext> sigcntxp);
|
||||
SysResult sys_getcontext(Thread *thread, ptr<UContext> ucp);
|
||||
SysResult sys_setcontext(Thread *thread, ptr<UContext> ucp);
|
||||
SysResult sys_swapcontext(Thread *thread, ptr<UContext> oucp,
|
||||
ptr<UContext> ucp);
|
||||
SysResult sys_swapoff(Thread *thread, ptr<const char> name);
|
||||
SysResult sys___acl_get_link(Thread *thread, ptr<const char> path,
|
||||
acl_type_t type, ptr<struct acl> aclp);
|
||||
|
|
@ -428,10 +436,9 @@ SysResult sys___acl_delete_link(Thread *thread, ptr<const char> path,
|
|||
acl_type_t type);
|
||||
SysResult sys___acl_aclcheck_link(Thread *thread, ptr<const char> path,
|
||||
acl_type_t type, ptr<struct acl> aclp);
|
||||
SysResult sys_sigwait(Thread *thread, ptr<const struct sigset> set,
|
||||
ptr<sint> sig);
|
||||
SysResult sys_thr_create(Thread *thread, ptr<struct ucontext> ctxt,
|
||||
ptr<slong> arg, sint flags);
|
||||
SysResult sys_sigwait(Thread *thread, ptr<const SigSet> set, ptr<sint> sig);
|
||||
SysResult sys_thr_create(Thread *thread, ptr<UContext> ctxt, ptr<slong> arg,
|
||||
sint flags);
|
||||
SysResult sys_thr_exit(Thread *thread, ptr<slong> state);
|
||||
SysResult sys_thr_self(Thread *thread, ptr<slong> id);
|
||||
SysResult sys_thr_kill(Thread *thread, slong id, sint sig);
|
||||
|
|
@ -636,8 +643,9 @@ SysResult sys_evf_cancel(Thread *thread, sint id, uint64_t value,
|
|||
ptr<sint> pNumWaitThreads);
|
||||
SysResult sys_query_memory_protection(Thread *thread, ptr<void> address,
|
||||
ptr<MemoryProtection> protection);
|
||||
SysResult sys_batch_map(Thread *thread, sint unk, sint flags, ptr<BatchMapEntry> entries,
|
||||
sint entriesCount, ptr<sint> processedCount);
|
||||
SysResult sys_batch_map(Thread *thread, sint unk, sint flags,
|
||||
ptr<BatchMapEntry> entries, sint entriesCount,
|
||||
ptr<sint> processedCount);
|
||||
SysResult sys_osem_create(Thread *thread, ptr<const char[32]> name, uint attrs,
|
||||
sint initCount, sint maxCount);
|
||||
SysResult sys_osem_delete(Thread *thread, sint id);
|
||||
|
|
@ -746,15 +754,16 @@ SysResult sys_physhm_unlink(Thread *thread /* TODO */);
|
|||
SysResult sys_resume_internal_hdd(Thread *thread /* TODO */);
|
||||
SysResult sys_thr_suspend_ucontext(Thread *thread, lwpid_t tid);
|
||||
SysResult sys_thr_resume_ucontext(Thread *thread, lwpid_t tid);
|
||||
SysResult sys_thr_get_ucontext(Thread *thread, lwpid_t tid, ptr<UContext> context);
|
||||
SysResult sys_thr_set_ucontext(Thread *thread, lwpid_t tid, ptr<UContext> context);
|
||||
SysResult sys_thr_get_ucontext(Thread *thread, lwpid_t tid,
|
||||
ptr<UContext> context);
|
||||
SysResult sys_thr_set_ucontext(Thread *thread, lwpid_t tid,
|
||||
ptr<UContext> context);
|
||||
SysResult sys_set_timezone_info(Thread *thread /* TODO */);
|
||||
SysResult sys_set_phys_fmem_limit(Thread *thread /* TODO */);
|
||||
SysResult sys_utc_to_localtime(Thread *thread, int64_t time, int64_t *localtime,
|
||||
orbis::timesec *_sec, int *_dst_sec);
|
||||
timesec *_sec, int *_dst_sec);
|
||||
SysResult sys_localtime_to_utc(Thread *thread, int64_t time, uint unk,
|
||||
int64_t *ptime, orbis::timesec *_sec,
|
||||
int *_dst_sec);
|
||||
int64_t *ptime, timesec *_sec, int *_dst_sec);
|
||||
SysResult sys_set_uevt(Thread *thread /* TODO */);
|
||||
SysResult sys_get_cpu_usage_proc(Thread *thread /* TODO */);
|
||||
SysResult sys_get_map_statistics(Thread *thread /* TODO */);
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ struct Process final {
|
|||
bool isInSandbox = false;
|
||||
EventEmitter event;
|
||||
|
||||
std::uint32_t sdkVersion = -1;
|
||||
std::uint64_t nextTlsSlot = 1;
|
||||
std::uint64_t lastTlsOffset = 0;
|
||||
|
||||
|
|
@ -81,6 +82,8 @@ struct Process final {
|
|||
utils::kmap<void *, utils::kstring> namedObjNames;
|
||||
utils::OwningIdMap<NamedObjInfo, uint, 65535, 1> namedObjIds;
|
||||
|
||||
utils::kmap<std::int32_t, SigAction> sigActions;
|
||||
|
||||
// Named memory ranges for debugging
|
||||
utils::shared_mutex namedMemMutex;
|
||||
utils::kmap<NamedMemoryRange, utils::kstring> namedMem;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ struct timespec;
|
|||
struct File;
|
||||
struct MemoryProtection;
|
||||
struct IoVec;
|
||||
struct UContext;
|
||||
|
||||
struct ProcessOps {
|
||||
SysResult (*mmap)(Thread *thread, caddr_t addr, size_t len, sint prot,
|
||||
|
|
@ -64,7 +65,7 @@ struct ProcessOps {
|
|||
uint64_t arg3);
|
||||
SysResult (*dynlib_unload_prx)(Thread *thread, ModuleHandle handle);
|
||||
|
||||
SysResult (*thr_create)(Thread *thread, ptr<struct ucontext> ctxt,
|
||||
SysResult (*thr_create)(Thread *thread, ptr<UContext> ctxt,
|
||||
ptr<slong> arg, sint flags);
|
||||
SysResult (*thr_new)(Thread *thread, ptr<thr_param> param, sint param_size);
|
||||
SysResult (*thr_exit)(Thread *thread, ptr<slong> state);
|
||||
|
|
|
|||
|
|
@ -19,5 +19,6 @@ enum class RegisterId {
|
|||
rax,
|
||||
rsp,
|
||||
rflags,
|
||||
rip,
|
||||
};
|
||||
} // namespace orbis
|
||||
|
|
|
|||
|
|
@ -4,12 +4,16 @@
|
|||
#include "orbis-config.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
#include "../KernelAllocator.hpp"
|
||||
#include "../ucontext.hpp"
|
||||
#include "../utils/SharedCV.hpp"
|
||||
#include "../utils/SharedMutex.hpp"
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
namespace orbis {
|
||||
struct Process;
|
||||
|
||||
struct Thread {
|
||||
utils::shared_mutex mtx;
|
||||
Process *tproc = nullptr;
|
||||
|
|
@ -21,8 +25,14 @@ struct Thread {
|
|||
uint64_t gsBase{};
|
||||
char name[32]{};
|
||||
|
||||
uint64_t sigMask[4] = {0x7fff'ffff, 0};
|
||||
SigSet sigMask = {0x7fff'ffff, ~0u, ~0u, ~0u};
|
||||
utils::shared_mutex suspend_mtx;
|
||||
utils::shared_cv suspend_cv;
|
||||
kdeque<int> signalQueue;
|
||||
kvector<UContext> sigReturns;
|
||||
std::atomic<unsigned> suspended{0};
|
||||
|
||||
std::int64_t hostTid = -1;
|
||||
lwpid_t tid = -1;
|
||||
ThreadState state = ThreadState::INACTIVE;
|
||||
std::thread handle;
|
||||
|
|
@ -35,6 +45,10 @@ struct Thread {
|
|||
// Print backtrace
|
||||
void where();
|
||||
|
||||
void suspend();
|
||||
void resume();
|
||||
void sendSignal(int signo);
|
||||
|
||||
// FIXME: implement thread destruction
|
||||
void incRef() {}
|
||||
void decRef() {}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,20 @@ struct Stack {
|
|||
};
|
||||
|
||||
struct SigSet {
|
||||
ulong bits[2];
|
||||
static constexpr auto min = 1;
|
||||
static constexpr auto max = 128;
|
||||
|
||||
uint bits[4];
|
||||
|
||||
bool test(unsigned signal) const {
|
||||
return (bits[(signal - 1) >> 5] & (1 << ((signal - 1) & 31))) != 0;
|
||||
}
|
||||
void set(unsigned signal) {
|
||||
bits[(signal - 1) >> 5] |= (1 << ((signal - 1) & 31));
|
||||
}
|
||||
void clear(unsigned signal) {
|
||||
bits[(signal - 1) >> 5] &= ~(1 << ((signal - 1) & 31));
|
||||
}
|
||||
};
|
||||
|
||||
struct UContext {
|
||||
|
|
@ -67,4 +80,87 @@ struct UContext {
|
|||
sint spare[4];
|
||||
sint unk1[3];
|
||||
};
|
||||
|
||||
static_assert(sizeof(UContext) == 0x500);
|
||||
|
||||
|
||||
enum Signal {
|
||||
kSigHup = 1,
|
||||
kSigInt = 2,
|
||||
kSigQuit = 3,
|
||||
kSigIll = 4,
|
||||
kSigTrap = 5,
|
||||
kSigAbrt = 6,
|
||||
kSigEmt = 7,
|
||||
kSigFpe = 8,
|
||||
kSigKill = 9,
|
||||
kSigBus = 10,
|
||||
kSigSegv = 11,
|
||||
kSigSys = 12,
|
||||
kSigPipe = 13,
|
||||
kSigAlrm = 14,
|
||||
kSigUrg = 16,
|
||||
kSigStop = 17,
|
||||
kSigTstp = 18,
|
||||
kSigCont = 19,
|
||||
kSigChld = 20,
|
||||
kSigTtin = 21,
|
||||
kSigTtou = 22,
|
||||
kSigIo = 23,
|
||||
kSigXcpu = 24,
|
||||
kSigXfsz = 25,
|
||||
kSigVtalrm = 26,
|
||||
kSigProf = 27,
|
||||
kSigWinch = 28,
|
||||
kSigInfo = 29,
|
||||
kSigUsr1 = 30,
|
||||
kSigUsr2 = 31,
|
||||
kSigThr = 32,
|
||||
};
|
||||
|
||||
struct SigAction {
|
||||
ptr<void(int32_t, void *, void *)> handler;
|
||||
sint flags;
|
||||
SigSet mask;
|
||||
};
|
||||
|
||||
union SigVal {
|
||||
sint integer;
|
||||
ptr<void> pointer;
|
||||
};
|
||||
|
||||
struct SigInfo {
|
||||
sint signo;
|
||||
sint errno_;
|
||||
sint code;
|
||||
sint pid;
|
||||
slong uid;
|
||||
sint status;
|
||||
ptr<void> addr;
|
||||
SigVal value;
|
||||
|
||||
union {
|
||||
struct {
|
||||
sint trapno;
|
||||
} fault;
|
||||
|
||||
struct {
|
||||
sint timerid;
|
||||
sint overrun;
|
||||
} timer;
|
||||
|
||||
struct {
|
||||
sint mqd;
|
||||
} mesgq;
|
||||
|
||||
struct {
|
||||
slong band;
|
||||
} poll;
|
||||
|
||||
struct {
|
||||
slong spare1;
|
||||
sint spare2[7];
|
||||
} spare;
|
||||
} reason;
|
||||
};
|
||||
} // namespace orbis
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ protected:
|
|||
}
|
||||
|
||||
// Internal waiting function
|
||||
void impl_wait(shared_mutex &mutex, unsigned _val,
|
||||
int impl_wait(shared_mutex &mutex, unsigned _val,
|
||||
std::uint64_t usec_timeout) noexcept;
|
||||
|
||||
// Try to notify up to _count threads
|
||||
|
|
@ -43,14 +43,14 @@ protected:
|
|||
public:
|
||||
constexpr shared_cv() = default;
|
||||
|
||||
void wait(shared_mutex &mutex, std::uint64_t usec_timeout = -1) noexcept {
|
||||
int wait(shared_mutex &mutex, std::uint64_t usec_timeout = -1) noexcept {
|
||||
const unsigned _val = add_waiter();
|
||||
if (!_val) {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex.unlock();
|
||||
impl_wait(mutex, _val, usec_timeout);
|
||||
return impl_wait(mutex, _val, usec_timeout);
|
||||
}
|
||||
|
||||
// Wake one thread
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class shared_mutex final {
|
|||
|
||||
void impl_lock_shared(unsigned val);
|
||||
void impl_unlock_shared(unsigned old);
|
||||
void impl_wait();
|
||||
int impl_wait();
|
||||
void impl_signal();
|
||||
void impl_lock(unsigned val);
|
||||
void impl_unlock(unsigned old);
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@
|
|||
#include "orbis/utils/Logs.hpp"
|
||||
#include <chrono>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <unistd.h>
|
||||
#include <thread>
|
||||
#include <csignal>
|
||||
|
||||
namespace orbis {
|
||||
thread_local Thread *g_currentThread;
|
||||
|
|
@ -13,7 +14,7 @@ thread_local Thread *g_currentThread;
|
|||
KernelContext &g_context = *[]() -> KernelContext * {
|
||||
// Allocate global shared kernel memory
|
||||
// TODO: randomize for hardening and reduce size
|
||||
auto ptr = mmap(reinterpret_cast<void *>(0x200'0000'0000), 0x1'0000'0000,
|
||||
auto ptr = mmap(reinterpret_cast<void *>(0x200'0000'0000), 0x2'0000'0000,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
if (ptr == MAP_FAILED)
|
||||
|
|
@ -32,7 +33,7 @@ KernelContext::KernelContext() {
|
|||
pthread_mutexattr_destroy(&mtx_attr);
|
||||
|
||||
// std::printf("orbis::KernelContext initialized, addr=%p\n", this);
|
||||
// std::printf("TSC frequency: %lu\n", getTscFreq());
|
||||
std::printf("TSC frequency: %lu\n", getTscFreq());
|
||||
}
|
||||
KernelContext::~KernelContext() {}
|
||||
|
||||
|
|
@ -71,7 +72,7 @@ void KernelContext::deleteProcess(Process *proc) {
|
|||
}
|
||||
|
||||
Process *KernelContext::findProcessById(pid_t pid) const {
|
||||
for (std::size_t i = 0; i < 5; ++i) {
|
||||
for (std::size_t i = 0; i < 20; ++i) {
|
||||
{
|
||||
std::lock_guard lock(m_proc_mtx);
|
||||
for (auto proc = m_processes; proc != nullptr; proc = proc->next) {
|
||||
|
|
@ -87,7 +88,7 @@ Process *KernelContext::findProcessById(pid_t pid) const {
|
|||
}
|
||||
|
||||
Process *KernelContext::findProcessByHostId(std::uint64_t pid) const {
|
||||
for (std::size_t i = 0; i < 5; ++i) {
|
||||
for (std::size_t i = 0; i < 20; ++i) {
|
||||
{
|
||||
std::lock_guard lock(m_proc_mtx);
|
||||
for (auto proc = m_processes; proc != nullptr; proc = proc->next) {
|
||||
|
|
@ -215,6 +216,7 @@ KernelContext::getUmtxChainIndexed(int i, Thread *t, uint32_t flags,
|
|||
if (flags & 1) {
|
||||
pid = 0; // Process shared (TODO)
|
||||
ORBIS_LOG_WARNING("Using process-shared umtx", t->tid, ptr, (p % 0x4000));
|
||||
t->where();
|
||||
}
|
||||
auto n = p + pid;
|
||||
if (flags & 1)
|
||||
|
|
@ -238,5 +240,21 @@ void log_class_string<kstring>::format(std::string &out, const void *arg) {
|
|||
}
|
||||
} // namespace logs
|
||||
|
||||
void Thread::suspend() {
|
||||
sendSignal(-1);
|
||||
}
|
||||
|
||||
void Thread::resume() {
|
||||
sendSignal(-2);
|
||||
}
|
||||
|
||||
void Thread::sendSignal(int signo) {
|
||||
std::lock_guard lock(mtx);
|
||||
signalQueue.push_back(signo);
|
||||
if (::tgkill(tproc->hostPid, hostTid, SIGUSR1) < 0) {
|
||||
perror("tgkill");
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::where() { tproc->ops->where(this); }
|
||||
} // namespace orbis
|
||||
|
|
|
|||
|
|
@ -21,8 +21,12 @@ void orbis::EventEmitter::emit(uint filter, uint fflags, intptr_t data) {
|
|||
if (note->event.filter != filter) {
|
||||
continue;
|
||||
}
|
||||
if (fflags != 0 && ((note->event.fflags & fflags) == 0)) {
|
||||
continue;
|
||||
if (fflags != 0) {
|
||||
if ((note->event.fflags & fflags) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
note->event.fflags = fflags;
|
||||
}
|
||||
|
||||
std::lock_guard lock(note->mutex);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ orbis::ErrorCode orbis::EventFlag::wait(Thread *thread, std::uint8_t waitMode,
|
|||
thread->evfIsCancelled = -1;
|
||||
|
||||
std::unique_lock lock(queueMtx);
|
||||
int result = 0;
|
||||
while (true) {
|
||||
if (isDeleted) {
|
||||
if (thread->evfIsCancelled == UINT64_MAX)
|
||||
|
|
@ -77,10 +78,10 @@ orbis::ErrorCode orbis::EventFlag::wait(Thread *thread, std::uint8_t waitMode,
|
|||
waitingThreads.emplace_back(waitingThread);
|
||||
|
||||
if (timeout) {
|
||||
thread->sync_cv.wait(queueMtx, *timeout);
|
||||
result = thread->sync_cv.wait(queueMtx, *timeout);
|
||||
update_timeout();
|
||||
} else {
|
||||
thread->sync_cv.wait(queueMtx);
|
||||
result = thread->sync_cv.wait(queueMtx);
|
||||
}
|
||||
|
||||
if (thread->evfIsCancelled == UINT64_MAX) {
|
||||
|
|
@ -89,7 +90,7 @@ orbis::ErrorCode orbis::EventFlag::wait(Thread *thread, std::uint8_t waitMode,
|
|||
}
|
||||
|
||||
// TODO: update thread state
|
||||
return {};
|
||||
return ErrorCode{result};
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::EventFlag::tryWait(Thread *thread,
|
||||
|
|
@ -137,7 +138,7 @@ std::size_t orbis::EventFlag::notify(NotifyType type, std::uint64_t bits) {
|
|||
|
||||
// TODO: update thread state
|
||||
// release wait on waiter thread
|
||||
thread->thread->sync_cv.notify_one(queueMtx);
|
||||
thread->thread->sync_cv.notify_all(queueMtx);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "thread/Process.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <chrono>
|
||||
#include <sys/mman.h>
|
||||
|
||||
orbis::ErrorCode orbis::ipmiCreateClient(Process *proc, void *clientImpl,
|
||||
const char *name,
|
||||
|
|
@ -15,9 +16,10 @@ orbis::ErrorCode orbis::ipmiCreateClient(Process *proc, void *clientImpl,
|
|||
|
||||
client->clientImpl = clientImpl;
|
||||
client->name = name;
|
||||
client->pid = proc->pid;
|
||||
client->process = proc;
|
||||
client->userData = config.userData;
|
||||
client->eventFlags.resize(32);
|
||||
client->messageQueues.resize(32);
|
||||
result = client;
|
||||
return {};
|
||||
}
|
||||
|
|
@ -72,7 +74,7 @@ orbis::ErrorCode orbis::ipmiCreateSession(Thread *thread, void *sessionImpl,
|
|||
session->client = conReq.client;
|
||||
session->server = server;
|
||||
conReq.client->session = session;
|
||||
conReq.client->sessionCv.notify_all(conReq.client->mutex);
|
||||
conReq.client->sessionCv.notify_one(conReq.client->mutex);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
@ -241,7 +243,6 @@ orbis::SysResult orbis::sysIpmiServerReceivePacket(Thread *thread,
|
|||
|
||||
IpmiServer::Packet _packet;
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, server->name, ": waiting for packet");
|
||||
{
|
||||
std::lock_guard lock(server->mutex);
|
||||
while (server->packets.empty()) {
|
||||
|
|
@ -251,20 +252,39 @@ orbis::SysResult orbis::sysIpmiServerReceivePacket(Thread *thread,
|
|||
_packet = std::move(server->packets.front());
|
||||
server->packets.pop_front();
|
||||
}
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, server->name, ": got packet");
|
||||
|
||||
if (_packet.info.type == 0x1) {
|
||||
// on connection packet
|
||||
|
||||
for (auto &conn : server->connectionRequests) {
|
||||
if ((ptr<void>)conn.clientTid == _packet.info.userData) {
|
||||
if (conn.clientTid == _packet.info.inputSize) {
|
||||
conn.serverTid = thread->tid;
|
||||
_packet.info.userData = nullptr;
|
||||
_packet.info.inputSize = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ((_packet.info.type & ~(0x10 | 0x8000)) == 0x41) {
|
||||
auto syncMessage = (IpmiSyncMessageHeader *)_packet.message.data();
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, server->name, syncMessage->methodId,
|
||||
syncMessage->numInData, syncMessage->numOutData,
|
||||
syncMessage->pid);
|
||||
} else if ((_packet.info.type & ~0x10) == 0x43) {
|
||||
auto asyncMessage = (IpmiAsyncMessageHeader *)_packet.message.data();
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, server->name, asyncMessage->methodId,
|
||||
asyncMessage->numInData, asyncMessage->pid);
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, server->name,
|
||||
*(std::uint64_t *)(*(long *)server->eventHandler + 0x18));
|
||||
}
|
||||
|
||||
if (_params.bufferSize < _packet.message.size()) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, "too small buffer", _params.bufferSize,
|
||||
_packet.message.size());
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
server->tidToClientTid[thread->tid] = _packet.clientTid;
|
||||
|
||||
ORBIS_RET_ON_ERROR(uwriteRaw((ptr<std::byte>)_params.buffer,
|
||||
_packet.message.data(), _packet.message.size()));
|
||||
_params.bufferSize = _packet.message.size();
|
||||
|
|
@ -280,7 +300,6 @@ orbis::SysResult orbis::sysIpmiSendConnectResult(Thread *thread,
|
|||
ptr<void> params,
|
||||
uint64_t paramsSz) {
|
||||
if (paramsSz != sizeof(sint)) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, "wrong param size");
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
|
|
@ -296,9 +315,9 @@ orbis::SysResult orbis::sysIpmiSessionRespondSync(Thread *thread,
|
|||
uint64_t paramsSz) {
|
||||
struct IpmiRespondParams {
|
||||
sint errorCode;
|
||||
uint32_t unk1;
|
||||
ptr<IpmiBufferInfo> buffers;
|
||||
uint32_t bufferCount;
|
||||
ptr<IpmiBufferInfo> buffers;
|
||||
uint32_t flags;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
|
|
@ -316,35 +335,37 @@ orbis::SysResult orbis::sysIpmiSessionRespondSync(Thread *thread,
|
|||
IpmiRespondParams _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiRespondParams>(params)));
|
||||
|
||||
if (_params.bufferCount > 1) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, "unexpected buffers count");
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
kvector<kvector<std::byte>> buffers;
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, session->client->name);
|
||||
thread->where();
|
||||
if ((_params.flags & 1) || _params.bufferCount != 1) {
|
||||
auto count = _params.bufferCount;
|
||||
buffers.reserve(count);
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
IpmiBufferInfo _buffer;
|
||||
ORBIS_RET_ON_ERROR(uread(_buffer, _params.buffers + i));
|
||||
|
||||
kvector<std::byte> data;
|
||||
|
||||
if (_params.errorCode == 0 && _params.bufferCount > 0 &&
|
||||
session->expectedOutput) {
|
||||
IpmiBufferInfo _buffer;
|
||||
ORBIS_RET_ON_ERROR(uread(_buffer, _params.buffers));
|
||||
|
||||
data.resize(_buffer.size);
|
||||
ORBIS_RET_ON_ERROR(ureadRaw(data.data(), _buffer.data, _buffer.size));
|
||||
auto &bufferData = buffers.emplace_back();
|
||||
bufferData.resize(_buffer.size);
|
||||
ORBIS_RET_ON_ERROR(
|
||||
ureadRaw(bufferData.data(), _buffer.data, _buffer.size));
|
||||
}
|
||||
}
|
||||
|
||||
std::lock_guard lock(session->mutex);
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, _params.errorCode);
|
||||
std::uint32_t clientTid;
|
||||
{
|
||||
std::lock_guard serverLock(session->server->mutex);
|
||||
clientTid = session->server->tidToClientTid.at(thread->tid);
|
||||
}
|
||||
|
||||
session->messageResponses.push_front({
|
||||
session->syncResponses.push_front({
|
||||
.errorCode = _params.errorCode,
|
||||
.data = std::move(data),
|
||||
.callerTid = clientTid,
|
||||
.data = std::move(buffers),
|
||||
});
|
||||
|
||||
session->responseCv.notify_one(session->mutex);
|
||||
session->responseCv.notify_all(session->mutex);
|
||||
return uwrite(result, 0u);
|
||||
}
|
||||
orbis::SysResult orbis::sysIpmiClientInvokeAsyncMethod(Thread *thread,
|
||||
|
|
@ -354,8 +375,8 @@ orbis::SysResult orbis::sysIpmiClientInvokeAsyncMethod(Thread *thread,
|
|||
uint64_t paramsSz) {
|
||||
struct IpmiAsyncCallParams {
|
||||
uint32_t method;
|
||||
uint32_t unkNotifee0;
|
||||
uint64_t unkNotifee1;
|
||||
uint32_t evfIndex;
|
||||
uint64_t evfValue;
|
||||
uint32_t numInData;
|
||||
uint32_t padding1;
|
||||
ptr<IpmiDataInfo> pInData;
|
||||
|
|
@ -378,20 +399,121 @@ orbis::SysResult orbis::sysIpmiClientInvokeAsyncMethod(Thread *thread,
|
|||
IpmiAsyncCallParams _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, (ptr<IpmiAsyncCallParams>)params));
|
||||
|
||||
ORBIS_LOG_TODO(__FUNCTION__, thread->tid, client->name, _params.method,
|
||||
_params.unkNotifee0, _params.unkNotifee1, _params.numInData,
|
||||
_params.padding1, _params.pInData, _params.pResult,
|
||||
_params.flags);
|
||||
thread->where();
|
||||
if (_params.flags > 1) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
if (_params.unkNotifee0 != -1) {
|
||||
client->eventFlags[_params.unkNotifee0].set(1);
|
||||
}
|
||||
std::lock_guard clientLock(client->mutex);
|
||||
auto session = client->session;
|
||||
|
||||
if (session == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
std::lock_guard sessionLock(session->mutex);
|
||||
auto server = session->server;
|
||||
|
||||
if (server == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard serverLock(server->mutex);
|
||||
|
||||
std::size_t inSize = 0;
|
||||
for (auto &data : std::span(_params.pInData, _params.numInData)) {
|
||||
inSize += data.size;
|
||||
}
|
||||
|
||||
auto size = sizeof(IpmiAsyncMessageHeader) + inSize +
|
||||
_params.numInData * sizeof(uint32_t);
|
||||
kvector<std::byte> message(size);
|
||||
auto msg = new (message.data()) IpmiAsyncMessageHeader;
|
||||
msg->sessionImpl = session->sessionImpl;
|
||||
msg->pid = thread->tproc->pid;
|
||||
msg->methodId = _params.method;
|
||||
msg->numInData = _params.numInData;
|
||||
|
||||
auto bufLoc = std::bit_cast<char *>(msg + 1);
|
||||
|
||||
for (auto &data : std::span(_params.pInData, _params.numInData)) {
|
||||
*std::bit_cast<uint32_t *>(bufLoc) = data.size;
|
||||
bufLoc += sizeof(uint32_t);
|
||||
ORBIS_RET_ON_ERROR(ureadRaw(bufLoc, data.data, data.size));
|
||||
bufLoc += data.size;
|
||||
}
|
||||
|
||||
uint type = 0x43;
|
||||
|
||||
if ((_params.flags & 1) == 0) {
|
||||
type |= 0x10;
|
||||
}
|
||||
|
||||
server->packets.push_back(
|
||||
{{.type = type, .clientKid = kid}, 0, session, std::move(message)});
|
||||
server->receiveCv.notify_one(server->mutex);
|
||||
}
|
||||
|
||||
if (_params.evfIndex != -1 && _params.evfValue != 0) {
|
||||
client->eventFlags[_params.evfIndex].set(_params.evfValue);
|
||||
}
|
||||
|
||||
ORBIS_RET_ON_ERROR(uwrite(_params.pResult, 0));
|
||||
return uwrite(result, 0u);
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sysImpiSessionRespondAsync(Thread *thread,
|
||||
ptr<uint> result, uint kid,
|
||||
ptr<void> params,
|
||||
uint64_t paramsSz) {
|
||||
struct IpmiAsyncRespondParams {
|
||||
uint method;
|
||||
uint pid;
|
||||
sint result;
|
||||
uint32_t numOutData;
|
||||
ptr<IpmiDataInfo> pOutData;
|
||||
uint32_t unk2; // == 1
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiAsyncRespondParams) == 0x20);
|
||||
|
||||
if (paramsSz != sizeof(IpmiAsyncRespondParams)) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto session = thread->tproc->ipmiMap.get(kid).cast<IpmiSession>();
|
||||
|
||||
if (session == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto client = session->client;
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
IpmiAsyncRespondParams _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, (ptr<IpmiAsyncRespondParams>)params));
|
||||
|
||||
kvector<kvector<std::byte>> outData;
|
||||
outData.reserve(_params.numOutData);
|
||||
for (auto data : std::span(_params.pOutData, _params.numOutData)) {
|
||||
auto &elem = outData.emplace_back();
|
||||
elem.resize(data.size);
|
||||
ORBIS_RET_ON_ERROR(ureadRaw(elem.data(), data.data, data.size));
|
||||
}
|
||||
|
||||
std::lock_guard clientLock(client->mutex);
|
||||
client->asyncResponses.push_back({
|
||||
.methodId = _params.method,
|
||||
.errorCode = _params.result,
|
||||
.data = std::move(outData),
|
||||
});
|
||||
|
||||
return uwrite(result, 0u);
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sysIpmiClientTryGetResult(Thread *thread,
|
||||
ptr<uint> result, uint kid,
|
||||
ptr<void> params,
|
||||
|
|
@ -421,19 +543,66 @@ orbis::SysResult orbis::sysIpmiClientTryGetResult(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
ORBIS_LOG_TODO(__FUNCTION__, thread->tid, client->name, _params.method,
|
||||
_params.unk, _params.pResult, _params.numOutData,
|
||||
_params.padding, _params.pOutData, _params.padding2);
|
||||
thread->where();
|
||||
ORBIS_RET_ON_ERROR(uwrite(_params.pResult, 0));
|
||||
return uwrite(result, 0u);
|
||||
while (true) {
|
||||
{
|
||||
std::lock_guard clientLock(client->mutex);
|
||||
|
||||
for (auto it = client->asyncResponses.begin();
|
||||
it != client->asyncResponses.end(); ++it) {
|
||||
if (it->methodId != _params.method) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto response = std::move(*it);
|
||||
client->asyncResponses.erase(it);
|
||||
|
||||
ORBIS_RET_ON_ERROR(uwrite(_params.pResult, it->errorCode));
|
||||
|
||||
if (response.data.size() != _params.numOutData) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, "responses count mismatch",
|
||||
response.data.size(), _params.numOutData);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < response.data.size(); ++i) {
|
||||
if (response.data.size() > _params.numOutData) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, "too many responses",
|
||||
response.data.size(), _params.numOutData);
|
||||
break;
|
||||
}
|
||||
|
||||
IpmiBufferInfo _outData;
|
||||
ORBIS_RET_ON_ERROR(uread(_outData, _params.pOutData + i));
|
||||
|
||||
auto &data = response.data[i];
|
||||
|
||||
if (_outData.capacity < data.size()) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, "too big response", _outData.capacity,
|
||||
data.size());
|
||||
continue;
|
||||
}
|
||||
|
||||
_outData.size = data.size();
|
||||
ORBIS_RET_ON_ERROR(
|
||||
uwriteRaw(_outData.data, data.data(), data.size()));
|
||||
ORBIS_RET_ON_ERROR(uwrite(_params.pOutData + i, _outData));
|
||||
}
|
||||
|
||||
return uwrite(result, 0u);
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(200));
|
||||
}
|
||||
|
||||
// return uwrite(result, 0x80020000 + static_cast<int>(ErrorCode::AGAIN));
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
|
||||
ptr<uint> result, uint kid,
|
||||
ptr<void> params,
|
||||
uint64_t paramsSz) {
|
||||
struct SceIpmiClientGetArgs {
|
||||
uint32_t unk; // 0
|
||||
uint32_t queueIndex;
|
||||
uint32_t padding;
|
||||
ptr<std::byte> message;
|
||||
ptr<uint64_t> pSize;
|
||||
|
|
@ -456,23 +625,24 @@ orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
|
|||
SceIpmiClientGetArgs _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, ptr<SceIpmiClientGetArgs>(params)));
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, client->name, client->messages.size(),
|
||||
_params.unk, _params.padding, _params.message, _params.pSize,
|
||||
_params.maxSize, _params.pTimeout);
|
||||
|
||||
std::lock_guard lock(client->mutex);
|
||||
|
||||
if (_params.queueIndex >= client->messageQueues.size()) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto &queue = client->messageQueues[_params.queueIndex];
|
||||
|
||||
using clock = std::chrono::high_resolution_clock;
|
||||
|
||||
clock::time_point timeoutPoint = clock::time_point::max();
|
||||
if (_params.pTimeout != nullptr) {
|
||||
std::uint32_t timeout{};
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, timeout);
|
||||
ORBIS_RET_ON_ERROR(uread(timeout, _params.pTimeout));
|
||||
timeoutPoint = clock::now() + std::chrono::microseconds(timeout);
|
||||
}
|
||||
|
||||
if (client->messages.empty()) {
|
||||
if (queue.messages.empty()) {
|
||||
if (timeoutPoint != clock::time_point::max()) {
|
||||
while (true) {
|
||||
auto now = clock::now();
|
||||
|
|
@ -484,9 +654,9 @@ orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
|
|||
|
||||
auto waitTime = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
timeoutPoint - now);
|
||||
client->messageCv.wait(client->mutex, waitTime.count());
|
||||
queue.messageCv.wait(client->mutex, waitTime.count());
|
||||
|
||||
if (!client->messages.empty()) {
|
||||
if (!queue.messages.empty()) {
|
||||
now = clock::now();
|
||||
|
||||
if (now >= timeoutPoint) {
|
||||
|
|
@ -503,13 +673,13 @@ orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
while (client->messages.empty()) {
|
||||
client->messageCv.wait(client->mutex);
|
||||
while (queue.messages.empty()) {
|
||||
queue.messageCv.wait(client->mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto &message = client->messages.front();
|
||||
auto &message = queue.messages.front();
|
||||
|
||||
if (_params.maxSize < message.size()) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, "too small buffer");
|
||||
|
|
@ -520,7 +690,7 @@ orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
|
|||
ORBIS_RET_ON_ERROR(uwrite(_params.pSize, message.size()));
|
||||
ORBIS_RET_ON_ERROR(
|
||||
uwriteRaw(_params.message, message.data(), message.size()));
|
||||
client->messages.pop_front();
|
||||
queue.messages.pop_front();
|
||||
return uwrite<uint>(result, 0);
|
||||
}
|
||||
|
||||
|
|
@ -529,7 +699,7 @@ orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
|
|||
ptr<void> params,
|
||||
uint64_t paramsSz) {
|
||||
struct SceIpmiClientTryGetArgs {
|
||||
uint32_t unk; // 0
|
||||
uint32_t queueIndex;
|
||||
uint32_t padding;
|
||||
ptr<std::byte> message;
|
||||
ptr<uint64_t> pSize;
|
||||
|
|
@ -548,18 +718,23 @@ orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
// ORBIS_LOG_ERROR(__FUNCTION__, client->name, client->messages.size());
|
||||
|
||||
SceIpmiClientTryGetArgs _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, ptr<SceIpmiClientTryGetArgs>(params)));
|
||||
|
||||
std::lock_guard lock(client->mutex);
|
||||
if (client->messages.empty()) {
|
||||
|
||||
if (_params.queueIndex >= client->messageQueues.size()) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto &queue = client->messageQueues[_params.queueIndex];
|
||||
|
||||
if (queue.messages.empty()) {
|
||||
return uwrite<uint>(result,
|
||||
0x80020000 + static_cast<int>(ErrorCode::AGAIN));
|
||||
}
|
||||
|
||||
auto &message = client->messages.front();
|
||||
auto &message = queue.messages.front();
|
||||
|
||||
if (_params.maxSize < message.size()) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, "too small buffer");
|
||||
|
|
@ -570,7 +745,7 @@ orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
|
|||
ORBIS_RET_ON_ERROR(uwrite(_params.pSize, message.size()));
|
||||
ORBIS_RET_ON_ERROR(
|
||||
uwriteRaw(_params.message, message.data(), message.size()));
|
||||
client->messages.pop_front();
|
||||
queue.messages.pop_front();
|
||||
return uwrite<uint>(result, 0);
|
||||
}
|
||||
|
||||
|
|
@ -579,7 +754,7 @@ orbis::SysResult orbis::sysIpmiSessionTrySendMessage(Thread *thread,
|
|||
ptr<void> params,
|
||||
uint64_t paramsSz) {
|
||||
struct SceIpmiClientTrySendArgs {
|
||||
uint32_t unk; // 0
|
||||
uint32_t queueIndex;
|
||||
uint32_t padding;
|
||||
ptr<std::byte> message;
|
||||
uint64_t size;
|
||||
|
|
@ -609,12 +784,16 @@ orbis::SysResult orbis::sysIpmiSessionTrySendMessage(Thread *thread,
|
|||
auto client = session->client;
|
||||
std::lock_guard lockClient(client->mutex);
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, session->server->name, client->name,
|
||||
client->messages.size(), _params.message, _params.size);
|
||||
auto &message = client->messages.emplace_back();
|
||||
if (_params.queueIndex >= client->messageQueues.size()) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto &queue = client->messageQueues[_params.queueIndex];
|
||||
|
||||
auto &message = queue.messages.emplace_back();
|
||||
message.resize(_params.size);
|
||||
ORBIS_RET_ON_ERROR(ureadRaw(message.data(), _params.message, _params.size));
|
||||
client->messageCv.notify_one(client->mutex);
|
||||
queue.messageCv.notify_all(client->mutex);
|
||||
return uwrite<uint>(result, 0);
|
||||
}
|
||||
|
||||
|
|
@ -640,11 +819,6 @@ orbis::SysResult orbis::sysIpmiClientDisconnect(Thread *thread,
|
|||
ORBIS_RET_ON_ERROR(uread(_params, ptr<SceIpmiClientDisconnectArgs>(params)));
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, client->name, _params.status);
|
||||
|
||||
std::lock_guard lock(client->mutex);
|
||||
|
||||
auto &message = client->messages.front();
|
||||
|
||||
ORBIS_RET_ON_ERROR(uwrite(_params.status, 0));
|
||||
return uwrite<uint>(result, 0);
|
||||
}
|
||||
|
|
@ -669,7 +843,8 @@ orbis::SysResult orbis::sysIpmiSessionGetClientPid(Thread *thread,
|
|||
|
||||
IpmiGetClientPidParams _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiGetClientPidParams>(params)));
|
||||
ORBIS_RET_ON_ERROR(uwrite<uint32_t>(_params.pid, session->client->pid));
|
||||
ORBIS_RET_ON_ERROR(
|
||||
uwrite<uint32_t>(_params.pid, session->client->process->pid));
|
||||
return uwrite<uint>(result, 0);
|
||||
}
|
||||
orbis::SysResult
|
||||
|
|
@ -680,8 +855,8 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
|
|||
uint32_t numInData;
|
||||
uint32_t numOutData;
|
||||
uint32_t unk;
|
||||
ptr<IpmiBufferInfo> pInData;
|
||||
ptr<IpmiDataInfo> pOutData;
|
||||
ptr<IpmiDataInfo> pInData;
|
||||
ptr<IpmiBufferInfo> pOutData;
|
||||
ptr<sint> pResult;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
|
@ -705,23 +880,12 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
std::lock_guard clientLock(client->mutex);
|
||||
auto session = client->session;
|
||||
|
||||
if (session == nullptr) {
|
||||
// ORBIS_LOG_TODO(__FUNCTION__, "waiting for connection", client->name,
|
||||
// _params.method);
|
||||
|
||||
// while (session == nullptr) {
|
||||
// client->sessionCv.wait(client->mutex);
|
||||
// session = client->session;
|
||||
// }
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, client->name, "sync call", _params.method);
|
||||
// thread->where();
|
||||
|
||||
std::lock_guard sessionLock(session->mutex);
|
||||
auto server = session->server;
|
||||
|
||||
|
|
@ -732,23 +896,14 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
|
|||
{
|
||||
std::lock_guard serverLock(server->mutex);
|
||||
|
||||
// ORBIS_LOG_TODO("IPMI: invokeSyncMethod", client->name, _params.method,
|
||||
// _params.numInData, _params.unk, _params.numOutData,
|
||||
// _params.pInData, _params.pOutData, _params.pResult,
|
||||
// _params.flags);
|
||||
std::size_t inSize = 0;
|
||||
for (auto &data : std::span(_params.pInData, _params.numInData)) {
|
||||
inSize += data.size;
|
||||
}
|
||||
|
||||
std::size_t outSize = 0;
|
||||
for (auto &data : std::span(_params.pOutData, _params.numOutData)) {
|
||||
outSize += data.size;
|
||||
}
|
||||
|
||||
auto size = sizeof(IpmiSyncMessageHeader) + inSize + outSize +
|
||||
_params.numInData * sizeof(uint32_t) +
|
||||
_params.numOutData * sizeof(uint32_t);
|
||||
auto headerSize = sizeof(IpmiSyncMessageHeader) + inSize +
|
||||
_params.numInData * sizeof(uint32_t);
|
||||
auto size = headerSize + _params.numOutData * sizeof(uint);
|
||||
|
||||
kvector<std::byte> message(size);
|
||||
auto msg = new (message.data()) IpmiSyncMessageHeader;
|
||||
|
|
@ -758,8 +913,6 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
|
|||
msg->numInData = _params.numInData;
|
||||
msg->numOutData = _params.numOutData;
|
||||
|
||||
ORBIS_LOG_TODO("IPMI: sync call", client->name, _params.method,
|
||||
thread->tproc->pid);
|
||||
auto bufLoc = std::bit_cast<char *>(msg + 1);
|
||||
|
||||
for (auto &data : std::span(_params.pInData, _params.numInData)) {
|
||||
|
|
@ -770,51 +923,87 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
|
|||
}
|
||||
|
||||
for (auto &data : std::span(_params.pOutData, _params.numOutData)) {
|
||||
*std::bit_cast<uint32_t *>(bufLoc) = data.size;
|
||||
bufLoc += sizeof(uint32_t) + data.size;
|
||||
*std::bit_cast<uint32_t *>(bufLoc) = data.capacity;
|
||||
bufLoc += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
uint type = 0x41;
|
||||
|
||||
if (_params.numInData == 1 && _params.numOutData == 1 &&
|
||||
server->pid == thread->tproc->pid) {
|
||||
if ((_params.flags & 1) == 0) {
|
||||
type |= 0x10;
|
||||
}
|
||||
|
||||
if ((_params.flags & 1) == 0) {
|
||||
if (server->pid == thread->tproc->pid) {
|
||||
type |= 0x8000;
|
||||
}
|
||||
|
||||
session->expectedOutput = _params.numOutData > 0;
|
||||
server->packets.push_back(
|
||||
{{.type = type, .clientKid = kid}, std::move(message)});
|
||||
server->receiveCv.notify_all(server->mutex);
|
||||
{{.inputSize = headerSize, .type = type, .clientKid = kid},
|
||||
thread->tid,
|
||||
session,
|
||||
std::move(message)});
|
||||
server->receiveCv.notify_one(server->mutex);
|
||||
}
|
||||
|
||||
while (session->messageResponses.empty()) {
|
||||
IpmiSession::SyncResponse response;
|
||||
|
||||
while (true) {
|
||||
session->responseCv.wait(session->mutex);
|
||||
}
|
||||
|
||||
auto response = std::move(session->messageResponses.front());
|
||||
session->messageResponses.pop_front();
|
||||
bool found = false;
|
||||
for (auto it = session->syncResponses.begin();
|
||||
it != session->syncResponses.end(); ++it) {
|
||||
if (it->callerTid != thread->tid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
response = std::move(*it);
|
||||
session->syncResponses.erase(it);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (response.errorCode != 0) {
|
||||
thread->where();
|
||||
}
|
||||
|
||||
ORBIS_RET_ON_ERROR(uwrite(_params.pResult, response.errorCode));
|
||||
if (_params.numOutData > 0 && _params.pOutData->size < response.data.size()) {
|
||||
return ErrorCode::INVAL;
|
||||
|
||||
if (response.data.size() != _params.numOutData) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, "responses amount mismatch",
|
||||
response.data.size(), _params.numOutData);
|
||||
}
|
||||
|
||||
if (_params.numOutData && _params.pOutData->size) {
|
||||
ORBIS_RET_ON_ERROR(uwriteRaw(_params.pOutData->data, response.data.data(),
|
||||
response.data.size()));
|
||||
_params.pOutData->size = response.data.size();
|
||||
for (std::size_t i = 0; i < response.data.size(); ++i) {
|
||||
if (response.data.size() > _params.numOutData) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, "too many responses", response.data.size(),
|
||||
_params.numOutData);
|
||||
break;
|
||||
}
|
||||
|
||||
IpmiBufferInfo _outData;
|
||||
ORBIS_RET_ON_ERROR(uread(_outData, _params.pOutData + i));
|
||||
|
||||
auto &data = response.data[i];
|
||||
|
||||
if (_outData.capacity < data.size()) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, "too big response", _outData.capacity,
|
||||
data.size());
|
||||
continue;
|
||||
}
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, i, _outData.data, _outData.capacity,
|
||||
data.size());
|
||||
|
||||
_outData.size = data.size();
|
||||
ORBIS_RET_ON_ERROR(uwriteRaw(_outData.data, data.data(), data.size()));
|
||||
ORBIS_RET_ON_ERROR(uwrite(_params.pOutData + i, _outData));
|
||||
}
|
||||
|
||||
ORBIS_LOG_TODO(__FUNCTION__, "sync message response", client->name,
|
||||
_params.method, response.errorCode, response.data.size());
|
||||
return uwrite<uint>(result, 0);
|
||||
}
|
||||
|
||||
|
|
@ -822,10 +1011,10 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
|
|||
uint kid, ptr<void> params,
|
||||
uint64_t paramsSz) {
|
||||
struct IpmiClientConnectParams {
|
||||
ptr<void> arg0;
|
||||
ptr<void> arg1;
|
||||
ptr<void> userData;
|
||||
ulong userDataLen;
|
||||
ptr<sint> status;
|
||||
ptr<void> arg3;
|
||||
ptr<sint> arg3;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiClientConnectParams) == 0x20);
|
||||
|
|
@ -847,17 +1036,10 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
|
|||
IpmiClientConnectParams _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiClientConnectParams>(params)));
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, client->name, "connect");
|
||||
|
||||
auto server = g_context.findIpmiServer(client->name);
|
||||
|
||||
if (server == nullptr) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, "waiting for server", client->name);
|
||||
|
||||
while (server == nullptr) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
server = g_context.findIpmiServer(client->name);
|
||||
}
|
||||
return SysResult::notAnError(ErrorCode::NOENT);
|
||||
}
|
||||
|
||||
std::lock_guard clientLock(client->mutex);
|
||||
|
|
@ -889,8 +1071,8 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
|
|||
};
|
||||
|
||||
struct ConnectMessageHeader {
|
||||
uint32_t pid;
|
||||
uint32_t unk0;
|
||||
uint32_t clientPid;
|
||||
uint32_t clientKid;
|
||||
QueueStats sync;
|
||||
QueueStats async;
|
||||
uint numEventFlag;
|
||||
|
|
@ -903,34 +1085,49 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
|
|||
|
||||
static_assert(sizeof(ConnectMessageHeader) == 0x150);
|
||||
|
||||
struct ConnectFields {
|
||||
uint unk0;
|
||||
uint unk1;
|
||||
};
|
||||
|
||||
kvector<std::byte> message{sizeof(ConnectMessageHeader) +
|
||||
sizeof(ConnectFields)};
|
||||
kvector<std::byte> message{
|
||||
sizeof(ConnectMessageHeader) + sizeof(uint) +
|
||||
std::max<std::size_t>(_params.userDataLen, 0x10)};
|
||||
auto header = new (message.data()) ConnectMessageHeader{};
|
||||
header->pid = thread->tproc->pid;
|
||||
header->clientPid = thread->tproc->pid;
|
||||
header->clientKid = kid;
|
||||
|
||||
server->packets.push_back(
|
||||
{{
|
||||
.userData = (ptr<void>)static_cast<ulong>(thread->tid),
|
||||
.type = 1,
|
||||
.clientKid = kid,
|
||||
},
|
||||
std::move(message)});
|
||||
header->sync.maxOutstanding = 1;
|
||||
header->sync.inDataSizeHardLimit = 0x10000;
|
||||
header->sync.outDataSizeHardLimit = 0x10000;
|
||||
header->async.maxOutstanding = 8;
|
||||
header->async.inDataSizeHardLimit = 0x10000;
|
||||
header->async.outDataSizeHardLimit = 0x10000;
|
||||
|
||||
header->numEventFlag = client->eventFlags.size();
|
||||
header->numMsgQueue = client->messageQueues.size();
|
||||
|
||||
for (auto &size : header->msgQueueSize) {
|
||||
size = 0x10000;
|
||||
}
|
||||
|
||||
if (_params.userDataLen != 0) {
|
||||
auto bufLoc = std::bit_cast<char *>(header + 1);
|
||||
*std::bit_cast<uint *>(bufLoc) = _params.userDataLen;
|
||||
ORBIS_RET_ON_ERROR(ureadRaw(bufLoc + sizeof(uint), _params.userData,
|
||||
_params.userDataLen));
|
||||
}
|
||||
|
||||
server->packets.push_back({{
|
||||
.inputSize = static_cast<ulong>(thread->tid),
|
||||
.type = 1,
|
||||
.clientKid = kid,
|
||||
},
|
||||
0,
|
||||
nullptr,
|
||||
std::move(message)});
|
||||
server->receiveCv.notify_one(server->mutex);
|
||||
}
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, client->name, "connect: packet sent");
|
||||
|
||||
while (client->session == nullptr) {
|
||||
client->sessionCv.wait(client->mutex);
|
||||
}
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, client->name, "connect: session created");
|
||||
ORBIS_RET_ON_ERROR(uwrite(_params.status, 0)); // TODO
|
||||
|
||||
{
|
||||
|
|
@ -940,6 +1137,32 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
|
|||
return uwrite(result, 0u);
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sysIpmiSessionGetClientAppId(Thread *thread,
|
||||
ptr<uint> result, uint kid,
|
||||
ptr<void> params,
|
||||
uint64_t paramsSz) {
|
||||
struct IpmiGetUserDataParam {
|
||||
ptr<uint> data;
|
||||
};
|
||||
|
||||
if (paramsSz != sizeof(IpmiGetUserDataParam)) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto session =
|
||||
dynamic_cast<IpmiSession *>(thread->tproc->ipmiMap.get(kid).get());
|
||||
|
||||
if (session == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
IpmiGetUserDataParam _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiGetUserDataParam>(params)));
|
||||
ORBIS_RET_ON_ERROR(
|
||||
uwrite(_params.data, session->client->process->appInfo.appId));
|
||||
return uwrite<uint>(result, 0);
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sysIpmiSessionGetUserData(Thread *thread,
|
||||
ptr<uint> result, uint kid,
|
||||
ptr<void> params,
|
||||
|
|
@ -990,6 +1213,31 @@ orbis::SysResult orbis::sysIpmiServerGetName(Thread *thread, ptr<uint> result,
|
|||
return uwrite<uint>(result, 0);
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sysIpmiClientGetName(Thread *thread, ptr<uint> result,
|
||||
uint kid, ptr<void> params,
|
||||
uint64_t paramsSz) {
|
||||
struct IpmiGetClientNameParams {
|
||||
ptr<char> name;
|
||||
};
|
||||
|
||||
if (paramsSz != sizeof(IpmiGetClientNameParams)) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto client = thread->tproc->ipmiMap.get(kid).cast<IpmiClient>();
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
IpmiGetClientNameParams _param;
|
||||
ORBIS_RET_ON_ERROR(uread(_param, ptr<IpmiGetClientNameParams>(params)));
|
||||
ORBIS_RET_ON_ERROR(
|
||||
uwriteRaw(_param.name, client->name.c_str(), client->name.size() + 1));
|
||||
|
||||
return uwrite<uint>(result, 0);
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sysIpmiClientWaitEventFlag(Thread *thread,
|
||||
ptr<uint> result, uint kid,
|
||||
ptr<void> params,
|
||||
|
|
@ -1015,10 +1263,6 @@ orbis::SysResult orbis::sysIpmiClientWaitEventFlag(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
ORBIS_LOG_TODO(__FUNCTION__, thread->tid, kid, client->name, _params.index,
|
||||
_params.padding0, _params.patternSet, _params.mode,
|
||||
_params.padding1, _params.pPatternSet, _params.pTimeout);
|
||||
|
||||
if (client->eventFlags.size() <= _params.index) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
|
@ -1030,17 +1274,20 @@ orbis::SysResult orbis::sysIpmiClientWaitEventFlag(Thread *thread,
|
|||
}
|
||||
|
||||
auto &evf = client->eventFlags[_params.index];
|
||||
auto waitResult =
|
||||
evf.wait(thread, _params.mode, _params.patternSet, &resultTimeout);
|
||||
auto waitResult = evf.wait(thread, _params.mode, _params.patternSet,
|
||||
_params.pTimeout != 0 ? &resultTimeout : nullptr);
|
||||
|
||||
if (_params.pPatternSet != nullptr) {
|
||||
ORBIS_RET_ON_ERROR(uwrite(_params.pPatternSet, thread->evfResultPattern));
|
||||
}
|
||||
|
||||
// FIXME
|
||||
// if (_params.pPatternSet != nullptr) {
|
||||
// ORBIS_RET_ON_ERROR(uwrite(_params.pPatternSet, thread->evfResultPattern));
|
||||
// }
|
||||
ORBIS_RET_ON_ERROR(uwrite(result, 0u));
|
||||
if (_params.pTimeout != nullptr) {
|
||||
ORBIS_RET_ON_ERROR(uwrite(_params.pTimeout, resultTimeout));
|
||||
}
|
||||
if (waitResult == ErrorCode::TIMEDOUT) {
|
||||
return SysResult::notAnError(ErrorCode::TIMEDOUT);
|
||||
}
|
||||
return waitResult;
|
||||
}
|
||||
|
||||
|
|
@ -1072,10 +1319,6 @@ orbis::SysResult orbis::sysIpmiClientPollEventFlag(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
// ORBIS_LOG_TODO(__FUNCTION__, thread->tid, kid, client->name, _params.index,
|
||||
// _params.padding0, _params.patternSet, _params.mode,
|
||||
// _params.padding1, _params.pPatternSet);
|
||||
|
||||
if (client->eventFlags.size() <= _params.index) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
|
@ -1116,8 +1359,6 @@ orbis::SysResult orbis::sysIpmiSessionSetEventFlag(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
ORBIS_LOG_TODO(__FUNCTION__, session->client->name, _params.patternSet,
|
||||
_params.index);
|
||||
auto client = session->client;
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ static orbis::SysResult doPltRelocation(orbis::Process *process,
|
|||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
*where = reinterpret_cast<std::uintptr_t>(defObj->base) + S;
|
||||
*where = S ? reinterpret_cast<std::uintptr_t>(defObj->base) + S : 0;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
|
@ -285,7 +285,7 @@ static orbis::SysResult doRelocation(orbis::Process *process,
|
|||
if (defObj == nullptr) {
|
||||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
*where = reinterpret_cast<std::uintptr_t>(defObj->base) + S + A;
|
||||
*where = S ? reinterpret_cast<std::uintptr_t>(defObj->base) + S + A : 0;
|
||||
return {};
|
||||
}
|
||||
return {};
|
||||
|
|
@ -295,7 +295,7 @@ static orbis::SysResult doRelocation(orbis::Process *process,
|
|||
if (defObj == nullptr) {
|
||||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
*where32 = reinterpret_cast<std::uintptr_t>(defObj->base) + S + A - P;
|
||||
*where32 = S ? reinterpret_cast<std::uintptr_t>(defObj->base) + S + A - P : 0;
|
||||
return {};
|
||||
}
|
||||
// case kRelCopy:
|
||||
|
|
@ -306,7 +306,7 @@ static orbis::SysResult doRelocation(orbis::Process *process,
|
|||
if (defObj == nullptr) {
|
||||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
*where = reinterpret_cast<std::uintptr_t>(defObj->base) + S;
|
||||
*where = S ? reinterpret_cast<std::uintptr_t>(defObj->base) + S : 0;
|
||||
return {};
|
||||
}
|
||||
case kRelRelative:
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
|
|||
break;
|
||||
}
|
||||
|
||||
file->event.emit(orbis::kEvFiltWrite);
|
||||
pipe->event->emit(orbis::kEvFiltWrite);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ static orbis::ErrorCode pipe_write(orbis::File *file, orbis::Uio *uio,
|
|||
cnt += vec.len;
|
||||
}
|
||||
|
||||
file->event.emit(orbis::kEvFiltRead);
|
||||
pipe->event->emit(orbis::kEvFiltRead);
|
||||
pipe->cv.notify_one(file->mtx);
|
||||
uio->resid -= cnt;
|
||||
uio->offset += cnt;
|
||||
|
|
@ -82,6 +82,8 @@ static orbis::FileOps pipe_ops = {
|
|||
std::pair<orbis::Ref<orbis::Pipe>, orbis::Ref<orbis::Pipe>> orbis::createPipe() {
|
||||
auto a = knew<Pipe>();
|
||||
auto b = knew<Pipe>();
|
||||
a->event = knew<EventEmitter>();
|
||||
b->event = knew<EventEmitter>();
|
||||
a->ops = &pipe_ops;
|
||||
b->ops = &pipe_ops;
|
||||
a->other = b;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
|
||||
orbis::SysResult orbis::sys_getcontext(Thread *thread,
|
||||
ptr<struct ucontext> ucp) {
|
||||
ptr<UContext> ucp) {
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_setcontext(Thread *thread,
|
||||
ptr<struct ucontext> ucp) {
|
||||
ptr<UContext> ucp) {
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_swapcontext(Thread *thread,
|
||||
ptr<struct ucontext> oucp,
|
||||
ptr<struct ucontext> ucp) {
|
||||
ptr<UContext> oucp,
|
||||
ptr<UContext> ucp) {
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#include "file.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include "stat.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
|
||||
orbis::SysResult orbis::sys_getdtablesize(Thread *thread) {
|
||||
return ErrorCode::NOSYS;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
|
||||
#include "KernelContext.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
|
||||
orbis::SysResult orbis::sys_kenv(Thread *thread, sint what,
|
||||
ptr<const char> name, ptr<char> value,
|
||||
|
|
|
|||
|
|
@ -104,14 +104,20 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
|
|||
return ErrorCode::BADF;
|
||||
}
|
||||
|
||||
std::unique_lock lock(fd->event.mutex);
|
||||
nodeIt->file = fd;
|
||||
// if (change.filter == kEvFiltWrite) {
|
||||
// nodeIt->triggered = true;
|
||||
// kq->cv.notify_all(kq->mtx);
|
||||
// }
|
||||
|
||||
fd->event.notes.insert(&*nodeIt);
|
||||
if (auto eventEmitter = fd->event) {
|
||||
std::unique_lock lock(eventEmitter->mutex);
|
||||
// if (change.filter == kEvFiltWrite) {
|
||||
// nodeIt->triggered = true;
|
||||
// kq->cv.notify_all(kq->mtx);
|
||||
// }
|
||||
nodeIt->triggered = true;
|
||||
eventEmitter->notes.insert(&*nodeIt);
|
||||
kq->cv.notify_all(kq->mtx);
|
||||
} else if (note.file->hostFd < 0) {
|
||||
ORBIS_LOG_ERROR("Unimplemented event emitter", change.ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -156,13 +162,23 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
|
|||
(nodeIt->event.fflags & ~kNoteFFlagsMask) | (fflags & kNoteFFlagsMask);
|
||||
|
||||
if (change.fflags & kNoteTrigger) {
|
||||
nodeIt->event.udata = change.udata;
|
||||
nodeIt->triggered = true;
|
||||
kq->cv.notify_all(kq->mtx);
|
||||
}
|
||||
} else if (change.filter == kEvFiltGraphicsCore ||
|
||||
change.filter == kEvFiltDisplay || change.filter == kEvFiltRegEv) {
|
||||
} else if (change.filter == kEvFiltGraphicsCore) {
|
||||
nodeIt->triggered = true;
|
||||
|
||||
if (change.ident == 0x84) {
|
||||
// clock change event
|
||||
nodeIt->event.data |= 1000ull << 16; // clock
|
||||
}
|
||||
kq->cv.notify_all(kq->mtx);
|
||||
} else if (change.filter == kEvFiltDisplay) {
|
||||
if (change.ident != 0x51000100000000 && change.ident != 0x63010100000000) {
|
||||
nodeIt->triggered = true;
|
||||
kq->cv.notify_all(kq->mtx);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
|
|
@ -233,7 +249,7 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
|
|||
auto now = clock::now();
|
||||
auto nowValue = now.time_since_epoch().count();
|
||||
|
||||
if (nowValue < nowValue + nsec) {
|
||||
if (nowValue <= nowValue + nsec) {
|
||||
timeoutPoint = now + std::chrono::nanoseconds(nsec);
|
||||
}
|
||||
}
|
||||
|
|
@ -242,76 +258,101 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
|
|||
std::vector<KEvent> result;
|
||||
result.reserve(nevents);
|
||||
|
||||
ErrorCode errorCode{};
|
||||
|
||||
if (kq->notes.empty()) {
|
||||
// ORBIS_LOG_ERROR(__FUNCTION__, "attempt to wait empty kqueue", fd,
|
||||
// nevents, timeoutPoint.time_since_epoch().count()); thread->where();
|
||||
// nevents,
|
||||
// timeoutPoint.time_since_epoch().count());
|
||||
// thread->where();
|
||||
|
||||
// return{};
|
||||
// std::abort();
|
||||
return {};
|
||||
}
|
||||
|
||||
// ORBIS_LOG_TODO(__FUNCTION__, "kevent wait", fd);
|
||||
|
||||
while (true) {
|
||||
bool waitHack = false;
|
||||
bool canSleep = true;
|
||||
std::lock_guard lock(kq->mtx);
|
||||
for (auto it = kq->notes.begin(); it != kq->notes.end();) {
|
||||
if (result.size() >= nevents) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto ¬e = *it;
|
||||
std::lock_guard lock(note.mutex);
|
||||
{
|
||||
std::lock_guard lock(kq->mtx);
|
||||
for (auto it = kq->notes.begin(); it != kq->notes.end();) {
|
||||
if (result.size() >= nevents) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!note.triggered) {
|
||||
if (note.event.filter == kEvFiltRead) {
|
||||
if (note.file->hostFd < 0 ||
|
||||
isReadEventTriggered(note.file->hostFd)) {
|
||||
note.triggered = true;
|
||||
} else {
|
||||
canSleep = false;
|
||||
auto ¬e = *it;
|
||||
bool erase = false;
|
||||
{
|
||||
std::lock_guard lock(note.mutex);
|
||||
|
||||
if (!note.triggered) {
|
||||
if (note.event.filter == kEvFiltRead) {
|
||||
if (note.file->hostFd >= 0 ) {
|
||||
if (isReadEventTriggered(note.file->hostFd)) {
|
||||
note.triggered = true;
|
||||
} else {
|
||||
canSleep = false;
|
||||
}
|
||||
}
|
||||
} else if (note.event.filter == kEvFiltWrite) {
|
||||
if (note.file->hostFd >= 0) {
|
||||
if (isWriteEventTriggered(note.file->hostFd)) {
|
||||
note.triggered = true;
|
||||
} else {
|
||||
canSleep = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (note.event.filter == kEvFiltWrite) {
|
||||
if (note.file->hostFd < 0 ||
|
||||
isWriteEventTriggered(note.file->hostFd)) {
|
||||
note.triggered = true;
|
||||
} else {
|
||||
canSleep = false;
|
||||
|
||||
if (note.enabled && note.triggered) {
|
||||
result.push_back(note.event);
|
||||
|
||||
if (note.event.filter == kEvFiltGraphicsCore ||
|
||||
note.event.filter == kEvFiltDisplay) {
|
||||
waitHack = true;
|
||||
}
|
||||
|
||||
if (note.event.flags & kEvDispatch) {
|
||||
note.enabled = false;
|
||||
}
|
||||
|
||||
if (note.event.flags & kEvOneshot) {
|
||||
erase = true;
|
||||
}
|
||||
|
||||
if (note.event.filter == kEvFiltRead || note.event.filter == kEvFiltWrite) {
|
||||
note.triggered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (note.enabled && note.triggered) {
|
||||
result.push_back(note.event);
|
||||
|
||||
if (note.event.filter == kEvFiltGraphicsCore ||
|
||||
note.event.filter == kEvFiltDisplay) {
|
||||
waitHack = true;
|
||||
}
|
||||
|
||||
if (note.event.flags & kEvDispatch) {
|
||||
note.enabled = false;
|
||||
}
|
||||
|
||||
if (note.event.flags & kEvOneshot) {
|
||||
if (erase) {
|
||||
it = kq->notes.erase(it);
|
||||
continue;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
if (!result.empty()) {
|
||||
// if (waitHack) {
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds(3));
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds(30));
|
||||
// }
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (timeoutPoint != clock::time_point::max()) {
|
||||
std::lock_guard lock(kq->mtx);
|
||||
auto now = clock::now();
|
||||
|
||||
if (now >= timeoutPoint) {
|
||||
errorCode = ErrorCode::TIMEDOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -322,13 +363,27 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
|
|||
}
|
||||
} else {
|
||||
if (canSleep) {
|
||||
std::lock_guard lock(kq->mtx);
|
||||
kq->cv.wait(kq->mtx);
|
||||
} else {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(30));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ORBIS_LOG_TODO(__FUNCTION__, "kevent wakeup", fd);
|
||||
|
||||
// for (auto evt : result) {
|
||||
// ORBIS_LOG_TODO(__FUNCTION__,
|
||||
// evt.ident,
|
||||
// evt.filter,
|
||||
// evt.flags,
|
||||
// evt.fflags,
|
||||
// evt.data,
|
||||
// evt.udata
|
||||
// );
|
||||
// }
|
||||
|
||||
ORBIS_RET_ON_ERROR(
|
||||
uwriteRaw(eventlist, result.data(), result.size() * sizeof(KEvent)));
|
||||
thread->retval[0] = result.size();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include "thread/ProcessOps.hpp"
|
||||
|
||||
orbis::SysResult orbis::sys_execve(Thread *thread, ptr<char> fname,
|
||||
ptr<ptr<char>> argv, ptr<ptr<char>> envv) {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#include "KernelContext.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/ProcessOps.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <chrono>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/wait.h>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
#include "thread/Process.hpp"
|
||||
|
||||
orbis::SysResult orbis::sys_exit(Thread *thread, sint status) {
|
||||
if (auto exit = thread->tproc->ops->exit) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#include "KernelContext.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include "thread/ProcessOps.hpp"
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#include "file.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include "uio.hpp"
|
||||
#include <sstream>
|
||||
|
||||
|
|
@ -39,11 +42,13 @@ orbis::SysResult orbis::sys_read(Thread *thread, sint fd, ptr<void> buf,
|
|||
auto cnt = io.offset - file->nextOff;
|
||||
file->nextOff = io.offset;
|
||||
|
||||
// ORBIS_LOG_ERROR(__FUNCTION__, fd, buf, nbyte, cnt);
|
||||
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_ERROR(__FUNCTION__, fd, buf, nbyte, offset);
|
||||
Ref<File> file = thread->tproc->fileDescriptors.get(fd);
|
||||
if (file == nullptr) {
|
||||
return ErrorCode::BADF;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <thread>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <pipe.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
|
||||
orbis::SysResult orbis::sys_getpid(Thread *thread) {
|
||||
|
|
@ -16,7 +18,10 @@ orbis::SysResult orbis::sys_getpgid(Thread *thread, pid_t pid) {
|
|||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_getsid(Thread *thread, pid_t pid) { return {}; }
|
||||
orbis::SysResult orbis::sys_getuid(Thread *thread) { return ErrorCode::NOSYS; }
|
||||
orbis::SysResult orbis::sys_getuid(Thread *thread) {
|
||||
thread->retval[0] = 1;
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_geteuid(Thread *thread) { return ErrorCode::NOSYS; }
|
||||
orbis::SysResult orbis::sys_getgid(Thread *thread) { return ErrorCode::NOSYS; }
|
||||
orbis::SysResult orbis::sys_getegid(Thread *thread) { return ErrorCode::NOSYS; }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
|
||||
namespace orbis {
|
||||
|
|
@ -88,5 +89,5 @@ orbis::SysResult orbis::sys_getrlimit(Thread *thread, uint which,
|
|||
}
|
||||
orbis::SysResult orbis::sys_getrusage(Thread *thread, sint who,
|
||||
ptr<struct rusage> rusage) {
|
||||
return ErrorCode::NOSYS;
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,10 +8,16 @@
|
|||
#include "orbis/time.hpp"
|
||||
#include "osem.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include "thread/ProcessOps.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "ucontext.hpp"
|
||||
#include "uio.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <thread>
|
||||
|
||||
orbis::SysResult orbis::sys_netcontrol(Thread *thread, sint fd, uint op,
|
||||
ptr<void> buf, uint nbuf) {
|
||||
|
|
@ -63,24 +69,33 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
|
|||
// ORBIS_LOG_ERROR(__FUNCTION__, op, id, len);
|
||||
// thread->where();
|
||||
|
||||
std::lock_guard lock(orbis::g_context.regMgrMtx);
|
||||
|
||||
if (op == 1) {
|
||||
// set int
|
||||
if (len != sizeof(uint32_t)) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, op, id, *(std::uint32_t *)value);
|
||||
g_context.regMgrInt[id] = *(std::uint32_t *)value;
|
||||
return {};
|
||||
}
|
||||
if (op == 2) {
|
||||
// get int
|
||||
if (len != sizeof(uint32_t)) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
if (id == 0x2010000) {
|
||||
return uwrite((ptr<uint>)value, 0u);
|
||||
}
|
||||
if (id == 0x7802c000) {
|
||||
return uwrite((ptr<uint>)value, 0u);
|
||||
}
|
||||
if (id == 0x78020500) {
|
||||
return uwrite((ptr<uint>)value, 0u);
|
||||
}
|
||||
if (id == 0x78020b00) {
|
||||
auto intValIt = g_context.regMgrInt.find(id);
|
||||
if (intValIt == g_context.regMgrInt.end()) {
|
||||
ORBIS_LOG_ERROR("registry int entry not exists", op, id, len);
|
||||
thread->where();
|
||||
// return ErrorCode::NOENT;
|
||||
return uwrite((ptr<uint>)value, 0u);
|
||||
return {};
|
||||
}
|
||||
return uwrite((ptr<uint>)value, intValIt->second);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
@ -93,6 +108,8 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
std::memset(value, 0, len);
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, op, id, len);
|
||||
thread->where();
|
||||
return {};
|
||||
|
|
@ -319,8 +336,8 @@ orbis::SysResult orbis::sys_evf_trywait(Thread *thread, sint id,
|
|||
}
|
||||
|
||||
auto result = evf->tryWait(thread, mode, patternSet);
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, evf->name, thread->tid, id, patternSet, mode,
|
||||
pPatternSet, result);
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, thread->tid, evf->name, thread->tid, id,
|
||||
patternSet, mode, pPatternSet, result);
|
||||
|
||||
if (pPatternSet != nullptr) {
|
||||
ORBIS_RET_ON_ERROR(uwrite(pPatternSet, thread->evfResultPattern));
|
||||
|
|
@ -670,7 +687,9 @@ orbis::SysResult orbis::sys_namedobj_delete(Thread *thread, uint id,
|
|||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_set_vm_container(Thread *thread /* TODO */) {
|
||||
return ErrorCode::NOSYS;
|
||||
ORBIS_LOG_TODO(__FUNCTION__);
|
||||
thread->where();
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_debug_init(Thread *thread /* TODO */) {
|
||||
return ErrorCode::NOSYS;
|
||||
|
|
@ -956,7 +975,21 @@ orbis::SysResult orbis::sys_mdbg_service(Thread *thread, uint32_t op,
|
|||
}
|
||||
|
||||
case 7: {
|
||||
// TODO: read string from userspace
|
||||
if (auto open = thread->tproc->ops->open) {
|
||||
Ref<File> console;
|
||||
auto result = open(thread, "/dev/console", 0, 0, &console);
|
||||
if (!result.value() && console && console->ops->write) {
|
||||
IoVec vec{.base = (char *)arg0, .len = std::strlen((char *)arg0)};
|
||||
|
||||
Uio uio{
|
||||
.iov = &vec,
|
||||
.iovcnt = 1,
|
||||
};
|
||||
if (console->ops->write(console.get(), &uio, thread) == ErrorCode{}) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
ORBIS_LOG_NOTICE("sys_mdbg_service", (char *)arg0);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1189,6 +1222,8 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
|
|||
case 0x241:
|
||||
return sysIpmiClientInvokeAsyncMethod(thread, result, kid, params,
|
||||
paramsSz);
|
||||
case 0x242:
|
||||
return sysImpiSessionRespondAsync(thread, result, kid, params, paramsSz);
|
||||
case 0x243:
|
||||
return sysIpmiClientTryGetResult(thread, result, kid, params, paramsSz);
|
||||
case 0x251:
|
||||
|
|
@ -1205,10 +1240,14 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
|
|||
return sysIpmiClientInvokeSyncMethod(thread, result, kid, params, paramsSz);
|
||||
case 0x400:
|
||||
return sysIpmiClientConnect(thread, result, kid, params, paramsSz);
|
||||
case 0x463:
|
||||
return sysIpmiSessionGetClientAppId(thread, result, kid, params, paramsSz);
|
||||
case 0x468:
|
||||
return sysIpmiSessionGetUserData(thread, result, kid, params, paramsSz);
|
||||
case 0x46a:
|
||||
return sysIpmiServerGetName(thread, result, kid, params, paramsSz);
|
||||
case 0x46b:
|
||||
return sysIpmiClientGetName(thread, result, kid, params, paramsSz);
|
||||
case 0x490:
|
||||
return sysIpmiClientWaitEventFlag(thread, result, kid, params, paramsSz);
|
||||
case 0x491:
|
||||
|
|
@ -1279,15 +1318,85 @@ orbis::SysResult orbis::sys_resume_internal_hdd(Thread *thread /* TODO */) {
|
|||
}
|
||||
orbis::SysResult orbis::sys_thr_suspend_ucontext(Thread *thread, lwpid_t tid) {
|
||||
// ORBIS_LOG_FATAL(__FUNCTION__, tid);
|
||||
auto t = tid == thread->tid ? thread
|
||||
: thread->tproc->threadsMap.get(tid % 10000 - 1);
|
||||
if (t == nullptr) {
|
||||
return ErrorCode::SRCH;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
unsigned prevSuspend = 0;
|
||||
if (t->suspended.compare_exchange_strong(prevSuspend, 1)) {
|
||||
t->suspend();
|
||||
|
||||
while (t->suspended == 0) {
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (t->suspended.compare_exchange_strong(prevSuspend, prevSuspend + 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_thr_resume_ucontext(Thread *thread, lwpid_t tid) {
|
||||
// ORBIS_LOG_FATAL(__FUNCTION__, tid);
|
||||
auto t = tid == thread->tid ? thread
|
||||
: thread->tproc->threadsMap.get(tid % 10000 - 1);
|
||||
if (t == nullptr) {
|
||||
return ErrorCode::SRCH;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
unsigned prevSuspend = 1;
|
||||
if (t->suspended.compare_exchange_strong(prevSuspend, 0)) {
|
||||
t->resume();
|
||||
|
||||
while (t->suspended != 0) {
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (prevSuspend == 0) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
if (t->suspended.compare_exchange_strong(prevSuspend, prevSuspend - 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_thr_get_ucontext(Thread *thread, lwpid_t tid,
|
||||
ptr<UContext> context) {
|
||||
// ORBIS_LOG_FATAL(__FUNCTION__, tid, context);
|
||||
|
||||
auto t = tid == thread->tid ? thread
|
||||
: thread->tproc->threadsMap.get(tid % 10000 - 1);
|
||||
if (t == nullptr) {
|
||||
return ErrorCode::SRCH;
|
||||
}
|
||||
|
||||
std::lock_guard lock(t->mtx);
|
||||
|
||||
if (t->suspended == 0) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
for (auto it = t->sigReturns.rbegin(); it != t->sigReturns.rend(); ++it) {
|
||||
auto &savedContext = t->sigReturns.back();
|
||||
if (savedContext.mcontext.rip < 0x100'0000'0000) {
|
||||
return uwrite(context, savedContext);
|
||||
}
|
||||
}
|
||||
ORBIS_LOG_FATAL(__FUNCTION__, "not found guest context");
|
||||
*context = {};
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_thr_set_ucontext(Thread *thread, lwpid_t tid,
|
||||
|
|
@ -1296,7 +1405,9 @@ orbis::SysResult orbis::sys_thr_set_ucontext(Thread *thread, lwpid_t tid,
|
|||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_set_timezone_info(Thread *thread /* TODO */) {
|
||||
return ErrorCode::NOSYS;
|
||||
ORBIS_LOG_ERROR(__FUNCTION__);
|
||||
thread->where();
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_set_phys_fmem_limit(Thread *thread /* TODO */) {
|
||||
return ErrorCode::NOSYS;
|
||||
|
|
@ -1423,7 +1534,9 @@ orbis::SysResult orbis::sys_blockpool_batch(Thread *thread /* TODO */) {
|
|||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_fdatasync(Thread *thread /* TODO */) {
|
||||
return ErrorCode::NOSYS;
|
||||
ORBIS_LOG_TODO(__FUNCTION__);
|
||||
thread->where();
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_dynlib_get_list2(Thread *thread /* TODO */) {
|
||||
return ErrorCode::NOSYS;
|
||||
|
|
|
|||
|
|
@ -1,67 +1,90 @@
|
|||
#include "KernelContext.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "ucontext.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <csignal>
|
||||
|
||||
orbis::SysResult orbis::sys_sigaction(Thread *thread, sint sig,
|
||||
ptr<struct sigaction> act,
|
||||
ptr<struct sigaction> oact) {
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_sigprocmask(Thread *thread, sint how,
|
||||
ptr<uint64_t> set, ptr<uint64_t> oset) {
|
||||
if (oset) {
|
||||
for (std::size_t i = 0; i < 2; ++i) {
|
||||
oset[i] = thread->sigMask[i];
|
||||
ptr<SigAction> act, ptr<SigAction> oact) {
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, sig, act, oact);
|
||||
|
||||
auto &sigAct = thread->tproc->sigActions[sig];
|
||||
if (oact != nullptr) {
|
||||
if (auto errc = uwrite(oact, sigAct); errc != orbis::ErrorCode{}) {
|
||||
return errc;
|
||||
}
|
||||
}
|
||||
|
||||
if (act != nullptr) {
|
||||
if (auto errc = uread(sigAct, act); errc != ErrorCode{}) {
|
||||
return errc;
|
||||
}
|
||||
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, sigAct.handler, sigAct.flags,
|
||||
sigAct.mask.bits[0], sigAct.mask.bits[1],
|
||||
sigAct.mask.bits[2], sigAct.mask.bits[3]);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sys_sigprocmask(Thread *thread, sint how,
|
||||
ptr<SigSet> set, ptr<SigSet> oset) {
|
||||
if (oset) {
|
||||
ORBIS_RET_ON_ERROR(uwrite(oset, thread->sigMask));
|
||||
}
|
||||
|
||||
if (set) {
|
||||
SigSet _set;
|
||||
ORBIS_RET_ON_ERROR(uread(_set, set));
|
||||
|
||||
switch (how) {
|
||||
case 0: // unblock
|
||||
for (std::size_t i = 0; i < 2; ++i) {
|
||||
thread->sigMask[i] &= ~set[i];
|
||||
}
|
||||
case 1: // block
|
||||
for (std::size_t i = 0; i < 2; ++i) {
|
||||
thread->sigMask[i] |= set[i];
|
||||
for (std::size_t i = 0; i < 4; ++i) {
|
||||
thread->sigMask.bits[i] |= _set.bits[i];
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // unblock
|
||||
for (std::size_t i = 0; i < 4; ++i) {
|
||||
thread->sigMask.bits[i] &= ~_set.bits[i];
|
||||
}
|
||||
break;
|
||||
case 3: // set
|
||||
for (std::size_t i = 0; i < 2; ++i) {
|
||||
thread->sigMask[i] = set[i];
|
||||
}
|
||||
thread->sigMask = _set;
|
||||
break;
|
||||
|
||||
default:
|
||||
ORBIS_LOG_ERROR("sys_sigprocmask: unimplemented how", how);
|
||||
thread->where();
|
||||
return {};
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
thread->sigMask.clear(kSigKill);
|
||||
thread->sigMask.clear(kSigStop);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_sigwait(Thread *thread,
|
||||
ptr<const struct sigset> set,
|
||||
orbis::SysResult orbis::sys_sigwait(Thread *thread, ptr<const SigSet> set,
|
||||
ptr<sint> sig) {
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_sigtimedwait(Thread *thread,
|
||||
ptr<const struct sigset> set,
|
||||
orbis::SysResult orbis::sys_sigtimedwait(Thread *thread, ptr<const SigSet> set,
|
||||
ptr<struct siginfo> info,
|
||||
ptr<const timespec> timeout) {
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_sigwaitinfo(Thread *thread,
|
||||
ptr<const struct sigset> set,
|
||||
orbis::SysResult orbis::sys_sigwaitinfo(Thread *thread, ptr<const SigSet> set,
|
||||
ptr<struct siginfo> info) {
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_sigpending(Thread *thread, ptr<struct sigset> set) {
|
||||
orbis::SysResult orbis::sys_sigpending(Thread *thread, ptr<SigSet> set) {
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_sigsuspend(Thread *thread,
|
||||
ptr<const struct sigset> set) {
|
||||
orbis::SysResult orbis::sys_sigsuspend(Thread *thread, ptr<const SigSet> set) {
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_sigaltstack(Thread *thread, ptr<struct stack_t> ss,
|
||||
|
|
@ -69,7 +92,7 @@ orbis::SysResult orbis::sys_sigaltstack(Thread *thread, ptr<struct stack_t> ss,
|
|||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_kill(Thread *thread, sint pid, sint signum) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, pid, signum);
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, pid, signum);
|
||||
|
||||
int hostPid = pid;
|
||||
if (pid > 0) {
|
||||
|
|
@ -81,10 +104,10 @@ orbis::SysResult orbis::sys_kill(Thread *thread, sint pid, sint signum) {
|
|||
}
|
||||
|
||||
// TODO: wrap signal
|
||||
int result = ::kill(hostPid, signum);
|
||||
if (result < 0) {
|
||||
return static_cast<ErrorCode>(errno);
|
||||
}
|
||||
// int result = ::kill(hostPid, signum);
|
||||
// if (result < 0) {
|
||||
// return static_cast<ErrorCode>(errno);
|
||||
// }
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
@ -96,8 +119,18 @@ orbis::SysResult orbis::sys_sigqueue(Thread *thread, pid_t pid, sint signum,
|
|||
ptr<void> value) {
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_sigreturn(Thread *thread,
|
||||
ptr<struct ucontext> sigcntxp) {
|
||||
return ErrorCode::NOSYS;
|
||||
orbis::SysResult orbis::sys_sigreturn(Thread *thread, ptr<UContext> sigcntxp) {
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, sigcntxp);
|
||||
|
||||
// auto sigRet = thread->sigReturns.front();
|
||||
// thread->sigReturns.erase(thread->sigReturns.begin(), thread->sigReturns.begin() + 1);
|
||||
// writeRegister(thread->context, RegisterId::rip, sigRet.rip);
|
||||
// writeRegister(thread->context, RegisterId::rsp, sigRet.rsp);
|
||||
// ORBIS_LOG_ERROR(__FUNCTION__, sigRet.rip, sigRet.rsp);
|
||||
return {};
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::nosys(Thread *thread) {
|
||||
thread->sendSignal(kSigSys);
|
||||
return{};
|
||||
}
|
||||
orbis::SysResult orbis::nosys(Thread *thread) { return ErrorCode::NOSYS; }
|
||||
|
|
|
|||
|
|
@ -1,16 +1,20 @@
|
|||
#include "KernelContext.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include "time.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
|
||||
orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
||||
uint namelen, ptr<void> old,
|
||||
ptr<size_t> oldlenp, ptr<void> new_,
|
||||
size_t newlen) {
|
||||
namespace orbis {
|
||||
SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
||||
ptr<void> old, ptr<size_t> oldlenp, ptr<void> new_,
|
||||
size_t newlen) {
|
||||
enum sysctl_ctl { unspec, kern, vm, vfs, net, debug, hw, machdep, user };
|
||||
|
||||
enum sysctl_kern {
|
||||
usrstack = 33,
|
||||
proc = 14,
|
||||
boottime = 21,
|
||||
usrstack = 33,
|
||||
arnd = 37,
|
||||
|
||||
// FIXME
|
||||
|
|
@ -22,10 +26,12 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
|||
rng_pseudo,
|
||||
backup_restore_mode,
|
||||
console,
|
||||
init_safe_mode
|
||||
init_safe_mode,
|
||||
geom,
|
||||
};
|
||||
|
||||
enum sysctl_hw {
|
||||
ncpu = 3,
|
||||
pagesize = 7,
|
||||
|
||||
// FIXME
|
||||
|
|
@ -49,6 +55,8 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
|||
tsc_freq = 1000,
|
||||
liverpool,
|
||||
bootparams,
|
||||
idps,
|
||||
openpsid_for_sys,
|
||||
};
|
||||
|
||||
enum sysctl_machdep_liverpool {
|
||||
|
|
@ -59,6 +67,10 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
|||
is_main_on_standby = 1000,
|
||||
};
|
||||
|
||||
enum sysctl_kern_geom {
|
||||
updtfmt = 1000,
|
||||
};
|
||||
|
||||
struct ProcInfo {
|
||||
char data[0x448];
|
||||
};
|
||||
|
|
@ -139,9 +151,47 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
|||
*(uint64_t *)old = 0;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (name[0] == kern && name[1] == geom && name[2] == updtfmt) {
|
||||
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
*(uint32_t *)old = 0;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (namelen == 4) {
|
||||
if (name[0] == kern && name[1] == proc && name[2] == 37) {
|
||||
if (oldlenp && old && *oldlenp == 4) {
|
||||
return uwrite(ptr<uint32_t>(old), ~0u);
|
||||
}
|
||||
}
|
||||
|
||||
if (name[0] == kern && name[1] == proc && name[2] == 36) {
|
||||
Process *process = thread->tproc;
|
||||
if (process->pid != name[3]) {
|
||||
process = g_context.findProcessById(name[3]);
|
||||
if (process == nullptr) {
|
||||
ORBIS_LOG_ERROR("get sdk version by pid: process not found", name[3],
|
||||
thread->tproc->pid);
|
||||
return ErrorCode::SRCH;
|
||||
}
|
||||
}
|
||||
|
||||
size_t oldlen;
|
||||
ORBIS_RET_ON_ERROR(uread(oldlen, oldlenp));
|
||||
|
||||
if (oldlen < sizeof(uint32_t)) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
ORBIS_RET_ON_ERROR(uwrite(ptr<uint32_t>(old), process->sdkVersion));
|
||||
ORBIS_LOG_ERROR("get sdk version by pid", name[3], process->sdkVersion);
|
||||
return uwrite(oldlenp, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
if (name[0] == kern && name[1] == proc && name[2] == 1) {
|
||||
ORBIS_LOG_ERROR("KERN_PROC_PROC 2");
|
||||
|
||||
|
|
@ -388,6 +438,31 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
|||
dest[count++] = hw;
|
||||
dest[count++] = config;
|
||||
dest[count++] = optical_out;
|
||||
} else if (searchName == "machdep.idps") {
|
||||
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
||||
std::fprintf(stderr, " %s error\n", searchName.data());
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
dest[count++] = machdep;
|
||||
dest[count++] = idps;
|
||||
} else if (searchName == "kern.geom.updtfmt") {
|
||||
if (*oldlenp < 3 * sizeof(uint32_t)) {
|
||||
std::fprintf(stderr, " %s error\n", searchName.data());
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
dest[count++] = kern;
|
||||
dest[count++] = geom;
|
||||
dest[count++] = updtfmt;
|
||||
} else if (searchName == "machdep.openpsid_for_sys") {
|
||||
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
||||
std::fprintf(stderr, " %s error\n", searchName.data());
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
dest[count++] = machdep;
|
||||
dest[count++] = openpsid_for_sys;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
|
|
@ -409,6 +484,19 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
|||
|
||||
case sysctl_ctl::kern:
|
||||
switch (name[1]) {
|
||||
case sysctl_kern::boottime: {
|
||||
// FIXME: implement boottime support
|
||||
if (*oldlenp < sizeof(timeval) || new_ != nullptr || newlen != 0) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
*oldlenp = sizeof(timeval);
|
||||
*ptr<timeval>(old) = {
|
||||
.tv_sec = 60,
|
||||
.tv_usec = 0,
|
||||
};
|
||||
return {};
|
||||
}
|
||||
case sysctl_kern::usrstack: {
|
||||
if (*oldlenp != 8 || new_ != nullptr || newlen != 0) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -424,7 +512,7 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
*(uint32_t *)old = 1;
|
||||
*(uint32_t *)old = 6;
|
||||
return {};
|
||||
|
||||
case sysctl_kern::sdk_version: {
|
||||
|
|
@ -432,8 +520,8 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
std::printf("Reporting SDK version %x\n", g_context.sdkVersion);
|
||||
*(uint32_t *)old = g_context.sdkVersion;
|
||||
std::printf("Reporting SDK version %x\n", thread->tproc->sdkVersion);
|
||||
*(uint32_t *)old = thread->tproc->sdkVersion;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
@ -501,6 +589,22 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
|||
*(std::uint32_t *)old = 0;
|
||||
return {};
|
||||
|
||||
case sysctl_kern::init_safe_mode:
|
||||
if (old && oldlenp) {
|
||||
ORBIS_LOG_ERROR("sysctl: get kern.init_safe_mode", oldlenp, new_,
|
||||
newlen);
|
||||
if (*oldlenp != 4) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
*(std::uint32_t *)old = g_context.safeMode;
|
||||
}
|
||||
if (new_ != nullptr && newlen == 4) {
|
||||
ORBIS_LOG_ERROR("sysctl: set kern.init_safe_mode",
|
||||
*(std::uint32_t *)new_, newlen);
|
||||
}
|
||||
return {};
|
||||
|
||||
default:
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
|
@ -550,6 +654,15 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
|||
*(uint32_t *)old = 0x4000;
|
||||
return {};
|
||||
|
||||
case sysctl_hw::ncpu:
|
||||
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
||||
|
||||
} else {
|
||||
|
||||
*(uint32_t *)old = 7;
|
||||
return {};
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -562,13 +675,37 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
*(uint64_t *)old = g_context.getTscFreq();
|
||||
if (std::string_view((char *)thread->tproc->appInfo.titleId) ==
|
||||
"NPXS20973") {
|
||||
ORBIS_LOG_ERROR("get tsc freq: returning patched value");
|
||||
*(uint64_t *)old = 1000000;
|
||||
} else {
|
||||
*(uint64_t *)old = g_context.getTscFreq();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
case sysctl_machdep::idps: {
|
||||
if (*oldlenp != 16 || new_ != nullptr || newlen != 0) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
std::memset(old, 0, 16);
|
||||
return uwrite<short>((short *)((char *)old + 4), 0x8401);
|
||||
}
|
||||
|
||||
case sysctl_machdep::openpsid_for_sys: {
|
||||
if (*oldlenp != 16 || new_ != nullptr || newlen != 0) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
std::memset(old, 0, 16);
|
||||
return {};
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
case sysctl_ctl::user:
|
||||
break;
|
||||
}
|
||||
|
|
@ -588,3 +725,29 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
|||
thread->where();
|
||||
return {};
|
||||
}
|
||||
} // namespace orbis
|
||||
|
||||
orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
||||
uint namelen, ptr<void> old,
|
||||
ptr<size_t> oldlenp, ptr<void> new_,
|
||||
size_t newlen) {
|
||||
|
||||
auto result = kern_sysctl(thread, name, namelen, old, oldlenp, new_, newlen);
|
||||
|
||||
if (result.isError()) {
|
||||
std::string concatName;
|
||||
for (unsigned int i = 0; i < namelen; ++i) {
|
||||
if (i != 0) {
|
||||
concatName += '.';
|
||||
}
|
||||
|
||||
concatName += std::to_string(name[i]);
|
||||
}
|
||||
|
||||
std::size_t oldLen = oldlenp ? *oldlenp : 0;
|
||||
ORBIS_LOG_TODO(__FUNCTION__, concatName, oldLen, new_, newlen);
|
||||
thread->where();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1,7 +1,11 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
#include "thread/ProcessOps.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include "ucontext.hpp"
|
||||
|
||||
orbis::SysResult orbis::sys_thr_create(Thread *thread,
|
||||
ptr<struct ucontext> ctxt,
|
||||
ptr<UContext> ctxt,
|
||||
ptr<slong> arg, sint flags) {
|
||||
if (auto thr_create = thread->tproc->ops->thr_create) {
|
||||
return thr_create(thread, ctxt, arg, flags);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
#include "time.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <ctime>
|
||||
#include <sys/time.h>
|
||||
|
||||
enum class ClockId {
|
||||
Realtime = 0,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
#include "file.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/ProcessOps.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include "uio.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <sys/socket.h>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
#include "file.hpp"
|
||||
#include "orbis-config.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/ProcessOps.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
|
||||
orbis::SysResult orbis::sys_shm_open(Thread *thread, ptr<const char> path,
|
||||
sint flags, mode_t mode) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "orbis/utils/Logs.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "time.hpp"
|
||||
#include "umtx.hpp"
|
||||
#include <chrono>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#include "stat.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/ProcessOps.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <filesystem>
|
||||
#include <span>
|
||||
|
|
@ -26,7 +29,7 @@ orbis::SysResult orbis::sys_statfs(Thread *thread, ptr<char> path,
|
|||
return {};
|
||||
}
|
||||
|
||||
std::strncpy(buf->f_fstypename, "exfatfs", sizeof(buf->f_fstypename));
|
||||
std::strncpy(buf->f_fstypename, "unionfs", sizeof(buf->f_fstypename));
|
||||
std::strncpy(buf->f_mntfromname, "/dev/super-hdd",
|
||||
sizeof(buf->f_mntfromname));
|
||||
std::strncpy(buf->f_mntonname, "/system/", sizeof(buf->f_mntonname));
|
||||
|
|
@ -41,7 +44,7 @@ orbis::SysResult orbis::sys_fstatfs(Thread *thread, sint fd,
|
|||
return {};
|
||||
}
|
||||
|
||||
std::strncpy(buf->f_fstypename, "exfatfs", sizeof(buf->f_fstypename));
|
||||
std::strncpy(buf->f_fstypename, "unionfs", sizeof(buf->f_fstypename));
|
||||
std::strncpy(buf->f_mntfromname, "/dev/super-hdd",
|
||||
sizeof(buf->f_mntfromname));
|
||||
std::strncpy(buf->f_mntonname, "/system/", sizeof(buf->f_mntonname));
|
||||
|
|
@ -66,7 +69,9 @@ orbis::SysResult orbis::sys_chroot(Thread *thread, ptr<char> path) {
|
|||
thread->tproc->root = path;
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_open(Thread *thread, ptr<char> path, sint flags,
|
||||
|
||||
// volatile bool debuggerPresent = false;
|
||||
orbis::SysResult orbis::sys_open(Thread *thread, ptr<const char> path, sint flags,
|
||||
sint mode) {
|
||||
if (auto open = thread->tproc->ops->open) {
|
||||
Ref<File> file;
|
||||
|
|
@ -77,7 +82,17 @@ orbis::SysResult orbis::sys_open(Thread *thread, ptr<char> path, sint flags,
|
|||
|
||||
auto fd = thread->tproc->fileDescriptors.insert(file);
|
||||
thread->retval[0] = fd;
|
||||
// ORBIS_LOG_NOTICE(__FUNCTION__, path, flags, mode, fd);
|
||||
// if (path == std::string_view{"/app0/psm/Application/resource/Sce.Vsh.ShellUI.SystemMessage.rco"}) {
|
||||
ORBIS_LOG_SUCCESS(__FUNCTION__, thread->tid, path, flags, mode, fd);
|
||||
if (path == std::string_view{"/app0/wave/wave1.fbxd"}) {
|
||||
thread->where();
|
||||
}
|
||||
|
||||
// while (debuggerPresent == false) {
|
||||
// std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
// }
|
||||
// // thread->where();
|
||||
// }
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
@ -85,6 +100,23 @@ orbis::SysResult orbis::sys_open(Thread *thread, ptr<char> path, sint flags,
|
|||
}
|
||||
orbis::SysResult orbis::sys_openat(Thread *thread, sint fd, ptr<char> path,
|
||||
sint flag, mode_t mode) {
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, fd, path, flag, mode);
|
||||
|
||||
if (fd == -100) {
|
||||
std::string cwd;
|
||||
{
|
||||
std::lock_guard lock(thread->tproc->mtx);
|
||||
cwd = std::string(thread->tproc->cwd);
|
||||
}
|
||||
|
||||
return sys_open(thread, (cwd + "/" + path).c_str(), flag, mode);
|
||||
}
|
||||
|
||||
Ref<File> file = thread->tproc->fileDescriptors.get(fd);
|
||||
if (file == nullptr) {
|
||||
return ErrorCode::BADF;
|
||||
}
|
||||
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_mknod(Thread *thread, ptr<char> path, sint mode,
|
||||
|
|
@ -171,6 +203,7 @@ orbis::SysResult orbis::sys_lseek(Thread *thread, sint fd, off_t offset,
|
|||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, fd, offset, whence, file->nextOff);
|
||||
thread->retval[0] = file->nextOff;
|
||||
return {};
|
||||
}
|
||||
|
|
@ -195,6 +228,7 @@ 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);
|
||||
Ref<File> file;
|
||||
auto result = thread->tproc->ops->open(thread, path, 0, 0, &file);
|
||||
if (result.isError()) {
|
||||
|
|
@ -246,7 +280,21 @@ orbis::SysResult orbis::sys_lpathconf(Thread *thread, ptr<char> path,
|
|||
}
|
||||
orbis::SysResult orbis::sys_readlink(Thread *thread, ptr<char> path,
|
||||
ptr<char> buf, size_t count) {
|
||||
return ErrorCode::INVAL;
|
||||
char _path[1024];
|
||||
ORBIS_RET_ON_ERROR(ureadString(_path, sizeof(_path), path));
|
||||
auto pathLen = std::strlen(_path);
|
||||
if (pathLen > count) {
|
||||
return ErrorCode::NAMETOOLONG;
|
||||
}
|
||||
|
||||
Ref<File> file;
|
||||
if (auto error = thread->tproc->ops->open(thread, path, 0, 0, &file); error.value()) {
|
||||
return error;
|
||||
}
|
||||
|
||||
ORBIS_RET_ON_ERROR(uwriteRaw(buf, _path, pathLen));
|
||||
thread->retval[0] = pathLen;
|
||||
return{};
|
||||
}
|
||||
orbis::SysResult orbis::sys_readlinkat(Thread *thread, sint fd, ptr<char> path,
|
||||
ptr<char> buf, size_t bufsize) {
|
||||
|
|
@ -390,6 +438,10 @@ orbis::SysResult orbis::sys_getdirentries(Thread *thread, sint fd,
|
|||
if (result.isError())
|
||||
return result;
|
||||
|
||||
for (auto &entry : std::span(entries + pos, next - pos)) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, entry.name);
|
||||
}
|
||||
|
||||
if (basep) {
|
||||
result = uwrite(basep, slong(file->nextOff));
|
||||
if (result.isError())
|
||||
|
|
|
|||
|
|
@ -1,6 +1,23 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
orbis::SysResult orbis::sys___getcwd(Thread *thread, ptr<char> buf,
|
||||
uint buflen) {
|
||||
return ErrorCode::NOSYS;
|
||||
|
||||
std::string cwd;
|
||||
|
||||
{
|
||||
std::lock_guard lock(thread->tproc->mtx);
|
||||
cwd = std::string(thread->tproc->cwd);
|
||||
}
|
||||
|
||||
if (buflen < cwd.size() + 1) {
|
||||
return ErrorCode::NOMEM;
|
||||
}
|
||||
|
||||
ORBIS_RET_ON_ERROR(uwriteRaw(buf, cwd.data(), cwd.size() + 1));
|
||||
return{};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
#include "thread/ProcessOps.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
|
||||
orbis::SysResult orbis::sys_mount(Thread *thread, ptr<char> type,
|
||||
ptr<char> path, sint flags, caddr_t data) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#include "error.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/ProcessOps.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
|
||||
orbis::SysResult orbis::sys_sbrk(Thread *, sint) {
|
||||
return ErrorCode::OPNOTSUPP;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#include "sys/syscall.hpp"
|
||||
#include "sys/sysentry.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ uint UmtxChain::notify_one(const UmtxKey &key) {
|
|||
if (it == sleep_queue.end())
|
||||
return 0;
|
||||
it->second.thr = nullptr;
|
||||
it->second.cv.notify_one(mtx);
|
||||
it->second.cv.notify_all(mtx);
|
||||
this->erase(&*it);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ orbis::ErrorCode orbis::umtx_unlock_umtx(Thread *thread, ptr<umtx> umtx,
|
|||
|
||||
orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr<void> addr, ulong id,
|
||||
std::uint64_t ut, bool is32, bool ipc) {
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, thread->tid, addr, id, ut, is32);
|
||||
ORBIS_LOG_NOTICE(__FUNCTION__, thread->tid, addr, id, ut, is32);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread, ipc, addr);
|
||||
auto node = chain.enqueue(key, thread);
|
||||
ErrorCode result = {};
|
||||
|
|
@ -74,15 +74,15 @@ orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr<void> addr, ulong id,
|
|||
if (val == id) {
|
||||
if (ut + 1 == 0) {
|
||||
while (true) {
|
||||
node->second.cv.wait(chain.mtx);
|
||||
if (node->second.thr != thread)
|
||||
result = ErrorCode{node->second.cv.wait(chain.mtx)};
|
||||
if (result != ErrorCode{} || node->second.thr != thread)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
std::uint64_t udiff = 0;
|
||||
while (true) {
|
||||
node->second.cv.wait(chain.mtx, ut - udiff);
|
||||
result = ErrorCode{node->second.cv.wait(chain.mtx, ut - udiff)};
|
||||
if (node->second.thr != thread)
|
||||
break;
|
||||
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
|
|
@ -92,16 +92,21 @@ orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr<void> addr, ulong id,
|
|||
result = ErrorCode::TIMEDOUT;
|
||||
break;
|
||||
}
|
||||
if (result != ErrorCode{}) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ORBIS_LOG_NOTICE(__FUNCTION__, "wakeup", thread->tid, addr);
|
||||
if (node->second.thr == thread)
|
||||
chain.erase(node);
|
||||
return result;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_wake(Thread *thread, ptr<void> addr, sint n_wake) {
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, thread->tid, addr, n_wake);
|
||||
ORBIS_LOG_NOTICE(__FUNCTION__, thread->tid, addr, n_wake);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread, true, addr);
|
||||
std::size_t count = chain.sleep_queue.count(key);
|
||||
if (key.pid == 0) {
|
||||
|
|
@ -174,16 +179,14 @@ static ErrorCode do_lock_normal(Thread *thread, ptr<umutex> m, uint flags,
|
|||
auto [chain, key, lock] = g_context.getUmtxChain1(thread, flags, m);
|
||||
auto node = chain.enqueue(key, thread);
|
||||
if (m->owner.compare_exchange_strong(owner, owner | kUmutexContested)) {
|
||||
node->second.cv.wait(chain.mtx, ut);
|
||||
if (node->second.thr == thread) {
|
||||
error = ErrorCode{node->second.cv.wait(chain.mtx, ut)};
|
||||
if (error == ErrorCode{} && node->second.thr == thread) {
|
||||
error = ErrorCode::TIMEDOUT;
|
||||
}
|
||||
}
|
||||
if (node->second.thr == thread)
|
||||
chain.erase(node);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
static ErrorCode do_lock_pi(Thread *thread, ptr<umutex> m, uint flags,
|
||||
std::uint64_t ut, umutex_lock_mode mode) {
|
||||
|
|
@ -219,7 +222,7 @@ static ErrorCode do_unlock_normal(Thread *thread, ptr<umutex> m, uint flags) {
|
|||
return {};
|
||||
}
|
||||
if (count)
|
||||
chain.notify_one(key);
|
||||
chain.notify_all(key);
|
||||
if (!ok)
|
||||
return ErrorCode::INVAL;
|
||||
return {};
|
||||
|
|
@ -303,12 +306,24 @@ orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr<ucond> cv,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
if ((wflags & kCvWaitClockId) != 0 && ut + 1) {
|
||||
ORBIS_LOG_FATAL("umtx_cv_wait: CLOCK_ID unimplemented", wflags);
|
||||
std::abort();
|
||||
ORBIS_LOG_WARNING("umtx_cv_wait: CLOCK_ID", wflags, cv->clockid);
|
||||
// std::abort();
|
||||
return ErrorCode::NOSYS;
|
||||
|
||||
}
|
||||
if ((wflags & kCvWaitAbsTime) != 0 && ut + 1) {
|
||||
ORBIS_LOG_FATAL("umtx_cv_wait: ABSTIME unimplemented", wflags);
|
||||
ORBIS_LOG_WARNING("umtx_cv_wait: ABSTIME unimplemented", wflags);
|
||||
auto now = std::chrono::time_point_cast<std::chrono::microseconds>(
|
||||
std::chrono::high_resolution_clock::now())
|
||||
.time_since_epoch()
|
||||
.count();
|
||||
|
||||
if (now > ut) {
|
||||
ut = 0;
|
||||
} else {
|
||||
ut = ut - now;
|
||||
}
|
||||
|
||||
std::abort();
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
|
@ -316,29 +331,39 @@ orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr<ucond> cv,
|
|||
auto [chain, key, lock] = g_context.getUmtxChain0(thread, cv->flags, cv);
|
||||
auto node = chain.enqueue(key, thread);
|
||||
|
||||
if (!cv->has_waiters.load(std::memory_order::relaxed))
|
||||
if (!cv->has_waiters.load(std::memory_order::relaxed)) {
|
||||
cv->has_waiters.store(1, std::memory_order::relaxed);
|
||||
}
|
||||
|
||||
ErrorCode result = umtx_unlock_umutex(thread, m);
|
||||
if (result == ErrorCode{}) {
|
||||
if (ut + 1 == 0) {
|
||||
while (true) {
|
||||
node->second.cv.wait(chain.mtx, ut);
|
||||
if (node->second.thr != thread)
|
||||
result = ErrorCode{node->second.cv.wait(chain.mtx, ut)};
|
||||
if (result != ErrorCode{} || node->second.thr != thread) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
std::uint64_t udiff = 0;
|
||||
while (true) {
|
||||
node->second.cv.wait(chain.mtx, ut - udiff);
|
||||
if (node->second.thr != thread)
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, ut - udiff);
|
||||
result = ErrorCode{node->second.cv.wait(chain.mtx, ut - udiff)};
|
||||
if (node->second.thr != thread) {
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, "wakeup");
|
||||
break;
|
||||
}
|
||||
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - start)
|
||||
.count();
|
||||
if (udiff >= ut) {
|
||||
result = ErrorCode::TIMEDOUT;
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, "timeout");
|
||||
break;
|
||||
}
|
||||
|
||||
if (result != ErrorCode{}) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -421,8 +446,8 @@ orbis::ErrorCode orbis::umtx_rw_rdlock(Thread *thread, ptr<urwlock> rwlock,
|
|||
|
||||
if (ut + 1 == 0) {
|
||||
while (true) {
|
||||
node->second.cv.wait(chain.mtx, ut);
|
||||
if (node->second.thr != thread) {
|
||||
result = ErrorCode{node->second.cv.wait(chain.mtx, ut)};
|
||||
if (result != ErrorCode{} || node->second.thr != thread) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -430,7 +455,7 @@ orbis::ErrorCode orbis::umtx_rw_rdlock(Thread *thread, ptr<urwlock> rwlock,
|
|||
auto start = std::chrono::steady_clock::now();
|
||||
std::uint64_t udiff = 0;
|
||||
while (true) {
|
||||
node->second.cv.wait(chain.mtx, ut - udiff);
|
||||
result = ErrorCode{node->second.cv.wait(chain.mtx, ut - udiff)};
|
||||
if (node->second.thr != thread)
|
||||
break;
|
||||
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
|
|
@ -440,6 +465,10 @@ orbis::ErrorCode orbis::umtx_rw_rdlock(Thread *thread, ptr<urwlock> rwlock,
|
|||
result = ErrorCode::TIMEDOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (result != ErrorCode{}) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -517,8 +546,8 @@ orbis::ErrorCode orbis::umtx_rw_wrlock(Thread *thread, ptr<urwlock> rwlock,
|
|||
|
||||
if (ut + 1 == 0) {
|
||||
while (true) {
|
||||
node->second.cv.wait(chain.mtx, ut);
|
||||
if (node->second.thr != thread) {
|
||||
error = ErrorCode{node->second.cv.wait(chain.mtx, ut)};
|
||||
if (error != ErrorCode{} || node->second.thr != thread) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -526,7 +555,7 @@ orbis::ErrorCode orbis::umtx_rw_wrlock(Thread *thread, ptr<urwlock> rwlock,
|
|||
auto start = std::chrono::steady_clock::now();
|
||||
std::uint64_t udiff = 0;
|
||||
while (true) {
|
||||
node->second.cv.wait(chain.mtx, ut - udiff);
|
||||
error = ErrorCode{node->second.cv.wait(chain.mtx, ut - udiff)};
|
||||
if (node->second.thr != thread)
|
||||
break;
|
||||
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
|
|
@ -536,6 +565,9 @@ orbis::ErrorCode orbis::umtx_rw_wrlock(Thread *thread, ptr<urwlock> rwlock,
|
|||
error = ErrorCode::TIMEDOUT;
|
||||
break;
|
||||
}
|
||||
if (error != ErrorCode{}) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -697,15 +729,15 @@ orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr<usem> sem,
|
|||
if (!sem->count) {
|
||||
if (ut + 1 == 0) {
|
||||
while (true) {
|
||||
node->second.cv.wait(chain.mtx, ut);
|
||||
if (node->second.thr != thread)
|
||||
result = ErrorCode{node->second.cv.wait(chain.mtx, ut)};
|
||||
if (result != ErrorCode{} || node->second.thr != thread)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
std::uint64_t udiff = 0;
|
||||
while (true) {
|
||||
node->second.cv.wait(chain.mtx, ut - udiff);
|
||||
result = ErrorCode{node->second.cv.wait(chain.mtx, ut - udiff)};
|
||||
if (node->second.thr != thread)
|
||||
break;
|
||||
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
|
|
@ -715,6 +747,9 @@ orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr<usem> sem,
|
|||
result = ErrorCode::TIMEDOUT;
|
||||
break;
|
||||
}
|
||||
if (result != ErrorCode{}) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include <unistd.h>
|
||||
|
||||
namespace orbis::utils {
|
||||
void shared_cv::impl_wait(shared_mutex &mutex, unsigned _val,
|
||||
int shared_cv::impl_wait(shared_mutex &mutex, unsigned _val,
|
||||
std::uint64_t usec_timeout) noexcept {
|
||||
// Not supposed to fail
|
||||
if (!_val) {
|
||||
|
|
@ -17,8 +17,10 @@ void shared_cv::impl_wait(shared_mutex &mutex, unsigned _val,
|
|||
timeout.tv_nsec = (usec_timeout % 1000'000) * 1000;
|
||||
timeout.tv_sec = (usec_timeout / 1000'000);
|
||||
|
||||
int result = 0;
|
||||
|
||||
while (true) {
|
||||
auto result = syscall(SYS_futex, &m_value, FUTEX_WAIT, _val,
|
||||
result = syscall(SYS_futex, &m_value, FUTEX_WAIT, _val,
|
||||
usec_timeout + 1 ? &timeout : nullptr, 0, 0);
|
||||
if (result < 0) {
|
||||
result = errno;
|
||||
|
|
@ -27,7 +29,7 @@ void shared_cv::impl_wait(shared_mutex &mutex, unsigned _val,
|
|||
// Cleanup
|
||||
const auto old = atomic_fetch_op(m_value, [&](unsigned &value) {
|
||||
// Remove waiter if no signals
|
||||
if (!(value & ~c_waiter_mask) && result != EAGAIN && result != EINTR) {
|
||||
if (!(value & ~c_waiter_mask) && result != EAGAIN) {
|
||||
value -= 1;
|
||||
}
|
||||
|
||||
|
|
@ -43,22 +45,24 @@ void shared_cv::impl_wait(shared_mutex &mutex, unsigned _val,
|
|||
|
||||
// Lock is already acquired
|
||||
if (old & c_locked_mask) {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Wait directly (waiter has been added)
|
||||
if (old & c_signal_mask) {
|
||||
mutex.impl_wait();
|
||||
return;
|
||||
return mutex.impl_wait();
|
||||
}
|
||||
|
||||
// Possibly spurious wakeup
|
||||
if (result != EAGAIN && result != EINTR) {
|
||||
if (result != EAGAIN) {
|
||||
break;
|
||||
}
|
||||
|
||||
_val = old;
|
||||
}
|
||||
|
||||
mutex.lock();
|
||||
return result;
|
||||
}
|
||||
|
||||
void shared_cv::impl_wake(shared_mutex &mutex, int _count) noexcept {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ void shared_mutex::impl_lock_shared(unsigned val) {
|
|||
if ((old % c_sig) + c_one >= c_sig)
|
||||
std::abort(); // "shared_mutex overflow"
|
||||
|
||||
impl_wait();
|
||||
while (impl_wait() != 0) {}
|
||||
lock_downgrade();
|
||||
}
|
||||
void shared_mutex::impl_unlock_shared(unsigned old) {
|
||||
|
|
@ -60,7 +60,7 @@ void shared_mutex::impl_unlock_shared(unsigned old) {
|
|||
impl_signal();
|
||||
}
|
||||
}
|
||||
void shared_mutex::impl_wait() {
|
||||
int shared_mutex::impl_wait() {
|
||||
while (true) {
|
||||
const auto [old, ok] = atomic_fetch_op(m_value, [](unsigned &value) {
|
||||
if (value >= c_sig) {
|
||||
|
|
@ -75,8 +75,15 @@ void shared_mutex::impl_wait() {
|
|||
break;
|
||||
}
|
||||
|
||||
syscall(SYS_futex, &m_value, FUTEX_WAIT, old, 0, 0, 0);
|
||||
int result = syscall(SYS_futex, &m_value, FUTEX_WAIT, old, 0, 0, 0);
|
||||
if (result < 0) {
|
||||
result = errno;
|
||||
}
|
||||
if (result == EINTR) {
|
||||
return EINTR;
|
||||
}
|
||||
}
|
||||
return{};
|
||||
}
|
||||
void shared_mutex::impl_signal() {
|
||||
m_value += c_sig;
|
||||
|
|
@ -116,7 +123,7 @@ void shared_mutex::impl_lock(unsigned val) {
|
|||
|
||||
if ((old % c_sig) + c_one >= c_sig)
|
||||
std::abort(); // "shared_mutex overflow"
|
||||
impl_wait();
|
||||
while (impl_wait() != 0) {}
|
||||
}
|
||||
void shared_mutex::impl_unlock(unsigned old) {
|
||||
if (old - c_one >= c_err)
|
||||
|
|
@ -148,7 +155,7 @@ void shared_mutex::impl_lock_upgrade() {
|
|||
return;
|
||||
}
|
||||
|
||||
impl_wait();
|
||||
while (impl_wait() != 0) {}
|
||||
}
|
||||
bool shared_mutex::lock_forced(int count) {
|
||||
if (count == 0)
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@ add_executable(rpcsx-os
|
|||
iodev/devctl.cpp
|
||||
iodev/uvd.cpp
|
||||
iodev/vce.cpp
|
||||
iodev/evlg.cpp
|
||||
iodev/srtc.cpp
|
||||
iodev/sshot.cpp
|
||||
iodev/lvdctl.cpp
|
||||
iodev/icc_power.cpp
|
||||
|
||||
main.cpp
|
||||
backtrace.cpp
|
||||
|
|
|
|||
|
|
@ -1,11 +1,35 @@
|
|||
#include "backtrace.hpp"
|
||||
#include "thread.hpp"
|
||||
#include "xbyak/xbyak.h"
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <libunwind.h>
|
||||
#include <link.h>
|
||||
#include <orbis/thread/Process.hpp>
|
||||
#include <sys/ucontext.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
extern std::uint64_t monoPimpAddress;
|
||||
|
||||
static auto callGuest = [] {
|
||||
struct SetContext : Xbyak::CodeGenerator {
|
||||
SetContext() {
|
||||
mov(rbx, rsp);
|
||||
mov(rsp, rdx);
|
||||
sub(rsp, 128);
|
||||
push(rbx);
|
||||
call(rsi);
|
||||
pop(rsp);
|
||||
ret();
|
||||
}
|
||||
} static setContextStorage;
|
||||
|
||||
return setContextStorage
|
||||
.getCode<const char * (*)(std::uint64_t, std::uint64_t, std::uint64_t)>();
|
||||
}();
|
||||
|
||||
bool allowMonoDebug = false;
|
||||
|
||||
std::size_t rx::printAddressLocation(char *dest, std::size_t destLen,
|
||||
orbis::Thread *thread,
|
||||
std::uint64_t address) {
|
||||
|
|
@ -19,10 +43,22 @@ std::size_t rx::printAddressLocation(char *dest, std::size_t destLen,
|
|||
continue;
|
||||
}
|
||||
|
||||
return std::snprintf(dest, destLen, "%s+%#" PRIx64 " (%#" PRIx64 ")",
|
||||
const char *name = "";
|
||||
if (monoPimpAddress && allowMonoDebug && (std::string_view(module->soName).contains(".dll.") || std::string_view(module->soName).contains(".exe."))) {
|
||||
allowMonoDebug = false;
|
||||
auto ctx = reinterpret_cast<ucontext_t *>(thread->context);
|
||||
rx::thread::setupSignalStack();
|
||||
auto prevFs = _readfsbase_u64();
|
||||
_writefsbase_u64(thread->fsBase);
|
||||
name = callGuest(address, monoPimpAddress, ctx->uc_mcontext.gregs[REG_RSP]);
|
||||
_writefsbase_u64(prevFs);
|
||||
allowMonoDebug = true;
|
||||
}
|
||||
|
||||
return std::snprintf(dest, destLen, "%s+%#" PRIx64 " (%#" PRIx64 ") %s",
|
||||
module->soName[0] != '\0' ? module->soName
|
||||
: module->moduleName,
|
||||
address - moduleBase, address);
|
||||
address - moduleBase, address, name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -68,7 +104,7 @@ void rx::printStackTrace(ucontext_t *context, int fileno) {
|
|||
static_cast<unsigned long>(proc_res == 0 ? off : 0));
|
||||
write(fileno, buffer, len);
|
||||
count++;
|
||||
} while (unw_step(&cursor) > 0 && count < 32);
|
||||
} while (unw_step(&cursor) > 0 && count < 64);
|
||||
funlockfile(stderr);
|
||||
}
|
||||
|
||||
|
|
@ -123,6 +159,6 @@ void rx::printStackTrace(ucontext_t *context, orbis::Thread *thread,
|
|||
|
||||
write(fileno, buffer, offset);
|
||||
count++;
|
||||
} while (unw_step(&cursor) > 0 && count < 32);
|
||||
} while (unw_step(&cursor) > 0 && count < 64);
|
||||
funlockfile(stderr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include <cstddef>
|
||||
#include <sys/ucontext.h>
|
||||
#include <cstdint>
|
||||
#include <ucontext.h>
|
||||
|
||||
namespace orbis {
|
||||
struct Thread;
|
||||
}
|
||||
|
||||
namespace rx {
|
||||
std::size_t printAddressLocation(char *dest, std::size_t destLen,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/SocketAddress.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/pipe.hpp"
|
||||
#include "orbis/stat.hpp"
|
||||
#include "orbis/thread/Process.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
|
|
@ -25,8 +24,8 @@
|
|||
#include <sys/un.h>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
struct HostFile : orbis::File {
|
||||
bool closeOnExit = true;
|
||||
|
|
@ -434,6 +433,7 @@ static orbis::ErrorCode socket_read(orbis::File *file, orbis::Uio *uio,
|
|||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
ORBIS_LOG_FATAL(__FUNCTION__, file, uio->iov->len);
|
||||
return host_fd_read(socket->hostFd, uio);
|
||||
}
|
||||
|
||||
|
|
@ -448,6 +448,7 @@ static orbis::ErrorCode socket_write(orbis::File *file, orbis::Uio *uio,
|
|||
return {};
|
||||
}
|
||||
|
||||
ORBIS_LOG_FATAL(__FUNCTION__, file, uio->iov->len);
|
||||
return host_fd_write(socket->hostFd, uio);
|
||||
}
|
||||
|
||||
|
|
@ -700,6 +701,39 @@ orbis::ErrorCode createSocket(orbis::Ref<orbis::File> *file,
|
|||
return {};
|
||||
}
|
||||
|
||||
static std::optional<std::string> findFileInDir(const std::filesystem::path &dir, const char *name) {
|
||||
for (auto entry : std::filesystem::directory_iterator(dir)) {
|
||||
auto entryName = entry.path().filename();
|
||||
if (strcasecmp(entryName.c_str(), name) == 0) {
|
||||
return entryName;
|
||||
}
|
||||
}
|
||||
return{};
|
||||
}
|
||||
|
||||
static std::optional<std::filesystem::path> toRealPath(const std::filesystem::path &inp) {
|
||||
if (inp.empty()) {
|
||||
return{};
|
||||
}
|
||||
|
||||
std::filesystem::path result;
|
||||
for (auto elem : inp) {
|
||||
if (result.empty() || std::filesystem::exists(result / elem)) {
|
||||
result /= elem;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto icaseElem = findFileInDir(result, elem.c_str());
|
||||
if (!icaseElem) {
|
||||
return{};
|
||||
}
|
||||
|
||||
result /= *icaseElem;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
orbis::ErrorCode HostFsDevice::open(orbis::Ref<orbis::File> *file,
|
||||
const char *path, std::uint32_t flags,
|
||||
std::uint32_t mode, orbis::Thread *thread) {
|
||||
|
|
@ -754,8 +788,21 @@ orbis::ErrorCode HostFsDevice::open(orbis::Ref<orbis::File> *file,
|
|||
|
||||
int hostFd = ::open(realPath.c_str(), realFlags, 0777);
|
||||
|
||||
orbis::ErrorCode error{};
|
||||
if (hostFd < 0) {
|
||||
error = convertErrno();
|
||||
|
||||
if (auto icaseRealPath = toRealPath(realPath)) {
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, path, realPath.c_str(), icaseRealPath->c_str());
|
||||
hostFd = ::open(icaseRealPath->c_str(), realFlags, 0777);
|
||||
|
||||
if (hostFd < 0) {
|
||||
ORBIS_LOG_ERROR("host_open failed", path, realPath.c_str(), icaseRealPath->c_str(), error);
|
||||
return convertErrno();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hostFd < 0) {
|
||||
auto error = convertErrno();
|
||||
ORBIS_LOG_ERROR("host_open failed", path, realPath.c_str(), error);
|
||||
return error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
struct IoDevice;
|
||||
|
||||
IoDevice *createDceCharacterDevice();
|
||||
|
|
@ -29,7 +30,7 @@ IoDevice *createBtCharacterDevice();
|
|||
IoDevice *createXptCharacterDevice();
|
||||
IoDevice *createCdCharacterDevice();
|
||||
IoDevice *createMetaDbgCharacterDevice();
|
||||
IoDevice *createHddCharacterDevice();
|
||||
IoDevice *createHddCharacterDevice(std::uint64_t size);
|
||||
IoDevice *createAoutCharacterDevice();
|
||||
IoDevice *createAVControlCharacterDevice();
|
||||
IoDevice *createHDMICharacterDevice();
|
||||
|
|
@ -42,3 +43,8 @@ IoDevice *createDevCtlCharacterDevice();
|
|||
IoDevice *createDevActCharacterDevice();
|
||||
IoDevice *createUVDCharacterDevice();
|
||||
IoDevice *createVCECharacterDevice();
|
||||
IoDevice *createEvlgCharacterDevice(int outputFd);
|
||||
IoDevice *createSrtcCharacterDevice();
|
||||
IoDevice *createScreenShotCharacterDevice();
|
||||
IoDevice *createLvdCtlCharacterDevice();
|
||||
IoDevice *createIccPowerCharacterDevice();
|
||||
|
|
|
|||
16
rpcsx-os/iodev/MBusEvent.hpp
Normal file
16
rpcsx-os/iodev/MBusEvent.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
|
||||
struct MBusEvent {
|
||||
orbis::uint32_t system;
|
||||
orbis::uint32_t eventId;
|
||||
orbis::uint64_t deviceId;
|
||||
orbis::uint32_t unk1; // device type?
|
||||
orbis::uint32_t subsystem;
|
||||
orbis::uint64_t unk2;
|
||||
orbis::uint64_t unk3;
|
||||
orbis::uint64_t unk4;
|
||||
};
|
||||
|
||||
static_assert(sizeof(MBusEvent) == 0x30);
|
||||
|
|
@ -1,22 +1,19 @@
|
|||
#include "io-device.hpp"
|
||||
#include "iodev/mbus_av.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/thread/Process.hpp"
|
||||
#include "orbis/thread/ProcessOps.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/uio.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include <bits/types/struct_iovec.h>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
struct AoutFile : orbis::File {};
|
||||
|
||||
static orbis::ErrorCode aout_ioctl(orbis::File *file, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
|
||||
ORBIS_LOG_FATAL("Unhandled aout ioctl", request);
|
||||
if (request == 0xc004500a) {
|
||||
std::this_thread::sleep_for(std::chrono::days(1));
|
||||
}
|
||||
thread->where();
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,21 @@
|
|||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
|
||||
struct CdFile : orbis::File {};
|
||||
|
||||
static orbis::ErrorCode cd_ioctl(orbis::File *file, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
void *argp, orbis::Thread *thread) {
|
||||
if (request == 0xc4a81602) {
|
||||
(*(std::uint32_t *)((char *)argp + 0x54)) = 1;
|
||||
// std::this_thread::sleep_for(std::chrono::hours(120));
|
||||
return {};
|
||||
}
|
||||
|
||||
ORBIS_LOG_FATAL("Unhandled cd ioctl", request);
|
||||
thread->where();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/error/ErrorCode.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/uio.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include <span>
|
||||
|
|
@ -50,6 +51,11 @@ static orbis::ErrorCode console_write(orbis::File *file, orbis::Uio *uio,
|
|||
|
||||
for (auto vec : std::span(uio->iov, uio->iovcnt)) {
|
||||
uio->offset += vec.len;
|
||||
if (std::string_view((char *)vec.base, vec.len).contains("begin_setControllerFocus")) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, thread->tid);
|
||||
thread->where();
|
||||
}
|
||||
|
||||
::write(dev->outputFd, vec.base, vec.len);
|
||||
::write(2, vec.base, vec.len);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/error/ErrorCode.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/thread/Process.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include "orbis/utils/SharedMutex.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/thread/Process.hpp"
|
||||
#include "vm.hpp"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
|
@ -21,18 +21,18 @@ struct VideoOutBuffer {
|
|||
};
|
||||
|
||||
struct RegisterBuffer {
|
||||
std::uint64_t canary; //arg5 data in FlipControlArgs:0: *arg5
|
||||
std::uint32_t index; //buffer index
|
||||
std::uint32_t vid; //video output port id ?
|
||||
std::uint64_t address; //left buffer ptr
|
||||
std::uint64_t address2; //right buffer ptr (Stereo)
|
||||
std::uint64_t canary; // arg5 data in FlipControlArgs:0: *arg5
|
||||
std::uint32_t index; // buffer index
|
||||
std::uint32_t vid; // video output port id ?
|
||||
std::uint64_t address; // left buffer ptr
|
||||
std::uint64_t address2; // right buffer ptr (Stereo)
|
||||
};
|
||||
|
||||
struct RegisterBufferAttributeArgs {
|
||||
std::uint64_t canary; //arg5 data in FlipControlArgs:0: *arg5
|
||||
std::uint8_t vid; //video output port id ?
|
||||
std::uint8_t submit; //0 = RegisterBuffers ; 1 = SubmitChangeBufferAttribute
|
||||
std::uint16_t unk3; //0
|
||||
std::uint64_t canary; // arg5 data in FlipControlArgs:0: *arg5
|
||||
std::uint8_t vid; // video output port id ?
|
||||
std::uint8_t submit; // 0 = RegisterBuffers ; 1 = SubmitChangeBufferAttribute
|
||||
std::uint16_t unk3; // 0
|
||||
std::uint32_t pixelFormat;
|
||||
std::uint32_t tilingMode; // 1 // tilingMode?
|
||||
std::uint32_t pitch;
|
||||
|
|
@ -45,29 +45,30 @@ struct RegisterBufferAttributeArgs {
|
|||
std::uint32_t reserved2;
|
||||
};
|
||||
|
||||
struct FlipRequestArgs { //submit_flip
|
||||
std::uint64_t canary; //arg5 data in FlipControlArgs:0: *arg5
|
||||
struct FlipRequestArgs { // submit_flip
|
||||
std::uint64_t canary; // arg5 data in FlipControlArgs:0: *arg5
|
||||
std::uint64_t displayBufferIndex;
|
||||
std::uint32_t flipMode; // flip mode?
|
||||
std::uint32_t unk1;
|
||||
std::uint64_t flipArg;
|
||||
std::uint64_t flipArg2; //not used
|
||||
std::uint64_t flipArg2; // not used
|
||||
std::uint32_t eop_nz;
|
||||
std::uint32_t unk2;
|
||||
std::uint32_t eop_val;
|
||||
std::uint32_t unk3;
|
||||
std::uint64_t unk4;
|
||||
std::uint64_t* rout; //extraout of result error
|
||||
std::uint64_t *rout; // extraout of result error
|
||||
};
|
||||
|
||||
struct FlipControlStatus {
|
||||
std::uint64_t flipArg;
|
||||
std::uint64_t flipArg2; //not used
|
||||
std::uint64_t flipArg2; // not used
|
||||
std::uint64_t count;
|
||||
std::uint64_t processTime;
|
||||
std::uint64_t tsc;
|
||||
std::uint32_t currentBuffer;
|
||||
std::uint32_t flipPendingNum0; //flipPendingNum = flipPendingNum0 + gcQueueNum + flipPendingNum1
|
||||
std::uint32_t flipPendingNum0; // flipPendingNum = flipPendingNum0 +
|
||||
// gcQueueNum + flipPendingNum1
|
||||
std::uint32_t gcQueueNum;
|
||||
std::uint32_t flipPendingNum1;
|
||||
std::uint32_t submitTsc;
|
||||
|
|
@ -76,7 +77,7 @@ struct FlipControlStatus {
|
|||
|
||||
struct FlipControlArgs {
|
||||
std::uint32_t id;
|
||||
// std::uint32_t padding;
|
||||
std::uint32_t padding;
|
||||
std::uint64_t arg2;
|
||||
void *ptr;
|
||||
std::uint64_t size; // 0x48 // size?
|
||||
|
|
@ -91,31 +92,31 @@ struct ResolutionStatus {
|
|||
std::uint32_t paneHeight;
|
||||
std::uint32_t refreshHz;
|
||||
std::uint32_t screenSizeInInch;
|
||||
std::byte padding[20];
|
||||
std::byte padding[20];
|
||||
};
|
||||
|
||||
//refreshRate = 0 REFRESH_RATE_UNKNOWN
|
||||
//refreshRate = 3; result.refreshHz = 0x426fc28f REFRESH_RATE_59_94HZ
|
||||
//refreshRate = 2, result.refreshHz = 0x42480000 REFRESH_RATE_50HZ
|
||||
//refreshRate = 1, result.refreshHz = 0x41bfd70a REFRESH_RATE_23_98HZ
|
||||
//refreshRate = 4, result.refreshHz = 0x41c00000
|
||||
//refreshRate = 5, result.refreshHz = 0x41f00000
|
||||
//refreshRate = 6, result.refreshHz = 0x41efc28f REFRESH_RATE_29_97HZ
|
||||
//refreshRate = 7, result.refreshHz = 0x41c80000
|
||||
//refreshRate = 9, result.refreshHz = 0x42700000
|
||||
//refreshRate = 10, result.refreshHz = 0x42400000
|
||||
//refreshRate = 0xb, result.refreshHz = 0x423fcccd
|
||||
//refreshRate = 0xc, result.refreshHz = 0x42c80000
|
||||
//refreshRate = 0xd, result.refreshHz = 0x42efc28f REFRESH_RATE_119_88HZ
|
||||
//refreshRate = 0xe, result.refreshHz = 0x42f00000
|
||||
//refreshRate = 0xf, result.refreshHz = 0x43480000
|
||||
//refreshRate = 0x10, result.refreshHz = 0x436fc28f
|
||||
//refreshRate = 0x11, result.refreshHz = 0x43700000
|
||||
//refreshRate = 0x14, result.refreshHz = 0x413fd70a
|
||||
//refreshRate = 0x15, result.refreshHz = 0x41400000
|
||||
//refreshRate = 0x16, result.refreshHz = 0x416fd70a
|
||||
//refreshRate = 0x17, result.refreshHz = 0x41700000
|
||||
//refreshRate = 0x23, result.refreshHz = 0x42b3d1ec REFRESH_RATE_89_91HZ
|
||||
// refreshRate = 0 REFRESH_RATE_UNKNOWN
|
||||
// refreshRate = 3; result.refreshHz = 0x426fc28f REFRESH_RATE_59_94HZ
|
||||
// refreshRate = 2, result.refreshHz = 0x42480000 REFRESH_RATE_50HZ
|
||||
// refreshRate = 1, result.refreshHz = 0x41bfd70a REFRESH_RATE_23_98HZ
|
||||
// refreshRate = 4, result.refreshHz = 0x41c00000
|
||||
// refreshRate = 5, result.refreshHz = 0x41f00000
|
||||
// refreshRate = 6, result.refreshHz = 0x41efc28f REFRESH_RATE_29_97HZ
|
||||
// refreshRate = 7, result.refreshHz = 0x41c80000
|
||||
// refreshRate = 9, result.refreshHz = 0x42700000
|
||||
// refreshRate = 10, result.refreshHz = 0x42400000
|
||||
// refreshRate = 0xb, result.refreshHz = 0x423fcccd
|
||||
// refreshRate = 0xc, result.refreshHz = 0x42c80000
|
||||
// refreshRate = 0xd, result.refreshHz = 0x42efc28f REFRESH_RATE_119_88HZ
|
||||
// refreshRate = 0xe, result.refreshHz = 0x42f00000
|
||||
// refreshRate = 0xf, result.refreshHz = 0x43480000
|
||||
// refreshRate = 0x10, result.refreshHz = 0x436fc28f
|
||||
// refreshRate = 0x11, result.refreshHz = 0x43700000
|
||||
// refreshRate = 0x14, result.refreshHz = 0x413fd70a
|
||||
// refreshRate = 0x15, result.refreshHz = 0x41400000
|
||||
// refreshRate = 0x16, result.refreshHz = 0x416fd70a
|
||||
// refreshRate = 0x17, result.refreshHz = 0x41700000
|
||||
// refreshRate = 0x23, result.refreshHz = 0x42b3d1ec REFRESH_RATE_89_91HZ
|
||||
|
||||
struct DceFile : public orbis::File {};
|
||||
|
||||
|
|
@ -182,6 +183,11 @@ static orbis::ErrorCode dce_ioctl(orbis::File *file, std::uint64_t request,
|
|||
std::memcpy(args->ptr, &flipStatus, sizeof(FlipControlStatus));
|
||||
} else if (args->id == 12) {
|
||||
*(std::uint64_t *)args->ptr = 0;
|
||||
} else if (args->id == 18) {
|
||||
// ORBIS_LOG_NOTICE("dce: get vblank status", args->size);
|
||||
if (args->size) {
|
||||
*(std::uint32_t *)args->size = 0xffff'0000;
|
||||
}
|
||||
} else if (args->id == 19) {
|
||||
// get resolution status
|
||||
auto status = (ResolutionStatus *)args->ptr;
|
||||
|
|
@ -189,21 +195,29 @@ static orbis::ErrorCode dce_ioctl(orbis::File *file, std::uint64_t request,
|
|||
status->heigth = 1080;
|
||||
status->paneWidth = 1920;
|
||||
status->paneHeight = 1080;
|
||||
status->refreshHz = 0x426fc28f;
|
||||
status->screenSizeInInch = 867;
|
||||
} else if (args->id == 9) {
|
||||
ORBIS_LOG_NOTICE("dce: FlipControl allocate", args->id, args->arg2,
|
||||
args->ptr, args->size);
|
||||
*(std::uint64_t *)args->ptr = 0; // dev offset
|
||||
*(std::uint64_t *)args->size = 0x100000; // size
|
||||
} else if (args->id == 31) {
|
||||
rx::bridge.header->bufferInUseAddress = args->size;
|
||||
// if ((std::uint64_t)args->ptr == 0xc) {
|
||||
// rx::bridge.header->bufferInUseAddress = args->size;
|
||||
// } else {
|
||||
// ORBIS_LOG_ERROR("buffer in use", args->ptr, args->size);
|
||||
// thread->where();
|
||||
// }
|
||||
// std::abort();
|
||||
return {};
|
||||
} else if (args->id == 33) { // adjust color
|
||||
std::printf("adjust color\n");
|
||||
return {};
|
||||
} else if (args->id == 0x1e) {
|
||||
// TODO
|
||||
return{};
|
||||
} else if (args->id != 0 && args->id != 1) { // used during open/close
|
||||
return {};
|
||||
} else if (args->id != 1) { // used during open/close
|
||||
ORBIS_LOG_NOTICE("dce: UNIMPLEMENTED FlipControl", args->id, args->arg2,
|
||||
args->ptr, args->size);
|
||||
|
||||
|
|
@ -242,8 +256,8 @@ static orbis::ErrorCode dce_ioctl(orbis::File *file, std::uint64_t request,
|
|||
ORBIS_LOG_ERROR("dce: RegisterBufferAttributes", args->canary, args->vid,
|
||||
args->submit, args->unk3, args->pixelFormat,
|
||||
args->tilingMode, args->pitch, args->width, args->height,
|
||||
args->unk4_zero, args->unk5_zero, args->options, args->reserved1,
|
||||
args->reserved2);
|
||||
args->unk4_zero, args->unk5_zero, args->options,
|
||||
args->reserved1, args->reserved2);
|
||||
|
||||
device->bufferAttributes.pixelFormat = args->pixelFormat;
|
||||
device->bufferAttributes.tilingMode = args->tilingMode;
|
||||
|
|
@ -257,12 +271,22 @@ static orbis::ErrorCode dce_ioctl(orbis::File *file, std::uint64_t request,
|
|||
// flip request
|
||||
auto args = reinterpret_cast<FlipRequestArgs *>(argp);
|
||||
|
||||
// ORBIS_LOG_ERROR("dce: FlipRequestArgs", args->arg1,
|
||||
// args->displayBufferIndex, args->flipMode, args->flipArg,
|
||||
// args->arg5, args->arg6, args->arg7, args->arg8);
|
||||
// ORBIS_LOG_ERROR("dce: FlipRequestArgs", args->canary,
|
||||
// args->displayBufferIndex, args->flipMode, args->unk1,
|
||||
// args->flipArg, args->flipArg2, args->eop_nz, args->unk2,
|
||||
// args->eop_val, args->unk3, args->unk4, args->rout);
|
||||
|
||||
rx::bridge.sendFlip(thread->tproc->pid, args->displayBufferIndex,
|
||||
/*args->flipMode,*/ args->flipArg);
|
||||
|
||||
// *args->rout = 0;
|
||||
|
||||
// rx::bridge.header->flipBuffer = args->displayBufferIndex;
|
||||
// rx::bridge.header->flipArg = args->flipArg;
|
||||
// rx::bridge.header->flipCount += 1;
|
||||
// *reinterpret_cast<std::uint64_t *>(rx::bridge.header->bufferInUseAddress)
|
||||
// =
|
||||
// 0;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ static const orbis::FileOps fileOps = {
|
|||
};
|
||||
|
||||
struct DevCtlDevice : IoDevice {
|
||||
orbis::kstring data;
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override {
|
||||
|
|
|
|||
60
rpcsx-os/iodev/evlg.cpp
Normal file
60
rpcsx-os/iodev/evlg.cpp
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/error/ErrorCode.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/uio.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include <span>
|
||||
#include <unistd.h>
|
||||
|
||||
struct EvlgFile : orbis::File {};
|
||||
struct EvlgDevice : IoDevice {
|
||||
int outputFd;
|
||||
|
||||
EvlgDevice(int outputFd)
|
||||
: outputFd(outputFd) {}
|
||||
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override;
|
||||
};
|
||||
|
||||
static orbis::ErrorCode evlg_ioctl(orbis::File *file, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
|
||||
ORBIS_LOG_FATAL("Unhandled evlg ioctl", request);
|
||||
return {};
|
||||
}
|
||||
|
||||
static orbis::ErrorCode evlg_write(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *thread) {
|
||||
auto dev = dynamic_cast<EvlgDevice *>(file->device.get());
|
||||
|
||||
for (auto vec : std::span(uio->iov, uio->iovcnt)) {
|
||||
uio->offset += vec.len;
|
||||
::write(dev->outputFd, vec.base, vec.len);
|
||||
::write(2, vec.base, vec.len);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static const orbis::FileOps fileOps = {
|
||||
.ioctl = evlg_ioctl,
|
||||
.write = evlg_write,
|
||||
};
|
||||
|
||||
orbis::ErrorCode EvlgDevice::open(orbis::Ref<orbis::File> *file,
|
||||
const char *path, std::uint32_t flags,
|
||||
std::uint32_t mode,
|
||||
orbis::Thread *thread) {
|
||||
auto newFile = orbis::knew<EvlgFile>();
|
||||
newFile->ops = &fileOps;
|
||||
newFile->device = this;
|
||||
|
||||
*file = newFile;
|
||||
return {};
|
||||
}
|
||||
|
||||
IoDevice *createEvlgCharacterDevice(int outputFd) {
|
||||
return orbis::knew<EvlgDevice>(outputFd);
|
||||
}
|
||||
|
|
@ -9,6 +9,24 @@ struct GbaseFile : orbis::File {};
|
|||
static orbis::ErrorCode gbase_ioctl(orbis::File *file, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
|
||||
if (request == 0xc0304510) {
|
||||
ORBIS_LOG_WARNING("gbase ioctl", request);
|
||||
struct Args {
|
||||
std::uint64_t unk0;
|
||||
std::uint64_t unk1;
|
||||
std::uint32_t currentClock;
|
||||
std::uint32_t unk2;
|
||||
std::uint64_t unk3;
|
||||
std::uint64_t unk4;
|
||||
std::uint64_t unk5;
|
||||
};
|
||||
|
||||
static_assert(sizeof(Args) == 48);
|
||||
*reinterpret_cast<Args *>(argp) = {
|
||||
.currentClock = 1,
|
||||
};
|
||||
return{};
|
||||
}
|
||||
ORBIS_LOG_FATAL("Unhandled gbase ioctl", request);
|
||||
thread->where();
|
||||
return {};
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@ static orbis::ErrorCode gc_ioctl(orbis::File *file, std::uint64_t request,
|
|||
auto args = reinterpret_cast<Args *>(argp);
|
||||
|
||||
// flockfile(stderr);
|
||||
// ORBIS_LOG_ERROR("gc ioctl 0xc0108102", args->arg0, args->count, args->cmds);
|
||||
// if (thread->tproc->pid != amdgpu::bridge::expGpuPid) {
|
||||
// ORBIS_LOG_ERROR("gc ioctl submit", args->arg0, args->count, args->cmds);
|
||||
// }
|
||||
|
||||
for (unsigned i = 0; i < args->count; ++i) {
|
||||
auto cmd = args->cmds + (i * 2);
|
||||
|
|
@ -73,6 +75,11 @@ static orbis::ErrorCode gc_ioctl(orbis::File *file, std::uint64_t request,
|
|||
// std::fprintf(stderr, " unkPreservedVal = %lx\n", unkPreservedVal);
|
||||
// std::fprintf(stderr, " size = %lu\n", size);
|
||||
|
||||
// for (std::size_t i = 0; i < std::min<std::size_t>(size, 64); i += 4) {
|
||||
// std::fprintf(stderr, "%08x ", *(unsigned *)(address + i));
|
||||
// }
|
||||
// std::fprintf(stderr, "\n");
|
||||
|
||||
rx::bridge.sendCommandBuffer(thread->tproc->pid, cmdId, address, size);
|
||||
}
|
||||
// funlockfile(stderr);
|
||||
|
|
@ -133,9 +140,8 @@ static orbis::ErrorCode gc_ioctl(orbis::File *file, std::uint64_t request,
|
|||
}
|
||||
|
||||
case 0xc0048116: { // submit done?
|
||||
ORBIS_LOG_ERROR("gc ioctl 0xc0048116", *(std::uint32_t *)argp);
|
||||
*(std::uint32_t *)argp = 1;
|
||||
thread->where();
|
||||
// ORBIS_LOG_ERROR("gc ioctl 0xc0048116", *(std::uint32_t *)argp);
|
||||
// thread->where();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,20 +9,39 @@
|
|||
|
||||
struct HddFile : orbis::File {};
|
||||
|
||||
struct HddDevice : IoDevice {
|
||||
std::uint64_t size;
|
||||
HddDevice(std::uint64_t size) : size(size) {}
|
||||
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *fs, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override;
|
||||
};
|
||||
|
||||
static_assert(0x120 - 24 == 0x108);
|
||||
static orbis::ErrorCode hdd_ioctl(orbis::File *fs, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
|
||||
auto device = fs->device.cast<HddDevice>();
|
||||
if (request == 0x40046480) { // DIOCGSECTORSIZE
|
||||
return orbis::uwrite(orbis::ptr<orbis::uint>(argp), 0x1000u);
|
||||
}
|
||||
|
||||
if (request == 0x40086481) { // hdd size
|
||||
if (device->size == 0) {
|
||||
ORBIS_LOG_FATAL("Unknown hdd size request", request);
|
||||
thread->where();
|
||||
}
|
||||
return orbis::uwrite(orbis::ptr<orbis::ulong>(argp), device->size);
|
||||
}
|
||||
|
||||
ORBIS_LOG_FATAL("Unhandled hdd ioctl", request);
|
||||
thread->where();
|
||||
return {};
|
||||
}
|
||||
|
||||
static orbis::ErrorCode hdd_read(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *thread) {
|
||||
orbis::Thread *thread) {
|
||||
auto dev = file->device.get();
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, uio->offset);
|
||||
|
|
@ -41,10 +60,12 @@ static orbis::ErrorCode hdd_read(orbis::File *file, orbis::Uio *uio,
|
|||
return {};
|
||||
}
|
||||
|
||||
|
||||
static orbis::ErrorCode hdd_stat(orbis::File *fs, orbis::Stat *sb,
|
||||
orbis::Thread *thread) {
|
||||
// TODO
|
||||
ORBIS_LOG_ERROR(__FUNCTION__);
|
||||
*sb = {};
|
||||
sb->mode = 0x2000;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
@ -54,17 +75,17 @@ static const orbis::FileOps fsOps = {
|
|||
.stat = hdd_stat,
|
||||
};
|
||||
|
||||
struct HddDevice : IoDevice {
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *fs, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override {
|
||||
auto newFile = orbis::knew<HddFile>();
|
||||
newFile->ops = &fsOps;
|
||||
newFile->device = this;
|
||||
orbis::ErrorCode HddDevice::open(orbis::Ref<orbis::File> *fs, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) {
|
||||
auto newFile = orbis::knew<HddFile>();
|
||||
newFile->ops = &fsOps;
|
||||
newFile->device = this;
|
||||
|
||||
*fs = newFile;
|
||||
return {};
|
||||
}
|
||||
};
|
||||
*fs = newFile;
|
||||
return {};
|
||||
}
|
||||
|
||||
IoDevice *createHddCharacterDevice() { return orbis::knew<HddDevice>(); }
|
||||
IoDevice *createHddCharacterDevice(std::uint64_t size) {
|
||||
return orbis::knew<HddDevice>(size);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,38 +14,39 @@ struct HidDevice : public IoDevice {
|
|||
};
|
||||
struct HidFile : public orbis::File {};
|
||||
|
||||
struct PadState {
|
||||
std::uint64_t timestamp;
|
||||
std::uint32_t unk;
|
||||
std::uint32_t buttons;
|
||||
std::uint8_t leftStickX;
|
||||
std::uint8_t leftStickY;
|
||||
std::uint8_t rightStickX;
|
||||
std::uint8_t rightStickY;
|
||||
std::uint8_t l2;
|
||||
std::uint8_t r2;
|
||||
};
|
||||
|
||||
static orbis::ErrorCode hid_ioctl(orbis::File *file, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
ORBIS_LOG_FATAL("hid ioctl", request);
|
||||
switch (request) {
|
||||
case 0x800c4802:
|
||||
ORBIS_LOG_FATAL("hid ioctl", request);
|
||||
thread->retval[0] = 1; // hid id
|
||||
return {};
|
||||
|
||||
case 0x8030482e: {
|
||||
ORBIS_LOG_FATAL("hid ioctl", request);
|
||||
// read state
|
||||
struct ReadStateArgs {
|
||||
std::uint32_t hidId;
|
||||
std::uint32_t unk0;
|
||||
void *state;
|
||||
amdgpu::bridge::PadState *state;
|
||||
std::uint32_t unk2;
|
||||
std::uint32_t *connected;
|
||||
std::uint32_t *unk4;
|
||||
std::uint64_t unk5;
|
||||
};
|
||||
|
||||
// struct PadState {
|
||||
// std::uint64_t timestamp;
|
||||
// std::uint32_t unk;
|
||||
// std::uint32_t buttons;
|
||||
// std::uint8_t leftStickX;
|
||||
// std::uint8_t leftStickY;
|
||||
// std::uint8_t rightStickX;
|
||||
// std::uint8_t rightStickY;
|
||||
// std::uint8_t l2;
|
||||
// std::uint8_t r2;
|
||||
// };
|
||||
|
||||
// enum {
|
||||
// kPadBtnL3 = 1 << 1,
|
||||
// kPadBtnR3 = 1 << 2,
|
||||
|
|
@ -70,8 +71,7 @@ static orbis::ErrorCode hid_ioctl(orbis::File *file, std::uint64_t request,
|
|||
// ORBIS_LOG_ERROR("hid read state", args.hidId, args.unk0, args.state,
|
||||
// args.unk2, args.connected, args.unk4, args.unk5);
|
||||
|
||||
auto state = (amdgpu::bridge::PadState *)args.state;
|
||||
*state = rx::bridge.header->kbPadState;
|
||||
*args.state = rx::bridge.header->kbPadState;
|
||||
*args.connected = 1;
|
||||
*args.unk4 = 1; // is wireless?
|
||||
thread->retval[0] = 1;
|
||||
|
|
@ -84,8 +84,25 @@ static orbis::ErrorCode hid_ioctl(orbis::File *file, std::uint64_t request,
|
|||
return {};
|
||||
}
|
||||
|
||||
case 0x80204829: {
|
||||
struct MiniReadStateArgs {
|
||||
orbis::uint hidId;
|
||||
orbis::uint unk0;
|
||||
orbis::ptr<amdgpu::bridge::PadState> state;
|
||||
orbis::uint count;
|
||||
orbis::uint padding;
|
||||
orbis::ptr<orbis::uint> unk5;
|
||||
};
|
||||
|
||||
auto args = *reinterpret_cast<MiniReadStateArgs *>(argp);
|
||||
*args.state = rx::bridge.header->kbPadState;
|
||||
thread->retval[0] = 1;
|
||||
return{};
|
||||
}
|
||||
|
||||
default:
|
||||
ORBIS_LOG_FATAL("Unhandled hid ioctl", request);
|
||||
thread->where();
|
||||
}
|
||||
|
||||
return {};
|
||||
|
|
|
|||
68
rpcsx-os/iodev/icc_power.cpp
Normal file
68
rpcsx-os/iodev/icc_power.cpp
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
|
||||
struct IccPowerDevice : IoDevice {
|
||||
std::uint8_t bootphase = 0;
|
||||
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override;
|
||||
};
|
||||
|
||||
static orbis::ErrorCode icc_power_ioctl(orbis::File *file,
|
||||
std::uint64_t request, void *argp,
|
||||
orbis::Thread *thread) {
|
||||
|
||||
// 0xc0019901 - bootphase set
|
||||
// 0xc0099902 - unk
|
||||
// 0x40019907 - bootphase get
|
||||
|
||||
auto iccPower = file->device.staticCast<IccPowerDevice>();
|
||||
|
||||
switch (request) {
|
||||
case 0xc0019901: {
|
||||
iccPower->bootphase = *reinterpret_cast<std::uint8_t *>(argp);
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, request, iccPower->bootphase);
|
||||
return{};
|
||||
}
|
||||
|
||||
case 0xc0099902: {
|
||||
auto &unk = *reinterpret_cast<std::uint32_t *>(argp);
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, request, unk);
|
||||
unk = 1;
|
||||
return{};
|
||||
}
|
||||
|
||||
case 0x40019907:
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, request);
|
||||
*reinterpret_cast<std::uint8_t *>(argp) = iccPower->bootphase;
|
||||
return{};
|
||||
}
|
||||
|
||||
ORBIS_LOG_FATAL("Unhandled icc_power ioctl", request);
|
||||
thread->where();
|
||||
return {};
|
||||
}
|
||||
|
||||
static const orbis::FileOps fileOps = {
|
||||
.ioctl = icc_power_ioctl,
|
||||
};
|
||||
|
||||
orbis::ErrorCode IccPowerDevice::open(orbis::Ref<orbis::File> *file,
|
||||
const char *path, std::uint32_t flags,
|
||||
std::uint32_t mode,
|
||||
orbis::Thread *thread) {
|
||||
auto newFile = orbis::knew<orbis::File>();
|
||||
newFile->ops = &fileOps;
|
||||
newFile->device = this;
|
||||
|
||||
*file = newFile;
|
||||
return {};
|
||||
}
|
||||
|
||||
IoDevice *createIccPowerCharacterDevice() {
|
||||
return orbis::knew<IccPowerDevice>();
|
||||
}
|
||||
33
rpcsx-os/iodev/lvdctl.cpp
Normal file
33
rpcsx-os/iodev/lvdctl.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
|
||||
struct LvdCtlFile : orbis::File {};
|
||||
|
||||
static orbis::ErrorCode lvdctl_ioctl(orbis::File *file, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
ORBIS_LOG_FATAL("Unhandled lvdctl ioctl", request);
|
||||
thread->where();
|
||||
return {};
|
||||
}
|
||||
|
||||
static const orbis::FileOps fileOps = {
|
||||
.ioctl = lvdctl_ioctl,
|
||||
};
|
||||
|
||||
struct LvdCtlDevice : IoDevice {
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override {
|
||||
auto newFile = orbis::knew<LvdCtlFile>();
|
||||
newFile->ops = &fileOps;
|
||||
newFile->device = this;
|
||||
|
||||
*file = newFile;
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
IoDevice *createLvdCtlCharacterDevice() { return orbis::knew<LvdCtlDevice>(); }
|
||||
|
|
@ -1,14 +1,11 @@
|
|||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/uio.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include "mbus.hpp"
|
||||
|
||||
struct MBusFile : orbis::File {};
|
||||
struct MBusDevice : IoDevice {
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override;
|
||||
};
|
||||
|
||||
static orbis::ErrorCode mbus_ioctl(orbis::File *file, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
|
|
@ -17,16 +14,52 @@ static orbis::ErrorCode mbus_ioctl(orbis::File *file, std::uint64_t request,
|
|||
return {};
|
||||
}
|
||||
|
||||
static orbis::ErrorCode mbus_read(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *thread) {
|
||||
auto mbus = file->device.staticCast<MBusDevice>();
|
||||
ORBIS_LOG_ERROR(__FUNCTION__);
|
||||
|
||||
MBusEvent event;
|
||||
{
|
||||
std::lock_guard lock(mbus->mtx);
|
||||
|
||||
// while (mbus->events.empty()) {
|
||||
// file->mtx.unlock();
|
||||
// mbus->cv.wait(mbusAv->mtx);
|
||||
// file->mtx.lock();
|
||||
// }
|
||||
|
||||
if (mbus->events.empty()) {
|
||||
return orbis::ErrorCode::BUSY;
|
||||
}
|
||||
|
||||
event = mbus->events.front();
|
||||
mbus->events.pop_front();
|
||||
}
|
||||
|
||||
return uio->write(event);
|
||||
}
|
||||
|
||||
static const orbis::FileOps fileOps = {
|
||||
.ioctl = mbus_ioctl,
|
||||
.read = mbus_read,
|
||||
};
|
||||
|
||||
void MBusDevice::emitEvent(const MBusEvent &event) {
|
||||
std::lock_guard lock(mtx);
|
||||
events.push_back(event);
|
||||
cv.notify_one(mtx);
|
||||
eventEmitter->emit(orbis::kEvFiltRead);
|
||||
}
|
||||
|
||||
orbis::ErrorCode MBusDevice::open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) {
|
||||
ORBIS_LOG_FATAL("mbus device open");
|
||||
auto newFile = orbis::knew<MBusFile>();
|
||||
newFile->ops = &fileOps;
|
||||
newFile->device = this;
|
||||
newFile->event = eventEmitter;
|
||||
|
||||
*file = newFile;
|
||||
return {};
|
||||
|
|
|
|||
21
rpcsx-os/iodev/mbus.hpp
Normal file
21
rpcsx-os/iodev/mbus.hpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include "io-device.hpp"
|
||||
#include "iodev/MBusEvent.hpp"
|
||||
#include "orbis/utils/SharedCV.hpp"
|
||||
#include "orbis/utils/SharedMutex.hpp"
|
||||
|
||||
|
||||
struct MBusDevice : IoDevice {
|
||||
orbis::shared_mutex mtx;
|
||||
orbis::shared_cv cv;
|
||||
orbis::kdeque<MBusEvent> events;
|
||||
orbis::Ref<orbis::EventEmitter> eventEmitter =
|
||||
orbis::knew<orbis::EventEmitter>();
|
||||
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override;
|
||||
|
||||
void emitEvent(const MBusEvent &event);
|
||||
};
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/note.hpp"
|
||||
#include "orbis/uio.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include "orbis/utils/SharedCV.hpp"
|
||||
|
|
@ -12,7 +13,6 @@ struct MBusAVFile : orbis::File {};
|
|||
|
||||
static orbis::ErrorCode mbus_av_ioctl(orbis::File *file, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
|
||||
ORBIS_LOG_FATAL("Unhandled mbus_av ioctl", request);
|
||||
return {};
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ static orbis::ErrorCode mbus_av_read(orbis::File *file, orbis::Uio *uio,
|
|||
orbis::Thread *thread) {
|
||||
auto mbusAv = file->device.staticCast<MBusAVDevice>();
|
||||
|
||||
MBusAVEvent event;
|
||||
MBusEvent event;
|
||||
{
|
||||
std::lock_guard lock(mbusAv->mtx);
|
||||
|
||||
|
|
@ -53,15 +53,18 @@ orbis::ErrorCode MBusAVDevice::open(orbis::Ref<orbis::File> *file,
|
|||
auto newFile = orbis::knew<MBusAVFile>();
|
||||
newFile->ops = &fileOps;
|
||||
newFile->device = this;
|
||||
newFile->event = eventEmitter;
|
||||
|
||||
*file = newFile;
|
||||
return {};
|
||||
}
|
||||
|
||||
void MBusAVDevice::emitEvent(const MBusAVEvent &event) {
|
||||
void MBusAVDevice::emitEvent(const MBusEvent &event) {
|
||||
std::lock_guard lock(mtx);
|
||||
events.push_back(event);
|
||||
cv.notify_one(mtx);
|
||||
|
||||
eventEmitter->emit(orbis::kEvFiltRead);
|
||||
}
|
||||
|
||||
IoDevice *createMBusAVCharacterDevice() { return orbis::knew<MBusAVDevice>(); }
|
||||
|
|
|
|||
|
|
@ -1,26 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include "io-device.hpp"
|
||||
#include "iodev/MBusEvent.hpp"
|
||||
#include "orbis/utils/SharedCV.hpp"
|
||||
#include "orbis/utils/SharedMutex.hpp"
|
||||
|
||||
struct MBusAVEvent {
|
||||
orbis::uint32_t unk0;
|
||||
orbis::uint32_t unk1;
|
||||
orbis::uint64_t unk2;
|
||||
char unk3[0x20];
|
||||
};
|
||||
|
||||
static_assert(sizeof(MBusAVEvent) == 0x30);
|
||||
|
||||
struct MBusAVDevice : IoDevice {
|
||||
orbis::shared_mutex mtx;
|
||||
orbis::shared_cv cv;
|
||||
orbis::kdeque<MBusAVEvent> events;
|
||||
orbis::kdeque<MBusEvent> events;
|
||||
orbis::Ref<orbis::EventEmitter> eventEmitter =
|
||||
orbis::knew<orbis::EventEmitter>();
|
||||
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override;
|
||||
|
||||
void emitEvent(const MBusAVEvent &event);
|
||||
void emitEvent(const MBusEvent &event);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/uio.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include "orbis/utils/SharedMutex.hpp"
|
||||
|
|
@ -22,19 +23,24 @@ struct NotificationDevice : IoDevice {
|
|||
orbis::Thread *thread) override;
|
||||
};
|
||||
|
||||
static orbis::ErrorCode notification_ioctl(orbis::File *file, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
static orbis::ErrorCode notification_ioctl(orbis::File *file,
|
||||
std::uint64_t request, void *argp,
|
||||
orbis::Thread *thread) {
|
||||
|
||||
ORBIS_LOG_FATAL("Unhandled notification ioctl", request);
|
||||
return {};
|
||||
}
|
||||
|
||||
static orbis::ErrorCode notification_read(orbis::File *file, orbis::Uio *uio, orbis::Thread *thread) {
|
||||
static orbis::ErrorCode notification_read(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *thread) {
|
||||
auto dev = dynamic_cast<NotificationDevice *>(file->device.get());
|
||||
ORBIS_LOG_FATAL(__FUNCTION__, dev->index);
|
||||
|
||||
while (true) {
|
||||
if (dev->data.empty()) {
|
||||
if (file->noBlock()) {
|
||||
return orbis::ErrorCode::WOULDBLOCK;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +59,8 @@ static orbis::ErrorCode notification_read(orbis::File *file, orbis::Uio *uio, or
|
|||
break;
|
||||
}
|
||||
|
||||
std::memmove(dev->data.data(), dev->data.data() + size, dev->data.size() - size);
|
||||
std::memmove(dev->data.data(), dev->data.data() + size,
|
||||
dev->data.size() - size);
|
||||
dev->data.resize(dev->data.size() - size);
|
||||
}
|
||||
|
||||
|
|
@ -62,9 +69,9 @@ static orbis::ErrorCode notification_read(orbis::File *file, orbis::Uio *uio, or
|
|||
return {};
|
||||
}
|
||||
|
||||
static orbis::ErrorCode notification_write(orbis::File *file, orbis::Uio *uio, orbis::Thread *thread) {
|
||||
static orbis::ErrorCode notification_write(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *thread) {
|
||||
auto dev = dynamic_cast<NotificationDevice *>(file->device.get());
|
||||
ORBIS_LOG_FATAL(__FUNCTION__, dev->index);
|
||||
|
||||
std::lock_guard lock(dev->mutex);
|
||||
|
||||
|
|
@ -83,15 +90,20 @@ static const orbis::FileOps fileOps = {
|
|||
.write = notification_write,
|
||||
};
|
||||
|
||||
orbis::ErrorCode NotificationDevice::open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) {
|
||||
orbis::ErrorCode NotificationDevice::open(orbis::Ref<orbis::File> *file,
|
||||
const char *path, std::uint32_t flags,
|
||||
std::uint32_t mode,
|
||||
orbis::Thread *thread) {
|
||||
auto newFile = orbis::knew<NotificationFile>();
|
||||
newFile->ops = &fileOps;
|
||||
newFile->device = this;
|
||||
newFile->flags = flags;
|
||||
newFile->mode = mode;
|
||||
|
||||
*file = newFile;
|
||||
return {};
|
||||
}
|
||||
|
||||
IoDevice *createNotificationCharacterDevice(int index) { return orbis::knew<NotificationDevice>(index); }
|
||||
IoDevice *createNotificationCharacterDevice(int index) {
|
||||
return orbis::knew<NotificationDevice>(index);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
|
||||
struct ScaninFile : orbis::File {};
|
||||
|
|
@ -9,6 +10,7 @@ static orbis::ErrorCode scanin_ioctl(orbis::File *file, std::uint64_t request,
|
|||
void *argp, orbis::Thread *thread) {
|
||||
|
||||
ORBIS_LOG_FATAL("Unhandled scanin ioctl", request);
|
||||
thread->where();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
|||
33
rpcsx-os/iodev/srtc.cpp
Normal file
33
rpcsx-os/iodev/srtc.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
|
||||
struct SrtcFile : orbis::File {};
|
||||
|
||||
static orbis::ErrorCode srtc_ioctl(orbis::File *file, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
ORBIS_LOG_FATAL("Unhandled srtc ioctl", request);
|
||||
thread->where();
|
||||
return {};
|
||||
}
|
||||
|
||||
static const orbis::FileOps fileOps = {
|
||||
.ioctl = srtc_ioctl,
|
||||
};
|
||||
|
||||
struct SrtcDevice : IoDevice {
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override {
|
||||
auto newFile = orbis::knew<SrtcFile>();
|
||||
newFile->ops = &fileOps;
|
||||
newFile->device = this;
|
||||
|
||||
*file = newFile;
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
IoDevice *createSrtcCharacterDevice() { return orbis::knew<SrtcDevice>(); }
|
||||
34
rpcsx-os/iodev/sshot.cpp
Normal file
34
rpcsx-os/iodev/sshot.cpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
|
||||
struct ScreenShotFile : orbis::File {};
|
||||
|
||||
static orbis::ErrorCode sshot_ioctl(orbis::File *file, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
|
||||
ORBIS_LOG_FATAL("Unhandled sshot ioctl", request);
|
||||
thread->where();
|
||||
return {};
|
||||
}
|
||||
|
||||
static const orbis::FileOps fileOps = {
|
||||
.ioctl = sshot_ioctl,
|
||||
};
|
||||
|
||||
struct ScreenShotDevice : IoDevice {
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override {
|
||||
auto newFile = orbis::knew<ScreenShotFile>();
|
||||
newFile->ops = &fileOps;
|
||||
newFile->device = this;
|
||||
|
||||
*file = newFile;
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
IoDevice *createScreenShotCharacterDevice() { return orbis::knew<ScreenShotDevice>(); }
|
||||
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
using orbis::utils::Ref;
|
||||
|
||||
std::uint64_t monoPimpAddress;
|
||||
|
||||
static std::vector<std::byte> unself(const std::byte *image, std::size_t size) {
|
||||
struct [[gnu::packed]] Header {
|
||||
std::uint32_t magic;
|
||||
|
|
@ -500,13 +502,15 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
result->tlsAlign = phdrs[tlsPhdrIndex].p_align;
|
||||
result->tlsSize = phdrs[tlsPhdrIndex].p_memsz;
|
||||
result->tlsInitSize = phdrs[tlsPhdrIndex].p_filesz;
|
||||
result->tlsInit = phdrs[tlsPhdrIndex].p_vaddr
|
||||
? imageBase - baseAddress + phdrs[tlsPhdrIndex].p_vaddr
|
||||
: nullptr;
|
||||
result->tlsInit =
|
||||
phdrs[tlsPhdrIndex].p_vaddr
|
||||
? imageBase - baseAddress + phdrs[tlsPhdrIndex].p_vaddr
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
if (gnuEhFramePhdrIndex >= 0 && phdrs[gnuEhFramePhdrIndex].p_vaddr > 0) {
|
||||
result->ehFrameHdr = imageBase - baseAddress + phdrs[gnuEhFramePhdrIndex].p_vaddr;
|
||||
result->ehFrameHdr =
|
||||
imageBase - baseAddress + phdrs[gnuEhFramePhdrIndex].p_vaddr;
|
||||
result->ehFrameHdrSize = phdrs[gnuEhFramePhdrIndex].p_memsz;
|
||||
|
||||
struct GnuExceptionInfo {
|
||||
|
|
@ -725,10 +729,10 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
|
||||
switch (dyn.d_tag) {
|
||||
case kElfDynamicTypeScePltGot:
|
||||
result->pltGot =
|
||||
dyn.d_un.d_ptr
|
||||
? reinterpret_cast<std::uint64_t *>(imageBase - baseAddress + dyn.d_un.d_ptr)
|
||||
: nullptr;
|
||||
result->pltGot = dyn.d_un.d_ptr
|
||||
? reinterpret_cast<std::uint64_t *>(
|
||||
imageBase - baseAddress + dyn.d_un.d_ptr)
|
||||
: nullptr;
|
||||
break;
|
||||
|
||||
case kElfDynamicTypeSceJmpRel:
|
||||
|
|
@ -781,6 +785,10 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
.type = static_cast<orbis::SymbolType>(type),
|
||||
};
|
||||
|
||||
if (symbol.address) {
|
||||
symbol.address -= baseAddress;
|
||||
}
|
||||
|
||||
if (sceStrtab != nullptr && sym.st_name != 0) {
|
||||
auto fullName = std::string_view(sceStrtab + sym.st_name);
|
||||
if (auto hashPos = fullName.find('#');
|
||||
|
|
@ -807,6 +815,10 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
symbol.libraryIndex = idToLibraryIndex.at(libaryNid);
|
||||
symbol.moduleIndex = idToModuleIndex.at(moduleNid);
|
||||
symbol.id = *decodeNid(name);
|
||||
if (name == "5JrIq4tzVIo") {
|
||||
monoPimpAddress = symbol.address + (std::uint64_t)imageBase;
|
||||
std::fprintf(stderr, "mono_pimp address = %lx\n", monoPimpAddress);
|
||||
}
|
||||
} else if (auto nid = decodeNid(fullName)) {
|
||||
symbol.id = *nid;
|
||||
symbol.libraryIndex = -1;
|
||||
|
|
@ -869,8 +881,8 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
}
|
||||
}
|
||||
|
||||
result->base = imageBase;
|
||||
result->size = imageSize;
|
||||
result->base = imageBase - baseAddress;
|
||||
result->size = imageSize + baseAddress;
|
||||
// std::printf("Needed modules: [");
|
||||
// for (bool isFirst = true; auto &module : result->neededModules) {
|
||||
// if (isFirst) {
|
||||
|
|
@ -898,9 +910,7 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
|
||||
std::printf("Loaded module '%s' (%lx) from object '%s', address: %p - %p\n",
|
||||
result->moduleName, (unsigned long)result->attributes,
|
||||
result->soName, result->base,
|
||||
(char *)result->base + result->size);
|
||||
|
||||
result->soName, imageBase, (char *)imageBase + result->size);
|
||||
for (auto mod : result->neededModules) {
|
||||
std::printf(" needed module '%s' (%lx)\n", mod.name.c_str(),
|
||||
(unsigned long)mod.attr);
|
||||
|
|
@ -969,8 +979,10 @@ Ref<orbis::Module> rx::linker::loadModuleFile(std::string_view path,
|
|||
image[2] != std::byte{'L'} || image[3] != std::byte{'F'}) {
|
||||
image = unself(image.data(), image.size());
|
||||
|
||||
std::ofstream(std::filesystem::path(path).filename().replace_extension("elf"), std::ios::binary)
|
||||
.write((const char *)image.data(), image.size());
|
||||
// std::ofstream(
|
||||
// std::filesystem::path(path).filename().replace_extension("elf"),
|
||||
// std::ios::binary)
|
||||
// .write((const char *)image.data(), image.size());
|
||||
}
|
||||
|
||||
return loadModule(image, thread->tproc);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "bridge.hpp"
|
||||
#include "io-device.hpp"
|
||||
#include "io-devices.hpp"
|
||||
#include "iodev/mbus.hpp"
|
||||
#include "iodev/mbus_av.hpp"
|
||||
#include "linker.hpp"
|
||||
#include "ops.hpp"
|
||||
|
|
@ -41,6 +42,72 @@
|
|||
|
||||
static int g_gpuPid;
|
||||
|
||||
void runBridge() {
|
||||
std::thread{[] {
|
||||
pthread_setname_np(pthread_self(), "Bridge");
|
||||
auto bridge = rx::bridge.header;
|
||||
|
||||
std::vector<std::uint64_t> fetchedCommands;
|
||||
fetchedCommands.reserve(std::size(bridge->cacheCommands));
|
||||
|
||||
while (true) {
|
||||
for (auto &command : bridge->cacheCommands) {
|
||||
std::uint64_t value = command.load(std::memory_order::relaxed);
|
||||
|
||||
if (value != 0) {
|
||||
fetchedCommands.push_back(value);
|
||||
command.store(0, std::memory_order::relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
if (fetchedCommands.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto command : fetchedCommands) {
|
||||
auto page = static_cast<std::uint32_t>(command);
|
||||
auto count = static_cast<std::uint32_t>(command >> 32) + 1;
|
||||
|
||||
auto pageFlags =
|
||||
bridge->cachePages[page].load(std::memory_order::relaxed);
|
||||
|
||||
auto address =
|
||||
static_cast<std::uint64_t>(page) * amdgpu::bridge::kHostPageSize;
|
||||
auto origVmProt = rx::vm::getPageProtection(address);
|
||||
int prot = 0;
|
||||
|
||||
if (origVmProt & rx::vm::kMapProtCpuRead) {
|
||||
prot |= PROT_READ;
|
||||
}
|
||||
if (origVmProt & rx::vm::kMapProtCpuWrite) {
|
||||
prot |= PROT_WRITE;
|
||||
}
|
||||
if (origVmProt & rx::vm::kMapProtCpuExec) {
|
||||
prot |= PROT_EXEC;
|
||||
}
|
||||
|
||||
if (pageFlags & amdgpu::bridge::kPageReadWriteLock) {
|
||||
prot &= ~(PROT_READ | PROT_WRITE);
|
||||
} else if (pageFlags & amdgpu::bridge::kPageWriteWatch) {
|
||||
prot &= ~PROT_WRITE;
|
||||
}
|
||||
|
||||
// std::fprintf(stderr, "protection %lx-%lx\n", address,
|
||||
// address + amdgpu::bridge::kHostPageSize * count);
|
||||
if (::mprotect(reinterpret_cast<void *>(address),
|
||||
amdgpu::bridge::kHostPageSize * count, prot)) {
|
||||
perror("protection failed");
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
fetchedCommands.clear();
|
||||
}
|
||||
}}.detach();
|
||||
}
|
||||
|
||||
extern bool allowMonoDebug;
|
||||
|
||||
__attribute__((no_stack_protector)) static void
|
||||
handle_signal(int sig, siginfo_t *info, void *ucontext) {
|
||||
if (auto hostFs = _readgsbase_u64()) {
|
||||
|
|
@ -121,7 +188,8 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) {
|
|||
}
|
||||
|
||||
if (orbis::g_currentThread != nullptr) {
|
||||
orbis::g_currentThread->tproc->event.emit(orbis::kEvFiltProc, orbis::kNoteExit, sig);
|
||||
orbis::g_currentThread->tproc->event.emit(orbis::kEvFiltProc,
|
||||
orbis::kNoteExit, sig);
|
||||
}
|
||||
|
||||
if (g_gpuPid > 0) {
|
||||
|
|
@ -129,6 +197,7 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) {
|
|||
// ::kill(g_gpuPid, SIGINT);
|
||||
}
|
||||
|
||||
allowMonoDebug = true;
|
||||
if (sig != SIGINT) {
|
||||
char buf[128] = "";
|
||||
int len = snprintf(buf, sizeof(buf), " [%s] %u: Signal address=%p\n",
|
||||
|
|
@ -172,34 +241,11 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) {
|
|||
}
|
||||
|
||||
void setupSigHandlers() {
|
||||
stack_t oss{};
|
||||
|
||||
// if (sigaltstack(nullptr, &oss) < 0 || oss.ss_size == 0) {
|
||||
auto sigStackSize = std::max<std::size_t>(
|
||||
SIGSTKSZ, utils::alignUp(64 * 1024 * 1024, sysconf(_SC_PAGE_SIZE)));
|
||||
|
||||
stack_t ss{};
|
||||
ss.ss_sp = malloc(sigStackSize);
|
||||
if (ss.ss_sp == NULL) {
|
||||
perror("malloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ss.ss_size = sigStackSize;
|
||||
ss.ss_flags = 1 << 31;
|
||||
|
||||
std::fprintf(stderr, "installing sp [%p, %p]\n", ss.ss_sp,
|
||||
(char *)ss.ss_sp + ss.ss_size);
|
||||
|
||||
if (sigaltstack(&ss, NULL) == -1) {
|
||||
perror("sigaltstack");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// }
|
||||
rx::thread::setupSignalStack();
|
||||
|
||||
struct sigaction act {};
|
||||
act.sa_sigaction = handle_signal;
|
||||
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_NODEFER;
|
||||
|
||||
if (sigaction(SIGSYS, &act, NULL)) {
|
||||
perror("Error sigaction:");
|
||||
|
|
@ -230,6 +276,11 @@ void setupSigHandlers() {
|
|||
perror("Error sigaction:");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (sigaction(SIGFPE, &act, NULL)) {
|
||||
perror("Error sigaction:");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
struct StackWriter {
|
||||
|
|
@ -330,8 +381,10 @@ static void ps4InitDev() {
|
|||
auto dmem1 = createDmemCharacterDevice(1);
|
||||
orbis::g_context.dmemDevice = dmem1;
|
||||
|
||||
auto consoleDev = createConsoleCharacterDevice(
|
||||
STDIN_FILENO, ::open("tty.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666));
|
||||
auto ttyFd = ::open("tty.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666);
|
||||
auto consoleDev = createConsoleCharacterDevice(STDIN_FILENO, ttyFd);
|
||||
auto mbus = static_cast<MBusDevice *>(createMBusCharacterDevice());
|
||||
auto mbusAv = static_cast<MBusAVDevice *>(createMBusAVCharacterDevice());
|
||||
|
||||
rx::vfs::addDevice("dmem0", createDmemCharacterDevice(0));
|
||||
rx::vfs::addDevice("npdrm", createNpdrmCharacterDevice());
|
||||
|
|
@ -346,6 +399,13 @@ static void ps4InitDev() {
|
|||
rx::vfs::addDevice("deci_stdin", consoleDev);
|
||||
rx::vfs::addDevice("deci_stdout", consoleDev);
|
||||
rx::vfs::addDevice("deci_stderr", consoleDev);
|
||||
rx::vfs::addDevice("deci_tty1", consoleDev);
|
||||
rx::vfs::addDevice("deci_tty2", consoleDev);
|
||||
rx::vfs::addDevice("deci_tty3", consoleDev);
|
||||
rx::vfs::addDevice("deci_tty4", consoleDev);
|
||||
rx::vfs::addDevice("deci_tty5", consoleDev);
|
||||
rx::vfs::addDevice("deci_tty6", consoleDev);
|
||||
rx::vfs::addDevice("deci_tty7", consoleDev);
|
||||
rx::vfs::addDevice("stdin", consoleDev);
|
||||
rx::vfs::addDevice("zero", createZeroCharacterDevice());
|
||||
rx::vfs::addDevice("null", createNullCharacterDevice());
|
||||
|
|
@ -361,26 +421,33 @@ static void ps4InitDev() {
|
|||
rx::vfs::addDevice("sbl_srv", createSblSrvCharacterDevice());
|
||||
rx::vfs::addDevice("ajm", createAjmCharacterDevice());
|
||||
rx::vfs::addDevice("urandom", createUrandomCharacterDevice());
|
||||
rx::vfs::addDevice("mbus", createMBusCharacterDevice());
|
||||
rx::vfs::addDevice("mbus", mbus);
|
||||
rx::vfs::addDevice("metadbg", createMetaDbgCharacterDevice());
|
||||
rx::vfs::addDevice("bt", createBtCharacterDevice());
|
||||
rx::vfs::addDevice("xpt0", createXptCharacterDevice());
|
||||
rx::vfs::addDevice("cd0", createXptCharacterDevice());
|
||||
rx::vfs::addDevice("da0x0.crypt", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("da0x1.crypt", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("da0x2.crypt", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("da0x3.crypt", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("da0x4.crypt", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("da0x5.crypt", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("cd0", createCdCharacterDevice());
|
||||
rx::vfs::addDevice("da0",
|
||||
createHddCharacterDevice(250ull * 1024 * 1024 * 1024));
|
||||
rx::vfs::addDevice("da0x0.crypt", createHddCharacterDevice(0x20000000));
|
||||
rx::vfs::addDevice("da0x1.crypt", createHddCharacterDevice(0x40000000));
|
||||
rx::vfs::addDevice("da0x2", createHddCharacterDevice(0x1000000));
|
||||
rx::vfs::addDevice("da0x2.crypt", createHddCharacterDevice(0x1000000));
|
||||
rx::vfs::addDevice("da0x3.crypt", createHddCharacterDevice(0x8000000));
|
||||
rx::vfs::addDevice("da0x4.crypt", createHddCharacterDevice(0x40000000));
|
||||
rx::vfs::addDevice("da0x4b.crypt", createHddCharacterDevice(0x40000000));
|
||||
rx::vfs::addDevice("da0x5.crypt", createHddCharacterDevice(0x40000000));
|
||||
rx::vfs::addDevice("da0x5b.crypt", createHddCharacterDevice(0x40000000));
|
||||
// rx::vfs::addDevice("da0x6x0", createHddCharacterDevice()); // boot log
|
||||
rx::vfs::addDevice("da0x6x2.crypt", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("da0x8", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("da0x9.crypt", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("da0x12.crypt", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("da0x13.crypt", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("da0x14.crypt", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("da0x15", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("da0x15.crypt", createHddCharacterDevice());
|
||||
rx::vfs::addDevice("da0x6", createHddCharacterDevice(0x200000000));
|
||||
rx::vfs::addDevice("da0x6x2.crypt", createHddCharacterDevice(0x200000000));
|
||||
rx::vfs::addDevice("da0x8", createHddCharacterDevice(0x40000000));
|
||||
rx::vfs::addDevice("da0x8.crypt", createHddCharacterDevice(0x40000000));
|
||||
rx::vfs::addDevice("da0x9.crypt", createHddCharacterDevice(0x200000000));
|
||||
rx::vfs::addDevice("da0x12.crypt", createHddCharacterDevice(0x180000000));
|
||||
rx::vfs::addDevice("da0x13.crypt", createHddCharacterDevice(0));
|
||||
rx::vfs::addDevice("da0x14.crypt", createHddCharacterDevice(0x40000000));
|
||||
rx::vfs::addDevice("da0x15", createHddCharacterDevice(0));
|
||||
rx::vfs::addDevice("da0x15.crypt", createHddCharacterDevice(0x400000000));
|
||||
rx::vfs::addDevice("notification0", createNotificationCharacterDevice(0));
|
||||
rx::vfs::addDevice("notification1", createNotificationCharacterDevice(1));
|
||||
rx::vfs::addDevice("notification2", createNotificationCharacterDevice(2));
|
||||
|
|
@ -392,7 +459,6 @@ static void ps4InitDev() {
|
|||
rx::vfs::addDevice("aout2", createAoutCharacterDevice());
|
||||
rx::vfs::addDevice("av_control", createAVControlCharacterDevice());
|
||||
rx::vfs::addDevice("hdmi", createHDMICharacterDevice());
|
||||
auto mbusAv = static_cast<MBusAVDevice *>(createMBusAVCharacterDevice());
|
||||
rx::vfs::addDevice("mbus_av", mbusAv);
|
||||
rx::vfs::addDevice("scanin", createScaninCharacterDevice());
|
||||
rx::vfs::addDevice("s3da", createS3DACharacterDevice());
|
||||
|
|
@ -402,17 +468,35 @@ static void ps4InitDev() {
|
|||
rx::vfs::addDevice("devctl", createDevCtlCharacterDevice());
|
||||
rx::vfs::addDevice("uvd", createUVDCharacterDevice());
|
||||
rx::vfs::addDevice("vce", createVCECharacterDevice());
|
||||
rx::vfs::addDevice("evlg1", createEvlgCharacterDevice(ttyFd));
|
||||
rx::vfs::addDevice("srtc", createSrtcCharacterDevice());
|
||||
rx::vfs::addDevice("sshot", createScreenShotCharacterDevice());
|
||||
rx::vfs::addDevice("lvdctl", createLvdCtlCharacterDevice());
|
||||
rx::vfs::addDevice("lvd0", createHddCharacterDevice(0x100000000));
|
||||
rx::vfs::addDevice("icc_power", createIccPowerCharacterDevice());
|
||||
|
||||
// mbus->emitEvent({
|
||||
// .system = 2,
|
||||
// .eventId = 1,
|
||||
// .deviceId = 0,
|
||||
// });
|
||||
|
||||
// mbus->emitEvent({
|
||||
// .system = 9,
|
||||
// .eventId = 1,
|
||||
// .deviceId = 100,
|
||||
// });
|
||||
|
||||
mbusAv->emitEvent({
|
||||
.system = 9,
|
||||
.eventId = 1,
|
||||
.deviceId = 100,
|
||||
});
|
||||
|
||||
auto shm = createShmDevice();
|
||||
rx::vfs::addDevice("shm", shm);
|
||||
orbis::g_context.shmDevice = shm;
|
||||
orbis::g_context.blockpoolDevice = createBlockPoolDevice();
|
||||
|
||||
mbusAv->emitEvent({
|
||||
.unk0 = 9,
|
||||
.unk1 = 1,
|
||||
.unk2 = 1,
|
||||
});
|
||||
}
|
||||
|
||||
static void ps4InitFd(orbis::Thread *mainThread) {
|
||||
|
|
@ -515,7 +599,7 @@ ExecEnv ps4CreateExecEnv(orbis::Thread *mainThread,
|
|||
std::uint64_t interpBase = 0;
|
||||
std::uint64_t entryPoint = executableModule->entryPoint;
|
||||
|
||||
if (orbis::g_context.sdkVersion == 0 && mainThread->tproc->processParam) {
|
||||
if (mainThread->tproc->processParam != nullptr) {
|
||||
auto processParam =
|
||||
reinterpret_cast<std::byte *>(mainThread->tproc->processParam);
|
||||
|
||||
|
|
@ -524,7 +608,14 @@ ExecEnv ps4CreateExecEnv(orbis::Thread *mainThread,
|
|||
+ sizeof(uint32_t) // magic
|
||||
+ sizeof(uint32_t); // entryCount
|
||||
|
||||
orbis::g_context.sdkVersion = *(uint32_t *)sdkVersion;
|
||||
mainThread->tproc->sdkVersion = *(uint32_t *)sdkVersion;
|
||||
}
|
||||
|
||||
if (orbis::g_context.sdkVersion == 0 && mainThread->tproc->sdkVersion != 0) {
|
||||
orbis::g_context.sdkVersion = mainThread->tproc->sdkVersion;
|
||||
}
|
||||
if (mainThread->tproc->sdkVersion == 0) {
|
||||
mainThread->tproc->sdkVersion = orbis::g_context.sdkVersion;
|
||||
}
|
||||
|
||||
if (executableModule->type != rx::linker::kElfTypeExec) {
|
||||
|
|
@ -677,9 +768,10 @@ static void runRpsxGpu() {
|
|||
static orbis::Semaphore *createSemaphore(std::string_view name, uint32_t attrs,
|
||||
uint64_t initCount,
|
||||
uint64_t maxCount) {
|
||||
auto result = orbis::g_context
|
||||
.createSemaphore(orbis::kstring(name), attrs, initCount, maxCount)
|
||||
.first;
|
||||
auto result =
|
||||
orbis::g_context
|
||||
.createSemaphore(orbis::kstring(name), attrs, initCount, maxCount)
|
||||
.first;
|
||||
std::memcpy(result->name, name.data(), name.size());
|
||||
result->name[name.size()] = 0;
|
||||
return result;
|
||||
|
|
@ -697,7 +789,7 @@ static void createShm(const char *name, uint32_t flags, uint32_t mode,
|
|||
orbis::Ref<orbis::File> shm;
|
||||
auto shmDevice = orbis::g_context.shmDevice.staticCast<IoDevice>();
|
||||
shmDevice->open(&shm, name, flags, mode, nullptr);
|
||||
shm->ops->truncate(shm.get(), 4096, nullptr);
|
||||
shm->ops->truncate(shm.get(), size, nullptr);
|
||||
}
|
||||
|
||||
struct IpmiServer {
|
||||
|
|
@ -866,59 +958,50 @@ struct IpmiServer {
|
|||
bufLoc += size;
|
||||
}
|
||||
|
||||
orbis::IpmiSession::SyncResponse response;
|
||||
response.errorCode = 0;
|
||||
orbis::ErrorCode result{};
|
||||
|
||||
if (auto it = syncHandlers.find(message->methodId);
|
||||
it != syncHandlers.end()) {
|
||||
auto &handler = it->second;
|
||||
|
||||
std::int32_t errorCode = 0;
|
||||
auto result = handler(errorCode, outData, inData);
|
||||
result = handler(response.errorCode, outData, inData);
|
||||
} else {
|
||||
std::fprintf(
|
||||
stderr,
|
||||
"Unimplemented sync method %s::%x(inBufCount=%x, outBufCount=%x)\n",
|
||||
session->server->name.c_str(), message->methodId, message->numInData,
|
||||
message->numOutData);
|
||||
|
||||
if (outData.empty()) {
|
||||
session->messageResponses.push_front({
|
||||
.errorCode = errorCode,
|
||||
.data = {},
|
||||
});
|
||||
} else {
|
||||
session->messageResponses.push_front({
|
||||
.errorCode = errorCode,
|
||||
.data = orbis::kvector<std::byte>(
|
||||
outData[0].data(), outData[0].data() + outData[0].size()),
|
||||
});
|
||||
// for (auto in : inData) {
|
||||
// std::fprintf(stderr, "in %zx\n", in.size());
|
||||
// }
|
||||
|
||||
// for (auto out : outData) {
|
||||
// std::fprintf(stderr, "out %zx\n", out.size());
|
||||
// }
|
||||
|
||||
for (auto out : outData) {
|
||||
std::memset(out.data(), 0, out.size());
|
||||
}
|
||||
|
||||
session->responseCv.notify_one(session->mutex);
|
||||
return {};
|
||||
// TODO:
|
||||
// response.errorCode = message->numOutData == 0 ||
|
||||
// (message->numOutData == 1 && outData[0].empty())
|
||||
// ? 0
|
||||
// : -1,
|
||||
}
|
||||
|
||||
std::fprintf(
|
||||
stderr,
|
||||
"Unimplemented sync method %s::%x(inBufCount=%x, outBufCount=%x)\n",
|
||||
session->server->name.c_str(), message->methodId, message->numInData,
|
||||
message->numOutData);
|
||||
|
||||
// for (auto in : inData) {
|
||||
// std::fprintf(stderr, "in %zx\n", in.size());
|
||||
// }
|
||||
|
||||
// for (auto out : outData) {
|
||||
// std::fprintf(stderr, "out %zx\n", out.size());
|
||||
// }
|
||||
for (auto out : outData) {
|
||||
response.data.push_back(orbis::kvector<std::byte>(
|
||||
(std::byte *)out.data(), (std::byte *)out.data() + out.size()));
|
||||
}
|
||||
|
||||
std::lock_guard lock(session->mutex);
|
||||
|
||||
session->messageResponses.push_front({
|
||||
// TODO:
|
||||
// .errorCode = message->numOutData == 0 ||
|
||||
// (message->numOutData == 1 && outData[0].empty())
|
||||
// ? 0
|
||||
// : -1,
|
||||
.errorCode = 0,
|
||||
.data = orbis::kvector<std::byte>(
|
||||
message->numOutData ? outData[0].size() : 0),
|
||||
});
|
||||
|
||||
session->syncResponses.push_front(std::move(response));
|
||||
session->responseCv.notify_one(session->mutex);
|
||||
return {};
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -929,7 +1012,8 @@ static IpmiServer &createIpmiServer(orbis::Process *process, const char *name) {
|
|||
auto server = std::make_shared<IpmiServer>();
|
||||
server->serverImpl = serverImpl;
|
||||
|
||||
std::thread{[server, serverImpl] {
|
||||
std::thread{[server, serverImpl, name] {
|
||||
pthread_setname_np(pthread_self(), name);
|
||||
while (true) {
|
||||
orbis::IpmiServer::Packet packet;
|
||||
{
|
||||
|
|
@ -964,8 +1048,9 @@ static IpmiServer &createIpmiServer(orbis::Process *process, const char *name) {
|
|||
conReq.client->session = session;
|
||||
|
||||
for (auto &message : server->messages) {
|
||||
conReq.client->messages.push_back(orbis::kvector<std::byte>(
|
||||
message.data(), message.data() + message.size()));
|
||||
conReq.client->messageQueues[0].messages.push_back(
|
||||
orbis::kvector<std::byte>(message.data(),
|
||||
message.data() + message.size()));
|
||||
}
|
||||
|
||||
conReq.client->sessionCv.notify_all(conReq.client->mutex);
|
||||
|
|
@ -1420,6 +1505,7 @@ int main(int argc, const char *argv[]) {
|
|||
bool enableAudio = false;
|
||||
bool asRoot = false;
|
||||
bool isSystem = false;
|
||||
bool isSafeMode = false;
|
||||
|
||||
int argIndex = 1;
|
||||
while (argIndex < argc) {
|
||||
|
|
@ -1459,6 +1545,14 @@ int main(int argc, const char *argv[]) {
|
|||
if (argv[argIndex] == std::string_view("--system")) {
|
||||
argIndex++;
|
||||
isSystem = true;
|
||||
asRoot = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argv[argIndex] == std::string_view("--safemode")) {
|
||||
argIndex++;
|
||||
isSafeMode = true;
|
||||
asRoot = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1503,80 +1597,20 @@ int main(int argc, const char *argv[]) {
|
|||
auto initProcess = orbis::g_context.createProcess(asRoot ? 1 : 10);
|
||||
// pthread_setname_np(pthread_self(), "10.MAINTHREAD");
|
||||
|
||||
std::thread{[] {
|
||||
pthread_setname_np(pthread_self(), "Bridge");
|
||||
auto bridge = rx::bridge.header;
|
||||
|
||||
std::vector<std::uint64_t> fetchedCommands;
|
||||
fetchedCommands.reserve(std::size(bridge->cacheCommands));
|
||||
|
||||
while (true) {
|
||||
for (auto &command : bridge->cacheCommands) {
|
||||
std::uint64_t value = command.load(std::memory_order::relaxed);
|
||||
|
||||
if (value != 0) {
|
||||
fetchedCommands.push_back(value);
|
||||
command.store(0, std::memory_order::relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
if (fetchedCommands.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto command : fetchedCommands) {
|
||||
auto page = static_cast<std::uint32_t>(command);
|
||||
auto count = static_cast<std::uint32_t>(command >> 32) + 1;
|
||||
|
||||
auto pageFlags =
|
||||
bridge->cachePages[page].load(std::memory_order::relaxed);
|
||||
|
||||
auto address =
|
||||
static_cast<std::uint64_t>(page) * amdgpu::bridge::kHostPageSize;
|
||||
auto origVmProt = rx::vm::getPageProtection(address);
|
||||
int prot = 0;
|
||||
|
||||
if (origVmProt & rx::vm::kMapProtCpuRead) {
|
||||
prot |= PROT_READ;
|
||||
}
|
||||
if (origVmProt & rx::vm::kMapProtCpuWrite) {
|
||||
prot |= PROT_WRITE;
|
||||
}
|
||||
if (origVmProt & rx::vm::kMapProtCpuExec) {
|
||||
prot |= PROT_EXEC;
|
||||
}
|
||||
|
||||
if (pageFlags & amdgpu::bridge::kPageReadWriteLock) {
|
||||
prot &= ~(PROT_READ | PROT_WRITE);
|
||||
} else if (pageFlags & amdgpu::bridge::kPageWriteWatch) {
|
||||
prot &= ~PROT_WRITE;
|
||||
}
|
||||
|
||||
// std::fprintf(stderr, "protection %lx-%lx\n", address,
|
||||
// address + amdgpu::bridge::kHostPageSize * count);
|
||||
if (::mprotect(reinterpret_cast<void *>(address),
|
||||
amdgpu::bridge::kHostPageSize * count, prot)) {
|
||||
perror("protection failed");
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
fetchedCommands.clear();
|
||||
}
|
||||
}}.detach();
|
||||
|
||||
int status = 0;
|
||||
|
||||
initProcess->sysent = &orbis::ps4_sysvec;
|
||||
initProcess->onSysEnter = onSysEnter;
|
||||
initProcess->onSysExit = onSysExit;
|
||||
initProcess->ops = &rx::procOpsTable;
|
||||
initProcess->hostPid = ::getpid();
|
||||
initProcess->appInfo = {
|
||||
.unk4 = (isSystem ? orbis::slong(0x80000000'00000000) : 0),
|
||||
};
|
||||
|
||||
if (isSystem) {
|
||||
amdgpu::bridge::expGpuPid = 50001;
|
||||
amdgpu::bridge::expGpuPid = isSafeMode ? 20001 : 60001;
|
||||
orbis::g_context.safeMode = isSafeMode ? 1 : 0;
|
||||
initProcess->authInfo = {
|
||||
.unk0 = 0x380000000000000f,
|
||||
.caps =
|
||||
|
|
@ -1623,6 +1657,7 @@ int main(int argc, const char *argv[]) {
|
|||
mainThread->tproc = initProcess;
|
||||
mainThread->tid = initProcess->pid + baseId;
|
||||
mainThread->state = orbis::ThreadState::RUNNING;
|
||||
mainThread->hostTid = ::gettid();
|
||||
|
||||
auto executableModule =
|
||||
rx::linker::loadModuleFile(argv[argIndex], mainThread);
|
||||
|
|
@ -1653,6 +1688,47 @@ int main(int argc, const char *argv[]) {
|
|||
|
||||
auto execEnv = ps4CreateExecEnv(mainThread, executableModule, isSystem);
|
||||
|
||||
// data transfer mode
|
||||
// 0 - normal
|
||||
// 1 - source
|
||||
// 2 - ?
|
||||
orbis::g_context.regMgrInt[0x2110000] = 0;
|
||||
|
||||
orbis::g_context.regMgrInt[0x20b0000] = 1; // prefer X
|
||||
orbis::g_context.regMgrInt[0x2020000] = 1; // region
|
||||
|
||||
// orbis::g_context.regMgrInt[0x2130000] = 0x1601;
|
||||
orbis::g_context.regMgrInt[0x2130000] = 0;
|
||||
orbis::g_context.regMgrInt[0x73800200] = 1;
|
||||
orbis::g_context.regMgrInt[0x73800300] = 0;
|
||||
orbis::g_context.regMgrInt[0x73800400] = 0;
|
||||
orbis::g_context.regMgrInt[0x73800500] = 0; // enable log
|
||||
|
||||
// user settings
|
||||
orbis::g_context.regMgrInt[0x7800100] = 0;
|
||||
orbis::g_context.regMgrInt[0x7810100] = 0;
|
||||
orbis::g_context.regMgrInt[0x7820100] = 0;
|
||||
orbis::g_context.regMgrInt[0x7830100] = 0;
|
||||
orbis::g_context.regMgrInt[0x7840100] = 0;
|
||||
orbis::g_context.regMgrInt[0x7850100] = 0;
|
||||
orbis::g_context.regMgrInt[0x7860100] = 0;
|
||||
orbis::g_context.regMgrInt[0x7870100] = 0;
|
||||
orbis::g_context.regMgrInt[0x7880100] = 0;
|
||||
orbis::g_context.regMgrInt[0x7890100] = 0;
|
||||
orbis::g_context.regMgrInt[0x78a0100] = 0;
|
||||
orbis::g_context.regMgrInt[0x78b0100] = 0;
|
||||
orbis::g_context.regMgrInt[0x78c0100] = 0;
|
||||
orbis::g_context.regMgrInt[0x78d0100] = 0;
|
||||
orbis::g_context.regMgrInt[0x78e0100] = 0;
|
||||
orbis::g_context.regMgrInt[0x78f0100] = 0;
|
||||
|
||||
orbis::g_context.regMgrInt[0x2040000] = 0; // do not require initial setup
|
||||
orbis::g_context.regMgrInt[0x2800600] = 0; // IDU version
|
||||
orbis::g_context.regMgrInt[0x2860100] = 0; // IDU mode
|
||||
orbis::g_context.regMgrInt[0x2860300] = 0; // Arcade mode
|
||||
orbis::g_context.regMgrInt[0x7010000] = 0; // auto login
|
||||
orbis::g_context.regMgrInt[0x9010000] = 0; // video out color effect
|
||||
|
||||
if (!isSystem) {
|
||||
createMiniSysCoreObjects(initProcess);
|
||||
createSysAvControlObjects(initProcess);
|
||||
|
|
@ -1662,12 +1738,26 @@ int main(int argc, const char *argv[]) {
|
|||
|
||||
// ?
|
||||
createIpmiServer(initProcess, "SceCdlgRichProf");
|
||||
createIpmiServer(initProcess, "SceRemoteplayIpc");
|
||||
createIpmiServer(initProcess, "SceRemoteplayIpc");
|
||||
createIpmiServer(initProcess, "SceGlsIpc");
|
||||
createIpmiServer(initProcess, "SceImeService");
|
||||
createIpmiServer(initProcess, "SceErrorDlgServ");
|
||||
|
||||
createEventFlag("SceNpTusIpc_0000000a", 0x120, 0);
|
||||
createSemaphore("SceLncSuspendBlock00000000", 0x101, 1, 1);
|
||||
createSemaphore("SceNpPlusLogger 0", 0x101, 0, 0x7fffffff);
|
||||
|
||||
createSemaphore("SceSaveData0000000000000001", 0x101, 0, 1);
|
||||
createSemaphore("SceSaveData0000000000000001_0", 0x101, 0, 1);
|
||||
createShm("SceSaveData0000000000000001_0", 0x202, 0x1b6, 0x40000);
|
||||
createShm("SceSaveDataI0000000000000001", 0x202, 0x1b6, 43008);
|
||||
createShm("SceSaveDataI0000000000000001_0", 0x202, 0x1b6, 43008);
|
||||
createEventFlag("SceSaveDataMemoryRUI00000010", 0x120, 1);
|
||||
initProcess->cwd = "/app0/";
|
||||
|
||||
launchDaemon(mainThread, "/system/sys/orbis_audiod.elf",
|
||||
{"/system/sys/orbis_audiod.elf"}, {});
|
||||
runBridge();
|
||||
status = ps4Exec(mainThread, execEnv, std::move(executableModule),
|
||||
ps4Argv, {});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "ops.hpp"
|
||||
#include "align.hpp"
|
||||
#include "amdgpu/bridge/bridge.hpp"
|
||||
#include "backtrace.hpp"
|
||||
#include "io-device.hpp"
|
||||
#include "io-devices.hpp"
|
||||
|
|
@ -39,7 +40,10 @@
|
|||
|
||||
using namespace orbis;
|
||||
|
||||
extern bool allowMonoDebug;
|
||||
|
||||
extern "C" void __register_frame(const void *);
|
||||
void runBridge();
|
||||
void setupSigHandlers();
|
||||
int ps4Exec(orbis::Thread *mainThread,
|
||||
orbis::utils::Ref<orbis::Module> executableModule,
|
||||
|
|
@ -252,7 +256,7 @@ orbis::SysResult minherit(orbis::Thread *thread, orbis::ptr<void> addr,
|
|||
|
||||
orbis::SysResult madvise(orbis::Thread *thread, orbis::ptr<void> addr,
|
||||
orbis::size_t len, orbis::sint behav) {
|
||||
return ErrorCode::INVAL;
|
||||
return {};
|
||||
}
|
||||
|
||||
orbis::SysResult mincore(orbis::Thread *thread, orbis::ptr<const void> addr,
|
||||
|
|
@ -402,6 +406,10 @@ orbis::SysResult dynlib_get_obj_member(orbis::Thread *thread,
|
|||
case 8:
|
||||
*addrp = module->moduleParam;
|
||||
return {};
|
||||
|
||||
default:
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, index);
|
||||
thread->where();
|
||||
}
|
||||
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -521,8 +529,9 @@ orbis::SysResult dynlib_unload_prx(orbis::Thread *thread,
|
|||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
|
||||
SysResult thr_create(orbis::Thread *thread, orbis::ptr<struct ucontext> ctxt,
|
||||
SysResult thr_create(orbis::Thread *thread, orbis::ptr<orbis::UContext> ctxt,
|
||||
ptr<orbis::slong> arg, orbis::sint flags) {
|
||||
ORBIS_LOG_FATAL(__FUNCTION__, ctxt, arg, flags);
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
SysResult thr_new(orbis::Thread *thread, orbis::ptr<thr_param> param,
|
||||
|
|
@ -551,9 +560,10 @@ SysResult thr_new(orbis::Thread *thread, orbis::ptr<thr_param> param,
|
|||
|
||||
// FIXME: implement scheduler
|
||||
|
||||
ORBIS_LOG_NOTICE("Starting child thread", childThread->tid,
|
||||
ORBIS_LOG_NOTICE("Starting child thread", thread->tid, childThread->tid,
|
||||
childThread->stackStart, _param.rtp, _param.name,
|
||||
_param.spare[0], _param.spare[1]);
|
||||
|
||||
if (_param.rtp != 0) {
|
||||
rtprio _rtp;
|
||||
ORBIS_RET_ON_ERROR(uread(_rtp, _param.rtp));
|
||||
|
|
@ -573,6 +583,7 @@ SysResult thr_new(orbis::Thread *thread, orbis::ptr<thr_param> param,
|
|||
context->uc_mcontext.gregs[REG_RIP] =
|
||||
reinterpret_cast<std::uintptr_t>(_param.start_func);
|
||||
|
||||
childThread->hostTid = ::gettid();
|
||||
childThread->context = context;
|
||||
childThread->state = orbis::ThreadState::RUNNING;
|
||||
|
||||
|
|
@ -598,23 +609,38 @@ SysResult thr_exit(orbis::Thread *thread, orbis::ptr<orbis::slong> state) {
|
|||
}
|
||||
|
||||
// FIXME: implement exit
|
||||
pthread_setname_np(pthread_self(), "dead");
|
||||
while (true) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(60));
|
||||
}
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
SysResult thr_kill(orbis::Thread *thread, orbis::slong id, orbis::sint sig) {
|
||||
return ErrorCode::NOTSUP;
|
||||
auto t = (std::lock_guard(thread->tproc->mtx),
|
||||
thread->tproc->threadsMap.get(id - thread->tproc->pid));
|
||||
if (t == nullptr) {
|
||||
return ErrorCode::SRCH;
|
||||
}
|
||||
|
||||
ORBIS_LOG_FATAL(__FUNCTION__, id, sig, t->hostTid);
|
||||
std::lock_guard lock(t->tproc->mtx);
|
||||
t->signalQueue.push_back(sig);
|
||||
::tgkill(t->tproc->hostPid, t->hostTid, SIGUSR1);
|
||||
return {};
|
||||
}
|
||||
|
||||
SysResult thr_kill2(orbis::Thread *thread, orbis::pid_t pid, orbis::slong id,
|
||||
orbis::sint sig) {
|
||||
ORBIS_LOG_FATAL(__FUNCTION__, pid, id, sig);
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
SysResult thr_suspend(orbis::Thread *thread,
|
||||
orbis::ptr<const orbis::timespec> timeout) {
|
||||
ORBIS_LOG_FATAL(__FUNCTION__, timeout);
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
SysResult thr_wake(orbis::Thread *thread, orbis::slong id) {
|
||||
ORBIS_LOG_FATAL(__FUNCTION__, id);
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
SysResult thr_set_name(orbis::Thread *thread, orbis::slong id,
|
||||
|
|
@ -626,7 +652,10 @@ SysResult thr_set_name(orbis::Thread *thread, orbis::slong id,
|
|||
orbis::SysResult unmount(orbis::Thread *thread, orbis::ptr<char> path,
|
||||
orbis::sint flags) {
|
||||
// TODO: support other that nullfs
|
||||
return rx::vfs::unlink(getAbsolutePath(path, thread), thread);
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, path);
|
||||
thread->where();
|
||||
rx::vfs::unlink(getAbsolutePath(path, thread), thread);
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult nmount(orbis::Thread *thread, orbis::ptr<orbis::IoVec> iovp,
|
||||
orbis::uint iovcnt, orbis::sint flags) {
|
||||
|
|
@ -747,6 +776,7 @@ SysResult fork(Thread *thread, slong flags) {
|
|||
process->ops = thread->tproc->ops;
|
||||
process->parentProcess = thread->tproc;
|
||||
process->authInfo = thread->tproc->authInfo;
|
||||
process->sdkVersion = thread->tproc->sdkVersion;
|
||||
for (auto [id, mod] : thread->tproc->modulesMap) {
|
||||
if (!process->modulesMap.insert(id, mod)) {
|
||||
std::abort();
|
||||
|
|
@ -769,6 +799,7 @@ SysResult fork(Thread *thread, slong flags) {
|
|||
|
||||
auto [baseId, newThread] = process->threadsMap.emplace();
|
||||
newThread->tproc = process;
|
||||
newThread->hostTid = ::gettid();
|
||||
newThread->tid = process->pid + baseId;
|
||||
newThread->state = orbis::ThreadState::RUNNING;
|
||||
newThread->context = thread->context;
|
||||
|
|
@ -790,9 +821,15 @@ SysResult fork(Thread *thread, slong flags) {
|
|||
|
||||
dup2(logFd, 1);
|
||||
dup2(logFd, 2);
|
||||
|
||||
if (childPid == amdgpu::bridge::expGpuPid) {
|
||||
runBridge();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
volatile bool debuggerPresent = false;
|
||||
|
||||
SysResult execve(Thread *thread, ptr<char> fname, ptr<ptr<char>> argv,
|
||||
ptr<ptr<char>> envv) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, fname);
|
||||
|
|
@ -835,7 +872,21 @@ SysResult execve(Thread *thread, ptr<char> fname, ptr<ptr<char>> argv,
|
|||
pthread_setname_np(pthread_self(), name.c_str());
|
||||
}
|
||||
|
||||
if (fname == std::string_view{"/app0/eboot.bin"}) {
|
||||
// FIXME: remove hack
|
||||
// _envv.push_back("MONO_LOG_LEVEL=debug");
|
||||
_envv.push_back("MONO_GC_PARAMS=nursery-size=128m");
|
||||
// _envv.push_back("MONO_GC_DEBUG=2,heap-dump=/app0/mono.dump");
|
||||
// _envv.push_back("GC_DONT_GC");
|
||||
}
|
||||
|
||||
std::printf("pid: %u\n", ::getpid());
|
||||
|
||||
// if (thread->tid == 60001) {
|
||||
// while (debuggerPresent == false) {
|
||||
// std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
// }
|
||||
// }
|
||||
{
|
||||
orbis::Ref<File> file;
|
||||
auto result = rx::vfs::open(path, kOpenFlagReadOnly, 0, &file, thread);
|
||||
|
|
|
|||
|
|
@ -143,6 +143,8 @@ inline uint64_t readRegister(void *context, RegisterId id) {
|
|||
return c->gregs[REG_RSP];
|
||||
case RegisterId::rflags:
|
||||
return c->gregs[REG_EFL];
|
||||
case RegisterId::rip:
|
||||
return c->gregs[REG_RIP];
|
||||
}
|
||||
std::fprintf(stderr, "***ERROR*** Unhandled RegisterId %d\n",
|
||||
static_cast<int>(id));
|
||||
|
|
@ -203,6 +205,9 @@ inline void writeRegister(void *context, RegisterId id, uint64_t value) {
|
|||
case RegisterId::rflags:
|
||||
c->gregs[REG_EFL] = value;
|
||||
return;
|
||||
case RegisterId::rip:
|
||||
c->gregs[REG_RIP] = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "orbis/sys/sysentry.hpp"
|
||||
#include "orbis/thread/Process.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include <asm/prctl.h>
|
||||
#include <csignal>
|
||||
#include <immintrin.h>
|
||||
|
|
@ -13,6 +14,12 @@
|
|||
#include <unistd.h>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
static std::size_t getSigStackSize() {
|
||||
static auto sigStackSize = std::max<std::size_t>(
|
||||
SIGSTKSZ, ::utils::alignUp(64 * 1024 * 1024, sysconf(_SC_PAGE_SIZE)));
|
||||
return sigStackSize;
|
||||
}
|
||||
|
||||
static auto setContext = [] {
|
||||
struct SetContext : Xbyak::CodeGenerator {
|
||||
SetContext() {
|
||||
|
|
@ -33,6 +40,60 @@ static auto setContext = [] {
|
|||
return setContextStorage.getCode<void (*)(const mcontext_t &)>();
|
||||
}();
|
||||
|
||||
static void copy(orbis::MContext &dst, const mcontext_t &src) {
|
||||
// dst.onstack = src.gregs[REG_ONSTACK];
|
||||
dst.rdi = src.gregs[REG_RDI];
|
||||
dst.rsi = src.gregs[REG_RSI];
|
||||
dst.rdx = src.gregs[REG_RDX];
|
||||
dst.rcx = src.gregs[REG_RCX];
|
||||
dst.r8 = src.gregs[REG_R8];
|
||||
dst.r9 = src.gregs[REG_R9];
|
||||
dst.rax = src.gregs[REG_RAX];
|
||||
dst.rbx = src.gregs[REG_RBX];
|
||||
dst.rbp = src.gregs[REG_RBP];
|
||||
dst.r10 = src.gregs[REG_R10];
|
||||
dst.r11 = src.gregs[REG_R11];
|
||||
dst.r12 = src.gregs[REG_R12];
|
||||
dst.r13 = src.gregs[REG_R13];
|
||||
dst.r14 = src.gregs[REG_R14];
|
||||
dst.r15 = src.gregs[REG_R15];
|
||||
dst.trapno = src.gregs[REG_TRAPNO];
|
||||
dst.fs = src.gregs[REG_CSGSFS] & 0xffff;
|
||||
dst.gs = (src.gregs[REG_CSGSFS] >> 16) & 0xffff;
|
||||
// dst.addr = src.gregs[REG_ADDR];
|
||||
// dst.flags = src.gregs[REG_FLAGS];
|
||||
// dst.es = src.gregs[REG_ES];
|
||||
// dst.ds = src.gregs[REG_DS];
|
||||
dst.err = src.gregs[REG_ERR];
|
||||
dst.rip = src.gregs[REG_RIP];
|
||||
dst.cs = (src.gregs[REG_CSGSFS] >> 32) & 0xffff;
|
||||
dst.rflags = src.gregs[REG_EFL];
|
||||
dst.rsp = src.gregs[REG_RSP];
|
||||
// dst.ss = src.gregs[REG_SS];
|
||||
dst.len = sizeof(orbis::MContext);
|
||||
// dst.fpformat = src.gregs[REG_FPFORMAT];
|
||||
// dst.ownedfp = src.gregs[REG_OWNEDFP];
|
||||
// dst.lbrfrom = src.gregs[REG_LBRFROM];
|
||||
// dst.lbrto = src.gregs[REG_LBRTO];
|
||||
// dst.aux1 = src.gregs[REG_AUX1];
|
||||
// dst.aux2 = src.gregs[REG_AUX2];
|
||||
// dst.fpstate = src.gregs[REG_FPSTATE];
|
||||
// dst.fsbase = src.gregs[REG_FSBASE];
|
||||
// dst.gsbase = src.gregs[REG_GSBASE];
|
||||
// dst.xfpustate = src.gregs[REG_XFPUSTATE];
|
||||
// dst.xfpustate_len = src.gregs[REG_XFPUSTATE_LEN];
|
||||
}
|
||||
|
||||
static void copy(orbis::Thread *thread, orbis::UContext &dst,
|
||||
const ucontext_t &src) {
|
||||
dst = {};
|
||||
dst.stack.sp = thread->stackStart;
|
||||
dst.stack.size = (char *)thread->stackEnd - (char *)thread->stackStart;
|
||||
dst.stack.align = 0x10000;
|
||||
dst.sigmask = thread->sigMask;
|
||||
copy(dst.mcontext, src.uc_mcontext);
|
||||
}
|
||||
|
||||
static __attribute__((no_stack_protector)) void
|
||||
handleSigSys(int sig, siginfo_t *info, void *ucontext) {
|
||||
if (auto hostFs = _readgsbase_u64()) {
|
||||
|
|
@ -43,50 +104,163 @@ handleSigSys(int sig, siginfo_t *info, void *ucontext) {
|
|||
// rx::thread::g_current, 1);
|
||||
auto thread = orbis::g_currentThread;
|
||||
auto prevContext = std::exchange(thread->context, ucontext);
|
||||
{
|
||||
std::lock_guard lock(thread->mtx);
|
||||
copy(thread, thread->sigReturns.emplace_back(),
|
||||
*reinterpret_cast<ucontext_t *>(ucontext));
|
||||
}
|
||||
if ((std::uint64_t)&thread < 0x100'0000'0000) {
|
||||
ORBIS_LOG_ERROR("unexpected sigsys signal stack", thread->tid, sig,
|
||||
(std::uint64_t)&thread);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
auto altStack = malloc(getSigStackSize());
|
||||
rx::thread::setupSignalStack(altStack);
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGUSR1);
|
||||
sigaddset(&set, SIGSYS);
|
||||
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
|
||||
|
||||
orbis::syscall_entry(thread);
|
||||
|
||||
pthread_sigmask(SIG_BLOCK, &set, NULL);
|
||||
|
||||
std::free(altStack);
|
||||
if (thread == orbis::g_currentThread) {
|
||||
std::lock_guard lock(thread->mtx);
|
||||
thread->sigReturns.pop_back();
|
||||
}
|
||||
thread = orbis::g_currentThread;
|
||||
thread->context = prevContext;
|
||||
_writefsbase_u64(thread->fsBase);
|
||||
}
|
||||
|
||||
__attribute__((no_stack_protector)) static void
|
||||
handleSigUser(int sig, siginfo_t *info, void *ucontext) {
|
||||
if (auto hostFs = _readgsbase_u64()) {
|
||||
_writefsbase_u64(hostFs);
|
||||
}
|
||||
|
||||
auto context = reinterpret_cast<ucontext_t *>(ucontext);
|
||||
bool inGuestCode = context->uc_mcontext.gregs[REG_RIP] < 0x100'0000'0000;
|
||||
auto thread = orbis::g_currentThread;
|
||||
|
||||
if ((std::uint64_t)&context < 0x100'0000'0000) {
|
||||
ORBIS_LOG_ERROR("unexpected sigusr signal stack", thread->tid, sig,
|
||||
inGuestCode, (std::uint64_t)&context);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
int guestSignal = -3;
|
||||
{
|
||||
std::lock_guard lock(thread->mtx);
|
||||
if (thread->signalQueue.empty()) {
|
||||
ORBIS_LOG_ERROR("unexpected user signal", thread->tid, sig, inGuestCode);
|
||||
return;
|
||||
}
|
||||
|
||||
guestSignal = thread->signalQueue.front();
|
||||
thread->signalQueue.pop_front();
|
||||
|
||||
copy(thread, thread->sigReturns.emplace_back(), *context);
|
||||
}
|
||||
|
||||
if (guestSignal == -1) {
|
||||
auto altStack = malloc(getSigStackSize());
|
||||
rx::thread::setupSignalStack(altStack);
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGUSR1);
|
||||
sigaddset(&set, SIGSYS);
|
||||
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
|
||||
|
||||
thread->suspended++;
|
||||
// ORBIS_LOG_ERROR("suspending thread", thread->tid);
|
||||
while (thread->suspended > 0) {
|
||||
::sleep(1);
|
||||
}
|
||||
|
||||
pthread_sigmask(SIG_BLOCK, &set, NULL);
|
||||
free(altStack);
|
||||
|
||||
// ORBIS_LOG_ERROR("thread wake", thread->tid);
|
||||
}
|
||||
|
||||
if (guestSignal == -2) {
|
||||
// ORBIS_LOG_ERROR("thread resume signal", thread->tid);
|
||||
|
||||
std::lock_guard lock(thread->mtx);
|
||||
thread->sigReturns.pop_back();
|
||||
--thread->suspended;
|
||||
}
|
||||
|
||||
if (inGuestCode) {
|
||||
_writefsbase_u64(thread->fsBase);
|
||||
}
|
||||
}
|
||||
|
||||
void rx::thread::initialize() {
|
||||
struct sigaction act {};
|
||||
act.sa_sigaction = handleSigSys;
|
||||
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
|
||||
sigaddset(&act.sa_mask, SIGSYS);
|
||||
sigaddset(&act.sa_mask, SIGUSR1);
|
||||
|
||||
if (sigaction(SIGSYS, &act, NULL)) {
|
||||
perror("Error sigaction:");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
act.sa_sigaction = handleSigUser;
|
||||
|
||||
if (sigaction(SIGUSR1, &act, NULL)) {
|
||||
perror("Error sigaction:");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void rx::thread::deinitialize() {}
|
||||
|
||||
void rx::thread::setupSignalStack() {
|
||||
stack_t ss{};
|
||||
void *rx::thread::setupSignalStack(void *address) {
|
||||
stack_t ss{}, oss{};
|
||||
|
||||
auto sigStackSize = std::max<std::size_t>(
|
||||
SIGSTKSZ, ::utils::alignUp(64 * 1024 * 1024, sysconf(_SC_PAGE_SIZE)));
|
||||
|
||||
ss.ss_sp = malloc(sigStackSize);
|
||||
if (ss.ss_sp == NULL) {
|
||||
perror("malloc");
|
||||
if (address == NULL) {
|
||||
std::fprintf(stderr, "attempt to set null signal stack, %p - %zx\n",
|
||||
address, getSigStackSize());
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ss.ss_size = sigStackSize;
|
||||
ss.ss_sp = address;
|
||||
ss.ss_size = getSigStackSize();
|
||||
ss.ss_flags = 1 << 31;
|
||||
|
||||
if (sigaltstack(&ss, NULL) == -1) {
|
||||
if (sigaltstack(&ss, &oss) == -1) {
|
||||
perror("sigaltstack");
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return oss.ss_sp;
|
||||
}
|
||||
|
||||
void *rx::thread::setupSignalStack() {
|
||||
auto data = malloc(getSigStackSize());
|
||||
if (data == nullptr) {
|
||||
std::fprintf(stderr, "malloc produces null, %zx\n", getSigStackSize());
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
return setupSignalStack(data);
|
||||
}
|
||||
|
||||
void rx::thread::setupThisThread() {
|
||||
sigset_t unblockSigs{};
|
||||
sigset_t oldSigmask{};
|
||||
sigaddset(&unblockSigs, SIGSYS);
|
||||
sigaddset(&unblockSigs, SIGUSR1);
|
||||
if (pthread_sigmask(SIG_UNBLOCK, &unblockSigs, &oldSigmask)) {
|
||||
perror("pthread_sigmask failed\n");
|
||||
std::exit(-1);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
namespace rx::thread {
|
||||
void initialize();
|
||||
void deinitialize();
|
||||
void setupSignalStack();
|
||||
void *setupSignalStack();
|
||||
void *setupSignalStack(void *address);
|
||||
void setupThisThread();
|
||||
|
||||
void invoke(orbis::Thread *thread);
|
||||
|
|
|
|||
|
|
@ -9,12 +9,39 @@
|
|||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
|
||||
static orbis::ErrorCode devfs_stat(orbis::File *file, orbis::Stat *sb,
|
||||
orbis::Thread *thread) {
|
||||
*sb = {}; // TODO
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
static orbis::FileOps devfs_ops = {
|
||||
.stat = devfs_stat,
|
||||
};
|
||||
|
||||
struct DevFs : IoDevice {
|
||||
std::map<std::string, orbis::Ref<IoDevice>, std::less<>> devices;
|
||||
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override {
|
||||
if (path[0] == '\0') {
|
||||
auto result = orbis::knew<orbis::File>();
|
||||
for (auto &[name, dev] : devices) {
|
||||
auto &entry = result->dirEntries.emplace_back();
|
||||
entry.fileno = result->dirEntries.size();
|
||||
entry.reclen = sizeof(orbis::Dirent);
|
||||
entry.type = orbis::kDtBlk;
|
||||
entry.namlen = name.size();
|
||||
std::strncpy(entry.name, name.c_str(), sizeof(entry.name));
|
||||
}
|
||||
|
||||
result->ops = &devfs_ops;
|
||||
*file = result;
|
||||
return{};
|
||||
}
|
||||
std::string_view devPath = path;
|
||||
if (auto pos = devPath.find('/'); pos != std::string_view::npos) {
|
||||
auto deviceName = devPath.substr(0, pos);
|
||||
|
|
@ -93,6 +120,20 @@ rx::vfs::get(const std::filesystem::path &guestPath) {
|
|||
|
||||
std::lock_guard lock(gMountMtx);
|
||||
|
||||
if (gDevFs != nullptr) {
|
||||
std::string_view devPath = "/dev/";
|
||||
if (path.starts_with(devPath) ||
|
||||
path == devPath.substr(0, devPath.size() - 1)) {
|
||||
if (path.size() > devPath.size()) {
|
||||
path.remove_prefix(devPath.size());
|
||||
} else {
|
||||
path = {};
|
||||
}
|
||||
|
||||
return { gDevFs, std::string(path) };
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &mount : gMountsMap) {
|
||||
if (!path.starts_with(mount.first)) {
|
||||
if (mount.first.size() - 1 != path.size() ||
|
||||
|
|
|
|||
|
|
@ -820,11 +820,7 @@ void *rx::vm::map(void *addr, std::uint64_t len, std::int32_t prot,
|
|||
|
||||
flags &= ~kMapFlagsAlignMask;
|
||||
|
||||
bool noOverwrite = addr != 0 && (flags & kMapFlagNoOverwrite) == kMapFlagNoOverwrite;
|
||||
if (noOverwrite) {
|
||||
flags |= kMapFlagFixed;
|
||||
}
|
||||
flags &= ~kMapFlagNoOverwrite;
|
||||
bool noOverwrite = (flags & (kMapFlagNoOverwrite | kMapFlagFixed)) == (kMapFlagNoOverwrite | kMapFlagFixed);
|
||||
|
||||
if (hitAddress & (alignment - 1)) {
|
||||
if (flags & kMapFlagStack) {
|
||||
|
|
@ -982,11 +978,11 @@ void *rx::vm::map(void *addr, std::uint64_t len, std::int32_t prot,
|
|||
}
|
||||
|
||||
if (auto thr = orbis::g_currentThread) {
|
||||
std::fprintf(stderr, "sending mapping %lx-%lx, pid %lx\n", address,
|
||||
address + len, thr->tproc->pid);
|
||||
if (!noOverwrite) {
|
||||
rx::bridge.sendMemoryProtect(thr->tproc->pid, address, len, prot);
|
||||
}
|
||||
// std::fprintf(stderr, "sending mapping %lx-%lx, pid %lx\n", address,
|
||||
// address + len, thr->tproc->pid);
|
||||
// if (!noOverwrite) {
|
||||
// rx::bridge.sendMemoryProtect(thr->tproc->pid, address, len, prot);
|
||||
// }
|
||||
} else {
|
||||
std::fprintf(stderr, "ignoring mapping %lx-%lx\n", address, address + len);
|
||||
}
|
||||
|
|
@ -1168,6 +1164,8 @@ bool rx::vm::virtualQuery(const void *addr, std::int32_t flags,
|
|||
auto alloc = *dmemIt;
|
||||
memoryType = alloc.payload.memoryType;
|
||||
blockFlags = kBlockFlagDirectMemory;
|
||||
std::fprintf(stderr, "virtual query %p", addr);
|
||||
std::fprintf(stderr, "memory type: %u\n", memoryType);
|
||||
}
|
||||
// TODO
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue