[orbis-kernel] Initial rfork implementation

This commit is contained in:
DH 2023-10-31 14:22:22 +03:00
parent 058c746ac1
commit e9897441fe
17 changed files with 294 additions and 50 deletions

View file

@ -659,7 +659,7 @@ SysResult sys_opmc_get_ctr(Thread *thread /* TODO */);
SysResult sys_budget_create(Thread *thread /* TODO */);
SysResult sys_budget_delete(Thread *thread /* TODO */);
SysResult sys_budget_get(Thread *thread /* TODO */);
SysResult sys_budget_set(Thread *thread /* TODO */);
SysResult sys_budget_set(Thread *thread, slong budget);
SysResult sys_virtual_query(Thread *thread, ptr<void> addr, uint64_t unk,
ptr<void> info, size_t infosz);
SysResult sys_mdbg_call(Thread *thread /* TODO */);

View file

@ -39,4 +39,6 @@ struct Thread {
void incRef() {}
void decRef() {}
};
extern thread_local Thread *g_currentThread;
} // namespace orbis

View file

@ -33,6 +33,16 @@ class RcIdMap {
}
}
bool insert(std::size_t index, T *object) {
if (mask.test(index)) {
return false;
}
mask.set(index);
objects[index] = object;
return true;
}
std::size_t insert(T *object) {
std::size_t index = mask.countr_one();
mask.set(index);
@ -117,6 +127,28 @@ public:
end_iterator end() const { return {}; }
private:
bool insert_impl(IdT id, T *object) {
std::lock_guard lock(mutex);
auto raw = static_cast<std::size_t>(id);
auto page = (raw - MinId) / ChunkSize;
auto index = (raw - MinId) % ChunkSize;
if (page >= ChunkCount) {
return false;
}
if (!m_chunks[page].insert(index, object)) {
return false;
}
if (m_chunks[page].mask.full()) {
m_fullChunks.set(page);
}
return true;
}
IdT insert_impl(T *object) {
std::lock_guard lock(mutex);
@ -159,7 +191,29 @@ public:
return result;
}
T *get(IdT id) {
bool insert(IdT id, T *object) {
if (insert_impl(id, object)) {
object->incRef();
return true;
}
return false;
}
bool insert(IdT id, const Ref<T> &ref) { return insert(id, ref.get()); }
bool insert(IdT id, Ref<T> &&ref) {
auto object = ref.release();
if (!insert_impl(id, object)) {
object->decRef();
return false;
}
return true;
}
Ref<T> get(IdT id) {
const auto rawId = static_cast<std::size_t>(id) - MinId;
if (rawId >= MaxId - MinId) {

View file

@ -6,11 +6,14 @@
#include <sys/unistd.h>
namespace orbis {
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,
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (!ptr)
std::abort();

View file

@ -1,10 +1,52 @@
#include "KernelContext.hpp"
#include "sys/sysproto.hpp"
#include "utils/Logs.hpp"
#include <cstdlib>
#include <unistd.h>
orbis::SysResult orbis::sys_fork(Thread *thread) { return ErrorCode::NOSYS; }
orbis::SysResult orbis::sys_pdfork(Thread *thread, ptr<sint> fdp, sint flags) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_vfork(Thread *thread) { return ErrorCode::NOSYS; }
orbis::SysResult orbis::sys_rfork(Thread *thread, sint flags) {
return ErrorCode::NOSYS;
ORBIS_LOG_TODO(__FUNCTION__, flags);
int hostPid = ::fork();
if (hostPid) {
thread->retval[0] = 10001;
thread->retval[1] = 0;
} else {
auto process = g_context.createProcess(10001);
std::lock_guard lock(thread->tproc->fileDescriptors.mutex);
process->sysent = thread->tproc->sysent;
process->onSysEnter = thread->tproc->onSysEnter;
process->onSysExit = thread->tproc->onSysExit;
process->ops = thread->tproc->ops;
process->isSystem = thread->tproc->isSystem;
for (auto [id, mod] : thread->tproc->modulesMap) {
if (!process->modulesMap.insert(id, mod)) {
std::abort();
}
}
for (auto [id, mod] : thread->tproc->fileDescriptors) {
if (!process->fileDescriptors.insert(id, mod)) {
std::abort();
}
}
auto [baseId, newThread] = process->threadsMap.emplace();
newThread->tproc = process;
newThread->tid = process->pid + baseId;
newThread->state = orbis::ThreadState::RUNNING;
newThread->context = thread->context;
newThread->fsBase = thread->fsBase;
orbis::g_currentThread = newThread;
newThread->retval[0] = 0;
newThread->retval[1] = 1;
}
return {};
}

View file

@ -51,7 +51,7 @@ orbis::SysResult orbis::sys_socketclose(Thread *thread, sint fd) {
return ErrorCode::BADF;
}
orbis::SysResult orbis::sys_netgetiflist(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
return {};
}
orbis::SysResult orbis::sys_mtypeprotect(Thread *thread /* TODO */) {
@ -215,8 +215,9 @@ orbis::SysResult orbis::sys_evf_open(Thread *thread, ptr<const char[32]> name) {
return sys_evf_create(thread, name, kEvfAttrShared, 0x400000);
}
if (std::string_view("SceShellCoreUtilAppFocus") == _name) {
return sys_evf_create(thread, name, kEvfAttrShared, 1);
if (std::string_view("SceShellCoreUtilAppFocus") == _name ||
std::string_view("SceBootStatusFlags") == _name) {
return sys_evf_create(thread, name, kEvfAttrShared, 0x2408);
}
return sys_evf_create(thread, name, kEvfAttrShared, 0);
return ErrorCode::SRCH;
@ -290,7 +291,7 @@ 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);
pPatternSet, result);
if (pPatternSet != nullptr) {
uwrite(pPatternSet, thread->evfResultPattern);
@ -332,7 +333,7 @@ orbis::SysResult orbis::sys_evf_cancel(Thread *thread, sint id, uint64_t value,
}
ORBIS_LOG_TRACE(__FUNCTION__, evf->name, thread->tid, id, value,
pNumWaitThreads);
pNumWaitThreads);
auto numWaitThreads = evf->cancel(value);
if (pNumWaitThreads != 0) {
@ -403,7 +404,7 @@ orbis::SysResult orbis::sys_osem_create(Thread *thread,
return {};
}
orbis::SysResult orbis::sys_osem_delete(Thread *thread, sint id) {
ORBIS_LOG_WARNING(__FUNCTION__, id);
ORBIS_LOG_TRACE(__FUNCTION__, id);
Ref<Semaphore> sem = thread->tproc->semMap.get(id);
if (sem == nullptr) {
return ErrorCode::SRCH;
@ -444,7 +445,7 @@ orbis::SysResult orbis::sys_osem_open(Thread *thread,
return {};
}
orbis::SysResult orbis::sys_osem_close(Thread *thread, sint id) {
ORBIS_LOG_WARNING(__FUNCTION__, id);
ORBIS_LOG_TRACE(__FUNCTION__, id);
if (!thread->tproc->semMap.close(id)) {
return ErrorCode::SRCH;
}
@ -473,7 +474,7 @@ orbis::SysResult orbis::sys_osem_wait(Thread *thread, sint id, sint need,
return {};
}
orbis::SysResult orbis::sys_osem_trywait(Thread *thread, sint id, sint need) {
ORBIS_LOG_NOTICE(__FUNCTION__, thread, id, need);
ORBIS_LOG_TRACE(__FUNCTION__, thread, id, need);
Ref<Semaphore> sem = thread->tproc->semMap.get(id);
if (need < 1 || need > sem->maxValue)
return ErrorCode::INVAL;
@ -485,7 +486,7 @@ orbis::SysResult orbis::sys_osem_trywait(Thread *thread, sint id, sint need) {
return {};
}
orbis::SysResult orbis::sys_osem_post(Thread *thread, sint id, sint count) {
ORBIS_LOG_NOTICE(__FUNCTION__, thread, id, count);
ORBIS_LOG_WARNING(__FUNCTION__, thread, id, count);
Ref<Semaphore> sem = thread->tproc->semMap.get(id);
if (count < 1 || count > sem->maxValue - sem->value)
return ErrorCode::INVAL;
@ -500,6 +501,7 @@ orbis::SysResult orbis::sys_osem_post(Thread *thread, sint id, sint count) {
orbis::SysResult orbis::sys_osem_cancel(Thread *thread, sint id, sint set,
ptr<uint> pNumWaitThreads) {
ORBIS_LOG_TODO(__FUNCTION__, thread, id, set, pNumWaitThreads);
std::abort();
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_namedobj_create(Thread *thread,
@ -589,8 +591,9 @@ orbis::SysResult orbis::sys_budget_delete(Thread *thread /* TODO */) {
orbis::SysResult orbis::sys_budget_get(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_budget_set(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
orbis::SysResult orbis::sys_budget_set(Thread *thread, slong budget) {
ORBIS_LOG_TODO(__FUNCTION__, budget);
return {};
}
orbis::SysResult orbis::sys_virtual_query(Thread *thread, ptr<void> addr,
uint64_t unk, ptr<void> info,
@ -601,9 +604,7 @@ orbis::SysResult orbis::sys_virtual_query(Thread *thread, ptr<void> addr,
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_mdbg_call(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_mdbg_call(Thread *thread /* TODO */) { return {}; }
orbis::SysResult orbis::sys_obs_sblock_create(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
}
@ -942,7 +943,8 @@ orbis::sys_dynlib_get_info_ex(Thread *thread, SceKernelModule handle,
return uwrite(destModuleInfoEx, result);
}
orbis::SysResult orbis::sys_budget_getid(Thread *thread) {
return ErrorCode::NOSYS;
thread->retval[0] = 1;
return {};
}
orbis::SysResult orbis::sys_budget_get_ptype(Thread *thread, sint budgetId) {
thread->retval[0] = 1;

View file

@ -57,6 +57,8 @@ void orbis::syscall_entry(Thread *thread) {
auto result = sysent.call(thread, args);
thread = orbis::g_currentThread;
if (thread->tproc->onSysExit != nullptr) {
thread->tproc->onSysExit(thread, syscall_num, args, sysent.narg,
result);