kernel: split context and allocator & initial implementation of process/thread local objects
Some checks are pending
Formatting check / formatting-check (push) Waiting to run
Build RPCSX / build-linux (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8.1-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8.2-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8.4-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8.5-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv9-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv9.1-a) (push) Waiting to run
Build RPCSX / build-android (x86_64, x86-64) (push) Waiting to run

This commit is contained in:
DH 2025-10-10 19:56:11 +03:00
parent b358d6b2c9
commit 2589143798
34 changed files with 774 additions and 597 deletions

View file

@ -1,139 +0,0 @@
#pragma once
#include "rx/LinkedNode.hpp"
#include "rx/Serializer.hpp"
#include <cassert>
namespace kernel {
namespace detail {
struct GlobalObjectCtl {
void (*construct)();
void (*destruct)();
void (*serialize)(rx::Serializer &);
void (*deserialize)(rx::Deserializer &);
};
template <typename NamespaceT, typename T> struct GlobalKernelObjectInstance {
static inline T *instance = nullptr;
static inline rx::LinkedNode<GlobalObjectCtl> ctl = {
.object = {
.construct = +[] { instance->construct(); },
.destruct = +[] { instance->destruct(); },
.serialize = +[](rx::Serializer &s) { instance->serialize(s); },
.deserialize = +[](rx::Deserializer &s) { instance->deserialize(s); },
},
};
};
} // namespace detail
template <typename NamespaceT> struct GlobalKernelObjectStorage {
template <typename T> static void AddObject() {
auto node = &detail::GlobalKernelObjectInstance<NamespaceT, T>::ctl;
auto head = GetHead();
if (head) {
head->prev = node;
node->next = head;
}
*GetHeadPtr() = node;
}
static void ConstructAll() {
for (auto it = GetHead(); it != nullptr; it = it->next) {
it->object.construct();
}
}
static void DestructAll() {
for (auto it = GetHead(); it != nullptr; it = it->next) {
it->object.destruct();
}
}
static void SerializeAll(rx::Serializer &s) {
for (auto it = GetHead(); it != nullptr; it = it->next) {
it->object.serialize(s);
}
}
static void DeserializeAll(rx::Deserializer &s) {
for (auto it = GetHead(); it != nullptr; it = it->next) {
it->object.deserialize(s);
}
}
private:
static rx::LinkedNode<detail::GlobalObjectCtl> *GetHead() {
return *GetHeadPtr();
}
static rx::LinkedNode<detail::GlobalObjectCtl> **GetHeadPtr() {
static rx::LinkedNode<detail::GlobalObjectCtl> *registry;
return &registry;
}
};
template <rx::Serializable T, typename NamespaceT>
requires std::is_default_constructible_v<T>
class GlobalKernelObject {
union U {
T object;
U() {}
~U() {}
};
U mHolder;
public:
template <typename = void> GlobalKernelObject() {
auto &instance =
detail::GlobalKernelObjectInstance<NamespaceT,
GlobalKernelObject>::instance;
assert(instance == nullptr);
instance = this;
GlobalKernelObjectStorage<NamespaceT>::template AddObject<
GlobalKernelObject>();
}
T *operator->() { return &mHolder.object; }
const T *operator->() const { return &mHolder.object; }
T &operator*() { return mHolder.object; }
const T &operator*() const { return mHolder.object; }
operator T &() { return mHolder.object; }
operator const T &() const { return mHolder.object; }
void serialize(rx::Serializer &s)
requires rx::Serializable<T>
{
s.serialize(mHolder.object);
}
void deserialize(rx::Deserializer &s)
requires rx::Serializable<T>
{
std::construct_at(&mHolder.object);
s.deserialize(mHolder.object);
}
T &get() { return mHolder.object; }
const T &get() const { return mHolder.object; }
private:
template <typename... Args>
requires(std::is_constructible_v<T, Args && ...>)
void construct(Args &&...args) noexcept(
std::is_nothrow_constructible_v<T, Args &&...>) {
std::construct_at(&mHolder.object, std::forward<Args>(args)...);
}
template <typename... Args>
void destruct() noexcept(std::is_nothrow_destructible_v<T>) {
mHolder.object.~T();
}
friend detail::GlobalKernelObjectInstance<NamespaceT, GlobalKernelObject>;
};
} // namespace kernel

View file

@ -0,0 +1,180 @@
#pragma once
#include "rx/Rc.hpp"
#include "rx/Serializer.hpp"
#include "rx/TypeId.hpp"
#include <memory>
#include <mutex>
namespace kernel {
class KernelObjectBase : public rx::RcBase {
rx::TypeId mType;
public:
KernelObjectBase(rx::TypeId type) : mType(type) {}
[[nodiscard]] rx::TypeId getType() const { return mType; }
template <typename T> [[nodiscard]] bool isa() const {
return mType == rx::TypeId::get<T>();
}
};
template <rx::Serializable StateT>
struct KernelObject : KernelObjectBase, StateT {
template <typename... Args>
KernelObject(Args &&...args)
: KernelObjectBase(rx::TypeId::get<StateT>()),
StateT(std::forward<Args>(args)...) {}
virtual void serialize(rx::Serializer &s) const {
if constexpr (requires(const KernelObject &instance) {
instance.lock();
instance.unlock();
}) {
std::lock_guard lock(*this);
s.serialize(static_cast<const StateT &>(*this));
} else {
s.serialize(static_cast<const StateT &>(*this));
}
}
virtual void deserialize(rx::Deserializer &s) {
s.deserialize(static_cast<StateT &>(*this));
}
};
namespace detail {
struct StaticObjectCtl {
std::size_t offset = -1ull;
void (*construct)(void *object);
void (*destruct)(void *object);
void (*serialize)(void *object, rx::Serializer &);
void (*deserialize)(void *object, rx::Deserializer &);
template <typename T> constexpr static StaticObjectCtl Create() {
return {
.construct =
+[](void *object) {
std::construct_at(reinterpret_cast<T *>(object));
},
.destruct = +[](void *object) { reinterpret_cast<T *>(object)->~T(); },
.serialize =
+[](void *object, rx::Serializer &serializer) {
serializer.serialize(*reinterpret_cast<T *>(object));
},
.deserialize =
+[](void *object, rx::Deserializer &deserializer) {
deserializer.deserialize(*reinterpret_cast<T *>(object));
},
};
}
};
struct GlobalScope;
struct ProcessScope;
struct ThreadScope;
} // namespace detail
template <typename NamespaceT, typename ScopeT> std::byte *getScopeStorage();
template <typename NamespaceT, typename ScopeT>
struct StaticKernelObjectStorage {
template <typename T> static std::uint32_t Allocate() {
auto &instance = GetInstance();
auto object = detail::StaticObjectCtl::Create<T>();
instance.m_registry.push_back(object);
auto offset = instance.m_size;
offset = rx::alignUp(offset, alignof(T));
instance.m_registry.back().offset = offset;
instance.m_size = offset + sizeof(T);
instance.m_alignment =
std::max<std::size_t>(alignof(T), instance.m_alignment);
// std::printf(
// "%s::Allocate(%s, %zu, %zu) -> %zu\n",
// rx::TypeId::get<StaticKernelObjectStorage<NamespaceT,
// ScopeT>>().getName().data(), rx::TypeId::get<T>().getName().data(),
// sizeof(T), alignof(T), offset);
return offset;
}
static std::size_t GetSize() { return GetInstance().m_size; }
static std::size_t GetAlignment() { return GetInstance().m_alignment; }
static std::byte *getScopeStorage() {
return kernel::getScopeStorage<NamespaceT, ScopeT>();
}
static void ConstructAll() {
auto &instance = GetInstance();
auto storage = getScopeStorage();
for (auto objectCtl : instance.m_registry) {
objectCtl.construct(storage + objectCtl.offset);
}
}
static void DestructAll() {
auto &instance = GetInstance();
auto storage = getScopeStorage();
for (auto objectCtl : instance.m_registry) {
objectCtl.destruct(storage + objectCtl.offset);
}
}
static void SerializeAll(rx::Serializer &s) {
auto &instance = GetInstance();
auto storage = getScopeStorage();
s.serialize(instance.m_size);
s.serialize(instance.m_registry.size());
for (auto objectCtl : instance.m_registry) {
objectCtl.serialize(storage + objectCtl.offset, s);
}
}
static void DeserializeAll(rx::Deserializer &s) {
auto &instance = GetInstance();
auto storage = getScopeStorage();
auto size = s.deserialize<std::size_t>();
auto registrySize = s.deserialize<std::size_t>();
if (size != instance.m_size || registrySize != instance.m_registry.size()) {
s.setFailure();
return;
}
for (auto objectCtl : instance.m_registry) {
objectCtl.deserialize(storage + objectCtl.offset, s);
}
}
private:
static StaticKernelObjectStorage &GetInstance() {
static StaticKernelObjectStorage instance;
return instance;
}
std::vector<detail::StaticObjectCtl> m_registry;
std::size_t m_size = 0;
std::size_t m_alignment = 1;
};
template <typename NamespaceT, typename ScopeT, rx::Serializable T>
class StaticObjectRef {
std::uint32_t mOffset;
public:
explicit StaticObjectRef(std::uint32_t offset) : mOffset(offset) {}
T *get() {
return reinterpret_cast<T *>(getScopeStorage<NamespaceT, ScopeT>() +
mOffset);
}
T *operator->() { return get(); }
};
} // namespace kernel

