orbis: implement protect dmem for pid

fixed void mappings
fixed fmem commit
add map flags validation
redirect stdout/stderr to log-init.txt
remove tty.txt, redirect to stdin/stdout
ipmi:
handle SceLncService::loadExec(status, "EXIT")
fill SceShellCoreUtil shm magic
This commit is contained in:
DH 2025-12-02 03:01:28 +03:00
parent b9d36bc0b8
commit 3f6fad89c2
21 changed files with 1088 additions and 299 deletions

View file

@ -6,7 +6,7 @@ namespace orbis {
enum class MemoryType : std::uint32_t {
Invalid = -1u,
WbOnion = 0, // write back, CPU bus
WCGarlic = 3, // combining, GPU bus
WcGarlic = 3, // combining, GPU bus
WbGarlic = 10, // write back, GPU bus
};
}

View file

@ -35,6 +35,10 @@ allocate(unsigned dmemIndex, rx::AddressRange searchRange, std::uint64_t len,
MemoryType memoryType, std::uint64_t alignment = kPageSize,
bool pooled = false);
std::pair<std::uint64_t, ErrorCode>
allocateSystem(unsigned dmemIndex, std::uint64_t len, MemoryType memoryType,
std::uint64_t alignment = kPageSize);
ErrorCode release(unsigned dmemIndex, rx::AddressRange range,
bool pooled = false);
@ -54,9 +58,17 @@ std::pair<rx::AddressRange, ErrorCode>
getAvailSize(unsigned dmemIndex, rx::AddressRange searchRange,
std::uint64_t alignment);
ErrorCode map(unsigned dmemIndex, rx::AddressRange range, std::uint64_t offset,
ErrorCode map(orbis::Process *process, unsigned dmemIndex,
rx::AddressRange range, std::uint64_t offset,
rx::EnumBitSet<vmem::Protection> protection);
ErrorCode notifyUnmap(orbis::Process *process, unsigned dmemIndex,
std::uint64_t offset, rx::AddressRange range);
ErrorCode protect(orbis::Process *process, unsigned dmemIndex,
rx::AddressRange range,
rx::EnumBitSet<vmem::Protection> prot);
std::pair<std::uint64_t, ErrorCode> getPmemOffset(unsigned dmemIndex,
std::uint64_t dmemOffset);
} // namespace orbis::dmem

View file

