[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:
DH 2024-01-13 20:57:02 +03:00
parent 8791312d4f
commit 65e653f5ef
81 changed files with 2586 additions and 761 deletions

View file

@ -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() {

View file

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

View file

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

View file

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

View file

@ -84,7 +84,7 @@ struct KNote {
~KNote();
};
struct EventEmitter {
struct EventEmitter : orbis::RcBase {
shared_mutex mutex;
std::set<KNote *, std::less<>, kallocator<KNote *>> notes;

View file

@ -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 */);

View file

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

View file

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

View file

@ -19,5 +19,6 @@ enum class RegisterId {
rax,
rsp,
rflags,
rip,
};
} // namespace orbis

View file

@ -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() {}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 &note = *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 &note = *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();

View file

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

View file

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

View file

@ -1,5 +1,7 @@
#include "KernelContext.hpp"
#include "sys/sysproto.hpp"
#include "thread/Process.hpp"
#include "thread/ProcessOps.hpp"
#include <cstdlib>
#include <unistd.h>

View file

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

View file

@ -1,4 +1,5 @@
#include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "utils/Logs.hpp"
#include <thread>

View file

@ -1,4 +1,6 @@
#include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
#include "utils/Logs.hpp"
#include <pipe.hpp>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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);

View file

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

View file

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

View file

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

View file

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

View file

@ -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
View 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);
}

View file

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

View file

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

View file

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

View file

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

View 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
View 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>(); }

View file

@ -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
View 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);
};

View file

@ -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>(); }

View file

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

View file

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

View file

@ -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
View 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
View 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>(); }

View file

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

View file

@ -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, {});
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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