View file

@ -7,6 +7,7 @@ add_library(obj.orbis-kernel OBJECT
src/event.cpp
src/evf.cpp
src/ipmi.cpp
src/KernelAllocator.cpp
src/KernelContext.cpp
src/umtx.cpp
src/sys/sys_acct.cpp

View file

@ -1,26 +0,0 @@
#pragma once
#include <kernel/GlobalKernelObject.hpp>
namespace orbis {
struct OrbisNamespace;
template <rx::Serializable T>
using GlobalKernelObject = kernel::GlobalKernelObject<T, OrbisNamespace>;
template <rx::Serializable T> GlobalKernelObject<T> createGlobalObject() {
return {};
}
inline void constructAllGlobals() {
kernel::GlobalKernelObjectStorage<OrbisNamespace>::ConstructAll();
}
inline void destructAllGlobals() {
kernel::GlobalKernelObjectStorage<OrbisNamespace>::DestructAll();
}
template <typename T> T &getGlobalObject() {
assert(detail::GlobalKernelObjectInstance<GlobalKernelObject<T>>::instance);
return kernel::detail::GlobalKernelObjectInstance<
OrbisNamespace, GlobalKernelObject<T>>::instance->get();
}
} // namespace orbis

View file

@ -10,7 +10,6 @@
#include <vector>
namespace orbis {
inline namespace utils {
void *kalloc(std::size_t size, std::size_t align);
void kfree(void *ptr, std::size_t size);
template <typename T> struct kallocator {
@ -51,7 +50,6 @@ template <typename K, typename T, typename Hash = std::hash<K>,
typename Pred = std::equal_to<K>>
using kunmap =
std::unordered_map<K, T, Hash, Pred, kallocator<std::pair<const K, T>>>;
} // namespace utils
template <typename T, typename... Args>
requires(std::is_constructible_v<T, Args...>)
@ -61,17 +59,17 @@ T *knew(Args &&...args) {
struct DynamicObject final : T {
using T::T;
void operator delete(void *pointer) { utils::kfree(pointer, sizeof(T)); }
void operator delete(void *pointer) { kfree(pointer, sizeof(T)); }
};
auto loc = static_cast<DynamicObject *>(
utils::kalloc(sizeof(DynamicObject), alignof(DynamicObject)));
kalloc(sizeof(DynamicObject), alignof(DynamicObject)));
return std::construct_at(loc, std::forward<Args>(args)...);
} else {
static_assert(!std::is_polymorphic_v<T>,
"Polymorphic type should be derived from rx::RcBase");
auto loc = static_cast<T *>(utils::kalloc(sizeof(T), alignof(T)));
auto loc = static_cast<T *>(kalloc(sizeof(T), alignof(T)));
return std::construct_at(loc, std::forward<Args>(args)...);
}
}
@ -80,8 +78,10 @@ T *knew(Args &&...args) {
template <typename T> void kdelete(T *ptr) {
static_assert(std::is_final_v<T>, "Uncertain type size");
ptr->~T();
utils::kfree(ptr, sizeof(T));
kfree(ptr, sizeof(T));
}
// clang-format on
void initializeAllocator();
void deinitializeAllocator();
} // namespace orbis

View file

@ -1,7 +1,7 @@
#pragma once
#include "AppInfo.hpp"
#include "Budget.hpp"
#include "KernelAllocator.hpp"
#include "KernelObject.hpp"
#include "evf.hpp"
#include "ipmi.hpp"
#include "orbis/note.hpp"
@ -50,12 +50,7 @@ public:
long getTscFreq();
void *kalloc(std::size_t size,
std::size_t align = __STDCPP_DEFAULT_NEW_ALIGNMENT__);
void kfree(void *ptr, std::size_t size);
std::pair<EventFlag *, bool> createEventFlag(utils::kstring name,
std::int32_t flags,
std::pair<EventFlag *, bool> createEventFlag(kstring name, std::int32_t flags,
std::uint64_t initPattern) {
std::lock_guard lock(m_evf_mtx);
@ -78,7 +73,7 @@ public:
return {};
}
std::pair<Semaphore *, bool> createSemaphore(utils::kstring name,
std::pair<Semaphore *, bool> createSemaphore(kstring name,
std::uint32_t attrs,
std::int32_t initCount,
std::int32_t maxCount) {
@ -100,8 +95,7 @@ public:
return {};
}
std::pair<rx::Ref<IpmiServer>, ErrorCode>
createIpmiServer(utils::kstring name) {
std::pair<rx::Ref<IpmiServer>, ErrorCode> createIpmiServer(kstring name) {
std::lock_guard lock(m_sem_mtx);
auto [it, inserted] = mIpmiServers.try_emplace(std::move(name), nullptr);
@ -128,15 +122,14 @@ public:
return {};
}
std::tuple<utils::kmap<utils::kstring, char[128]> &,
std::unique_lock<rx::shared_mutex>>
std::tuple<kmap<kstring, char[128]> &, std::unique_lock<rx::shared_mutex>>
getKernelEnv() {
std::unique_lock lock(m_kenv_mtx);
return {m_kenv, std::move(lock)};
}
void setKernelEnv(std::string_view key, std::string_view value) {
auto &kenvValue = m_kenv[utils::kstring(key)];
auto &kenvValue = m_kenv[kstring(key)];
auto len = std::min(sizeof(kenvValue) - 1, value.size());
std::memcpy(kenvValue, value.data(), len);
kenvValue[len] = '0';
@ -177,14 +170,10 @@ public:
return processTypeBudgets[static_cast<int>(processType)];
}
void serialize(rx::Serializer &) const {}
void deserialize(rx::Deserializer &) {}
private:
rx::shared_mutex m_heap_mtx;
rx::shared_mutex m_heap_map_mtx;
void *m_heap_next = this + 1;
utils::kmultimap<std::size_t, void *> m_free_heap;
utils::kmultimap<std::size_t, void *> m_used_node;
std::atomic<long> m_tsc_freq{0};
rx::shared_mutex m_thread_id_mtx;
@ -193,17 +182,17 @@ private:
rx::LinkedNode<Process> *m_processes = nullptr;
rx::shared_mutex m_evf_mtx;
utils::kmap<utils::kstring, rx::Ref<EventFlag>> m_event_flags;
kmap<kstring, rx::Ref<EventFlag>> m_event_flags;
rx::shared_mutex m_sem_mtx;
utils::kmap<utils::kstring, rx::Ref<Semaphore>> m_semaphores;
kmap<kstring, rx::Ref<Semaphore>> m_semaphores;
rx::shared_mutex mIpmiServerMtx;
utils::kmap<utils::kstring, rx::Ref<IpmiServer>> mIpmiServers;
kmap<kstring, rx::Ref<IpmiServer>> mIpmiServers;
rx::shared_mutex m_kenv_mtx;
utils::kmap<utils::kstring, char[128]> m_kenv; // max size: 127 + '\0'
kmap<kstring, char[128]> m_kenv; // max size: 127 + '\0'
};
extern KernelContext &g_context;
extern GlobalObjectRef<KernelContext> g_context;
} // namespace orbis

View file

@ -0,0 +1,108 @@
#pragma once
#include <kernel/KernelObject.hpp>
namespace orbis {
struct OrbisNamespace;
template <rx::Serializable StateT>
using GlobalObjectRef =
kernel::StaticObjectRef<OrbisNamespace, kernel::detail::GlobalScope,
StateT>;
template <rx::Serializable StateT>
using ProcessLocalObjectRef =
kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ProcessScope,
StateT>;
template <rx::Serializable StateT>
using ThreadLocalObjectRef =
kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ThreadScope,
StateT>;
template <rx::Serializable StateT>
GlobalObjectRef<StateT> createGlobalObject() {
auto layoutOffset = kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::GlobalScope>::template Allocate<StateT>();
return GlobalObjectRef<StateT>(layoutOffset);
}
template <rx::Serializable StateT>
kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ProcessScope, StateT>
createProcessLocalObject() {
auto layoutOffset = kernel::StaticKernelObjectStorage<
OrbisNamespace,
kernel::detail::ProcessScope>::template Allocate<StateT>();
return kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ProcessScope,
StateT>(layoutOffset);
}
template <rx::Serializable StateT>
kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ThreadScope, StateT>
createThreadLocalObject() {
auto layoutOffset = kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ThreadScope>::template Allocate<StateT>();
return kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ThreadScope,
StateT>(layoutOffset);
}
inline void constructAllGlobals() {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::GlobalScope>::ConstructAll();
}
inline void constructAllProcessLocals() {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ProcessScope>::ConstructAll();
}
inline void constructAllThreadLocals() {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ThreadScope>::ConstructAll();
}
inline void destructAllGlobals() {
kernel::StaticKernelObjectStorage<OrbisNamespace,
kernel::detail::GlobalScope>::DestructAll();
}
inline void destructAllProcessLocals() {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ProcessScope>::DestructAll();
}
inline void destructAllThreadLocals() {
kernel::StaticKernelObjectStorage<OrbisNamespace,
kernel::detail::ThreadScope>::DestructAll();
}
inline void serializeAllGlobals(rx::Serializer &s) {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::GlobalScope>::SerializeAll(s);
}
inline void serializeAllProcessLocals(rx::Serializer &s) {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ProcessScope>::SerializeAll(s);
}
inline void serializeAllThreadLocals(rx::Serializer &s) {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ThreadScope>::SerializeAll(s);
}
inline void deserializeAllGlobals(rx::Deserializer &s) {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::GlobalScope>::DeserializeAll(s);
}
inline void deserializeAllProcessLocals(rx::Deserializer &s) {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ProcessScope>::DeserializeAll(s);
}
inline void deserializeAllThreadLocals(rx::Deserializer &s) {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ThreadScope>::DeserializeAll(s);
}
} // namespace orbis

View file

@ -57,7 +57,7 @@ struct EventFlag final {
};
rx::shared_mutex queueMtx;
utils::kvector<WaitingThread> waitingThreads;
kvector<WaitingThread> waitingThreads;
enum class NotifyType { Set, Cancel, Destroy };

View file

@ -82,7 +82,7 @@ struct File : rx::RcBase {
int flags = 0;
int mode = 0;
int hostFd = -1;
utils::kvector<Dirent> dirEntries;
kvector<Dirent> dirEntries;
bool noBlock() const { return (flags & 4) != 0; }
};

View file

@ -21,7 +21,7 @@ enum class DynType : std::uint8_t {
};
struct ModuleNeeded {
utils::kstring name;
kstring name;
std::uint16_t version;
std::uint64_t attr;
bool isExport;
@ -67,7 +67,7 @@ struct Relocation {
struct Module final {
Process *proc{};
utils::kstring vfsPath;
kstring vfsPath;
char moduleName[256]{};
char soName[256]{};
ModuleHandle id{};
@ -110,15 +110,15 @@ struct Module final {
bool isTlsDone = false;
utils::kstring interp;
utils::kvector<Symbol> symbols;
utils::kvector<Relocation> pltRelocations;
utils::kvector<Relocation> nonPltRelocations;
utils::kvector<ModuleNeeded> neededModules;
utils::kvector<ModuleNeeded> neededLibraries;
utils::kvector<rx::Ref<Module>> importedModules;
utils::kvector<rx::Ref<Module>> namespaceModules;
utils::kvector<utils::kstring> needed;
kstring interp;
kvector<Symbol> symbols;
kvector<Relocation> pltRelocations;
kvector<Relocation> nonPltRelocations;
kvector<ModuleNeeded> neededModules;
kvector<ModuleNeeded> neededLibraries;
kvector<rx::Ref<Module>> importedModules;
kvector<rx::Ref<Module>> namespaceModules;
kvector<kstring> needed;
std::atomic<unsigned> references{0};

View file

@ -93,13 +93,13 @@ struct Process final {
// Named objects for debugging
rx::shared_mutex namedObjMutex;
utils::kmap<void *, utils::kstring> namedObjNames;
kmap<void *, kstring> namedObjNames;
rx::OwningIdMap<NamedObjInfo, uint, 65535, 1> namedObjIds;
utils::kmap<std::int32_t, SigAction> sigActions;
kmap<std::int32_t, SigAction> sigActions;
// Named memory ranges for debugging
rx::shared_mutex namedMemMutex;
utils::kmap<NamedMemoryRange, utils::kstring> namedMem;
kmap<NamedMemoryRange, kstring> namedMem;
};
} // namespace orbis

View file

@ -0,0 +1,221 @@
#include "KernelAllocator.hpp"
#include "KernelObject.hpp"
#include "rx/Serializer.hpp"
#include "rx/SharedMutex.hpp"
#include "rx/print.hpp"
#include <sys/mman.h>
static const std::uint64_t g_allocProtWord = 0xDEADBEAFBADCAFE1;
static constexpr std::uintptr_t kHeapBaseAddress = 0x00000600'0000'0000;
static constexpr auto kHeapSize = 0x1'0000'0000;
static constexpr int kDebugHeap = 0;
namespace orbis {
struct KernelMemoryResource {
mutable rx::shared_mutex m_heap_mtx;
rx::shared_mutex m_heap_map_mtx;
void *m_heap_next = nullptr;
kmultimap<std::size_t, void *> m_free_heap;
kmultimap<std::size_t, void *> m_used_node;
~KernelMemoryResource() {
::munmap(std::bit_cast<void *>(kHeapBaseAddress), kHeapSize);
}
void *kalloc(std::size_t size,
std::size_t align = __STDCPP_DEFAULT_NEW_ALIGNMENT__);
void kfree(void *ptr, std::size_t size);
void serialize(rx::Serializer &) const {
// FIXME: implement
}
void deserialize(rx::Deserializer &) {
// FIXME: implement
}
void lock() const { m_heap_mtx.lock(); }
void unlock() const { m_heap_mtx.unlock(); }
};
static KernelMemoryResource *sMemoryResource;
static std::byte *sGlobalStorage;
using GlobalStorage =
kernel::StaticKernelObjectStorage<OrbisNamespace,
kernel::detail::GlobalScope>;
void initializeAllocator() {
auto ptr = (std::byte *)::mmap(std::bit_cast<void *>(kHeapBaseAddress),
kHeapSize, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (ptr == MAP_FAILED) {
perror("mmap failed");
FILE *maps = std::fopen("/proc/self/maps", "r");
char *line = nullptr;
std::size_t size = 0;
while (getline(&line, &size, maps) > 0) {
std::puts(line);
}
std::free(line);
std::fclose(maps);
std::abort();
}
sMemoryResource = new (ptr) KernelMemoryResource();
sMemoryResource->m_heap_next = ptr + sizeof(KernelMemoryResource);
rx::print(stderr, "global: size {}, alignment {}\n", GlobalStorage::GetSize(),
GlobalStorage::GetAlignment());
// allocate whole global storage
sGlobalStorage = (std::byte *)sMemoryResource->kalloc(
GlobalStorage::GetSize(), GlobalStorage::GetAlignment());
}
void deinitializeAllocator() {
sMemoryResource->kfree(sGlobalStorage, GlobalStorage::GetSize());
delete sMemoryResource;
sMemoryResource = nullptr;
sGlobalStorage = nullptr;
}
void *KernelMemoryResource::kalloc(std::size_t size, std::size_t align) {
size = (size + (__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1)) &
~(__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1);
if (!size)
std::abort();
if (m_heap_map_mtx.try_lock()) {
std::lock_guard lock(m_heap_map_mtx, std::adopt_lock);
// Try to reuse previously freed block
for (auto [it, end] = m_free_heap.equal_range(size); it != end; ++it) {
auto result = it->second;
if (!(std::bit_cast<std::uintptr_t>(result) & (align - 1))) {
auto node = m_free_heap.extract(it);
node.key() = 0;
node.mapped() = nullptr;
m_used_node.insert(m_used_node.begin(), std::move(node));
// std::fprintf(stderr, "kalloc: reuse %p-%p, size = %lx\n", result,
// (char *)result + size, size);
if (kDebugHeap > 0) {
std::memcpy(std::bit_cast<std::byte *>(result) + size,
&g_allocProtWord, sizeof(g_allocProtWord));
}
return result;
}
}
}
std::lock_guard lock(m_heap_mtx);
align = std::max<std::size_t>(align, __STDCPP_DEFAULT_NEW_ALIGNMENT__);
auto heap = reinterpret_cast<std::uintptr_t>(m_heap_next);
heap = (heap + (align - 1)) & ~(align - 1);
if (kDebugHeap > 1) {
if (auto diff = (heap + size + sizeof(g_allocProtWord)) % 4096; diff != 0) {
heap += 4096 - diff;
heap &= ~(align - 1);
}
}
if (heap + size > kHeapBaseAddress + kHeapSize) {
std::fprintf(stderr, "out of kernel memory");
std::abort();
}
// Check overflow
if (heap + size < heap) {
std::fprintf(stderr, "too big allocation");
std::abort();
}
// std::fprintf(stderr, "kalloc: allocate %lx-%lx, size = %lx, align=%lx\n",
// heap, heap + size, size, align);
auto result = reinterpret_cast<void *>(heap);
if (kDebugHeap > 0) {
std::memcpy(std::bit_cast<std::byte *>(result) + size, &g_allocProtWord,
sizeof(g_allocProtWord));
}
if (kDebugHeap > 0) {
m_heap_next =
reinterpret_cast<void *>(heap + size + sizeof(g_allocProtWord));
} else {
m_heap_next = reinterpret_cast<void *>(heap + size);
}
if (kDebugHeap > 1) {
heap = reinterpret_cast<std::uintptr_t>(m_heap_next);
align = std::min<std::size_t>(align, 4096);
heap = (heap + (align - 1)) & ~(align - 1);
size = 4096;
// std::fprintf(stderr, "kalloc: protect %lx-%lx, size = %lx, align=%lx\n",
// heap, heap + size, size, align);
auto result = ::mmap(reinterpret_cast<void *>(heap), size, PROT_NONE,
MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, -1, 0);
if (result == MAP_FAILED) {
std::fprintf(stderr, "failed to protect memory");
std::abort();
}
m_heap_next = reinterpret_cast<void *>(heap + size);
}
return result;
}
void KernelMemoryResource::kfree(void *ptr, std::size_t size) {
size = (size + (__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1)) &
~(__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1);
if (!size)
std::abort();
if (std::bit_cast<std::uintptr_t>(ptr) < kHeapBaseAddress ||
std::bit_cast<std::uintptr_t>(ptr) + size >
kHeapBaseAddress + kHeapSize) {
std::fprintf(stderr, "kfree: invalid address");
std::abort();
}
if (kDebugHeap > 0) {
if (std::memcmp(std::bit_cast<std::byte *>(ptr) + size, &g_allocProtWord,
sizeof(g_allocProtWord)) != 0) {
std::fprintf(stderr, "kernel heap corruption\n");
std::abort();
}
std::memset(ptr, 0xcc, size + sizeof(g_allocProtWord));
}
// std::fprintf(stderr, "kfree: release %p-%p, size = %lx\n", ptr,
// (char *)ptr + size, size);
std::lock_guard lock(m_heap_map_mtx);
if (!m_used_node.empty()) {
auto node = m_used_node.extract(m_used_node.begin());
node.key() = size;
node.mapped() = ptr;
m_free_heap.insert(std::move(node));
} else {
m_free_heap.emplace(size, ptr);
}
}
void kfree(void *ptr, std::size_t size) {
return sMemoryResource->kfree(ptr, size);
}
void *kalloc(std::size_t size, std::size_t align) {
return sMemoryResource->kalloc(size, align);
}
} // namespace orbis
template <>
std::byte *
kernel::getScopeStorage<orbis::OrbisNamespace, kernel::detail::GlobalScope>() {
return orbis::sGlobalStorage;
}

View file

@ -1,4 +1,5 @@
#include "orbis/KernelContext.hpp"
#include "KernelObject.hpp"
#include "orbis/thread/Process.hpp"
#include "orbis/thread/ProcessOps.hpp"
#include "orbis/utils/Logs.hpp"
@ -13,37 +14,10 @@
#include <unistd.h>
#include <utility>
static const std::uint64_t g_allocProtWord = 0xDEADBEAFBADCAFE1;
static constexpr std::uintptr_t kHeapBaseAddress = 0x00000600'0000'0000;
static constexpr auto kHeapSize = 0x1'0000'0000;
static constexpr int kDebugHeap = 0;
namespace orbis {
GlobalObjectRef<KernelContext> g_context = createGlobalObject<KernelContext>();
thread_local Thread *g_currentThread;
KernelContext &g_context = *[]() -> KernelContext * {
// Allocate global shared kernel memory
// TODO: randomize for hardening and reduce size
auto ptr = mmap(std::bit_cast<void *>(kHeapBaseAddress), kHeapSize,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (ptr == MAP_FAILED) {
perror("mmap failed");
FILE *maps = fopen("/proc/self/maps", "r");
char *line = nullptr;
std::size_t size = 0;
while (getline(&line, &size, maps) > 0) {
std::printf("%s", line);
}
free(line);
fclose(maps);
std::abort();
}
return new (ptr) KernelContext;
}();
KernelContext::KernelContext() {
// std::printf("orbis::KernelContext initialized, addr=%p\n", this);
// std::printf("TSC frequency: %lu\n", getTscFreq());
@ -158,138 +132,6 @@ long KernelContext::getTscFreq() {
return m_tsc_freq.load();
}
void *KernelContext::kalloc(std::size_t size, std::size_t align) {
size = (size + (__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1)) &
~(__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1);
if (!size)
std::abort();
if (m_heap_map_mtx.try_lock()) {
std::lock_guard lock(m_heap_map_mtx, std::adopt_lock);
// Try to reuse previously freed block
for (auto [it, end] = m_free_heap.equal_range(size); it != end; ++it) {
auto result = it->second;
if (!(std::bit_cast<std::uintptr_t>(result) & (align - 1))) {
auto node = m_free_heap.extract(it);
node.key() = 0;
node.mapped() = nullptr;
m_used_node.insert(m_used_node.begin(), std::move(node));
// std::fprintf(stderr, "kalloc: reuse %p-%p, size = %lx\n", result,
// (char *)result + size, size);
if (kDebugHeap > 0) {
std::memcpy(std::bit_cast<std::byte *>(result) + size,
&g_allocProtWord, sizeof(g_allocProtWord));
}
return result;
}
}
}
std::lock_guard lock(m_heap_mtx);
align = std::max<std::size_t>(align, __STDCPP_DEFAULT_NEW_ALIGNMENT__);
auto heap = reinterpret_cast<std::uintptr_t>(m_heap_next);
heap = (heap + (align - 1)) & ~(align - 1);
if (kDebugHeap > 1) {
if (auto diff = (heap + size + sizeof(g_allocProtWord)) % 4096; diff != 0) {
heap += 4096 - diff;
heap &= ~(align - 1);
}
}
if (heap + size > kHeapBaseAddress + kHeapSize) {
std::fprintf(stderr, "out of kernel memory");
std::abort();
}
// Check overflow
if (heap + size < heap) {
std::fprintf(stderr, "too big allocation");
std::abort();
}
// std::fprintf(stderr, "kalloc: allocate %lx-%lx, size = %lx, align=%lx\n",
// heap, heap + size, size, align);
auto result = reinterpret_cast<void *>(heap);
if (kDebugHeap > 0) {
std::memcpy(std::bit_cast<std::byte *>(result) + size, &g_allocProtWord,
sizeof(g_allocProtWord));
}
if (kDebugHeap > 0) {
m_heap_next =
reinterpret_cast<void *>(heap + size + sizeof(g_allocProtWord));
} else {
m_heap_next = reinterpret_cast<void *>(heap + size);
}
if (kDebugHeap > 1) {
heap = reinterpret_cast<std::uintptr_t>(m_heap_next);
align = std::min<std::size_t>(align, 4096);
heap = (heap + (align - 1)) & ~(align - 1);
size = 4096;
// std::fprintf(stderr, "kalloc: protect %lx-%lx, size = %lx, align=%lx\n",
// heap, heap + size, size, align);
auto result = ::mmap(reinterpret_cast<void *>(heap), size, PROT_NONE,
MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, -1, 0);
if (result == MAP_FAILED) {
std::fprintf(stderr, "failed to protect memory");
std::abort();
}
m_heap_next = reinterpret_cast<void *>(heap + size);
}
return result;
}
void KernelContext::kfree(void *ptr, std::size_t size) {
size = (size + (__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1)) &
~(__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1);
if (!size)
std::abort();
if (std::bit_cast<std::uintptr_t>(ptr) < kHeapBaseAddress ||
std::bit_cast<std::uintptr_t>(ptr) + size >
kHeapBaseAddress + kHeapSize) {
std::fprintf(stderr, "kfree: invalid address");
std::abort();
}
if (kDebugHeap > 0) {
if (std::memcmp(std::bit_cast<std::byte *>(ptr) + size, &g_allocProtWord,
sizeof(g_allocProtWord)) != 0) {
std::fprintf(stderr, "kernel heap corruption\n");
std::abort();
}
std::memset(ptr, 0xcc, size + sizeof(g_allocProtWord));
}
// std::fprintf(stderr, "kfree: release %p-%p, size = %lx\n", ptr,
// (char *)ptr + size, size);
std::lock_guard lock(m_heap_map_mtx);
if (!m_used_node.empty()) {
auto node = m_used_node.extract(m_used_node.begin());
node.key() = size;
node.mapped() = ptr;
m_free_heap.insert(std::move(node));
} else {
m_free_heap.emplace(size, ptr);
}
}
inline namespace utils {
void kfree(void *ptr, std::size_t size) { return g_context.kfree(ptr, size); }
void *kalloc(std::size_t size, std::size_t align) {
return g_context.kalloc(size, align);
}
} // namespace utils
inline namespace logs {
template <>
void log_class_string<kstring>::format(std::string &out, const void *arg) {

View file

@ -30,7 +30,7 @@ orbis::ErrorCode orbis::ipmiCreateServer(Process *proc, void *serverImpl,
const char *name,
const IpmiCreateServerConfig &config,
rx::Ref<IpmiServer> &result) {
auto [server, errorCode] = g_context.createIpmiServer(name);
auto [server, errorCode] = g_context->createIpmiServer(name);
ORBIS_RET_ON_ERROR(errorCode);
server->serverImpl = serverImpl;
@ -44,9 +44,9 @@ orbis::ErrorCode orbis::ipmiCreateServer(Process *proc, void *serverImpl,
orbis::ErrorCode orbis::ipmiCreateSession(Thread *thread, void *sessionImpl,
ptr<void> userData,
rx::Ref<IpmiSession> &result) {
std::unique_lock ipmiMapLock(g_context.ipmiMap.mutex);
std::unique_lock ipmiMapLock(g_context->ipmiMap.mutex);
for (auto [kid, obj] : g_context.ipmiMap) {
for (auto [kid, obj] : g_context->ipmiMap) {
auto server = dynamic_cast<IpmiServer *>(obj);
if (server == nullptr) {
continue;
@ -104,7 +104,7 @@ orbis::SysResult orbis::sysIpmiCreateClient(Thread *thread, ptr<uint> result,
ORBIS_RET_ON_ERROR(ipmiCreateClient(thread->tproc, _params.clientImpl, _name,
_config, client));
auto kid = g_context.ipmiMap.insert(std::move(client));
auto kid = g_context->ipmiMap.insert(std::move(client));
if (kid == -1) {
return ErrorCode::MFILE;
@ -139,7 +139,7 @@ orbis::SysResult orbis::sysIpmiCreateServer(Thread *thread, ptr<uint> result,
ORBIS_RET_ON_ERROR(ureadString(_name, sizeof(_name), _params.name));
ORBIS_RET_ON_ERROR(ipmiCreateServer(thread->tproc, _params.serverImpl, _name,
_config, server));
auto kid = g_context.ipmiMap.insert(std::move(server));
auto kid = g_context->ipmiMap.insert(std::move(server));
if (kid == -1) {
return ErrorCode::MFILE;
@ -184,7 +184,7 @@ orbis::SysResult orbis::sysIpmiCreateSession(Thread *thread, ptr<uint> result,
ORBIS_RET_ON_ERROR(
ipmiCreateSession(thread, _params.sessionImpl, _userData.data, session));
auto kid = g_context.ipmiMap.insert(std::move(session));
auto kid = g_context->ipmiMap.insert(std::move(session));
if (kid == -1) {
return ErrorCode::MFILE;
@ -233,7 +233,7 @@ orbis::SysResult orbis::sysIpmiServerReceivePacket(Thread *thread,
ORBIS_RET_ON_ERROR(
uread(_params, ptr<IpmiServerReceivePacketParams>(params)));
auto server = g_context.ipmiMap.get(kid).cast<IpmiServer>();
auto server = g_context->ipmiMap.get(kid).cast<IpmiServer>();
if (server == nullptr) {
return ErrorCode::INVAL;
@ -301,7 +301,7 @@ orbis::SysResult orbis::sysIpmiSendConnectResult(Thread *thread,
ORBIS_LOG_NOTICE(__FUNCTION__, kid);
auto ipmiObject = g_context.ipmiMap.get(kid);
auto ipmiObject = g_context->ipmiMap.get(kid);
if (ipmiObject == nullptr) {
return ErrorCode::INVAL;
}
@ -352,7 +352,7 @@ orbis::SysResult orbis::sysIpmiSessionRespondSync(Thread *thread,
return ErrorCode::INVAL;
}
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
if (session == nullptr) {
return ErrorCode::INVAL;
@ -422,7 +422,7 @@ orbis::SysResult orbis::sysIpmiClientInvokeAsyncMethod(Thread *thread,
return ErrorCode::INVAL;
}
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
@ -513,7 +513,7 @@ orbis::SysResult orbis::sysImpiSessionRespondAsync(Thread *thread,
return ErrorCode::INVAL;
}
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
if (session == nullptr) {
return ErrorCode::INVAL;
@ -572,7 +572,7 @@ orbis::SysResult orbis::sysIpmiClientTryGetResult(Thread *thread,
IpmiTryGetResultParams _params;
ORBIS_RET_ON_ERROR(uread(_params, (ptr<IpmiTryGetResultParams>)params));
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
@ -649,7 +649,7 @@ orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
return ErrorCode::INVAL;
}
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
@ -750,7 +750,7 @@ orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
return ErrorCode::INVAL;
}
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
@ -804,7 +804,7 @@ orbis::SysResult orbis::sysIpmiSessionTrySendMessage(Thread *thread,
return ErrorCode::INVAL;
}
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
if (session == nullptr) {
return ErrorCode::INVAL;
@ -847,7 +847,7 @@ orbis::SysResult orbis::sysIpmiClientDisconnect(Thread *thread,
return ErrorCode::INVAL;
}
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
@ -873,7 +873,7 @@ orbis::SysResult orbis::sysIpmiSessionGetClientPid(Thread *thread,
return ErrorCode::INVAL;
}
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
if (session == nullptr) {
return ErrorCode::INVAL;
@ -900,7 +900,7 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
return ErrorCode::INVAL;
}
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
@ -1040,7 +1040,7 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
return ErrorCode::INVAL;
}
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
@ -1053,7 +1053,7 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
IpmiClientConnectParams _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiClientConnectParams>(params)));
auto server = g_context.findIpmiServer(client->name);
auto server = g_context->findIpmiServer(client->name);
if (server == nullptr) {
return SysResult::notAnError(ErrorCode::NOENT);
@ -1173,7 +1173,7 @@ orbis::SysResult orbis::sysIpmiSessionGetClientAppId(Thread *thread,
return ErrorCode::INVAL;
}
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
if (session == nullptr) {
return ErrorCode::INVAL;
@ -1198,7 +1198,7 @@ orbis::SysResult orbis::sysIpmiSessionGetUserData(Thread *thread,
return ErrorCode::INVAL;
}
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
if (session == nullptr) {
return ErrorCode::INVAL;
@ -1221,7 +1221,7 @@ orbis::SysResult orbis::sysIpmiServerGetName(Thread *thread, ptr<uint> result,
return ErrorCode::INVAL;
}
auto server = g_context.ipmiMap.get(kid).cast<IpmiServer>();
auto server = g_context->ipmiMap.get(kid).cast<IpmiServer>();
if (server == nullptr) {
return ErrorCode::INVAL;
@ -1246,7 +1246,7 @@ orbis::SysResult orbis::sysIpmiClientGetName(Thread *thread, ptr<uint> result,
return ErrorCode::INVAL;
}
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
@ -1283,7 +1283,7 @@ orbis::SysResult orbis::sysIpmiClientWaitEventFlag(Thread *thread,
IpmiWaitEventFlagParam _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiWaitEventFlagParam>(params)));
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
@ -1344,7 +1344,7 @@ orbis::SysResult orbis::sysIpmiClientPollEventFlag(Thread *thread,
IpmiPollEventFlagParam _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiPollEventFlagParam>(params)));
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
@ -1384,7 +1384,7 @@ orbis::SysResult orbis::sysIpmiSessionSetEventFlag(Thread *thread,
IpmiSetEventFlagParam _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiSetEventFlagParam>(params)));
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
if (session == nullptr) {
return ErrorCode::INVAL;

View file

@ -97,7 +97,7 @@ orbis::SysResult orbis::sys_cpuset_getaffinity(Thread *thread, cpulevel_t level,
if (id == ~id_t(0) || id == thread->tproc->pid) {
whichProcess = thread->tproc;
} else {
whichProcess = g_context.findProcessById(id);
whichProcess = g_context->findProcessById(id);
if (whichProcess == nullptr) {
return ErrorCode::SRCH;
@ -163,7 +163,7 @@ orbis::SysResult orbis::sys_cpuset_setaffinity(Thread *thread, cpulevel_t level,
} else {
ORBIS_LOG_ERROR(__FUNCTION__, "process not found", level, which, id,
cpusetsize);
whichProcess = g_context.findProcessById(id);
whichProcess = g_context->findProcessById(id);
if (whichProcess == nullptr) {
return ErrorCode::SRCH;

View file

@ -89,7 +89,7 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
nodeIt = kq->notes.begin();
if (change.filter == kEvFiltProc) {
auto process = g_context.findProcessById(change.ident);
auto process = g_context->findProcessById(change.ident);
if (process == nullptr) {
return ErrorCode::SRCH;
}
@ -124,7 +124,7 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
}
} else if (change.filter == kEvFiltGraphicsCore ||
change.filter == kEvFiltDisplay) {
g_context.deviceEventEmitter->subscribe(&*nodeIt);
g_context->deviceEventEmitter->subscribe(&*nodeIt);
}
}
}
@ -185,7 +185,7 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
nodeIt->event.data |= 1000ull << 16; // clock
kq->cv.notify_all(kq->mtx);
} else if (g_context.fwType == FwType::Ps5 &&
} else if (g_context->fwType == FwType::Ps5 &&
change.filter == kEvFiltGraphicsCore && change.ident == 0) {
nodeIt->triggered = true;
kq->cv.notify_all(kq->mtx);

View file

@ -25,7 +25,7 @@ orbis::SysResult orbis::sys_wait4(Thread *thread, sint pid, ptr<sint> status,
int hostPid = pid;
if (pid > 0) {
auto process = g_context.findProcessById(pid);
auto process = g_context->findProcessById(pid);
if (process == nullptr) {
return ErrorCode::SRCH;
}
@ -42,7 +42,7 @@ orbis::SysResult orbis::sys_wait4(Thread *thread, sint pid, ptr<sint> status,
ORBIS_LOG_ERROR(__FUNCTION__, pid, status, options, rusage, result, stat);
auto process = g_context.findProcessByHostId(result);
auto process = g_context->findProcessByHostId(result);
if (process == nullptr) {
ORBIS_LOG_ERROR("host process not found", result);
continue;

View file

@ -80,7 +80,7 @@ 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);
std::lock_guard lock(orbis::g_context->regMgrMtx);
if (op == 1) {
// set int
@ -89,7 +89,7 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
}
ORBIS_LOG_ERROR(__FUNCTION__, op, id, *(std::uint32_t *)value);
g_context.regMgrInt[id] = *(std::uint32_t *)value;
g_context->regMgrInt[id] = *(std::uint32_t *)value;
return {};
}
if (op == 2) {
@ -98,8 +98,8 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
return ErrorCode::INVAL;
}
auto intValIt = g_context.regMgrInt.find(id);
if (intValIt == g_context.regMgrInt.end()) {
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;
@ -774,7 +774,7 @@ orbis::SysResult orbis::sys_budget_create(Thread *thread, ptr<char> name,
BudgetInfo _resources[kMaxBudgets];
ORBIS_RET_ON_ERROR(uread(_resources, resources, count));
auto processTypeBudget = g_context.getProcessTypeBudget(processType);
auto processTypeBudget = g_context->getProcessTypeBudget(processType);
int invalidResourceCount = 0;
for (auto &resource : std::span(_resources, count)) {
@ -804,7 +804,7 @@ orbis::SysResult orbis::sys_budget_create(Thread *thread, ptr<char> name,
rx::Ref budget =
orbis::knew<Budget>(_name, processType, std::span(_resources, count));
auto id = g_context.budgets.insert(budget);
auto id = g_context->budgets.insert(budget);
thread->retval[0] = id;
return {};
}
@ -845,9 +845,9 @@ orbis::SysResult orbis::sys_budget_get(Thread *thread, sint id,
}
budget =
g_context.getProcessTypeBudget(static_cast<Budget::ProcessType>(id));
g_context->getProcessTypeBudget(static_cast<Budget::ProcessType>(id));
} else {
budget = g_context.budgets.get(id);
budget = g_context->budgets.get(id);
if (!budget) {
return ErrorCode::SRCH;
@ -873,7 +873,7 @@ orbis::SysResult orbis::sys_budget_set(Thread *thread, sint budgetId) {
return ErrorCode::NOSYS;
}
auto budget = g_context.budgets.get(budgetId);
auto budget = g_context->budgets.get(budgetId);
if (!budget) {
return ErrorCode::SRCH;
}
@ -940,7 +940,7 @@ orbis::SysResult orbis::sys_dmem_container(Thread *thread, uint id) {
orbis::SysResult orbis::sys_get_authinfo(Thread *thread, pid_t pid,
ptr<AuthInfo> info) {
auto process = pid > 0 ? g_context.findProcessById(pid) : thread->tproc;
auto process = pid > 0 ? g_context->findProcessById(pid) : thread->tproc;
if (process == nullptr) {
return ErrorCode::SRCH;
}
@ -1188,7 +1188,7 @@ orbis::SysResult orbis::sys_randomized_path(Thread *thread, sint type,
}
orbis::SysResult orbis::sys_rdup(Thread *thread, sint pid, sint fd) {
ORBIS_LOG_TODO(__FUNCTION__, pid, fd);
for (auto it = g_context.getProcessList(); it != nullptr; it = it->next) {
for (auto it = g_context->getProcessList(); it != nullptr; it = it->next) {
auto &p = it->object;
if (p.pid != pid) {
continue;
@ -1297,7 +1297,7 @@ orbis::SysResult orbis::sys_budget_get_ptype(Thread *thread, sint pid) {
if (pid < 0 || pid == thread->tproc->pid) {
process = thread->tproc;
} else {
process = g_context.findProcessById(pid);
process = g_context->findProcessById(pid);
if (!process) {
return ErrorCode::SRCH;
@ -1344,7 +1344,7 @@ orbis::SysResult orbis::sys_thr_get_name(Thread *thread, lwpid_t lwpid,
searchThread = thread->tproc->threadsMap.get(lwpid - thread->tproc->pid);
if (searchThread == nullptr) {
if (auto process = g_context.findProcessById(lwpid)) {
if (auto process = g_context->findProcessById(lwpid)) {
searchThread = process->threadsMap.get(lwpid - process->pid);
}
}
@ -1446,7 +1446,7 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
return sysIpmiSessionSetEventFlag(thread, result, kid, params, paramsSz);
}
if (auto ipmi = g_context.ipmiMap.get(kid)) {
if (auto ipmi = g_context->ipmiMap.get(kid)) {
if (auto client = ipmi.cast<IpmiClient>()) {
ORBIS_LOG_TODO(__FUNCTION__, thread->tid, op, client->name, result,
params, paramsSz);
@ -1652,7 +1652,7 @@ orbis::sys_get_kernel_mem_statistics(Thread *thread /* TODO */) {
orbis::SysResult orbis::sys_get_sdk_compiled_version(Thread *thread,
ptr<const char> path) {
ORBIS_LOG_ERROR(__FUNCTION__, path);
thread->retval[0] = g_context.sdkVersion;
thread->retval[0] = g_context->sdkVersion;
return {};
}
orbis::SysResult orbis::sys_app_state_change(Thread *thread, sint state) {
@ -1680,7 +1680,7 @@ orbis::SysResult orbis::sys_budget_get_ptype_of_budget(Thread *thread,
return ErrorCode::NOSYS;
}
rx::Ref<Budget> budget = g_context.budgets.get(budgetId);
rx::Ref<Budget> budget = g_context->budgets.get(budgetId);
if (!budget) {
return ErrorCode::SRCH;
@ -1877,10 +1877,10 @@ orbis::SysResult orbis::sys_begin_app_mount(Thread *thread,
rx::Ref appInfo = orbis::knew<RcAppInfo>();
AppInfoEx *appInfoData = appInfo.get();
auto handle = g_context.appInfos.insert(appInfo);
auto handle = g_context->appInfos.insert(appInfo);
ORBIS_LOG_TODO(__FUNCTION__, handle);
thread->where();
if (handle == decltype(g_context.appInfos)::npos) {
if (handle == decltype(g_context->appInfos)::npos) {
return ErrorCode::DOOFUS;
}

View file

@ -114,7 +114,7 @@ orbis::SysResult orbis::sys_kill(Thread *thread, sint pid, sint signum) {
int hostPid = pid;
if (pid > 0) {
auto process = g_context.findProcessById(pid);
auto process = g_context->findProcessById(pid);
if (process == nullptr) {
return ErrorCode::SRCH;
}

View file

@ -92,7 +92,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
// 4.17.0.0.3.0
if (name[0] == net && name[1] == 17 && name[2] == 0 && name[3] == 0 &&
name[4] == 3 && name[5] == 0) {
if (g_context.fwSdkVersion == 0) {
if (g_context->fwSdkVersion == 0) {
// proto fw
return {};
}
@ -197,7 +197,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
return ErrorCode::INVAL;
}
auto budget = g_context.budgets.get(thread->tproc->budgetId);
auto budget = g_context->budgets.get(thread->tproc->budgetId);
auto fmem = budget->get(BudgetResource::Fmem);
*(uint64_t *)old = fmem.total;
return {};
@ -208,7 +208,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
return ErrorCode::INVAL;
}
auto budget = g_context.budgets.get(thread->tproc->budgetId);
auto budget = g_context->budgets.get(thread->tproc->budgetId);
auto fmem = budget->get(BudgetResource::Fmem);
auto result = (uint64_t *)old;
@ -225,7 +225,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
ORBIS_LOG_ERROR("KERN_PROC_PROC 2");
if (namelen >= 4) {
auto process = g_context.findProcessById(name[3]);
auto process = g_context->findProcessById(name[3]);
if (process == nullptr || process->exitStatus.has_value()) {
return ErrorCode::SRCH;
}
@ -245,7 +245,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
}
if (name[0] == kern && name[1] == proc && name[2] == 55) {
if (g_context.fwType != FwType::Ps5) {
if (g_context->fwType != FwType::Ps5) {
return orbis::ErrorCode::INVAL;
}
@ -259,7 +259,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
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]);
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);
@ -276,7 +276,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
auto sdkVersion = process->sdkVersion;
if (sdkVersion == 0) {
sdkVersion = g_context.fwSdkVersion;
sdkVersion = g_context->fwSdkVersion;
}
ORBIS_RET_ON_ERROR(uwrite(ptr<uint32_t>(old), sdkVersion));
@ -290,7 +290,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
// 1 - 14 - 35 - pid
Process *process = thread->tproc;
if (process->pid != name[3] && name[3] != -1) {
process = g_context.findProcessById(name[3]);
process = g_context->findProcessById(name[3]);
if (process == nullptr) {
ORBIS_LOG_ERROR("appinfo process not found", name[3],
thread->tproc->pid);
@ -384,7 +384,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
}
if (name[0] == kern && name[1] == proc && name[2] == 64) {
auto appInfo = g_context.appInfos.get(name[3]);
auto appInfo = g_context->appInfos.get(name[3]);
if (appInfo == nullptr) {
return ErrorCode::SRCH; // ?
}
@ -418,7 +418,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
if (name[0] == 1 && name[1] == proc && name[2] == 65) {
// AppInfo by appId get/set
// 1 - 14 - 65 - appId
auto appInfo = g_context.appInfos.get(name[3]);
auto appInfo = g_context->appInfos.get(name[3]);
if (appInfo == nullptr) {
ORBIS_LOG_ERROR("appinfo appId not found", name[3], thread->tproc->pid);
return ErrorCode::SRCH;
@ -461,7 +461,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
if (name[0] == kern && name[1] == proc && name[2] == 68) {
Process *process = thread->tproc;
if (process->pid != name[3]) {
process = g_context.findProcessById(name[3]);
process = g_context->findProcessById(name[3]);
if (process == nullptr) {
ORBIS_LOG_ERROR("get ps5 sdk version by pid: process not found",
name[3], thread->tproc->pid);
@ -478,7 +478,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
auto sdkVersion = process->sdkVersion;
if (sdkVersion == 0) {
sdkVersion = g_context.fwSdkVersion;
sdkVersion = g_context->fwSdkVersion;
}
ORBIS_RET_ON_ERROR(uwrite(ptr<uint32_t>(old), sdkVersion));
@ -699,7 +699,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
dest[count++] = budgets;
dest[count++] = mlock_avail;
} else if (searchName == "hw.sce_main_socid") {
if (g_context.fwType != FwType::Ps5) {
if (g_context->fwType != FwType::Ps5) {
return ErrorCode::INVAL;
}
@ -844,7 +844,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
return ErrorCode::INVAL;
}
*(std::uint32_t *)old = g_context.safeMode;
*(std::uint32_t *)old = g_context->safeMode;
}
if (new_ != nullptr && newlen == 4) {
ORBIS_LOG_ERROR("sysctl: set kern.init_safe_mode",
@ -902,7 +902,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
return {};
case sysctl_hw::sce_main_socid:
if (g_context.fwType != FwType::Ps5) {
if (g_context->fwType != FwType::Ps5) {
return ErrorCode::INVAL;
}
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
@ -933,13 +933,13 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
return ErrorCode::INVAL;
}
if (g_context.fwType != FwType::Ps5 &&
if (g_context->fwType != FwType::Ps5 &&
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();
*(uint64_t *)old = g_context->getTscFreq();
}
return {};
}

View file

@ -1,5 +1,5 @@
#include "orbis/umtx.hpp"
#include "GlobalKernelObject.hpp"
#include "KernelObject.hpp"
#include "error.hpp"
#include "orbis-config.hpp"
#include "orbis/thread.hpp"
@ -25,7 +25,7 @@ struct UmtxCond {
struct UmtxChain {
rx::shared_mutex mtx;
using queue_type = utils::kmultimap<UmtxKey, UmtxCond>;
using queue_type = kmultimap<UmtxKey, UmtxCond>;
queue_type sleep_queue;
queue_type spare_queue;