mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-06 16:49:59 +01:00
implement unix socket ops
implement cross process dmem support implement ipmi try send message implement sys_batch_map store saves to game directory (.rpcsx subfolder) fix get dir entries added uvd & vce devices
This commit is contained in:
parent
a6211b514f
commit
6e25f347d3
|
|
@ -1,10 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <orbis/utils/SharedMutex.hpp>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <initializer_list>
|
||||
#include <orbis/utils/SharedCV.hpp>
|
||||
|
||||
namespace amdgpu::bridge {
|
||||
extern std::uint32_t expGpuPid;
|
||||
|
|
@ -45,7 +45,8 @@ enum class CommandId : std::uint32_t {
|
|||
Nop,
|
||||
ProtectMemory,
|
||||
CommandBuffer,
|
||||
Flip
|
||||
Flip,
|
||||
MapDmem,
|
||||
};
|
||||
|
||||
struct CmdMemoryProt {
|
||||
|
|
@ -77,6 +78,15 @@ struct CmdFlip {
|
|||
std::uint64_t arg;
|
||||
};
|
||||
|
||||
struct CmdMapDmem {
|
||||
std::uint64_t offset;
|
||||
std::uint64_t address;
|
||||
std::uint64_t size;
|
||||
std::uint32_t prot;
|
||||
std::uint32_t pid;
|
||||
std::uint32_t dmemIndex;
|
||||
};
|
||||
|
||||
enum {
|
||||
kPageWriteWatch = 1 << 0,
|
||||
kPageReadWriteLock = 1 << 1,
|
||||
|
|
@ -91,6 +101,7 @@ struct BridgeHeader {
|
|||
std::uint64_t info;
|
||||
std::uint32_t pullerPid;
|
||||
std::uint32_t pusherPid;
|
||||
std::atomic<std::uint64_t> lock;
|
||||
volatile std::uint64_t flags;
|
||||
std::uint64_t vmAddress;
|
||||
std::uint64_t vmSize;
|
||||
|
|
@ -103,7 +114,7 @@ struct BridgeHeader {
|
|||
std::uint32_t memoryAreaCount;
|
||||
std::uint32_t commandBufferCount;
|
||||
std::uint32_t bufferCount;
|
||||
CmdMemoryProt memoryAreas[128];
|
||||
CmdMemoryProt memoryAreas[512];
|
||||
CmdCommandBuffer commandBuffers[32];
|
||||
CmdBuffer buffers[10];
|
||||
// orbis::shared_mutex cacheCommandMtx;
|
||||
|
|
@ -125,6 +136,7 @@ struct Command {
|
|||
CmdCommandBuffer commandBuffer;
|
||||
CmdBuffer buffer;
|
||||
CmdFlip flip;
|
||||
CmdMapDmem mapDmem;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -137,9 +149,6 @@ enum class BridgeFlags {
|
|||
struct BridgePusher {
|
||||
BridgeHeader *header = nullptr;
|
||||
|
||||
BridgePusher() = default;
|
||||
BridgePusher(BridgeHeader *header) : header(header) {}
|
||||
|
||||
void setVm(std::uint64_t address, std::uint64_t size, const char *name) {
|
||||
header->vmAddress = address;
|
||||
header->vmSize = size;
|
||||
|
|
@ -155,6 +164,12 @@ 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) {
|
||||
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) {
|
||||
|
|
@ -181,6 +196,11 @@ private:
|
|||
}
|
||||
|
||||
void sendCommand(CommandId id, std::initializer_list<std::uint64_t> args) {
|
||||
std::uint64_t exp = 0;
|
||||
while (!header->lock.compare_exchange_weak(exp, 1, std::memory_order::acquire, std::memory_order::relaxed)) {
|
||||
exp = 0;
|
||||
}
|
||||
|
||||
std::size_t cmdSize = args.size() + 1;
|
||||
std::uint64_t pos = getPushPosition(cmdSize);
|
||||
|
||||
|
|
@ -189,6 +209,7 @@ private:
|
|||
header->commands[pos++] = arg;
|
||||
}
|
||||
header->push = pos;
|
||||
header->lock.store(0, std::memory_order::release);
|
||||
}
|
||||
|
||||
std::uint64_t getPushPosition(std::uint64_t cmdSize) {
|
||||
|
|
@ -279,6 +300,15 @@ private:
|
|||
result.flip.bufferIndex = args[1];
|
||||
result.flip.arg = args[2];
|
||||
return result;
|
||||
|
||||
case CommandId::MapDmem:
|
||||
result.mapDmem.pid = args[0];
|
||||
result.mapDmem.dmemIndex = args[1];
|
||||
result.mapDmem.address = args[2];
|
||||
result.mapDmem.size = args[3];
|
||||
result.mapDmem.prot = args[4];
|
||||
result.mapDmem.offset = args[5];
|
||||
return result;
|
||||
}
|
||||
|
||||
__builtin_trap();
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ using namespace amdgpu::device;
|
|||
static const bool kUseDirectMemory = false;
|
||||
static amdgpu::bridge::BridgeHeader *g_bridge;
|
||||
|
||||
void *g_rwMemory;
|
||||
// void *g_rwMemory;
|
||||
std::size_t g_memorySize;
|
||||
std::uint64_t g_memoryBase;
|
||||
RemoteMemory g_hostMemory;
|
||||
|
|
@ -4577,6 +4577,9 @@ static auto g_commandHandlers = [] {
|
|||
static void handleCommandBuffer(TaskChain &waitTaskSet, QueueRegisters ®s,
|
||||
std::span<std::uint32_t> &packets) {
|
||||
while (!packets.empty()) {
|
||||
// std::uint64_t address =
|
||||
// (char *)packets.data() - g_hostMemory.shmPointer + 0x40000;
|
||||
// std::fprintf(stderr, "address = %lx\n", address);
|
||||
auto cmd = packets[0];
|
||||
auto type = getBits(cmd, 31, 30);
|
||||
|
||||
|
|
@ -4637,29 +4640,29 @@ void amdgpu::device::AmdgpuDevice::handleProtectMemory(std::uint64_t address,
|
|||
break;
|
||||
|
||||
case PROT_WRITE | PROT_READ:
|
||||
protStr = "W";
|
||||
protStr = "RW";
|
||||
break;
|
||||
|
||||
default:
|
||||
protStr = "unknown";
|
||||
break;
|
||||
}
|
||||
std::printf("Allocated area at %zx, size %lx, prot %s\n", address, size,
|
||||
protStr);
|
||||
std::fprintf(stderr, "Allocated area at %zx, size %lx, prot %s\n", address,
|
||||
size, protStr);
|
||||
} else {
|
||||
memoryAreaTable.unmap(beginPage, endPage);
|
||||
std::printf("Unmapped area at %zx, size %lx\n", address, size);
|
||||
std::fprintf(stderr, "Unmapped area at %zx, size %lx\n", address, size);
|
||||
}
|
||||
|
||||
std::size_t index = 0;
|
||||
for (auto area : memoryAreaTable) {
|
||||
// std::printf("area %lx-%lx\n", area.beginAddress * kPageSize,
|
||||
// area.endAddress * kPageSize);
|
||||
|
||||
if (index >= std::size(g_bridge->memoryAreas)) {
|
||||
util::unreachable("too many memory areas");
|
||||
}
|
||||
|
||||
// std::printf("area %lx-%lx\n", area.beginAddress * kPageSize,
|
||||
// area.endAddress * kPageSize);
|
||||
|
||||
g_bridge->memoryAreas[index++] = {
|
||||
.address = area.beginAddress * kPageSize,
|
||||
.size = (area.endAddress - area.beginAddress) * kPageSize,
|
||||
|
|
@ -4685,11 +4688,16 @@ void amdgpu::device::AmdgpuDevice::handleCommandBuffer(std::uint64_t queueId,
|
|||
|
||||
if (inserted) {
|
||||
std::printf("creation queue %lx\n", queueId);
|
||||
it->second.sched.enqueue([=, queue = &it->second] {
|
||||
if (queueId == 0xc0023f00) {
|
||||
setThreadName("Graphics queue");
|
||||
} else {
|
||||
setThreadName(("Compute queue" + std::to_string(queueId)).c_str());
|
||||
it->second.sched.enqueue([=, queue = &it->second,
|
||||
initialized = false] mutable {
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
|
||||
if (queueId == 0xc0023f00) {
|
||||
setThreadName("Graphics queue");
|
||||
} else {
|
||||
setThreadName(("Compute queue" + std::to_string(queueId)).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
Queue::CommandBuffer *commandBuffer;
|
||||
|
|
@ -4715,7 +4723,7 @@ void amdgpu::device::AmdgpuDevice::handleCommandBuffer(std::uint64_t queueId,
|
|||
});
|
||||
}
|
||||
|
||||
// std::printf("address = %lx, count = %lx\n", address, count);
|
||||
// std::fprintf(stderr, "address = %lx, count = %lx\n", address, count);
|
||||
|
||||
std::lock_guard lock(it->second.mtx);
|
||||
it->second.commandBuffers.push_back(
|
||||
|
|
|
|||
9
orbis-kernel/include/orbis/SocketAddress.hpp
Normal file
9
orbis-kernel/include/orbis/SocketAddress.hpp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
namespace orbis {
|
||||
struct SocketAddress {
|
||||
unsigned char len;
|
||||
unsigned char family;
|
||||
char data[14];
|
||||
};
|
||||
} // namespace orbis
|
||||
|
|
@ -14,6 +14,9 @@ struct KNote;
|
|||
struct Thread;
|
||||
struct Stat;
|
||||
struct Uio;
|
||||
struct SocketAddress;
|
||||
struct msghdr;
|
||||
struct sf_hdtr;
|
||||
|
||||
struct FileOps {
|
||||
std::int32_t flags;
|
||||
|
|
@ -41,6 +44,33 @@ struct FileOps {
|
|||
Thread *thread) = nullptr;
|
||||
ErrorCode (*munmap)(File *file, void **address, std::uint64_t size,
|
||||
Thread *thread) = nullptr;
|
||||
|
||||
ErrorCode (*bind)(orbis::File *file, SocketAddress *address,
|
||||
std::size_t addressLen, Thread *thread) = nullptr;
|
||||
ErrorCode (*listen)(orbis::File *file, int backlog, Thread *thread) = nullptr;
|
||||
ErrorCode (*accept)(orbis::File *file, SocketAddress *address,
|
||||
std::uint32_t *addressLen, Thread *thread) = nullptr;
|
||||
ErrorCode (*connect)(orbis::File *file, SocketAddress *address,
|
||||
std::uint32_t addressLen, Thread *thread) = nullptr;
|
||||
ErrorCode (*sendto)(orbis::File *file, const void *buf, size_t len,
|
||||
sint flags, caddr_t to, sint tolen,
|
||||
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,
|
||||
Thread *thread) = nullptr;
|
||||
ErrorCode (*recvmsg)(orbis::File *file, msghdr *msg, sint flags,
|
||||
Thread *thread) = nullptr;
|
||||
ErrorCode (*shutdown)(orbis::File *file, sint how, Thread *thread) = nullptr;
|
||||
ErrorCode (*setsockopt)(orbis::File *file, sint level, sint name,
|
||||
const void *val, sint valsize,
|
||||
Thread *thread) = nullptr;
|
||||
ErrorCode (*getsockopt)(orbis::File *file, sint level, sint name, void *val,
|
||||
sint *avalsize, Thread *thread) = nullptr;
|
||||
ErrorCode (*sendfile)(orbis::File *file, sint fd, off_t offset, size_t nbytes,
|
||||
ptr<struct sf_hdtr> hdtr, ptr<off_t> sbytes, sint flags,
|
||||
Thread *thread) = nullptr;
|
||||
};
|
||||
|
||||
struct File : RcBase {
|
||||
|
|
@ -49,6 +79,7 @@ struct File : RcBase {
|
|||
const FileOps *ops = nullptr;
|
||||
Ref<RcBase> device;
|
||||
std::uint64_t nextOff = 0;
|
||||
int hostFd = -1;
|
||||
utils::kvector<Dirent> dirEntries;
|
||||
};
|
||||
} // namespace orbis
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@ struct IpmiSession : RcBase {
|
|||
EventFlag evf{0, 0};
|
||||
shared_cv connectCv;
|
||||
bool expectedOutput = false; // TODO: verify
|
||||
bool connected = false; // TODO: implement more states
|
||||
sint connectionStatus{0};
|
||||
};
|
||||
|
||||
|
|
@ -152,8 +151,16 @@ SysResult sysIpmiSendConnectResult(Thread *thread, ptr<uint> result, uint kid,
|
|||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiSessionRespondSync(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,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiSessionTrySendMessage(Thread *thread, ptr<uint> result,
|
||||
uint kid, ptr<void> params,
|
||||
uint64_t paramsSz);
|
||||
SysResult sysIpmiClientDisconnect(Thread *thread, ptr<uint> result,
|
||||
uint kid, ptr<void> params,
|
||||
uint64_t paramsSz);
|
||||
SysResult sysIpmiSessionGetClientPid(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include <set>
|
||||
|
||||
namespace orbis {
|
||||
|
||||
struct File;
|
||||
static constexpr auto kEvFiltRead = -1;
|
||||
static constexpr auto kEvFiltWrite = -2;
|
||||
static constexpr auto kEvFiltAio = -3;
|
||||
|
|
@ -75,6 +75,7 @@ struct KQueue;
|
|||
struct KNote {
|
||||
shared_mutex mutex;
|
||||
Ref<KQueue> queue;
|
||||
Ref<File> file;
|
||||
KEvent event{};
|
||||
bool enabled = true;
|
||||
bool triggered = false;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ struct timespec;
|
|||
struct Stat;
|
||||
struct stack_t;
|
||||
struct IoVec;
|
||||
struct BatchMapEntry;
|
||||
|
||||
SysResult nosys(Thread *thread);
|
||||
|
||||
|
|
@ -53,13 +54,13 @@ SysResult sys_recvmsg(Thread *thread, sint s, ptr<struct msghdr> msg,
|
|||
SysResult sys_sendmsg(Thread *thread, sint s, ptr<struct msghdr> msg,
|
||||
sint flags);
|
||||
SysResult sys_recvfrom(Thread *thread, sint s, caddr_t buf, size_t len,
|
||||
sint flags, ptr<struct sockaddr> from,
|
||||
sint flags, ptr<SocketAddress> from,
|
||||
ptr<uint32_t> fromlenaddr);
|
||||
SysResult sys_accept(Thread *thread, sint s, ptr<struct sockaddr> from,
|
||||
SysResult sys_accept(Thread *thread, sint s, ptr<SocketAddress> from,
|
||||
ptr<uint32_t> fromlenaddr);
|
||||
SysResult sys_getpeername(Thread *thread, sint fdes, ptr<struct sockaddr> asa,
|
||||
SysResult sys_getpeername(Thread *thread, sint fdes, ptr<SocketAddress> asa,
|
||||
ptr<uint32_t> alen);
|
||||
SysResult sys_getsockname(Thread *thread, sint fdes, ptr<struct sockaddr> asa,
|
||||
SysResult sys_getsockname(Thread *thread, sint fdes, ptr<SocketAddress> asa,
|
||||
ptr<uint32_t> alen);
|
||||
SysResult sys_access(Thread *thread, ptr<char> path, sint flags);
|
||||
SysResult sys_chflags(Thread *thread, ptr<char> path, sint flags);
|
||||
|
|
@ -634,7 +635,8 @@ 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 /* TODO */);
|
||||
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);
|
||||
|
|
@ -720,7 +722,8 @@ SysResult sys_get_proc_type_info(Thread *thread, ptr<sint> destProcessInfo);
|
|||
SysResult sys_get_resident_count(Thread *thread, pid_t pid);
|
||||
SysResult sys_prepare_to_suspend_process(Thread *thread, pid_t pid);
|
||||
SysResult sys_get_resident_fmem_count(Thread *thread, pid_t pid);
|
||||
SysResult sys_thr_get_name(Thread *thread, lwpid_t lwpid);
|
||||
SysResult sys_thr_get_name(Thread *thread, lwpid_t lwpid, char *buf,
|
||||
size_t buflen);
|
||||
SysResult sys_set_gpo(Thread *thread /* TODO */);
|
||||
SysResult sys_get_paging_stats_of_all_objects(Thread *thread /* TODO */);
|
||||
SysResult sys_test_debug_rwmem(Thread *thread /* TODO */);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ struct ProcessOps {
|
|||
SysResult (*blockpool_unmap)(Thread *thread, caddr_t addr, size_t len);
|
||||
SysResult (*socket)(Thread *thread, ptr<const char> name, sint domain,
|
||||
sint type, sint protocol, Ref<File> *file);
|
||||
SysResult (*socketpair)(Thread *thread, sint domain, sint type, sint protocol,
|
||||
Ref<File> *a, Ref<File> *b);
|
||||
SysResult (*shm_unlink)(Thread *thread, const char *path);
|
||||
SysResult (*dynlib_get_obj_member)(Thread *thread, ModuleHandle handle,
|
||||
uint64_t index, ptr<ptr<void>> addrp);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <span>
|
||||
|
||||
namespace orbis {
|
||||
struct IoVec {
|
||||
|
|
@ -25,5 +28,27 @@ struct Uio {
|
|||
UioSeg segflg;
|
||||
UioRw rw;
|
||||
void *td;
|
||||
|
||||
std::size_t write(const void *data, std::size_t size) {
|
||||
auto pos = reinterpret_cast<const std::byte *>(data);
|
||||
auto end = pos + size;
|
||||
|
||||
for (auto vec : std::span(iov, iovcnt)) {
|
||||
if (pos >= end) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto nextPos = std::min(pos + vec.len, end);
|
||||
std::memcpy(vec.base, pos, nextPos - pos);
|
||||
pos = nextPos;
|
||||
}
|
||||
|
||||
return size - (end - pos);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::size_t write(const T &object) {
|
||||
return write(&object, sizeof(T));
|
||||
}
|
||||
};
|
||||
} // namespace orbis
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ struct RcBase {
|
|||
void incRef() {
|
||||
if (!_total_size)
|
||||
std::abort();
|
||||
if (references.fetch_add(1, std::memory_order::relaxed) > 512) {
|
||||
if (references.fetch_add(1, std::memory_order::relaxed) > 4096) {
|
||||
assert(!"too many references");
|
||||
}
|
||||
}
|
||||
|
|
@ -81,7 +81,7 @@ public:
|
|||
template <typename OT>
|
||||
requires(std::is_base_of_v<T, OT>)
|
||||
Ref &operator=(Ref<OT> &&other) {
|
||||
other.swap(*this);
|
||||
other.template cast<T>().swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -340,6 +340,23 @@ orbis::SysResult orbis::sysIpmiSessionRespondSync(Thread *thread,
|
|||
session->responseCv.notify_one(session->mutex);
|
||||
return uwrite(result, 0u);
|
||||
}
|
||||
orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
|
||||
ptr<uint> result, uint kid,
|
||||
ptr<void> params,
|
||||
uint64_t paramsSz) {
|
||||
auto client = thread->tproc->ipmiMap.get(kid).cast<IpmiClient>();
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, client->name, client->messages.size(),
|
||||
paramsSz);
|
||||
while (true) {
|
||||
std::this_thread::sleep_for(std::chrono::days(1));
|
||||
}
|
||||
return uwrite<uint>(result, 0x80020000 + static_cast<int>(ErrorCode::AGAIN));
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
|
||||
ptr<uint> result, uint kid,
|
||||
|
|
@ -365,6 +382,8 @@ 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)));
|
||||
|
||||
|
|
@ -389,6 +408,81 @@ orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
|
|||
return uwrite<uint>(result, 0);
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sysIpmiSessionTrySendMessage(Thread *thread,
|
||||
ptr<uint> result, uint kid,
|
||||
ptr<void> params,
|
||||
uint64_t paramsSz) {
|
||||
struct SceIpmiClientTrySendArgs {
|
||||
uint32_t unk; // 0
|
||||
uint32_t padding;
|
||||
ptr<std::byte> message;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
static_assert(sizeof(SceIpmiClientTrySendArgs) == 0x18);
|
||||
|
||||
if (paramsSz != sizeof(SceIpmiClientTrySendArgs)) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto session = thread->tproc->ipmiMap.get(kid).cast<IpmiSession>();
|
||||
|
||||
if (session == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
SceIpmiClientTrySendArgs _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, ptr<SceIpmiClientTrySendArgs>(params)));
|
||||
|
||||
std::lock_guard lock(session->mutex);
|
||||
|
||||
if (session->client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
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();
|
||||
message.resize(_params.size);
|
||||
ORBIS_RET_ON_ERROR(ureadRaw(message.data(), _params.message, _params.size));
|
||||
client->messageCv.notify_one(client->mutex);
|
||||
return uwrite<uint>(result, 0);
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sysIpmiClientDisconnect(Thread *thread,
|
||||
ptr<uint> result, uint kid,
|
||||
ptr<void> params,
|
||||
uint64_t paramsSz) {
|
||||
struct SceIpmiClientDisconnectArgs {
|
||||
ptr<sint> status;
|
||||
};
|
||||
|
||||
if (paramsSz != sizeof(SceIpmiClientDisconnectArgs)) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto client = thread->tproc->ipmiMap.get(kid).cast<IpmiClient>();
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
SceIpmiClientDisconnectArgs _params;
|
||||
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);
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sysIpmiSessionGetClientPid(Thread *thread,
|
||||
ptr<uint> result, uint kid,
|
||||
ptr<void> params,
|
||||
|
|
@ -474,7 +568,6 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
|
|||
// _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;
|
||||
|
|
@ -499,8 +592,6 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
|
|||
|
||||
ORBIS_LOG_TODO("IPMI: sync call", client->name, _params.method,
|
||||
thread->tproc->pid);
|
||||
thread->where();
|
||||
|
||||
auto bufLoc = std::bit_cast<char *>(msg + 1);
|
||||
|
||||
for (auto &data : std::span(_params.pInData, _params.numInData)) {
|
||||
|
|
@ -539,6 +630,10 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
|
|||
auto response = std::move(session->messageResponses.front());
|
||||
session->messageResponses.pop_front();
|
||||
|
||||
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;
|
||||
|
|
@ -753,11 +848,12 @@ orbis::SysResult orbis::sysIpmiClientPollEventFlag(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
ORBIS_LOG_TODO(__FUNCTION__, client->name, _params.index, _params.patternSet,
|
||||
_params.mode, _params.pPatternSet);
|
||||
// ORBIS_LOG_TODO(__FUNCTION__, client->name, _params.index,
|
||||
// _params.patternSet,
|
||||
// _params.mode, _params.pPatternSet);
|
||||
ORBIS_RET_ON_ERROR(uwrite(_params.pPatternSet, 0u));
|
||||
// client->evf.set(_params.a);
|
||||
return ErrorCode::BUSY;
|
||||
return SysResult::notAnError(ErrorCode::BUSY);
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sysIpmiSessionWaitEventFlag(Thread *thread,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#include "pipe.hpp"
|
||||
#include "error/ErrorCode.hpp"
|
||||
#include "file.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "uio.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <span>
|
||||
|
||||
static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
|
||||
|
|
@ -9,16 +11,31 @@ static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
|
|||
auto pipe = static_cast<orbis::Pipe *>(file);
|
||||
while (true) {
|
||||
if (pipe->data.empty()) {
|
||||
pipe->cv.wait(file->mtx);
|
||||
continue;
|
||||
// pipe->cv.wait(file->mtx);
|
||||
// ORBIS_LOG_ERROR(__FUNCTION__, "wakeup", thread->name, thread->tid, file);
|
||||
// continue;
|
||||
return orbis::ErrorCode::WOULDBLOCK;
|
||||
}
|
||||
|
||||
for (auto vec : std::span(uio->iov, uio->iovcnt)) {
|
||||
auto size = std::min<std::size_t>(pipe->data.size(), vec.len);
|
||||
|
||||
if (size == 0) {
|
||||
pipe->data.clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (size > pipe->data.size()) {
|
||||
size = pipe->data.size();
|
||||
}
|
||||
|
||||
uio->offset += size;
|
||||
std::memcpy(vec.base, pipe->data.data(), size);
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, thread->name, thread->tid, file, size, pipe->data.size(), uio->offset, file->nextOff);
|
||||
|
||||
if (pipe->data.size() == size) {
|
||||
pipe->data.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -37,20 +54,30 @@ static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
|
|||
static orbis::ErrorCode pipe_write(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *thread) {
|
||||
auto pipe = static_cast<orbis::Pipe *>(file);
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, thread->name, thread->tid, file);
|
||||
|
||||
std::size_t cnt = 0;
|
||||
for (auto vec : std::span(uio->iov, uio->iovcnt)) {
|
||||
auto offset = pipe->data.size();
|
||||
pipe->data.resize(offset + vec.len);
|
||||
std::memcpy(pipe->data.data(), vec.base, vec.len);
|
||||
ORBIS_RET_ON_ERROR(orbis::ureadRaw(pipe->data.data(), vec.base, vec.len));
|
||||
cnt += vec.len;
|
||||
}
|
||||
|
||||
file->event.emit(orbis::kEvFiltRead);
|
||||
pipe->cv.notify_one(file->mtx);
|
||||
uio->resid = 0;
|
||||
return {};
|
||||
uio->resid -= cnt;
|
||||
uio->offset += cnt;
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, thread->name, thread->tid, file, uio->resid, uio->offset, file->nextOff, cnt);
|
||||
thread->where();
|
||||
return{};
|
||||
}
|
||||
|
||||
static orbis::FileOps pipe_ops = {.read = pipe_read, .write = pipe_write};
|
||||
static orbis::FileOps pipe_ops = {
|
||||
.read = pipe_read,
|
||||
.write = pipe_write,
|
||||
};
|
||||
|
||||
orbis::Ref<orbis::Pipe> orbis::createPipe() {
|
||||
auto result = knew<Pipe>();
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <chrono>
|
||||
#include <list>
|
||||
#include <span>
|
||||
#include <sys/select.h>
|
||||
|
||||
orbis::SysResult orbis::sys_kqueue(Thread *thread) {
|
||||
auto queue = knew<KQueue>();
|
||||
|
|
@ -33,6 +34,28 @@ orbis::SysResult orbis::sys_kqueueex(Thread *thread, ptr<char> name,
|
|||
return {};
|
||||
}
|
||||
|
||||
static bool isReadEventTriggered(int hostFd) {
|
||||
fd_set fds{};
|
||||
FD_SET(hostFd, &fds);
|
||||
timeval timeout{};
|
||||
if (::select(hostFd + 1, &fds, nullptr, nullptr, &timeout) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return FD_ISSET(hostFd, &fds);
|
||||
}
|
||||
|
||||
static bool isWriteEventTriggered(int hostFd) {
|
||||
fd_set fds{};
|
||||
FD_SET(hostFd, &fds);
|
||||
timeval timeout{};
|
||||
if (::select(hostFd + 1, nullptr, &fds, nullptr, &timeout) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return FD_ISSET(hostFd, &fds);
|
||||
}
|
||||
|
||||
namespace orbis {
|
||||
static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
|
||||
auto nodeIt = kq->notes.end();
|
||||
|
|
@ -82,11 +105,11 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
|
|||
}
|
||||
|
||||
std::unique_lock lock(fd->event.mutex);
|
||||
|
||||
if (change.filter == kEvFiltWrite) {
|
||||
nodeIt->triggered = true;
|
||||
kq->cv.notify_all(kq->mtx);
|
||||
}
|
||||
nodeIt->file = fd;
|
||||
// if (change.filter == kEvFiltWrite) {
|
||||
// nodeIt->triggered = true;
|
||||
// kq->cv.notify_all(kq->mtx);
|
||||
// }
|
||||
|
||||
fd->event.notes.insert(&*nodeIt);
|
||||
}
|
||||
|
|
@ -176,14 +199,16 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
|
|||
for (auto &changePtr : std::span(changelist, nchanges)) {
|
||||
KEvent change;
|
||||
ORBIS_RET_ON_ERROR(uread(change, &changePtr));
|
||||
ORBIS_LOG_TODO(__FUNCTION__, change.ident, change.filter, change.flags,
|
||||
change.fflags, change.data, change.udata);
|
||||
ORBIS_LOG_TODO(__FUNCTION__, fd, change.ident, change.filter,
|
||||
change.flags, change.fflags, change.data, change.udata);
|
||||
|
||||
if (auto result = keventChange(kq.get(), change, thread);
|
||||
result.value() != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
kq->cv.notify_all(kq->mtx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -217,7 +242,17 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
|
|||
std::vector<KEvent> result;
|
||||
result.reserve(nevents);
|
||||
|
||||
if (kq->notes.empty()) {
|
||||
// ORBIS_LOG_ERROR(__FUNCTION__, "attempt to wait empty kqueue", fd,
|
||||
// nevents, timeoutPoint.time_since_epoch().count()); thread->where();
|
||||
// return{};
|
||||
// std::abort();
|
||||
return {};
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
@ -227,9 +262,32 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
|
|||
auto ¬e = *it;
|
||||
std::lock_guard lock(note.mutex);
|
||||
|
||||
if (!note.triggered) {
|
||||
if (note.event.filter == kEvFiltRead) {
|
||||
if (note.file->hostFd < 0 ||
|
||||
isReadEventTriggered(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;
|
||||
}
|
||||
|
|
@ -244,6 +302,9 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
|
|||
}
|
||||
|
||||
if (!result.empty()) {
|
||||
// if (waitHack) {
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds(3));
|
||||
// }
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -256,9 +317,13 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
|
|||
|
||||
auto waitTimeout = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
timeoutPoint - now);
|
||||
kq->cv.wait(kq->mtx, waitTimeout.count());
|
||||
if (canSleep) {
|
||||
kq->cv.wait(kq->mtx, waitTimeout.count());
|
||||
}
|
||||
} else {
|
||||
kq->cv.wait(kq->mtx);
|
||||
if (canSleep) {
|
||||
kq->cv.wait(kq->mtx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,11 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
|
|||
return {};
|
||||
}
|
||||
|
||||
if (int_value->encoded_id == 0x29b56169422aa3dd) {
|
||||
int_value->value = 2;
|
||||
return {};
|
||||
}
|
||||
|
||||
// 0x503f69bde385a6ac // allow loading from dev machine?
|
||||
// 0x2d946f62aef8f878
|
||||
|
||||
|
|
@ -162,7 +167,6 @@ orbis::SysResult orbis::sys_dl_notify_event(Thread *thread /* TODO */) {
|
|||
}
|
||||
orbis::SysResult orbis::sys_evf_create(Thread *thread, ptr<const char[32]> name,
|
||||
sint attrs, uint64_t initPattern) {
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, name, attrs, initPattern);
|
||||
if (name == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
|
@ -215,7 +219,9 @@ orbis::SysResult orbis::sys_evf_create(Thread *thread, ptr<const char[32]> name,
|
|||
std::strncpy(eventFlag->name, _name, 32);
|
||||
}
|
||||
|
||||
thread->retval[0] = thread->tproc->evfMap.insert(eventFlag);
|
||||
auto fd = thread->tproc->evfMap.insert(eventFlag);
|
||||
thread->retval[0] = fd;
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, name, attrs, initPattern, fd);
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_evf_delete(Thread *thread, sint id) {
|
||||
|
|
@ -229,7 +235,6 @@ orbis::SysResult orbis::sys_evf_delete(Thread *thread, sint id) {
|
|||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_evf_open(Thread *thread, ptr<const char[32]> name) {
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, name);
|
||||
char _name[32];
|
||||
if (auto result = ureadString(_name, sizeof(_name), (const char *)name);
|
||||
result != ErrorCode{}) {
|
||||
|
|
@ -239,10 +244,13 @@ orbis::SysResult orbis::sys_evf_open(Thread *thread, ptr<const char[32]> name) {
|
|||
auto eventFlag = thread->tproc->context->findEventFlag(_name);
|
||||
|
||||
if (eventFlag == nullptr) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, _name, "not exists");
|
||||
return ErrorCode::NOENT;
|
||||
}
|
||||
|
||||
thread->retval[0] = thread->tproc->evfMap.insert(eventFlag);
|
||||
auto fd = thread->tproc->evfMap.insert(eventFlag);
|
||||
thread->retval[0] = fd;
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, name, fd);
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_evf_close(Thread *thread, sint id) {
|
||||
|
|
@ -370,8 +378,70 @@ orbis::sys_query_memory_protection(Thread *thread, ptr<void> address,
|
|||
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_batch_map(Thread *thread /* TODO */) {
|
||||
return ErrorCode::NOSYS;
|
||||
|
||||
namespace orbis {
|
||||
struct BatchMapEntry {
|
||||
ptr<char> start;
|
||||
off_t offset;
|
||||
size_t length;
|
||||
char protection;
|
||||
char type;
|
||||
short reserved;
|
||||
sint operation; // 0 - map direct
|
||||
// 1 - unmap
|
||||
// 2 - protect
|
||||
// 3 - map flexible
|
||||
// 4 - type protect
|
||||
};
|
||||
} // namespace orbis
|
||||
|
||||
orbis::SysResult orbis::sys_batch_map(Thread *thread, sint unk, sint flags,
|
||||
ptr<BatchMapEntry> entries,
|
||||
sint entriesCount,
|
||||
ptr<sint> processedCount) {
|
||||
auto ops = thread->tproc->ops;
|
||||
SysResult result = ErrorCode{};
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, unk, flags, entries, entriesCount,
|
||||
processedCount);
|
||||
|
||||
int processed = 0;
|
||||
for (int i = 0; i < entriesCount; ++i) {
|
||||
BatchMapEntry _entry;
|
||||
ORBIS_RET_ON_ERROR(uread(_entry, entries + i));
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, _entry.operation, ptr<void>(_entry.start),
|
||||
_entry.length, int(_entry.type), int(_entry.protection),
|
||||
_entry.offset);
|
||||
|
||||
switch (_entry.operation) {
|
||||
case 0:
|
||||
result = ops->dmem_mmap(thread, _entry.start, _entry.length, _entry.type,
|
||||
_entry.protection, flags, _entry.offset);
|
||||
break;
|
||||
case 1:
|
||||
result = ops->munmap(thread, _entry.start, _entry.length);
|
||||
break;
|
||||
case 2:
|
||||
result =
|
||||
ops->mprotect(thread, _entry.start, _entry.length, _entry.protection);
|
||||
break;
|
||||
default:
|
||||
result = ErrorCode::INVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, result.value());
|
||||
|
||||
if (result.value()) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, result.value());
|
||||
break;
|
||||
}
|
||||
|
||||
++processed;
|
||||
}
|
||||
|
||||
thread->retval[0] = 0;
|
||||
ORBIS_RET_ON_ERROR(uwrite(processedCount, processed));
|
||||
return result;
|
||||
}
|
||||
orbis::SysResult orbis::sys_osem_create(Thread *thread,
|
||||
ptr<const char[32]> name, uint attrs,
|
||||
|
|
@ -418,6 +488,7 @@ orbis::SysResult orbis::sys_osem_create(Thread *thread,
|
|||
sem = insertedSem;
|
||||
} else {
|
||||
sem = knew<Semaphore>(attrs, initCount, maxCount);
|
||||
std::strncpy(sem->name, _name, 32);
|
||||
}
|
||||
|
||||
thread->retval[0] = thread->tproc->semMap.insert(sem);
|
||||
|
|
@ -1048,8 +1119,26 @@ orbis::SysResult orbis::sys_prepare_to_suspend_process(Thread *thread,
|
|||
orbis::SysResult orbis::sys_get_resident_fmem_count(Thread *thread, pid_t pid) {
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_thr_get_name(Thread *thread, lwpid_t lwpid) {
|
||||
return ErrorCode::NOSYS;
|
||||
orbis::SysResult orbis::sys_thr_get_name(Thread *thread, lwpid_t lwpid,
|
||||
char *buf, size_t buflen) {
|
||||
Thread *searchThread;
|
||||
if (thread->tid == lwpid) {
|
||||
searchThread = thread;
|
||||
} else {
|
||||
searchThread = thread->tproc->threadsMap.get(lwpid);
|
||||
if (searchThread == nullptr) {
|
||||
return ErrorCode::SRCH;
|
||||
}
|
||||
}
|
||||
|
||||
auto namelen = std::strlen(searchThread->name);
|
||||
|
||||
if (namelen >= buflen) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
ORBIS_RET_ON_ERROR(uwriteRaw(buf, searchThread->name, namelen));
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_set_gpo(Thread *thread /* TODO */) {
|
||||
return ErrorCode::NOSYS;
|
||||
|
|
@ -1095,10 +1184,16 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
|
|||
return sysIpmiSendConnectResult(thread, result, kid, params, paramsSz);
|
||||
case 0x232:
|
||||
return sysIpmiSessionRespondSync(thread, result, kid, params, paramsSz);
|
||||
case 0x251:
|
||||
return sysIpmiClientGetMessage(thread, result, kid, params, paramsSz);
|
||||
case 0x252:
|
||||
return sysIpmiClientTryGetMessage(thread, result, kid, params, paramsSz);
|
||||
case 0x254:
|
||||
return sysIpmiSessionTrySendMessage(thread, result, kid, params, paramsSz);
|
||||
case 0x302:
|
||||
return sysIpmiSessionGetClientPid(thread, result, kid, params, paramsSz);
|
||||
case 0x310:
|
||||
return sysIpmiClientDisconnect(thread, result, kid, params, paramsSz);
|
||||
case 0x320:
|
||||
return sysIpmiClientInvokeSyncMethod(thread, result, kid, params, paramsSz);
|
||||
case 0x400:
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
#include "pipe.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "uio.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <chrono>
|
||||
#include <sys/socket.h>
|
||||
#include <thread>
|
||||
|
||||
orbis::SysResult orbis::sys_socket(Thread *thread, sint domain, sint type,
|
||||
sint protocol) {
|
||||
|
|
@ -24,37 +21,89 @@ orbis::SysResult orbis::sys_socket(Thread *thread, sint domain, sint type,
|
|||
}
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sys_bind(Thread *thread, sint s, caddr_t name,
|
||||
sint namelen) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, s, name, namelen);
|
||||
return {};
|
||||
// ORBIS_LOG_ERROR(__FUNCTION__, s, name, namelen);
|
||||
|
||||
auto file = thread->tproc->fileDescriptors.get(s);
|
||||
if (file == nullptr) {
|
||||
return ErrorCode::BADF;
|
||||
}
|
||||
|
||||
if (auto bind = file->ops->bind) {
|
||||
return bind(file.get(), ptr<SocketAddress>(name), namelen, thread);
|
||||
}
|
||||
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sys_listen(Thread *thread, sint s, sint backlog) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, s, backlog);
|
||||
return {};
|
||||
auto file = thread->tproc->fileDescriptors.get(s);
|
||||
if (file == nullptr) {
|
||||
return ErrorCode::BADF;
|
||||
}
|
||||
|
||||
if (auto listen = file->ops->listen) {
|
||||
return listen(file.get(), backlog, thread);
|
||||
}
|
||||
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sys_accept(Thread *thread, sint s,
|
||||
ptr<struct sockaddr> from,
|
||||
ptr<SocketAddress> from,
|
||||
ptr<uint32_t> fromlenaddr) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, s, from, fromlenaddr);
|
||||
std::this_thread::sleep_for(std::chrono::days(1));
|
||||
return SysResult::notAnError(ErrorCode::WOULDBLOCK);
|
||||
auto file = thread->tproc->fileDescriptors.get(s);
|
||||
if (file == nullptr) {
|
||||
return ErrorCode::BADF;
|
||||
}
|
||||
|
||||
if (auto accept = file->ops->accept) {
|
||||
return accept(file.get(), from, fromlenaddr, thread);
|
||||
}
|
||||
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
|
||||
orbis::SysResult orbis::sys_connect(Thread *thread, sint s, caddr_t name,
|
||||
sint namelen) {
|
||||
return ErrorCode::NOSYS;
|
||||
auto file = thread->tproc->fileDescriptors.get(s);
|
||||
if (file == nullptr) {
|
||||
return ErrorCode::BADF;
|
||||
}
|
||||
|
||||
if (auto connect = file->ops->connect) {
|
||||
return connect(file.get(), ptr<SocketAddress>(name), namelen, thread);
|
||||
}
|
||||
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
orbis::SysResult orbis::sys_socketpair(Thread *thread, sint domain, sint type,
|
||||
sint protocol, ptr<sint> rsv) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, domain, type, protocol, rsv);
|
||||
ORBIS_LOG_TODO(__FUNCTION__, domain, type, protocol, rsv);
|
||||
if (auto socketpair = thread->tproc->ops->socketpair) {
|
||||
Ref<File> a;
|
||||
Ref<File> b;
|
||||
auto result = socketpair(thread, domain, type, protocol, &a, &b);
|
||||
|
||||
auto pipe = createPipe();
|
||||
auto a = thread->tproc->fileDescriptors.insert(pipe);
|
||||
auto b = thread->tproc->fileDescriptors.insert(pipe);
|
||||
if (auto errc = uwrite(rsv, a); errc != ErrorCode{}) {
|
||||
return errc;
|
||||
if (result.isError()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
auto aFd = thread->tproc->fileDescriptors.insert(a);
|
||||
auto bFd = thread->tproc->fileDescriptors.insert(b);
|
||||
|
||||
if (auto errc = uwrite(rsv, aFd); errc != ErrorCode{}) {
|
||||
return errc;
|
||||
}
|
||||
|
||||
return uwrite(rsv + 1, bFd);
|
||||
}
|
||||
return uwrite(rsv + 1, b);
|
||||
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_sendto(Thread *thread, sint s, caddr_t buf,
|
||||
size_t len, sint flags, caddr_t to,
|
||||
|
|
@ -67,54 +116,82 @@ orbis::SysResult orbis::sys_sendmsg(Thread *thread, sint s,
|
|||
}
|
||||
orbis::SysResult orbis::sys_recvfrom(Thread *thread, sint s, caddr_t buf,
|
||||
size_t len, sint flags,
|
||||
ptr<struct sockaddr> from,
|
||||
ptr<SocketAddress> from,
|
||||
ptr<uint32_t> fromlenaddr) {
|
||||
auto pipe = thread->tproc->fileDescriptors.get(s).cast<Pipe>();
|
||||
if (pipe == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
auto file = thread->tproc->fileDescriptors.get(s);
|
||||
if (file == nullptr) {
|
||||
return ErrorCode::BADF;
|
||||
}
|
||||
|
||||
std::lock_guard lock(pipe->mtx);
|
||||
IoVec io = {
|
||||
.base = buf,
|
||||
.len = len,
|
||||
};
|
||||
Uio uio{
|
||||
.iov = &io,
|
||||
.iovcnt = 1,
|
||||
.segflg = UioSeg::UserSpace,
|
||||
.rw = UioRw::Read,
|
||||
.td = thread,
|
||||
};
|
||||
pipe->ops->read(pipe.get(), &uio, thread);
|
||||
thread->retval[0] = uio.offset;
|
||||
return {};
|
||||
if (auto recvfrom = file->ops->recvfrom) {
|
||||
return SysResult::notAnError(recvfrom(file.get(), buf, len, flags, from, fromlenaddr, thread));
|
||||
}
|
||||
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
orbis::SysResult orbis::sys_recvmsg(Thread *thread, sint s,
|
||||
ptr<struct msghdr> msg, sint flags) {
|
||||
return ErrorCode::NOSYS;
|
||||
auto file = thread->tproc->fileDescriptors.get(s);
|
||||
if (file == nullptr) {
|
||||
return ErrorCode::BADF;
|
||||
}
|
||||
|
||||
if (auto recvmsg = file->ops->recvmsg) {
|
||||
return recvmsg(file.get(), msg, flags, thread);
|
||||
}
|
||||
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
orbis::SysResult orbis::sys_shutdown(Thread *thread, sint s, sint how) {
|
||||
return ErrorCode::NOSYS;
|
||||
auto file = thread->tproc->fileDescriptors.get(s);
|
||||
if (file == nullptr) {
|
||||
return ErrorCode::BADF;
|
||||
}
|
||||
|
||||
if (auto shutdown = file->ops->shutdown) {
|
||||
return shutdown(file.get(), how, thread);
|
||||
}
|
||||
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
orbis::SysResult orbis::sys_setsockopt(Thread *thread, sint s, sint level,
|
||||
sint name, caddr_t val, sint valsize) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, s, level, name, val, valsize);
|
||||
return {};
|
||||
auto file = thread->tproc->fileDescriptors.get(s);
|
||||
if (file == nullptr) {
|
||||
return ErrorCode::BADF;
|
||||
}
|
||||
|
||||
if (auto setsockopt = file->ops->setsockopt) {
|
||||
return setsockopt(file.get(), level, name, val, valsize, thread);
|
||||
}
|
||||
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
orbis::SysResult orbis::sys_getsockopt(Thread *thread, sint s, sint level,
|
||||
sint name, caddr_t val,
|
||||
ptr<sint> avalsize) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, s, level, name, val, avalsize);
|
||||
return {};
|
||||
auto file = thread->tproc->fileDescriptors.get(s);
|
||||
if (file == nullptr) {
|
||||
return ErrorCode::BADF;
|
||||
}
|
||||
|
||||
if (auto getsockopt = file->ops->getsockopt) {
|
||||
return getsockopt(file.get(), level, name, val, avalsize, thread);
|
||||
}
|
||||
|
||||
return ErrorCode::NOTSUP;
|
||||
}
|
||||
orbis::SysResult orbis::sys_getsockname(Thread *thread, sint fdes,
|
||||
ptr<struct sockaddr> asa,
|
||||
ptr<SocketAddress> asa,
|
||||
ptr<uint32_t> alen) {
|
||||
return ErrorCode::NOSYS;
|
||||
// return uwrite<uint32_t>(alen, sizeof(SockAddr));
|
||||
ORBIS_LOG_TODO(__FUNCTION__);
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_getpeername(Thread *thread, sint fdes,
|
||||
ptr<struct sockaddr> asa,
|
||||
ptr<SocketAddress> asa,
|
||||
ptr<uint32_t> alen) {
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,19 +2,52 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <filesystem>
|
||||
#include <span>
|
||||
|
||||
orbis::SysResult orbis::sys_sync(Thread *thread) { return ErrorCode::NOSYS; }
|
||||
orbis::SysResult orbis::sys_quotactl(Thread *thread, ptr<char> path, sint cmd,
|
||||
sint uid, caddr_t arg) {
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
namespace orbis {
|
||||
struct statfs {
|
||||
char pad[0x118];
|
||||
char f_fstypename[16]; /* filesystem type name */
|
||||
char f_mntfromname[88]; /* mounted filesystem */
|
||||
char f_mntonname[88]; /* directory on which mounted */
|
||||
};
|
||||
} // namespace orbis
|
||||
|
||||
orbis::SysResult orbis::sys_statfs(Thread *thread, ptr<char> path,
|
||||
ptr<struct statfs> buf) {
|
||||
return ErrorCode::NOSYS;
|
||||
if (buf == 0) {
|
||||
thread->retval[0] = 1;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::strncpy(buf->f_fstypename, "exfatfs", 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));
|
||||
|
||||
thread->retval[0] = 1;
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_fstatfs(Thread *thread, sint fd,
|
||||
ptr<struct statfs> buf) {
|
||||
return ErrorCode::NOSYS;
|
||||
if (buf == 0) {
|
||||
thread->retval[0] = 1;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::strncpy(buf->f_fstypename, "exfatfs", 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));
|
||||
|
||||
thread->retval[0] = 1;
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_getfsstat(Thread *thread, ptr<struct statfs> buf,
|
||||
slong bufsize, sint flags) {
|
||||
|
|
@ -231,7 +264,7 @@ orbis::SysResult orbis::sys_fchflags(Thread *thread, sint fd, sint flags) {
|
|||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_chmod(Thread *thread, ptr<char> path, sint mode) {
|
||||
return ErrorCode::NOSYS;
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_fchmodat(Thread *thread, sint fd, ptr<char> path,
|
||||
mode_t mode, sint flag) {
|
||||
|
|
@ -353,7 +386,7 @@ orbis::SysResult orbis::sys_getdirentries(Thread *thread, sint fd,
|
|||
auto next = std::min<uint64_t>(file->dirEntries.size(), pos + rmax);
|
||||
file->nextOff = next * sizeof(orbis::Dirent);
|
||||
SysResult result{};
|
||||
result = uwrite((orbis::Dirent *)buf, entries + pos, next - pos);
|
||||
result = uwrite(ptr<orbis::Dirent>(buf), entries + pos, next - pos);
|
||||
if (result.isError())
|
||||
return result;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include <GLFW/glfw3.h> // TODO: make in optional
|
||||
|
||||
// TODO
|
||||
extern void *g_rwMemory;
|
||||
// extern void *g_rwMemory;
|
||||
extern std::size_t g_memorySize;
|
||||
extern std::uint64_t g_memoryBase;
|
||||
extern amdgpu::RemoteMemory g_hostMemory;
|
||||
|
|
@ -739,16 +739,36 @@ int main(int argc, const char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int dmemFd[3];
|
||||
|
||||
for (std::size_t i = 0; i < std::size(dmemFd); ++i) {
|
||||
auto path = "/dev/shm/rpcsx-dmem-" + std::to_string(i);
|
||||
if (!std::filesystem::exists(path)) {
|
||||
std::printf("Waiting for dmem %zu\n", i);
|
||||
while (!std::filesystem::exists(path)) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(300));
|
||||
}
|
||||
}
|
||||
|
||||
dmemFd[i] = ::shm_open(("/rpcsx-dmem-" + std::to_string(i)).c_str(), O_RDWR,
|
||||
S_IRUSR | S_IWUSR);
|
||||
|
||||
if (dmemFd[i] < 0) {
|
||||
std::printf("failed to open dmem shared memory %zu\n", i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct stat memoryStat;
|
||||
::fstat(memoryFd, &memoryStat);
|
||||
amdgpu::RemoteMemory memory{(char *)::mmap(
|
||||
nullptr, memoryStat.st_size, PROT_NONE, MAP_SHARED, memoryFd, 0)};
|
||||
|
||||
extern void *g_rwMemory;
|
||||
// extern void *g_rwMemory;
|
||||
g_memorySize = memoryStat.st_size;
|
||||
g_memoryBase = 0x40000;
|
||||
g_rwMemory = ::mmap(nullptr, g_memorySize, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
memoryFd, 0);
|
||||
// g_rwMemory = ::mmap(nullptr, g_memorySize, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
// memoryFd, 0);
|
||||
|
||||
g_hostMemory = memory;
|
||||
|
||||
|
|
@ -997,6 +1017,16 @@ int main(int argc, const char *argv[]) {
|
|||
break;
|
||||
}
|
||||
|
||||
case amdgpu::bridge::CommandId::MapDmem: {
|
||||
auto addr = g_hostMemory.getPointer(cmd.mapDmem.address);
|
||||
auto mapping = ::mmap(addr, cmd.mapDmem.size,
|
||||
PROT_READ | PROT_WRITE /*TODO: cmd.mapDmem.prot >> 4*/,
|
||||
MAP_FIXED | MAP_SHARED, dmemFd[cmd.mapDmem.dmemIndex],
|
||||
cmd.mapDmem.offset);
|
||||
device.handleProtectMemory(cmd.mapDmem.address, cmd.mapDmem.size, 0x33 /*TODO: cmd.mapDmem.prot*/);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
util::unreachable("Unexpected command id %u\n", (unsigned)cmd.id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ add_executable(rpcsx-os
|
|||
iodev/devstat.cpp
|
||||
iodev/devact.cpp
|
||||
iodev/devctl.cpp
|
||||
iodev/uvd.cpp
|
||||
iodev/vce.cpp
|
||||
|
||||
main.cpp
|
||||
backtrace.cpp
|
||||
|
|
|
|||
|
|
@ -1,26 +1,36 @@
|
|||
#include "io-device.hpp"
|
||||
#include "align.hpp"
|
||||
#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"
|
||||
#include "orbis/uio.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include "vfs.hpp"
|
||||
#include "vm.hpp"
|
||||
#include <cerrno>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <filesystem>
|
||||
#include <netinet/in.h>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
struct HostFile : orbis::File {
|
||||
int hostFd = -1;
|
||||
bool closeOnExit = true;
|
||||
bool alignTruncate = false;
|
||||
|
||||
~HostFile() {
|
||||
if (hostFd > 0 && closeOnExit) {
|
||||
|
|
@ -31,7 +41,11 @@ struct HostFile : orbis::File {
|
|||
|
||||
struct SocketFile : orbis::File {
|
||||
orbis::utils::kstring name;
|
||||
int hostFd = -1;
|
||||
int dom = -1;
|
||||
int type = -1;
|
||||
int prot = -1;
|
||||
|
||||
orbis::kmap<int, orbis::kvector<std::byte>> options;
|
||||
|
||||
~SocketFile() {
|
||||
if (hostFd > 0) {
|
||||
|
|
@ -40,24 +54,6 @@ struct SocketFile : orbis::File {
|
|||
}
|
||||
};
|
||||
|
||||
struct HostFsDevice : IoDevice {
|
||||
orbis::kstring hostPath;
|
||||
|
||||
explicit HostFsDevice(orbis::kstring path) : hostPath(std::move(path)) {}
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override;
|
||||
orbis::ErrorCode unlink(const char *path, bool recursive,
|
||||
orbis::Thread *thread) override;
|
||||
orbis::ErrorCode createSymlink(const char *target, const char *linkPath,
|
||||
orbis::Thread *thread) override;
|
||||
orbis::ErrorCode mkdir(const char *path, int mode,
|
||||
orbis::Thread *thread) override;
|
||||
orbis::ErrorCode rmdir(const char *path, orbis::Thread *thread) override;
|
||||
orbis::ErrorCode rename(const char *from, const char *to,
|
||||
orbis::Thread *thread) override;
|
||||
};
|
||||
|
||||
static orbis::ErrorCode convertErrc(std::errc errc) {
|
||||
if (errc == std::errc{}) {
|
||||
return {};
|
||||
|
|
@ -252,57 +248,22 @@ orbis::ErrorCode convertErrno() {
|
|||
return orbis::ErrorCode::IO;
|
||||
}
|
||||
|
||||
static orbis::ErrorCode host_read(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *) {
|
||||
auto hostFile = static_cast<HostFile *>(file);
|
||||
if (!hostFile->dirEntries.empty())
|
||||
return orbis::ErrorCode::ISDIR;
|
||||
|
||||
static orbis::ErrorCode host_fd_read(int hostFd, orbis::Uio *uio) {
|
||||
std::vector<iovec> vec;
|
||||
for (auto entry : std::span(uio->iov, uio->iovcnt)) {
|
||||
vec.push_back({.iov_base = entry.base, .iov_len = entry.len});
|
||||
}
|
||||
|
||||
ssize_t cnt = 0;
|
||||
if (hostFile->hostFd == 0) {
|
||||
for (auto io : vec) {
|
||||
cnt += ::read(hostFile->hostFd, io.iov_base, io.iov_len);
|
||||
|
||||
if (cnt != io.iov_len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cnt = ::preadv(hostFile->hostFd, vec.data(), vec.size(), uio->offset);
|
||||
}
|
||||
if (cnt < 0) {
|
||||
return convertErrno();
|
||||
}
|
||||
|
||||
uio->resid -= cnt;
|
||||
uio->offset += cnt;
|
||||
return {};
|
||||
}
|
||||
|
||||
static orbis::ErrorCode host_write(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *) {
|
||||
auto hostFile = static_cast<HostFile *>(file);
|
||||
if (!hostFile->dirEntries.empty())
|
||||
return orbis::ErrorCode::ISDIR;
|
||||
|
||||
std::vector<iovec> vec;
|
||||
for (auto entry : std::span(uio->iov, uio->iovcnt)) {
|
||||
vec.push_back({.iov_base = entry.base, .iov_len = entry.len});
|
||||
}
|
||||
|
||||
ssize_t cnt =
|
||||
::pwritev(hostFile->hostFd, vec.data(), vec.size(), uio->offset);
|
||||
|
||||
auto cnt = ::preadv(hostFd, vec.data(), vec.size(), uio->offset);
|
||||
if (cnt < 0) {
|
||||
cnt = 0;
|
||||
for (auto io : vec) {
|
||||
auto result = ::write(hostFile->hostFd, io.iov_base, io.iov_len);
|
||||
auto result = ::read(hostFd, io.iov_base, io.iov_len);
|
||||
if (result < 0) {
|
||||
return convertErrno();
|
||||
if (cnt == 0) {
|
||||
return convertErrno();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cnt += result;
|
||||
|
|
@ -318,6 +279,58 @@ static orbis::ErrorCode host_write(orbis::File *file, orbis::Uio *uio,
|
|||
return {};
|
||||
}
|
||||
|
||||
static orbis::ErrorCode host_fd_write(int hostFd, orbis::Uio *uio) {
|
||||
std::vector<iovec> vec;
|
||||
for (auto entry : std::span(uio->iov, uio->iovcnt)) {
|
||||
vec.push_back({.iov_base = entry.base, .iov_len = entry.len});
|
||||
}
|
||||
|
||||
ssize_t cnt = ::pwritev(hostFd, vec.data(), vec.size(), uio->offset);
|
||||
|
||||
if (cnt < 0) {
|
||||
cnt = 0;
|
||||
|
||||
for (auto io : vec) {
|
||||
auto result = ::write(hostFd, io.iov_base, io.iov_len);
|
||||
if (result < 0) {
|
||||
if (cnt == 0) {
|
||||
return convertErrno();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
cnt += result;
|
||||
|
||||
if (cnt != io.iov_len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uio->resid -= cnt;
|
||||
uio->offset += cnt;
|
||||
return {};
|
||||
}
|
||||
|
||||
static orbis::ErrorCode host_read(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *) {
|
||||
auto hostFile = static_cast<HostFile *>(file);
|
||||
if (!hostFile->dirEntries.empty())
|
||||
return orbis::ErrorCode::ISDIR;
|
||||
|
||||
return host_fd_read(hostFile->hostFd, uio);
|
||||
}
|
||||
|
||||
static orbis::ErrorCode host_write(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *) {
|
||||
auto hostFile = static_cast<HostFile *>(file);
|
||||
if (!hostFile->dirEntries.empty())
|
||||
return orbis::ErrorCode::ISDIR;
|
||||
|
||||
return host_fd_write(hostFile->hostFd, uio);
|
||||
}
|
||||
|
||||
static orbis::ErrorCode host_mmap(orbis::File *file, void **address,
|
||||
std::uint64_t size, std::int32_t prot,
|
||||
std::int32_t flags, std::int64_t offset,
|
||||
|
|
@ -388,15 +401,15 @@ static orbis::ErrorCode host_stat(orbis::File *file, orbis::Stat *sb,
|
|||
static orbis::ErrorCode host_truncate(orbis::File *file, std::uint64_t len,
|
||||
orbis::Thread *thread) {
|
||||
auto hostFile = static_cast<HostFile *>(file);
|
||||
if (!hostFile->dirEntries.empty())
|
||||
if (!hostFile->dirEntries.empty()) {
|
||||
return orbis::ErrorCode::ISDIR;
|
||||
|
||||
// hack for audio control shared memory
|
||||
std::uint64_t realLen = len;
|
||||
if (len == 3880) {
|
||||
realLen = 0x10000;
|
||||
}
|
||||
if (::ftruncate(hostFile->hostFd, realLen)) {
|
||||
|
||||
if (hostFile->alignTruncate) {
|
||||
len = utils::alignUp(len, rx::vm::kPageSize);
|
||||
}
|
||||
|
||||
if (::ftruncate(hostFile->hostFd, len)) {
|
||||
return convertErrno();
|
||||
}
|
||||
|
||||
|
|
@ -410,6 +423,221 @@ static orbis::ErrorCode socket_ioctl(orbis::File *file, std::uint64_t request,
|
|||
return {};
|
||||
}
|
||||
|
||||
static orbis::ErrorCode socket_read(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *) {
|
||||
auto socket = static_cast<SocketFile *>(file);
|
||||
|
||||
if (socket->hostFd < 0) {
|
||||
while (true) {
|
||||
std::this_thread::sleep_for(std::chrono::days(1));
|
||||
}
|
||||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
return host_fd_read(socket->hostFd, uio);
|
||||
}
|
||||
|
||||
static orbis::ErrorCode socket_write(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *) {
|
||||
auto socket = static_cast<SocketFile *>(file);
|
||||
|
||||
if (socket->hostFd < 0) {
|
||||
for (auto io : std::span(uio->iov, uio->iovcnt)) {
|
||||
uio->offset += io.len;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
return host_fd_write(socket->hostFd, uio);
|
||||
}
|
||||
|
||||
static orbis::ErrorCode socket_bind(orbis::File *file,
|
||||
orbis::SocketAddress *address,
|
||||
std::size_t addressLen,
|
||||
orbis::Thread *thread) {
|
||||
auto socket = static_cast<SocketFile *>(file);
|
||||
|
||||
if (socket->hostFd < 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (address->family == 1) {
|
||||
auto vfsPath = std::string_view((const char *)address->data);
|
||||
auto [device, path] = rx::vfs::get(vfsPath);
|
||||
|
||||
if (auto hostDev = device.cast<HostFsDevice>()) {
|
||||
auto socketPath = std::filesystem::path(hostDev->hostPath);
|
||||
socketPath /= path;
|
||||
|
||||
if (socketPath.native().size() >= sizeof(sockaddr_un::sun_path)) {
|
||||
return orbis::ErrorCode::NAMETOOLONG;
|
||||
}
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, vfsPath, socketPath.native());
|
||||
|
||||
sockaddr_un un{.sun_family = AF_UNIX};
|
||||
std::strncpy(un.sun_path, socketPath.c_str(), sizeof(un.sun_path));
|
||||
if (::bind(socket->hostFd, reinterpret_cast<::sockaddr *>(&un),
|
||||
sizeof(un)) < 0) {
|
||||
return convertErrno();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return orbis::ErrorCode::NOTSUP;
|
||||
}
|
||||
|
||||
static orbis::ErrorCode socket_listen(orbis::File *file, int backlog,
|
||||
orbis::Thread *thread) {
|
||||
auto socket = static_cast<SocketFile *>(file);
|
||||
|
||||
if (socket->hostFd < 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (::listen(socket->hostFd, backlog) < 0) {
|
||||
return convertErrno();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
static orbis::ErrorCode socket_accept(orbis::File *file,
|
||||
orbis::SocketAddress *address,
|
||||
std::uint32_t *addressLen,
|
||||
orbis::Thread *thread) {
|
||||
auto socket = static_cast<SocketFile *>(file);
|
||||
|
||||
if (socket->hostFd < 0) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, socket->name, "wait forever");
|
||||
|
||||
while (true) {
|
||||
std::this_thread::sleep_for(std::chrono::days(1));
|
||||
}
|
||||
}
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, socket->name);
|
||||
|
||||
if (socket->dom == 1 && socket->type == 1 && socket->prot == 0) {
|
||||
sockaddr_un un{.sun_family = AF_UNIX};
|
||||
socklen_t len = sizeof(un);
|
||||
int result =
|
||||
::accept(socket->hostFd, reinterpret_cast<sockaddr *>(&un), &len);
|
||||
|
||||
if (result < 0) {
|
||||
return convertErrno();
|
||||
}
|
||||
|
||||
if (addressLen && address) {
|
||||
*addressLen = 2;
|
||||
}
|
||||
|
||||
auto guestSocket = wrapSocket(result, "", 1, 1, 0);
|
||||
auto guestFd = thread->tproc->fileDescriptors.insert(guestSocket);
|
||||
thread->retval[0] = guestFd;
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, socket->name, guestFd);
|
||||
return {};
|
||||
}
|
||||
|
||||
return orbis::ErrorCode::NOTSUP;
|
||||
}
|
||||
|
||||
static orbis::ErrorCode socket_connect(orbis::File *file,
|
||||
orbis::SocketAddress *address,
|
||||
std::uint32_t addressLen,
|
||||
orbis::Thread *thread) {
|
||||
auto socket = static_cast<SocketFile *>(file);
|
||||
|
||||
if (socket->hostFd < 0) {
|
||||
return orbis::ErrorCode::CONNREFUSED;
|
||||
}
|
||||
|
||||
if (address->family == 1) {
|
||||
auto vfsPath = std::string_view((const char *)address->data);
|
||||
auto [device, path] = rx::vfs::get(vfsPath);
|
||||
|
||||
if (auto hostDev = device.cast<HostFsDevice>()) {
|
||||
auto socketPath = std::filesystem::path(hostDev->hostPath);
|
||||
socketPath /= path;
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, vfsPath, socketPath.native());
|
||||
|
||||
if (socketPath.native().size() >= sizeof(sockaddr_un::sun_path)) {
|
||||
return orbis::ErrorCode::NAMETOOLONG;
|
||||
}
|
||||
|
||||
sockaddr_un un{.sun_family = AF_UNIX};
|
||||
std::strncpy(un.sun_path, socketPath.c_str(), sizeof(un.sun_path));
|
||||
if (::connect(socket->hostFd, reinterpret_cast<::sockaddr *>(&un),
|
||||
sizeof(un)) < 0) {
|
||||
return convertErrno();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return orbis::ErrorCode::NOTSUP;
|
||||
}
|
||||
|
||||
orbis::ErrorCode socket_setsockopt(orbis::File *file, orbis::sint level,
|
||||
orbis::sint name, const void *val,
|
||||
orbis::sint valsize, orbis::Thread *thread) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, level, name);
|
||||
auto socket = static_cast<SocketFile *>(file);
|
||||
orbis::kvector<std::byte> option(valsize);
|
||||
std::memcpy(option.data(), val, valsize);
|
||||
socket->options[name] = std::move(option);
|
||||
return {};
|
||||
}
|
||||
|
||||
orbis::ErrorCode socket_getsockopt(orbis::File *file, orbis::sint level,
|
||||
orbis::sint name, void *val,
|
||||
orbis::sint *avalsize,
|
||||
orbis::Thread *thread) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, level, name);
|
||||
auto socket = static_cast<SocketFile *>(file);
|
||||
auto &option = socket->options[name];
|
||||
if (option.size() > *avalsize) {
|
||||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
*avalsize = option.size();
|
||||
std::memcpy(val, option.data(), option.size());
|
||||
return {};
|
||||
}
|
||||
|
||||
orbis::ErrorCode socket_recvfrom(orbis::File *file, void *buf,
|
||||
orbis::size_t len, orbis::sint flags,
|
||||
orbis::SocketAddress *from,
|
||||
orbis::uint32_t *fromlenaddr,
|
||||
orbis::Thread *thread) {
|
||||
auto socket = static_cast<SocketFile *>(file);
|
||||
|
||||
if (socket->hostFd < 0) {
|
||||
return orbis::ErrorCode::CONNREFUSED;
|
||||
}
|
||||
|
||||
if (socket->dom == 1 && socket->type == 1 && socket->prot == 0) {
|
||||
auto count = ::recvfrom(socket->hostFd, buf, len, flags, nullptr, nullptr);
|
||||
if (count < 0) {
|
||||
return convertErrno();
|
||||
}
|
||||
thread->retval[0] = count;
|
||||
|
||||
if (from && fromlenaddr) {
|
||||
from->len = 0;
|
||||
from->family = 1;
|
||||
*fromlenaddr = 2;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return orbis::ErrorCode::NOTSUP;
|
||||
}
|
||||
|
||||
static const orbis::FileOps hostOps = {
|
||||
.read = host_read,
|
||||
.write = host_write,
|
||||
|
|
@ -420,29 +648,55 @@ static const orbis::FileOps hostOps = {
|
|||
|
||||
static const orbis::FileOps socketOps = {
|
||||
.ioctl = socket_ioctl,
|
||||
.read = socket_read,
|
||||
.write = socket_write,
|
||||
.bind = socket_bind,
|
||||
.listen = socket_listen,
|
||||
.accept = socket_accept,
|
||||
.connect = socket_connect,
|
||||
.recvfrom = socket_recvfrom,
|
||||
.setsockopt = socket_setsockopt,
|
||||
.getsockopt = socket_getsockopt,
|
||||
};
|
||||
|
||||
IoDevice *createHostIoDevice(orbis::kstring hostPath) {
|
||||
while (hostPath.size() > 1 && hostPath.ends_with("/")) {
|
||||
IoDevice *createHostIoDevice(orbis::kstring hostPath,
|
||||
orbis::kstring virtualPath) {
|
||||
while (hostPath.size() > 0 && hostPath.ends_with("/")) {
|
||||
hostPath.resize(hostPath.size() - 1);
|
||||
}
|
||||
|
||||
return orbis::knew<HostFsDevice>(std::move(hostPath));
|
||||
return orbis::knew<HostFsDevice>(std::move(hostPath), std::move(virtualPath));
|
||||
}
|
||||
|
||||
orbis::Ref<orbis::File> wrapSocket(int hostFd, orbis::kstring name, int dom,
|
||||
int type, int prot) {
|
||||
auto s = orbis::knew<SocketFile>();
|
||||
s->name = std::move(name);
|
||||
s->dom = dom;
|
||||
s->type = type;
|
||||
s->prot = prot;
|
||||
s->hostFd = hostFd;
|
||||
s->ops = &socketOps;
|
||||
return s;
|
||||
}
|
||||
|
||||
orbis::ErrorCode createSocket(orbis::Ref<orbis::File> *file,
|
||||
orbis::kstring name, int dom, int type,
|
||||
int prot) {
|
||||
auto fd = ::socket(dom, type, prot);
|
||||
// if (fd < 0) {
|
||||
// return convertErrno();
|
||||
// }
|
||||
// ORBIS_LOG_ERROR(__FUNCTION__, name, dom, type, prot);
|
||||
// *file = orbis::createPipe();
|
||||
// return {};
|
||||
int fd = -1;
|
||||
|
||||
auto s = orbis::knew<SocketFile>();
|
||||
s->name = std::move(name);
|
||||
s->hostFd = fd;
|
||||
s->ops = &socketOps;
|
||||
*file = s;
|
||||
if (dom == 1 && type == 1 && prot == 0) {
|
||||
fd = ::socket(dom, type, prot);
|
||||
|
||||
if (fd < 0) {
|
||||
return convertErrno();
|
||||
}
|
||||
}
|
||||
|
||||
*file = wrapSocket(fd, std::move(name), dom, type, prot);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
@ -502,36 +756,49 @@ orbis::ErrorCode HostFsDevice::open(orbis::Ref<orbis::File> *file,
|
|||
|
||||
if (hostFd < 0) {
|
||||
auto error = convertErrno();
|
||||
ORBIS_LOG_ERROR("host_open failed", path, realPath, error);
|
||||
ORBIS_LOG_ERROR("host_open failed", path, realPath.c_str(), error);
|
||||
return error;
|
||||
}
|
||||
|
||||
// Assume the file is a directory and try to read direntries
|
||||
orbis::utils::kvector<orbis::Dirent> dirEntries;
|
||||
char hostEntryBuffer[sizeof(dirent64) * 4];
|
||||
while (true) {
|
||||
::dirent64 hostEntry{};
|
||||
auto r = getdents64(hostFd, &hostEntry, sizeof(hostEntry));
|
||||
auto r = getdents64(hostFd, hostEntryBuffer, sizeof(hostEntryBuffer));
|
||||
if (r <= 0)
|
||||
break;
|
||||
|
||||
if (hostEntry.d_name == std::string_view("..") ||
|
||||
hostEntry.d_name == std::string_view(".")) {
|
||||
continue;
|
||||
}
|
||||
std::size_t offset = 0;
|
||||
|
||||
auto &entry = dirEntries.emplace_back();
|
||||
entry.fileno = dirEntries.size(); // TODO
|
||||
entry.reclen = sizeof(entry);
|
||||
entry.namlen = std::strlen(hostEntry.d_name);
|
||||
std::strncpy(entry.name, hostEntry.d_name, sizeof(entry.name));
|
||||
if (hostEntry.d_type == DT_REG)
|
||||
entry.type = orbis::kDtReg;
|
||||
else if (hostEntry.d_type == DT_DIR || hostEntry.d_type == DT_LNK)
|
||||
entry.type = orbis::kDtDir; // Assume symlinks to be dirs
|
||||
else {
|
||||
ORBIS_LOG_ERROR("host_open: unknown directory entry d_type", realPath,
|
||||
hostEntry.d_name, hostEntry.d_type);
|
||||
dirEntries.pop_back();
|
||||
while (offset < r) {
|
||||
::dirent64 *entryPtr =
|
||||
reinterpret_cast<dirent64 *>(hostEntryBuffer + offset);
|
||||
offset += entryPtr->d_reclen;
|
||||
|
||||
if (entryPtr->d_name == std::string_view("..") ||
|
||||
entryPtr->d_name == std::string_view(".") ||
|
||||
entryPtr->d_name == std::string_view(".rpcsx")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// auto entryPath = (std::filesystem::path(virtualPath) / path /
|
||||
// entryPtr->d_name).lexically_normal().string();
|
||||
std::string entryPath = entryPtr->d_name;
|
||||
|
||||
auto &entry = dirEntries.emplace_back();
|
||||
entry.fileno = dirEntries.size(); // TODO
|
||||
entry.reclen = sizeof(entry);
|
||||
entry.namlen = entryPath.length();
|
||||
std::strncpy(entry.name, entryPath.c_str(), sizeof(entry.name));
|
||||
if (entryPtr->d_type == DT_REG)
|
||||
entry.type = orbis::kDtReg;
|
||||
else if (entryPtr->d_type == DT_DIR || entryPtr->d_type == DT_LNK)
|
||||
entry.type = orbis::kDtDir; // Assume symlinks to be dirs
|
||||
else {
|
||||
ORBIS_LOG_ERROR("host_open: unknown directory entry d_type",
|
||||
realPath.c_str(), entryPtr->d_name, entryPtr->d_type);
|
||||
dirEntries.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -585,11 +852,12 @@ orbis::ErrorCode HostFsDevice::rename(const char *from, const char *to,
|
|||
return convertErrorCode(ec);
|
||||
}
|
||||
|
||||
orbis::File *createHostFile(int hostFd, orbis::Ref<IoDevice> device) {
|
||||
orbis::File *createHostFile(int hostFd, orbis::Ref<IoDevice> device, bool alignTruncate) {
|
||||
auto newFile = orbis::knew<HostFile>();
|
||||
newFile->hostFd = hostFd;
|
||||
newFile->ops = &hostOps;
|
||||
newFile->device = device;
|
||||
newFile->alignTruncate = alignTruncate;
|
||||
return newFile;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,9 +48,29 @@ struct IoDevice : orbis::RcBase {
|
|||
}
|
||||
};
|
||||
|
||||
struct HostFsDevice : IoDevice {
|
||||
orbis::kstring hostPath;
|
||||
orbis::kstring virtualPath;
|
||||
|
||||
HostFsDevice(orbis::kstring path, orbis::kstring virtualPath) : hostPath(std::move(path)), virtualPath(std::move(virtualPath)) {}
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override;
|
||||
orbis::ErrorCode unlink(const char *path, bool recursive,
|
||||
orbis::Thread *thread) override;
|
||||
orbis::ErrorCode createSymlink(const char *target, const char *linkPath,
|
||||
orbis::Thread *thread) override;
|
||||
orbis::ErrorCode mkdir(const char *path, int mode,
|
||||
orbis::Thread *thread) override;
|
||||
orbis::ErrorCode rmdir(const char *path, orbis::Thread *thread) override;
|
||||
orbis::ErrorCode rename(const char *from, const char *to,
|
||||
orbis::Thread *thread) override;
|
||||
};
|
||||
|
||||
orbis::ErrorCode convertErrno();
|
||||
IoDevice *createHostIoDevice(orbis::kstring hostPath);
|
||||
IoDevice *createHostIoDevice(orbis::kstring hostPath, orbis::kstring virtualPath);
|
||||
orbis::Ref<orbis::File> wrapSocket(int hostFd, orbis::kstring name, int dom, int type, int prot);
|
||||
orbis::ErrorCode createSocket(orbis::Ref<orbis::File> *file,
|
||||
orbis::kstring name, int dom, int type, int prot);
|
||||
orbis::File *createHostFile(int hostFd, orbis::Ref<IoDevice> device);
|
||||
orbis::File *createHostFile(int hostFd, orbis::Ref<IoDevice> device, bool alignTruncate = false);
|
||||
IoDevice *createFdWrapDevice(int fd);
|
||||
|
|
|
|||
|
|
@ -40,3 +40,5 @@ IoDevice *createGbaseCharacterDevice();
|
|||
IoDevice *createDevStatCharacterDevice();
|
||||
IoDevice *createDevCtlCharacterDevice();
|
||||
IoDevice *createDevActCharacterDevice();
|
||||
IoDevice *createUVDCharacterDevice();
|
||||
IoDevice *createVCECharacterDevice();
|
||||
|
|
|
|||
|
|
@ -1,26 +1,31 @@
|
|||
#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 <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) {
|
||||
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 {};
|
||||
}
|
||||
|
||||
static orbis::ErrorCode aout_write(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *) {
|
||||
uio->resid = 0;
|
||||
for (auto entry : std::span(uio->iov, uio->iovcnt)) {
|
||||
uio->offset += entry.len;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
@ -33,9 +38,11 @@ struct AoutDevice : IoDevice {
|
|||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override {
|
||||
ORBIS_LOG_FATAL("aout device open", path, flags, mode);
|
||||
auto newFile = orbis::knew<AoutFile>();
|
||||
newFile->ops = &fileOps;
|
||||
newFile->device = this;
|
||||
thread->where();
|
||||
|
||||
*file = newFile;
|
||||
return {};
|
||||
|
|
|
|||
|
|
@ -49,9 +49,10 @@ static orbis::ErrorCode console_write(orbis::File *file, orbis::Uio *uio,
|
|||
auto dev = dynamic_cast<ConsoleDevice *>(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);
|
||||
}
|
||||
uio->resid = 0;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ static orbis::ErrorCode dce_ioctl(orbis::File *file, std::uint64_t request,
|
|||
ORBIS_LOG_NOTICE("dce: UNIMPLEMENTED FlipControl", args->id, args->arg2,
|
||||
args->ptr, args->size);
|
||||
|
||||
thread->where();
|
||||
std::fflush(stdout);
|
||||
//__builtin_trap();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,16 @@
|
|||
#include "dmem.hpp"
|
||||
#include "bridge.hpp"
|
||||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/thread/Process.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include "vm.hpp"
|
||||
#include <fcntl.h>
|
||||
#include <mutex>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct DmemFile : public orbis::File {};
|
||||
|
||||
|
|
@ -21,18 +26,46 @@ static constexpr auto dmemSize = 8ull * 1024 * 1024 * 1024;
|
|||
// static const std::uint64_t nextOffset = 0;
|
||||
// static const std::uint64_t memBeginAddress = 0xfe0000000;
|
||||
|
||||
DmemDevice::~DmemDevice() {
|
||||
if (shmFd > 0) {
|
||||
close(shmFd);
|
||||
}
|
||||
|
||||
shm_unlink(("/rpcsx-dmem-" + std::to_string(index)).c_str());
|
||||
}
|
||||
|
||||
orbis::ErrorCode DmemDevice::mmap(void **address, std::uint64_t len,
|
||||
std::int32_t prot, std::int32_t flags,
|
||||
std::int64_t directMemoryStart) {
|
||||
auto result =
|
||||
rx::vm::map(*address, len, prot, flags, 0, this, directMemoryStart);
|
||||
if (prot == 0) {
|
||||
// hack
|
||||
// fixme: implement protect for pid
|
||||
prot = rx::vm::kMapProtCpuWrite | rx::vm::kMapProtCpuRead |
|
||||
rx::vm::kMapProtGpuAll;
|
||||
}
|
||||
|
||||
ORBIS_LOG_WARNING("dmem mmap", index, directMemoryStart, prot, flags, result);
|
||||
auto result =
|
||||
rx::vm::map(*address, len, prot, flags, rx::vm::kMapInternalReserveOnly,
|
||||
this, directMemoryStart);
|
||||
|
||||
ORBIS_LOG_WARNING("dmem mmap", index, directMemoryStart, prot, flags, result,
|
||||
*address);
|
||||
if (result == (void *)-1) {
|
||||
return orbis::ErrorCode::NOMEM; // TODO
|
||||
}
|
||||
|
||||
if (::mmap(result, len, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, shmFd,
|
||||
directMemoryStart) == (void *)-1) {
|
||||
std::abort();
|
||||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
rx::bridge.sendMapDmem(orbis::g_currentThread->tproc->pid, index,
|
||||
reinterpret_cast<std::uint64_t>(result), len, prot,
|
||||
directMemoryStart);
|
||||
|
||||
*address = result;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
@ -61,6 +94,7 @@ static orbis::ErrorCode dmem_ioctl(orbis::File *file, std::uint64_t request,
|
|||
args->alignment, &args->size);
|
||||
}
|
||||
|
||||
case 0xc0288010: // sceKernelAllocateDirectMemoryForMiniApp
|
||||
case 0xc0288011:
|
||||
case 0xc0288001: { // sceKernelAllocateDirectMemory
|
||||
auto args = reinterpret_cast<AllocateDirectMemoryArgs *>(argp);
|
||||
|
|
@ -69,6 +103,21 @@ static orbis::ErrorCode dmem_ioctl(orbis::File *file, std::uint64_t request,
|
|||
args->alignment, args->memoryType);
|
||||
}
|
||||
|
||||
case 0xc018800d: { // transfer budget
|
||||
return {};
|
||||
}
|
||||
|
||||
case 0xc018800f: { // protect memory for pid
|
||||
struct Args {
|
||||
std::uint64_t address;
|
||||
std::uint64_t size;
|
||||
std::uint32_t pid; // 0 if all
|
||||
std::uint32_t prot;
|
||||
};
|
||||
return {};
|
||||
}
|
||||
|
||||
case 0x80108015: // sceKernelCheckedReleaseDirectMemory
|
||||
case 0x80108002: { // sceKernelReleaseDirectMemory
|
||||
struct Args {
|
||||
std::uint64_t address;
|
||||
|
|
@ -302,5 +351,14 @@ IoDevice *createDmemCharacterDevice(int index) {
|
|||
auto *newDevice = orbis::knew<DmemDevice>();
|
||||
newDevice->index = index;
|
||||
newDevice->dmemTotalSize = dmemSize;
|
||||
auto shmFd = ::shm_open(("/rpcsx-dmem-" + std::to_string(index)).c_str(),
|
||||
O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
|
||||
if (ftruncate(shmFd, dmemSize) < 0) {
|
||||
::close(shmFd);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
newDevice->shmFd = shmFd;
|
||||
return newDevice;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,11 @@
|
|||
struct DmemDevice : public IoDevice {
|
||||
orbis::shared_mutex mtx;
|
||||
int index;
|
||||
int shmFd = -1;
|
||||
std::size_t dmemTotalSize;
|
||||
|
||||
~DmemDevice();
|
||||
|
||||
struct AllocationInfo {
|
||||
std::uint32_t memoryType;
|
||||
|
||||
|
|
|
|||
|
|
@ -132,8 +132,9 @@ static orbis::ErrorCode gc_ioctl(orbis::File *file, std::uint64_t request,
|
|||
break;
|
||||
}
|
||||
|
||||
case 0xc0048116: {
|
||||
case 0xc0048116: { // submit done?
|
||||
ORBIS_LOG_ERROR("gc ioctl 0xc0048116", *(std::uint32_t *)argp);
|
||||
*(std::uint32_t *)argp = 1;
|
||||
thread->where();
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ static orbis::ErrorCode notification_write(orbis::File *file, orbis::Uio *uio, o
|
|||
auto offset = dev->data.size();
|
||||
dev->data.resize(offset + vec.len);
|
||||
std::memcpy(dev->data.data(), vec.base, vec.len);
|
||||
uio->offset += vec.len;
|
||||
}
|
||||
uio->resid = 0;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/uio.hpp"
|
||||
#include <span>
|
||||
|
||||
struct NullDevice : public IoDevice {
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
|
|
@ -11,7 +12,9 @@ struct NullFile : public orbis::File {};
|
|||
|
||||
static orbis::ErrorCode null_write(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *) {
|
||||
uio->resid = 0;
|
||||
for (auto entry : std::span(uio->iov, uio->iovcnt)) {
|
||||
uio->offset += entry.len;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ orbis::ErrorCode ShmDevice::open(orbis::Ref<orbis::File> *file,
|
|||
auto name = realShmPath(path);
|
||||
auto realFlags = O_RDWR; // TODO
|
||||
|
||||
std::size_t size = 0;
|
||||
if (flags & 0x200) {
|
||||
realFlags |= O_CREAT;
|
||||
}
|
||||
|
|
@ -47,11 +46,8 @@ orbis::ErrorCode ShmDevice::open(orbis::Ref<orbis::File> *file,
|
|||
if (fd < 0) {
|
||||
return convertErrno();
|
||||
}
|
||||
auto hostFile = createHostFile(fd, this);
|
||||
if (size != 0) {
|
||||
hostFile->ops->truncate(hostFile, size, thread);
|
||||
}
|
||||
|
||||
auto hostFile = createHostFile(fd, this, true);
|
||||
*file = hostFile;
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
32
rpcsx-os/iodev/uvd.cpp
Normal file
32
rpcsx-os/iodev/uvd.cpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
|
||||
struct UVDFile : orbis::File {};
|
||||
|
||||
static orbis::ErrorCode uvd_ioctl(orbis::File *file, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
|
||||
ORBIS_LOG_FATAL("Unhandled uvd ioctl", request);
|
||||
return {};
|
||||
}
|
||||
|
||||
static const orbis::FileOps fileOps = {
|
||||
.ioctl = uvd_ioctl,
|
||||
};
|
||||
|
||||
struct UVDDevice : 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<UVDFile>();
|
||||
newFile->ops = &fileOps;
|
||||
newFile->device = this;
|
||||
|
||||
*file = newFile;
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
IoDevice *createUVDCharacterDevice() { return orbis::knew<UVDDevice>(); }
|
||||
45
rpcsx-os/iodev/vce.cpp
Normal file
45
rpcsx-os/iodev/vce.cpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#include "io-device.hpp"
|
||||
#include "orbis/KernelAllocator.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
|
||||
struct VCEFile : orbis::File {};
|
||||
|
||||
static orbis::ErrorCode vce_ioctl(orbis::File *file, std::uint64_t request,
|
||||
void *argp, orbis::Thread *thread) {
|
||||
|
||||
switch (request) {
|
||||
case 0xc0048406:
|
||||
*reinterpret_cast<std::uint32_t *>(argp) = 0x700;
|
||||
return{};
|
||||
|
||||
case 0x80488401:
|
||||
auto unkAddress = *reinterpret_cast<std::uint64_t *>(argp);
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, request, unkAddress);
|
||||
return{};
|
||||
}
|
||||
|
||||
ORBIS_LOG_FATAL("Unhandled vce ioctl", request);
|
||||
thread->where();
|
||||
return {};
|
||||
}
|
||||
|
||||
static const orbis::FileOps fileOps = {
|
||||
.ioctl = vce_ioctl,
|
||||
};
|
||||
|
||||
struct VCEDevice : 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<VCEFile>();
|
||||
newFile->ops = &fileOps;
|
||||
newFile->device = this;
|
||||
|
||||
*file = newFile;
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
IoDevice *createVCECharacterDevice() { return orbis::knew<VCEDevice>(); }
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
#include <bit>
|
||||
#include <crypto/sha1.h>
|
||||
#include <elf.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <orbis/thread/Process.hpp>
|
||||
|
|
@ -968,7 +969,7 @@ 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("a.out", std::ios::binary)
|
||||
std::ofstream(std::filesystem::path(path).filename().replace_extension("elf"), std::ios::binary)
|
||||
.write((const char *)image.data(), image.size());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "thread.hpp"
|
||||
#include "vfs.hpp"
|
||||
#include "vm.hpp"
|
||||
#include "xbyak/xbyak.h"
|
||||
#include <rx/Version.hpp>
|
||||
|
||||
#include <elf.h>
|
||||
|
|
@ -120,7 +121,7 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) {
|
|||
|
||||
if (g_gpuPid > 0) {
|
||||
// stop gpu thread
|
||||
::kill(g_gpuPid, SIGINT);
|
||||
// ::kill(g_gpuPid, SIGINT);
|
||||
}
|
||||
|
||||
if (sig != SIGINT) {
|
||||
|
|
@ -314,7 +315,9 @@ static void onSysExit(orbis::Thread *thread, int id, uint64_t *args,
|
|||
std::fprintf(stderr, ") -> Status %d, Value %lx:%lx\n", result.value(),
|
||||
thread->retval[0], thread->retval[1]);
|
||||
|
||||
thread->where();
|
||||
if (result.isError()) {
|
||||
thread->where();
|
||||
}
|
||||
funlockfile(stderr);
|
||||
}
|
||||
|
||||
|
|
@ -391,6 +394,8 @@ static void ps4InitDev() {
|
|||
rx::vfs::addDevice("devstat", createDevStatCharacterDevice());
|
||||
rx::vfs::addDevice("devact", createDevActCharacterDevice());
|
||||
rx::vfs::addDevice("devctl", createDevCtlCharacterDevice());
|
||||
rx::vfs::addDevice("uvd", createUVDCharacterDevice());
|
||||
rx::vfs::addDevice("vce", createVCECharacterDevice());
|
||||
|
||||
auto shm = createShmDevice();
|
||||
rx::vfs::addDevice("shm", shm);
|
||||
|
|
@ -532,6 +537,23 @@ ExecEnv ps4CreateExecEnv(orbis::Thread *mainThread,
|
|||
std::abort();
|
||||
}
|
||||
|
||||
for (auto sym : libkernel->symbols) {
|
||||
if (sym.id == 0xd2f4e7e480cc53d0) {
|
||||
auto address = (uint64_t)libkernel->base + sym.address;
|
||||
::mprotect((void *)utils::alignDown(address, 0x1000), utils::alignUp(sym.size + sym.address, 0x1000), PROT_WRITE);
|
||||
std::printf("patching sceKernelGetMainSocId\n");
|
||||
struct GetMainSocId : Xbyak::CodeGenerator {
|
||||
GetMainSocId(std::uint64_t address, std::uint64_t size) : Xbyak::CodeGenerator(size, (void *)address) {
|
||||
mov(eax, 0x710f00);
|
||||
ret();
|
||||
}
|
||||
} gen{ address, sym.size };
|
||||
|
||||
::mprotect((void *)utils::alignDown(address, 0x1000), utils::alignUp(sym.size + sym.address, 0x1000), PROT_READ | PROT_EXEC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (orbis::g_context.fwSdkVersion == 0) {
|
||||
auto moduleParam = reinterpret_cast<std::byte *>(libkernel->moduleParam);
|
||||
auto fwSdkVersion = moduleParam //
|
||||
|
|
@ -607,7 +629,7 @@ static void runRpsxGpu() {
|
|||
isRpsxGpuPid(bridgeHeader->pullerPid)) {
|
||||
bridgeHeader->pusherPid = ::getpid();
|
||||
g_gpuPid = bridgeHeader->pullerPid;
|
||||
rx::bridge = bridgeHeader;
|
||||
rx::bridge.header = bridgeHeader;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -617,7 +639,7 @@ static void runRpsxGpu() {
|
|||
bridgeHeader = amdgpu::bridge::createShmCommandBuffer(cmdBufferName);
|
||||
}
|
||||
bridgeHeader->pusherPid = ::getpid();
|
||||
rx::bridge = bridgeHeader;
|
||||
rx::bridge.header = bridgeHeader;
|
||||
|
||||
auto rpcsxGpuPath = getSelfDir() / "rpcsx-gpu";
|
||||
|
||||
|
|
@ -686,6 +708,22 @@ struct IpmiServer {
|
|||
return *this;
|
||||
}
|
||||
|
||||
IpmiServer &createSyncHandlerStub(std::uint32_t methodId,
|
||||
std::function<std::int32_t()> handler) {
|
||||
syncHandlers[methodId] =
|
||||
[=](std::int32_t &errorCode, std::vector<std::span<std::byte>> &outData,
|
||||
const std::vector<std::span<std::byte>> &inData)
|
||||
-> orbis::ErrorCode {
|
||||
if (!outData.empty()) {
|
||||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
errorCode = handler();
|
||||
return {};
|
||||
};
|
||||
return *this;
|
||||
}
|
||||
|
||||
IpmiServer &createSyncHandler(
|
||||
std::uint32_t methodId,
|
||||
std::function<std::int32_t(void *out, std::uint64_t &outSize)> handler) {
|
||||
|
|
@ -693,7 +731,7 @@ struct IpmiServer {
|
|||
[=](std::int32_t &errorCode, std::vector<std::span<std::byte>> &outData,
|
||||
const std::vector<std::span<std::byte>> &inData)
|
||||
-> orbis::ErrorCode {
|
||||
if (outData.size() != 1) {
|
||||
if (outData.size() < 1) {
|
||||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
|
|
@ -732,6 +770,34 @@ struct IpmiServer {
|
|||
return *this;
|
||||
}
|
||||
|
||||
template <typename OutT, typename InT>
|
||||
IpmiServer &createSyncHandler(
|
||||
std::uint32_t methodId,
|
||||
std::function<std::int32_t(OutT &out, const InT ¶m)> handler) {
|
||||
syncHandlers[methodId] =
|
||||
[=](std::int32_t &errorCode, std::vector<std::span<std::byte>> &outData,
|
||||
const std::vector<std::span<std::byte>> &inData)
|
||||
-> orbis::ErrorCode {
|
||||
if (outData.size() != 1 || inData.size() != 1) {
|
||||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
if (inData[0].size() != sizeof(InT)) {
|
||||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
if (outData[0].size() < sizeof(OutT)) {
|
||||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
OutT out;
|
||||
errorCode = handler(out, *reinterpret_cast<InT *>(inData[0].data()));
|
||||
std::memcpy(outData[0].data(), &out, sizeof(out));
|
||||
outData[0] = outData[0].subspan(0, sizeof(OutT));
|
||||
return {};
|
||||
};
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
IpmiServer &
|
||||
createSyncHandler(std::uint32_t methodId,
|
||||
|
|
@ -811,9 +877,22 @@ struct IpmiServer {
|
|||
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());
|
||||
// }
|
||||
|
||||
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),
|
||||
|
|
@ -914,6 +993,8 @@ static void createMiniSysCoreObjects(orbis::Process *process) {
|
|||
static void createSysAvControlObjects(orbis::Process *process) {
|
||||
createIpmiServer(process, "SceAvSettingIpc");
|
||||
|
||||
createIpmiServer(process, "SceAvCaptureIpc");
|
||||
createEventFlag("SceAvCaptureIpc", 0x121, 0);
|
||||
createEventFlag("SceAvSettingEvf", 0x121, 0xffff00000000);
|
||||
|
||||
createShm("/SceAvSetting", 0xa02, 0x1a4, 4096);
|
||||
|
|
@ -1009,14 +1090,48 @@ static void createShellCoreObjects(orbis::Process *process) {
|
|||
createIpmiServer(process, "SceNetCtl");
|
||||
createIpmiServer(process, "SceNpMgrIpc")
|
||||
.createSyncHandler(
|
||||
0, [=](void *out, std::uint64_t &size) -> std::int32_t {
|
||||
0,
|
||||
[=](void *out, std::uint64_t &size) -> std::int32_t {
|
||||
std::string_view result = "SceNpMgrEvf";
|
||||
if (size < result.size() + 1) {
|
||||
return 0x8002'0000 + static_cast<int>(orbis::ErrorCode::INVAL);
|
||||
}
|
||||
std::strncpy((char *)out, result.data(), result.size() + 1);
|
||||
size = result.size() + 1;
|
||||
orbis::g_context.createEventFlag("SceNpMgrEvf", 0x200, 0);
|
||||
orbis::g_context.createEventFlag(orbis::kstring(result), 0x200, 0);
|
||||
return 0;
|
||||
})
|
||||
.createSyncHandlerStub(0xd, [=] -> std::int32_t { return 0; });
|
||||
createIpmiServer(process, "SceNpService")
|
||||
.createSyncHandler<std::uint32_t>(0, [=](void *out, std::uint64_t &size,
|
||||
std::uint32_t val) { return 0; })
|
||||
.createSyncHandler(0xa0001,
|
||||
[=](void *out, std::uint64_t &size) -> std::int32_t {
|
||||
if (size < 1) {
|
||||
return 0x8002'0000 +
|
||||
static_cast<int>(orbis::ErrorCode::INVAL);
|
||||
}
|
||||
size = 1;
|
||||
*reinterpret_cast<std::uint8_t *>(out) = 1;
|
||||
return 0;
|
||||
})
|
||||
.createSyncHandler(0xa0002,
|
||||
[=](void *out, std::uint64_t &size) -> std::int32_t {
|
||||
if (size < 1) {
|
||||
return 0x8002'0000 +
|
||||
static_cast<int>(orbis::ErrorCode::INVAL);
|
||||
}
|
||||
size = 1;
|
||||
*reinterpret_cast<std::uint8_t *>(out) = 1;
|
||||
return 0;
|
||||
})
|
||||
.createSyncHandler<std::uint32_t, std::uint32_t>(
|
||||
0xd0000, // sceNpTpipIpcClientGetShmIndex
|
||||
[=](std::uint32_t &shmIndex, std::uint32_t appId) -> std::int32_t {
|
||||
shmIndex = 0;
|
||||
return 0;
|
||||
});
|
||||
createIpmiServer(process, "SceNpService");
|
||||
|
||||
createIpmiServer(process, "SceNpTrophyIpc");
|
||||
createIpmiServer(process, "SceNpUdsIpc");
|
||||
createIpmiServer(process, "SceLibNpRifMgrIpc");
|
||||
|
|
@ -1033,7 +1148,45 @@ static void createShellCoreObjects(orbis::Process *process) {
|
|||
createIpmiServer(process, "ScePatchChecker");
|
||||
createIpmiServer(process, "SceMorpheusUpdService");
|
||||
createIpmiServer(process, "ScePsmSharedDmem");
|
||||
createIpmiServer(process, "SceSaveData");
|
||||
createIpmiServer(process, "SceSaveData")
|
||||
.createSyncHandler(
|
||||
0x12340001,
|
||||
[](void *out, std::uint64_t &size) -> std::int32_t {
|
||||
{
|
||||
auto [dev, devPath] = rx::vfs::get("/app0");
|
||||
if (auto hostFs = dev.cast<HostFsDevice>()) {
|
||||
std::error_code ec;
|
||||
auto saveDir = hostFs->hostPath + "/.rpcsx/saves/";
|
||||
if (!std::filesystem::exists(saveDir)) {
|
||||
return 0x8002'0000 +
|
||||
static_cast<int>(orbis::ErrorCode::NOENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string_view result = "/saves";
|
||||
if (size < result.size() + 1) {
|
||||
return 0x8002'0000 + static_cast<int>(orbis::ErrorCode::INVAL);
|
||||
}
|
||||
std::strncpy((char *)out, result.data(), result.size() + 1);
|
||||
size = result.size() + 1;
|
||||
orbis::g_context.createEventFlag(orbis::kstring(result), 0x200, 0);
|
||||
return 0;
|
||||
})
|
||||
.createSyncHandler(
|
||||
0x12340002, [](void *out, std::uint64_t &size) -> std::int32_t {
|
||||
{
|
||||
auto [dev, devPath] = rx::vfs::get("/app0");
|
||||
if (auto hostFs = dev.cast<HostFsDevice>()) {
|
||||
std::error_code ec;
|
||||
auto saveDir = hostFs->hostPath + "/.rpcsx/saves/";
|
||||
std::filesystem::create_directories(saveDir, ec);
|
||||
rx::vfs::mount("/saves/",
|
||||
createHostIoDevice(saveDir, "/saves/"));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
createIpmiServer(process, "SceStickerCoreServer");
|
||||
createIpmiServer(process, "SceDbRecoveryShellCore");
|
||||
createIpmiServer(process, "SceUserService")
|
||||
|
|
@ -1096,6 +1249,8 @@ static void createShellCoreObjects(orbis::Process *process) {
|
|||
createEventFlag("SceLncUtilAppStatus1", 0x100, 0);
|
||||
createEventFlag("SceAppMessaging1", 0x120, 1);
|
||||
createEventFlag("SceShellCoreUtil1", 0x120, 0x3f8c);
|
||||
createEventFlag("SceNpScoreIpc_" + fmtHex(process->pid), 0x120, 0);
|
||||
createEventFlag("/vmicDdEvfAin", 0x120, 0);
|
||||
|
||||
createSemaphore("SceAppMessaging1", 0x101, 1, 0x7fffffff);
|
||||
createSemaphore("SceLncSuspendBlock1", 0x101, 1, 10000);
|
||||
|
|
@ -1144,7 +1299,7 @@ static orbis::SysResult launchDaemon(orbis::Thread *thread, std::string path,
|
|||
};
|
||||
|
||||
process->authInfo = {
|
||||
.unk0 = 0x3100000000000001,
|
||||
.unk0 = 0x380000000000000f,
|
||||
.caps =
|
||||
{
|
||||
-1ul,
|
||||
|
|
@ -1207,6 +1362,8 @@ static orbis::SysResult launchDaemon(orbis::Thread *thread, std::string path,
|
|||
thread->tproc->processParam = executableModule->processParam;
|
||||
thread->tproc->processParamSize = executableModule->processParamSize;
|
||||
|
||||
g_traceSyscalls = false;
|
||||
|
||||
thread->tproc->event.emit(orbis::kEvFiltProc, orbis::kNoteExec);
|
||||
|
||||
std::thread([&] {
|
||||
|
|
@ -1260,8 +1417,9 @@ int main(int argc, const char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
rx::vfs::mount(argv[argIndex + 2],
|
||||
createHostIoDevice(argv[argIndex + 1]));
|
||||
rx::vfs::mount(
|
||||
argv[argIndex + 2],
|
||||
createHostIoDevice(argv[argIndex + 1], argv[argIndex + 2]));
|
||||
argIndex += 3;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1323,7 +1481,7 @@ int main(int argc, const char *argv[]) {
|
|||
// rx::vm::printHostStats();
|
||||
orbis::g_context.allocatePid();
|
||||
auto initProcess = orbis::g_context.createProcess(asRoot ? 1 : 10);
|
||||
pthread_setname_np(pthread_self(), "10.MAINTHREAD");
|
||||
// pthread_setname_np(pthread_self(), "10.MAINTHREAD");
|
||||
|
||||
std::thread{[] {
|
||||
pthread_setname_np(pthread_self(), "Bridge");
|
||||
|
|
@ -1400,7 +1558,7 @@ int main(int argc, const char *argv[]) {
|
|||
if (isSystem) {
|
||||
amdgpu::bridge::expGpuPid = 50001;
|
||||
initProcess->authInfo = {
|
||||
.unk0 = 0x3100000000000001,
|
||||
.unk0 = 0x380000000000000f,
|
||||
.caps =
|
||||
{
|
||||
-1ul,
|
||||
|
|
@ -1482,6 +1640,9 @@ int main(int argc, const char *argv[]) {
|
|||
createGnmCompositorObjects(initProcess);
|
||||
createShellCoreObjects(initProcess);
|
||||
|
||||
createIpmiServer(initProcess, "SceCdlgRichProf"); // ?
|
||||
initProcess->cwd = "/app0/";
|
||||
|
||||
launchDaemon(mainThread, "/system/sys/orbis_audiod.elf",
|
||||
{"/system/sys/orbis_audiod.elf"}, {});
|
||||
status = ps4Exec(mainThread, execEnv, std::move(executableModule),
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <string>
|
||||
#include <string_view>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
@ -356,6 +357,26 @@ orbis::SysResult socket(orbis::Thread *thread, orbis::ptr<const char> name,
|
|||
return createSocket(file, name ? name : "", domain, type, protocol);
|
||||
}
|
||||
|
||||
orbis::SysResult socketPair(orbis::Thread *thread, orbis::sint domain,
|
||||
orbis::sint type, orbis::sint protocol,
|
||||
Ref<File> *a, Ref<File> *b) {
|
||||
|
||||
if (domain == 1 && type == 1 && protocol == 0) {
|
||||
int fds[2];
|
||||
if (::socketpair(domain, type, protocol, fds)) {
|
||||
return convertErrno();
|
||||
}
|
||||
|
||||
*a = wrapSocket(fds[0], "", domain, type, protocol);
|
||||
*b = wrapSocket(fds[1], "", domain, type, protocol);
|
||||
}
|
||||
|
||||
auto result = wrapSocket(-1, "", domain, type, protocol);
|
||||
*a = result;
|
||||
*b = result;
|
||||
return {};
|
||||
}
|
||||
|
||||
orbis::SysResult shm_unlink(orbis::Thread *thread, const char *path) {
|
||||
auto dev = static_cast<IoDevice *>(orbis::g_context.shmDevice.get());
|
||||
return dev->unlink(path, false, thread);
|
||||
|
|
@ -879,6 +900,7 @@ ProcessOps rx::procOpsTable = {
|
|||
.blockpool_map = blockpool_map,
|
||||
.blockpool_unmap = blockpool_unmap,
|
||||
.socket = socket,
|
||||
.socketpair = socketPair,
|
||||
.shm_unlink = shm_unlink,
|
||||
.dynlib_get_obj_member = dynlib_get_obj_member,
|
||||
.dynlib_dlsym = dynlib_dlsym,
|
||||
|
|
|
|||
|
|
@ -43,19 +43,23 @@ using caddr_t = ptr<char>;
|
|||
|
||||
[[nodiscard]] inline ErrorCode
|
||||
ureadRaw(void *kernelAddress, ptr<const void> userAddress, size_t size) {
|
||||
auto addr = reinterpret_cast<std::uintptr_t>(userAddress);
|
||||
if (addr < 0x40000 || addr + size > 0x100'0000'0000 || addr + size < addr)
|
||||
return ErrorCode::FAULT;
|
||||
std::memcpy(kernelAddress, userAddress, size);
|
||||
if (size != 0) {
|
||||
auto addr = reinterpret_cast<std::uintptr_t>(userAddress);
|
||||
if (addr < 0x40000 || addr + size > 0x100'0000'0000 || addr + size < addr)
|
||||
return ErrorCode::FAULT;
|
||||
std::memcpy(kernelAddress, userAddress, size);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]] inline ErrorCode
|
||||
uwriteRaw(ptr<void> userAddress, const void *kernelAddress, size_t size) {
|
||||
auto addr = reinterpret_cast<std::uintptr_t>(userAddress);
|
||||
if (addr < 0x40000 || addr + size > 0x100'0000'0000 || addr + size < addr)
|
||||
return ErrorCode::FAULT;
|
||||
std::memcpy(userAddress, kernelAddress, size);
|
||||
if (size != 0) {
|
||||
auto addr = reinterpret_cast<std::uintptr_t>(userAddress);
|
||||
if (addr < 0x40000 || addr + size > 0x100'0000'0000 || addr + size < addr)
|
||||
return ErrorCode::FAULT;
|
||||
std::memcpy(userAddress, kernelAddress, size);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +77,8 @@ uwriteRaw(ptr<void> userAddress, const void *kernelAddress, size_t size) {
|
|||
return {};
|
||||
}
|
||||
|
||||
template <typename T> [[nodiscard]] ErrorCode uread(T &result, ptr<const T> pointer) {
|
||||
template <typename T>
|
||||
[[nodiscard]] ErrorCode uread(T &result, ptr<const T> pointer) {
|
||||
return ureadRaw(&result, pointer, sizeof(T));
|
||||
}
|
||||
|
||||
|
|
@ -90,14 +95,15 @@ template <typename T, typename U>
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] ErrorCode uread(T *result, ptr<const T> pointer, std::size_t count) {
|
||||
[[nodiscard]] ErrorCode uread(T *result, ptr<const T> pointer,
|
||||
std::size_t count) {
|
||||
return ureadRaw(&result, pointer, sizeof(T) * count);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] ErrorCode uwrite(ptr<T> pointer, const T *data,
|
||||
std::size_t count) {
|
||||
return uwriteRaw(pointer, &data, sizeof(T) * count);
|
||||
return uwriteRaw(pointer, data, sizeof(T) * count);
|
||||
}
|
||||
|
||||
inline uint64_t readRegister(void *context, RegisterId id) {
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ void rx::vfs::addDevice(std::string name, IoDevice *device) {
|
|||
gDevFs->devices[std::move(name)] = device;
|
||||
}
|
||||
|
||||
static std::pair<orbis::Ref<IoDevice>, std::string>
|
||||
get(const std::filesystem::path &guestPath) {
|
||||
std::pair<orbis::Ref<IoDevice>, std::string>
|
||||
rx::vfs::get(const std::filesystem::path &guestPath) {
|
||||
std::string normalPath = std::filesystem::path(guestPath).lexically_normal();
|
||||
std::string_view path = normalPath;
|
||||
orbis::Ref<IoDevice> device;
|
||||
|
|
@ -95,11 +95,18 @@ get(const std::filesystem::path &guestPath) {
|
|||
|
||||
for (auto &mount : gMountsMap) {
|
||||
if (!path.starts_with(mount.first)) {
|
||||
continue;
|
||||
if (mount.first.size() - 1 != path.size() ||
|
||||
!std::string_view(mount.first).starts_with(path)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
device = mount.second;
|
||||
path.remove_prefix(mount.first.length());
|
||||
if (path.size() > mount.first.length()) {
|
||||
path.remove_prefix(mount.first.length());
|
||||
} else {
|
||||
path = {};
|
||||
}
|
||||
return {mount.second, std::string(path)};
|
||||
}
|
||||
|
||||
|
|
@ -131,6 +138,7 @@ orbis::SysResult rx::vfs::open(std::string_view path, int flags, int mode,
|
|||
if (device == nullptr) {
|
||||
return orbis::ErrorCode::NOENT;
|
||||
}
|
||||
// std::fprintf(stderr, "sys_open %s\n", std::string(path).c_str());
|
||||
return device->open(file, devPath.c_str(), flags, mode, thread);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ void fork();
|
|||
void initialize();
|
||||
void deinitialize();
|
||||
void addDevice(std::string name, IoDevice *device);
|
||||
std::pair<orbis::Ref<IoDevice>, std::string>
|
||||
get(const std::filesystem::path &guestPath);
|
||||
orbis::SysResult mount(const std::filesystem::path &guestPath, IoDevice *dev);
|
||||
orbis::SysResult open(std::string_view path, int flags, int mode,
|
||||
orbis::Ref<orbis::File> *file, orbis::Thread *thread);
|
||||
|
|
|
|||
124
rpcsx-os/vm.cpp
124
rpcsx-os/vm.cpp
|
|
@ -304,8 +304,8 @@ struct Block {
|
|||
Group groups[kGroupsInBlock];
|
||||
|
||||
void setFlags(std::uint64_t firstPage, std::uint64_t pagesCount,
|
||||
std::uint32_t flags) {
|
||||
modifyFlags(firstPage, pagesCount, flags, ~static_cast<std::uint32_t>(0));
|
||||
std::uint32_t flags, bool noOverwrite) {
|
||||
modifyFlags(firstPage, pagesCount, flags, ~static_cast<std::uint32_t>(0), noOverwrite);
|
||||
}
|
||||
|
||||
void addFlags(std::uint64_t firstPage, std::uint64_t pagesCount,
|
||||
|
|
@ -342,7 +342,8 @@ struct Block {
|
|||
}
|
||||
|
||||
void modifyFlags(std::uint64_t firstPage, std::uint64_t pagesCount,
|
||||
std::uint32_t addFlags, std::uint32_t removeFlags) {
|
||||
std::uint32_t addFlags, std::uint32_t removeFlags,
|
||||
bool noOverwrite = false) {
|
||||
std::uint64_t groupIndex = firstPage / kGroupSize;
|
||||
|
||||
std::uint64_t addAllocatedFlags =
|
||||
|
|
@ -387,6 +388,10 @@ struct Block {
|
|||
|
||||
auto &group = groups[groupIndex++];
|
||||
|
||||
if (noOverwrite) {
|
||||
mask &= ~group.allocated;
|
||||
}
|
||||
|
||||
group.allocated = (group.allocated & ~(removeAllocatedFlags & mask)) |
|
||||
(addAllocatedFlags & mask);
|
||||
group.shared = (group.shared & ~(removeSharedFlags & mask)) |
|
||||
|
|
@ -405,30 +410,61 @@ struct Block {
|
|||
(addGpuWritableFlags & mask);
|
||||
}
|
||||
|
||||
while (pagesCount >= kGroupSize) {
|
||||
pagesCount -= kGroupSize;
|
||||
if (noOverwrite) {
|
||||
while (pagesCount >= kGroupSize) {
|
||||
pagesCount -= kGroupSize;
|
||||
|
||||
auto &group = groups[groupIndex++];
|
||||
auto &group = groups[groupIndex++];
|
||||
auto mask = ~group.allocated;
|
||||
|
||||
group.allocated =
|
||||
(group.allocated & ~removeAllocatedFlags) | addAllocatedFlags;
|
||||
group.shared = (group.shared & ~removeSharedFlags) | addSharedFlags;
|
||||
group.readable =
|
||||
(group.readable & ~removeReadableFlags) | addReadableFlags;
|
||||
group.writable =
|
||||
(group.writable & ~removeWritableFlags) | addWritableFlags;
|
||||
group.executable =
|
||||
(group.executable & ~removeExecutableFlags) | addExecutableFlags;
|
||||
group.gpuReadable =
|
||||
(group.gpuReadable & ~removeGpuReadableFlags) | addGpuReadableFlags;
|
||||
group.gpuWritable =
|
||||
(group.gpuWritable & ~removeGpuWritableFlags) | addGpuWritableFlags;
|
||||
group.allocated = (group.allocated & ~(removeAllocatedFlags & mask)) |
|
||||
(addAllocatedFlags & mask);
|
||||
group.shared = (group.shared & ~(removeSharedFlags & mask)) |
|
||||
(addSharedFlags & mask);
|
||||
group.readable = (group.readable & ~(removeReadableFlags & mask)) |
|
||||
(addReadableFlags & mask);
|
||||
group.writable = (group.writable & ~(removeWritableFlags & mask)) |
|
||||
(addWritableFlags & mask);
|
||||
group.executable =
|
||||
(group.executable & ~(removeExecutableFlags & mask)) |
|
||||
(addExecutableFlags & mask);
|
||||
group.gpuReadable =
|
||||
(group.gpuReadable & ~(removeGpuReadableFlags & mask)) |
|
||||
(addGpuReadableFlags & mask);
|
||||
group.gpuWritable =
|
||||
(group.gpuWritable & ~(removeGpuWritableFlags & mask)) |
|
||||
(addGpuWritableFlags & mask);
|
||||
}
|
||||
} else {
|
||||
while (pagesCount >= kGroupSize) {
|
||||
pagesCount -= kGroupSize;
|
||||
|
||||
auto &group = groups[groupIndex++];
|
||||
|
||||
group.allocated =
|
||||
(group.allocated & ~removeAllocatedFlags) | addAllocatedFlags;
|
||||
group.shared = (group.shared & ~removeSharedFlags) | addSharedFlags;
|
||||
group.readable =
|
||||
(group.readable & ~removeReadableFlags) | addReadableFlags;
|
||||
group.writable =
|
||||
(group.writable & ~removeWritableFlags) | addWritableFlags;
|
||||
group.executable =
|
||||
(group.executable & ~removeExecutableFlags) | addExecutableFlags;
|
||||
group.gpuReadable =
|
||||
(group.gpuReadable & ~removeGpuReadableFlags) | addGpuReadableFlags;
|
||||
group.gpuWritable =
|
||||
(group.gpuWritable & ~removeGpuWritableFlags) | addGpuWritableFlags;
|
||||
}
|
||||
}
|
||||
|
||||
if (pagesCount > 0) {
|
||||
auto mask = makePagesMask(0, pagesCount);
|
||||
auto &group = groups[groupIndex++];
|
||||
|
||||
if (noOverwrite) {
|
||||
mask &= ~group.allocated;
|
||||
}
|
||||
|
||||
group.allocated = (group.allocated & ~(removeAllocatedFlags & mask)) |
|
||||
(addAllocatedFlags & mask);
|
||||
group.shared = (group.shared & ~(removeSharedFlags & mask)) |
|
||||
|
|
@ -645,7 +681,7 @@ static void reserve(std::uint64_t startAddress, std::uint64_t endAddress) {
|
|||
auto pagesCount = (endAddress - startAddress + (rx::vm::kPageSize - 1)) >>
|
||||
rx::vm::kPageShift;
|
||||
|
||||
gBlocks[blockIndex - kFirstBlock].setFlags(firstPage, pagesCount, kAllocated);
|
||||
gBlocks[blockIndex - kFirstBlock].setFlags(firstPage, pagesCount, kAllocated, false);
|
||||
}
|
||||
|
||||
void rx::vm::fork(std::uint64_t pid) {
|
||||
|
|
@ -784,6 +820,12 @@ 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;
|
||||
|
||||
if (hitAddress & (alignment - 1)) {
|
||||
if (flags & kMapFlagStack) {
|
||||
hitAddress = utils::alignDown(hitAddress - 1, alignment);
|
||||
|
|
@ -844,18 +886,17 @@ void *rx::vm::map(void *addr, std::uint64_t len, std::int32_t prot,
|
|||
}
|
||||
|
||||
if (address == 0) {
|
||||
// for (auto blockIndex = kFirstUserBlock; blockIndex <= kLastUserBlock;
|
||||
// ++blockIndex) {
|
||||
std::size_t blockIndex = 0; // system managed block
|
||||
for (auto blockIndex = kFirstBlock; blockIndex <= 2; ++blockIndex) {
|
||||
// std::size_t blockIndex = 0; // system managed block
|
||||
|
||||
auto pageAddress =
|
||||
gBlocks[blockIndex - kFirstBlock].findFreePages(pagesCount, alignment);
|
||||
auto pageAddress = gBlocks[blockIndex - kFirstBlock].findFreePages(
|
||||
pagesCount, alignment);
|
||||
|
||||
if (pageAddress != kBadAddress) {
|
||||
address = (pageAddress << kPageShift) | (blockIndex * kBlockSize);
|
||||
// break;
|
||||
if (pageAddress != kBadAddress) {
|
||||
address = (pageAddress << kPageShift) | (blockIndex * kBlockSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
if (address == 0) {
|
||||
|
|
@ -881,9 +922,19 @@ void *rx::vm::map(void *addr, std::uint64_t len, std::int32_t prot,
|
|||
bool isShared = (flags & kMapFlagShared) == kMapFlagShared;
|
||||
flags &= ~(kMapFlagFixed | kMapFlagAnonymous | kMapFlagShared);
|
||||
|
||||
gBlocks[(address >> kBlockShift) - kFirstBlock].setFlags(
|
||||
(address & kBlockMask) >> kPageShift, pagesCount,
|
||||
(prot & (kMapProtCpuAll | kMapProtGpuAll)) | kAllocated | (isShared ? kShared : 0));
|
||||
auto &block = gBlocks[(address >> kBlockShift) - kFirstBlock];
|
||||
if (noOverwrite) {
|
||||
auto firstPage = (address & kBlockMask) >> kPageShift;
|
||||
for (std::size_t i = 0; i < pagesCount; ++i) {
|
||||
if (block.getProtection(firstPage + i)) {
|
||||
return (void *)-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
block.setFlags((address & kBlockMask) >> kPageShift, pagesCount,
|
||||
(prot & (kMapProtCpuAll | kMapProtGpuAll)) | kAllocated |
|
||||
(isShared ? kShared : 0), false);
|
||||
|
||||
/*
|
||||
if (flags & kMapFlagStack) {
|
||||
|
|
@ -933,7 +984,9 @@ 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);
|
||||
rx::bridge.sendMemoryProtect(thr->tproc->pid, address, len, prot);
|
||||
if (!noOverwrite) {
|
||||
rx::bridge.sendMemoryProtect(thr->tproc->pid, address, len, prot);
|
||||
}
|
||||
} else {
|
||||
std::fprintf(stderr, "ignoring mapping %lx-%lx\n", address, address + len);
|
||||
}
|
||||
|
|
@ -1001,7 +1054,7 @@ bool rx::vm::protect(void *addr, std::uint64_t size, std::int32_t prot) {
|
|||
|
||||
gBlocks[(address >> kBlockShift) - kFirstBlock].setFlags(
|
||||
(address & kBlockMask) >> kPageShift, pages,
|
||||
kAllocated | (prot & (kMapProtCpuAll | kMapProtGpuAll)));
|
||||
kAllocated | (prot & (kMapProtCpuAll | kMapProtGpuAll)), false);
|
||||
|
||||
if (auto thr = orbis::g_currentThread) {
|
||||
rx::bridge.sendMemoryProtect(
|
||||
|
|
@ -1014,7 +1067,8 @@ bool rx::vm::protect(void *addr, std::uint64_t size, std::int32_t prot) {
|
|||
|
||||
static std::int32_t getPageProtectionImpl(std::uint64_t address) {
|
||||
return gBlocks[(address >> kBlockShift) - kFirstBlock].getProtection(
|
||||
(address & kBlockMask) >> rx::vm::kPageShift) & ~kShared;
|
||||
(address & kBlockMask) >> rx::vm::kPageShift) &
|
||||
~kShared;
|
||||
}
|
||||
|
||||
bool rx::vm::queryProtection(const void *addr, std::uint64_t *startAddress,
|
||||
|
|
|
|||
Loading…
Reference in a new issue