orbis: initial physical memory emulation support (not used)

avoid unconditional linux specific types/api usage
This commit is contained in:
DH 2025-11-09 21:38:23 +03:00
parent 07b1f422ef
commit 9fc036d9a5
23 changed files with 831 additions and 67 deletions

View file

@ -2,7 +2,10 @@
#include "error/ErrorCode.hpp"
#include "orbis-config.hpp"
#include "rx/AddressRange.hpp"
#include "rx/EnumBitSet.hpp"
#include "rx/Rc.hpp"
#include "rx/mem.hpp"
#include <bit>
#include <type_traits>
@ -27,7 +30,7 @@ enum OpenFlags {
struct File;
struct Thread;
struct Process;
struct IoDevice : rx::RcBase {
virtual ErrorCode open(rx::Ref<File> *file, const char *path,
std::uint32_t flags, std::uint32_t mode,
@ -56,6 +59,12 @@ struct IoDevice : rx::RcBase {
virtual ErrorCode ioctl(std::uint64_t request, orbis::ptr<void> argp,
Thread *thread);
virtual ErrorCode map(rx::AddressRange range, std::int64_t offset,
rx::EnumBitSet<rx::mem::Protection> protection,
Process *process) {
return ErrorCode::NOTSUP;
}
};
namespace ioctl {

View file

@ -20,6 +20,12 @@ public:
[[nodiscard]] int value() const { return mValue < 0 ? -mValue : mValue; }
[[nodiscard]] bool isError() const { return mValue < 0; }
[[nodiscard]] ErrorCode errc() const {
return static_cast<ErrorCode>(value());
}
explicit operator bool() const { return mValue != 0; }
[[nodiscard]] auto operator<=>(ErrorCode ec) const {
return static_cast<ErrorCode>(value()) <=> ec;
}

View file

@ -0,0 +1,16 @@
#pragma once
#include "error/ErrorCode.hpp"
#include "rx/AddressRange.hpp"
#include <cstdint>
namespace orbis {
struct Process;
}
namespace orbis::fmem {
ErrorCode initialize(Process *process, std::uint64_t size);
void destroy(Process *process);
std::pair<rx::AddressRange, ErrorCode> allocate(Process *process,
std::uint64_t size);
ErrorCode deallocate(Process *process, rx::AddressRange range);
} // namespace orbis::fmem

View file

@ -0,0 +1,38 @@
#pragma once
#include "error/ErrorCode.hpp"
#include "kernel/MemoryResource.hpp"
#include "rx/AddressRange.hpp"
#include "rx/EnumBitSet.hpp"
#include <cstdint>
namespace orbis {
using kernel::AllocationFlags;
struct IoDevice;
} // namespace orbis
namespace orbis::pmem {
enum class MemoryType : std::uint32_t {
Invalid = -1u,
WbOnion = 0, // write back, CPU bus
WCGarlic = 3, // combining, GPU bus
WbGarlic = 10, // write back, GPU bus
};
struct AllocatedMemory {
rx::AddressRange range;
MemoryType memoryType;
};
ErrorCode initialize(std::uint64_t size);
void destroy();
std::pair<rx::AddressRange, ErrorCode>
allocate(std::uint64_t addressHint, std::uint64_t size, MemoryType memoryType,
rx::EnumBitSet<AllocationFlags> flags, std::uint64_t alignment);
ErrorCode deallocate(rx::AddressRange range);
std::optional<AllocatedMemory> query(std::uint64_t address);
ErrorCode map(std::uint64_t virtualAddress, rx::AddressRange range,
rx::EnumBitSet<rx::mem::Protection> protection);
std::size_t getSize();
IoDevice *getDevice();
} // namespace orbis::pmem

View file

@ -13,6 +13,8 @@ using cpusetid_t = sint;
using cpuwhich_t = sint;
using cpulevel_t = sint;
using SceKernelModule = ModuleHandle;
using SockLen = uint32_t;
using id_t = uint32_t;
struct Thread;
struct AuthInfo;
@ -501,17 +503,15 @@ SysResult sys_rtprio_thread(Thread *thread, sint function, lwpid_t lwpid,
ptr<struct rtprio> rtp);
SysResult sys_sctp_peeloff(Thread *thread, sint sd, uint32_t name);
SysResult sys_sctp_generic_sendmsg(Thread *thread, sint sd, caddr_t msg,
sint mlen, caddr_t to, __socklen_t tolen,
sint mlen, caddr_t to, SockLen tolen,
ptr<struct sctp_sndrcvinfo> sinfo,
sint flags);
SysResult sys_sctp_generic_sendmsg_iov(Thread *thread, sint sd, ptr<IoVec> iov,
sint iovlen, caddr_t to,
__socklen_t tolen,
sint iovlen, caddr_t to, SockLen tolen,
ptr<struct sctp_sndrcvinfo> sinfo,
sint flags);
SysResult sys_sctp_generic_recvmsg(Thread *thread, sint sd, ptr<IoVec> iov,
sint iovlen, caddr_t from,
__socklen_t fromlen,
sint iovlen, caddr_t from, SockLen fromlen,
ptr<struct sctp_sndrcvinfo> sinfo,
sint flags);
SysResult sys_pread(Thread *thread, sint fd, ptr<void> buf, size_t nbyte,
@ -587,9 +587,9 @@ SysResult sys_cap_getmode(Thread *thread, ptr<uint> modep);
SysResult sys_pdfork(Thread *thread, ptr<sint> fdp, sint flags);
SysResult sys_pdkill(Thread *thread, sint fd, sint signum);
SysResult sys_pdgetpid(Thread *thread, sint fd, ptr<pid_t> pidp);
SysResult sys_pselect(Thread *thread, sint nd, ptr<fd_set> in, ptr<fd_set> ou,
ptr<fd_set> ex, ptr<const timespec> ts,
ptr<const sigset_t> sm);
SysResult sys_pselect(Thread *thread, sint nd, ptr<fd_set_t> in,
ptr<fd_set_t> ou, ptr<fd_set_t> ex,
ptr<const timespec> ts, ptr<const SigSet> sm);
SysResult sys_getloginclass(Thread *thread, ptr<char> namebuf, size_t namelen);
SysResult sys_setloginclass(Thread *thread, ptr<char> namebuf);
SysResult sys_rctl_get_racct(Thread *thread, ptr<const void> inbufp,

View file

@ -0,0 +1,93 @@
#pragma once
#include "kernel/MemoryResource.hpp"
#include "orbis-config.hpp"
#include "rx/AddressRange.hpp"
#include "rx/EnumBitSet.hpp"
#include "rx/StaticString.hpp"
#include <string_view>
namespace orbis {
using kernel::AllocationFlags;
}
namespace orbis {
struct IoDevice;
struct Process;
namespace vmem {
static constexpr auto kPageSize = 16 * 1024;
enum class Protection {
CpuRead,
CpuWrite,
CpuExec,
GpuRead = 4,
GpuWrite,
bitset_last = GpuWrite
};
enum class BlockFlags {
FlexibleMemory,
DirectMemory,
Stack,
PooledMemory,
Commited,
Allocated,
bitset_last = Allocated
};
inline constexpr auto kProtCpuReadWrite =
Protection::CpuRead | Protection::CpuWrite;
inline constexpr auto kProtCpuAll =
Protection::CpuRead | Protection::CpuWrite | Protection::CpuExec;
inline constexpr auto kProtGpuAll = Protection::GpuRead | Protection::GpuWrite;
#pragma pack(push, 1)
struct QueryResult {
uint64_t start;
uint64_t end;
uint64_t offset;
uint32_t protection;
uint32_t memoryType;
uint32_t flags;
rx::StaticCString<32> name;
uint32_t _padding;
};
static_assert(sizeof(QueryResult) == 72);
struct MemoryProtection {
uint64_t startAddress;
uint64_t endAddress;
rx::EnumBitSet<Protection> prot;
uint32_t _padding;
};
static_assert(sizeof(MemoryProtection) == 24);
#pragma pack(pop)
void initialize(Process *process, bool force = false);
void fork(Process *process, Process *parentThread);
std::pair<rx::AddressRange, ErrorCode>
reserve(Process *process, std::uint64_t addressHint, std::uint64_t size,
rx::EnumBitSet<AllocationFlags> allocFlags);
std::pair<rx::AddressRange, ErrorCode>
map(Process *process, std::uint64_t addressHint, std::uint64_t size,
rx::EnumBitSet<AllocationFlags> allocFlags,
rx::EnumBitSet<Protection> prot = {},
rx::EnumBitSet<BlockFlags> blockFlags = {},
std::uint64_t alignment = kPageSize, std::string_view name = {},
IoDevice *device = nullptr, std::int64_t deviceOffset = 0);
ErrorCode unmap(Process *process, rx::AddressRange range);
ErrorCode setName(Process *process, rx::AddressRange range,
std::string_view name);
std::optional<QueryResult> query(Process *process, std::uint64_t address);
std::optional<MemoryProtection> queryProtection(Process *process,
std::uint64_t address);
} // namespace vmem
} // namespace orbis