@ -105,6 +105,7 @@ struct Module final {
DynType dynType = DynType::None;
uint32_t refCount{};
uint32_t phNum{};
uint64_t phdrAddress{};

View file

@ -786,7 +786,7 @@ SysResult sys_localtime_to_utc(Thread *thread, int64_t time, uint unk,
SysResult sys_set_uevt(Thread *thread /* TODO */);
SysResult sys_get_cpu_usage_proc(Thread *thread /* TODO */);
SysResult sys_get_map_statistics(Thread *thread /* TODO */);
SysResult sys_set_chicken_switches(Thread *thread /* TODO */);
SysResult sys_set_chicken_switches(Thread *thread, sint flags);
SysResult sys_extend_page_table_pool(Thread *thread);
SysResult sys_extend_page_table_pool2(Thread *thread);
SysResult sys_get_kernel_mem_statistics(Thread *thread /* TODO */);

View file

@ -20,6 +20,7 @@
#include "rx/Serializer.hpp"
#include "rx/SharedMutex.hpp"
#include <optional>
#include <type_traits>
namespace orbis {
class KernelContext;
@ -93,6 +94,7 @@ struct Process final {
std::optional<sint> exitStatus;
std::uint32_t sdkVersion = 0;
bool allowDmemAliasing = false;
std::uint64_t nextTlsSlot = 1;
std::uint64_t lastTlsOffset = 0;
@ -126,6 +128,50 @@ struct Process final {
}
Budget *getBudget() const;
template <typename Cb>
requires(alignof(Cb) <= 8 && sizeof(Cb) <= 64) &&
(std::is_same_v<std::invoke_result_t<Cb>, void> ||
(alignof(std::invoke_result_t<Cb>) <= 8 &&
sizeof(std::invoke_result_t<Cb>) <= 64))
std::invoke_result_t<Cb> invoke(Cb &&fn) {
auto constructObject = [](void *to, void *from) {
new (to) Cb(std::move(*reinterpret_cast<Cb *>(from)));
};
auto destroyObject = [](void *object) {
reinterpret_cast<Cb *>(object)->~Cb();
};
if constexpr (std::is_same_v<std::invoke_result_t<Cb>, void>) {
invokeImpl(
nullptr, nullptr, &fn, constructObject, destroyObject,
[](void *, void *fnPtr) { (*reinterpret_cast<Cb *>(fnPtr))(); });
} else {
alignas(std::invoke_result_t<Cb>) char
result[sizeof(std::invoke_result_t<Cb>)];
invokeImpl(
&result,
[](void *to, void *from) {
new (to) std::invoke_result_t<Cb>(
std::move(*reinterpret_cast<std::invoke_result_t<Cb> *>(from)));
},
&fn, constructObject, destroyObject,
[](void *result, void *fnPtr) {
new (result)
std::invoke_result_t<Cb>((*reinterpret_cast<Cb *>(fnPtr))());
});
return std::move(*reinterpret_cast<std::invoke_result_t<Cb> *>(result));
}
}
void invokeAsync(void (*fn)());
private:
void invokeImpl(void *returnValue, void (*copyResult)(void *to, void *from),
void *fnPtr, void (*constructObject)(void *to, void *from),
void (*destroyObject)(void *to),
void (*invokeImpl)(void *returnValue, void *fnPtr));
};
pid_t allocatePid();

View file

@ -44,6 +44,7 @@ enum class BlockFlagsEx : std::uint8_t {
Private,
Shared,
PoolControl,
Void,
Reserved,
bitset_last = Reserved
@ -149,6 +150,31 @@ toGpuProtection(rx::EnumBitSet<Protection> prot) {
return result;
}
inline bool validateProtection(rx::EnumBitSet<Protection> &prot) {
prot = rx::EnumBitSet<Protection>::fromUnderlying(prot.toUnderlying() & 0xff);
if (prot & ~(kProtCpuAll | kProtGpuAll)) {
return false;
}
if (prot & Protection::CpuWrite) {
prot |= Protection::CpuRead;
}
return true;
}
inline bool validateMemoryType(MemoryType type,
rx::EnumBitSet<Protection> prot) {
if (type == MemoryType::WbGarlic) {
if (prot & (Protection::CpuWrite | Protection::GpuWrite)) {
return false;
}
}
return true;
}
void initialize(Process *process, bool force = false);
void fork(Process *process, Process *parentThread);
@ -164,22 +190,27 @@ mapFile(Process *process, std::uint64_t addressHint, std::uint64_t size,
rx::EnumBitSet<Protection> prot, rx::EnumBitSet<BlockFlags> blockFlags,
rx::EnumBitSet<BlockFlagsEx> blockFlagsEx, File *file,
std::uint64_t fileOffset, std::string_view name = {},
std::uint64_t alignment = kPageSize,
std::uint64_t alignment = kPageSize, std::uint64_t callerAddress = 0,
MemoryType type = MemoryType::Invalid);
std::pair<rx::AddressRange, ErrorCode>
mapDirect(Process *process, std::uint64_t addressHint,
rx::AddressRange directRange, rx::EnumBitSet<Protection> prot,
rx::EnumBitSet<AllocationFlags> allocFlags,
std::string_view name = {}, std::uint64_t alignment = kPageSize,
MemoryType type = MemoryType::Invalid);
std::pair<rx::AddressRange, ErrorCode> mapDirect(
Process *process, std::uint64_t addressHint, rx::AddressRange directRange,
rx::EnumBitSet<Protection> prot, rx::EnumBitSet<AllocationFlags> allocFlags,
std::string_view name = {}, std::uint64_t alignment = kPageSize,
std::uint64_t callerAddress = 0, MemoryType type = MemoryType::Invalid);
std::pair<rx::AddressRange, ErrorCode>
mapFlex(Process *process, std::uint64_t size, rx::EnumBitSet<Protection> prot,
std::uint64_t addressHint = 0,
rx::EnumBitSet<AllocationFlags> allocFlags = {},
rx::EnumBitSet<BlockFlags> blockFlags = {}, std::string_view name = {},
std::uint64_t alignment = kPageSize);
std::uint64_t alignment = kPageSize, std::uint64_t callerAddress = 0);
std::pair<rx::AddressRange, ErrorCode>
mapVoid(Process *process, std::uint64_t size, std::uint64_t addressHint = 0,
rx::EnumBitSet<AllocationFlags> allocFlags = {},
std::string_view name = {}, std::uint64_t alignment = kPageSize,
std::uint64_t callerAddress = 0);
std::pair<rx::AddressRange, ErrorCode>
commitPooled(Process *process, rx::AddressRange addressRange, MemoryType type,
@ -191,7 +222,6 @@ ErrorCode protect(Process *process, rx::AddressRange range,
ErrorCode unmap(Process *process, rx::AddressRange range);
ErrorCode setName(Process *process, rx::AddressRange range,
std::string_view name);
ErrorCode setType(Process *process, rx::AddressRange range, MemoryType type);
ErrorCode setTypeAndProtect(Process *process, rx::AddressRange range,
MemoryType type, rx::EnumBitSet<Protection> prot);
std::optional<QueryResult> query(Process *process, std::uint64_t address,