Skip to content

Commit

Permalink
ps5: collect type of process and firmware
Browse files Browse the repository at this point in the history
add
initial gc and dce ioctls implementation
  • Loading branch information
DHrpcs3 committed Nov 20, 2024
1 parent ffe2837 commit b6556e8
Show file tree
Hide file tree
Showing 11 changed files with 297 additions and 41 deletions.
11 changes: 10 additions & 1 deletion orbis-kernel/include/orbis/KernelContext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ struct UmtxChain {
uint notify_n(const UmtxKey &key, sint count);
};

enum class FwType : std::uint8_t {
Unknown,
Ps4,
Ps5,
};

class alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) KernelContext final {
public:
KernelContext();
Expand Down Expand Up @@ -192,7 +198,10 @@ class alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) KernelContext final {

shared_mutex regMgrMtx;
kmap<std::uint32_t, std::uint32_t> regMgrInt;
std::vector<std::tuple<std::uint8_t*, size_t>> dialogs{};
std::vector<std::tuple<std::uint8_t *, size_t>> dialogs{};

FwType fwType = FwType::Unknown;
bool isDevKit = false;

private:
shared_mutex m_heap_mtx;
Expand Down
8 changes: 8 additions & 0 deletions orbis-kernel/include/orbis/module/Module.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ namespace orbis {
struct Thread;
struct Process;

enum class DynType : std::uint8_t {
None,
Ps4,
Ps5,
};

struct ModuleNeeded {
utils::kstring name;
std::uint16_t version;
Expand Down Expand Up @@ -98,6 +104,8 @@ struct Module final {
uint16_t flags{};
uint64_t entryPoint{};

DynType dynType = DynType::None;

uint32_t phNum{};
uint64_t phdrAddress{};

Expand Down
7 changes: 7 additions & 0 deletions orbis-kernel/include/orbis/thread/Process.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ struct NamedMemoryRange {
}
};

enum class ProcessType : std::uint8_t {
FreeBsd,
Ps4,
Ps5,
};

struct Process final {
KernelContext *context = nullptr;
pid_t pid = -1;
Expand All @@ -54,6 +60,7 @@ struct Process final {
Process *parentProcess = nullptr;
shared_mutex mtx;
int vmId = -1;
ProcessType type = ProcessType::FreeBsd;
void (*onSysEnter)(Thread *thread, int id, uint64_t *args,
int argsCount) = nullptr;
void (*onSysExit)(Thread *thread, int id, uint64_t *args, int argsCount,
Expand Down
4 changes: 4 additions & 0 deletions orbis-kernel/src/sys/sys_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
// hp3d idle
nodeIt->triggered = true;
kq->cv.notify_all(kq->mtx);
} else if (g_context.fwType == FwType::Ps5 &&
change.filter == kEvFiltGraphicsCore && change.ident == 0) {
nodeIt->triggered = true;
kq->cv.notify_all(kq->mtx);
}

return {};
Expand Down
12 changes: 12 additions & 0 deletions orbis-kernel/src/sys/sys_sysctl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,18 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
}
}

if (name[0] == kern && name[1] == proc && name[2] == 55) {
if (g_context.fwType != FwType::Ps5) {
return orbis::ErrorCode::INVAL;
}

if (oldlenp && old && *oldlenp == 4) {
return uwrite<uint32_t>(ptr<uint32_t>(old),
thread->tproc->type == ProcessType::Ps5 ? 1
: 0);
}
}

if (name[0] == kern && name[1] == proc && name[2] == 36) {
Process *process = thread->tproc;
if (process->pid != name[3]) {
Expand Down
34 changes: 34 additions & 0 deletions rpcsx/iodev/dce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,47 @@ static void initDceMemory(DceDevice *device) {
device->dmemOffset = start;
}

static orbis::ErrorCode dce_mmap(orbis::File *file, void **address,
std::uint64_t size, std::int32_t prot,
std::int32_t flags, std::int64_t offset,
orbis::Thread *thread);

static orbis::ErrorCode dce_ioctl(orbis::File *file, std::uint64_t request,
void *argp, orbis::Thread *thread) {
auto device = static_cast<DceDevice *>(file->device.get());

auto gpu = amdgpu::DeviceCtl{orbis::g_context.gpuDevice};
auto &gpuCtx = gpu.getContext();

// std::this_thread::sleep_for(std::chrono::seconds(5));

if (orbis::g_context.fwType == orbis::FwType::Ps5) {
if (request == 0x80308217) {
auto args = reinterpret_cast<FlipControlArgs *>(argp);

if (args->id == 9) {
ORBIS_LOG_NOTICE("dce: FlipControl allocate", args->id, args->padding,
args->arg2, args->ptr, args->size, args->arg5,
args->arg6);

void *address;
ORBIS_RET_ON_ERROR(
dce_mmap(file, &address, vm::kPageSize,
vm::kMapProtCpuReadWrite | vm::kMapProtGpuAll,
vm::kMapFlagShared, 0, thread));

*(void **)args->ptr = address;
*(std::uint64_t *)args->arg5 = vm::kPageSize;

return {};
}

ORBIS_LOG_FATAL("dce: unimplemented 0x80308217 request", args->id,
args->padding, args->arg2, args->ptr, args->size,
args->arg5, args->arg6);
}
}

if (request == 0xc0308203) {
// returns:
// PERM
Expand Down
130 changes: 130 additions & 0 deletions rpcsx/iodev/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,136 @@ static orbis::ErrorCode gc_ioctl(orbis::File *file, std::uint64_t request,
*reinterpret_cast<void **>(argp) = device->submitArea;
break;

case 0xc004812e: {
if (orbis::g_context.fwType != orbis::FwType::Ps5) {
return orbis::ErrorCode::INVAL;
}

struct Args {
std::uint16_t unk;
std::uint16_t flag;
};

auto args = reinterpret_cast<Args *>(argp);
args->unk = 0;
args->flag = 0;
return {};
}

case 0xc0488131: {
if (orbis::g_context.fwType != orbis::FwType::Ps5) {
return orbis::ErrorCode::INVAL;
}

// ps5 submit header
struct Args {
orbis::uint32_t unk0;
orbis::uint32_t contextControl[3];
orbis::uint32_t cmds[3 * 4];
orbis::uint64_t status;
};

static_assert(sizeof(Args) == 72);

auto args = reinterpret_cast<Args *>(argp);

// ORBIS_LOG_ERROR("gc submit header", args->status, args->unk0,
// args->contextControl[0], args->contextControl[1],
// args->contextControl[2]);

// for (std::size_t i = 0; i < 3; ++i) {
// auto offset = i * 4;
// ORBIS_LOG_ERROR("gc submit header cmd", i, args->cmds[offset],
// args->cmds[offset + 1], args->cmds[offset + 2],
// args->cmds[offset + 3]);
// }

// thread->where();

if (auto gpu = amdgpu::DeviceCtl{orbis::g_context.gpuDevice}) {
if (args->contextControl[0]) {
gpu.submitGfxCommand(gcFile->gfxPipe,
orbis::g_currentThread->tproc->vmId,
{args->contextControl, 3});
}

for (std::size_t i = 0; i < 3; ++i) {
auto offset = i * 4;

if (args->cmds[offset] == 0) {
continue;
}

ORBIS_LOG_ERROR("submit header", i, args->status, args->cmds[offset],
args->cmds[offset + 1], args->cmds[offset + 2],
args->cmds[offset + 3]);
gpu.submitGfxCommand(gcFile->gfxPipe,
orbis::g_currentThread->tproc->vmId,
{args->cmds + offset, 4});
}

gpu.waitForIdle();
args->status = 0;
} else {
return orbis::ErrorCode::BUSY;
}

return {};
}

case 0xc0188132: {
if (orbis::g_context.fwType != orbis::FwType::Ps5) {
return orbis::ErrorCode::INVAL;
}

struct Submit {
std::uint64_t unk0;
std::uint64_t unk1;
std::uint64_t address;
std::uint64_t size;
};

struct Args {
orbis::uint32_t unk0; // ringId?
orbis::uint32_t count;
orbis::ptr<Submit> submits;
orbis::uint32_t status;
orbis::uint32_t padding;
};

static_assert(sizeof(Args) == 24);
auto args = reinterpret_cast<Args *>(argp);

// ORBIS_LOG_ERROR("gc submit", args->unk0, args->count, args->submits,
// args->status, args->padding);

// for (std::size_t i = 0; i < args->count / 2; ++i) {
// ORBIS_LOG_ERROR("gc submit cmd", i, args->submits[i].address,
// args->submits[i].size, args->submits[i].unk0,
// args->submits[i].unk1);
// }

if (auto gpu = amdgpu::DeviceCtl{orbis::g_context.gpuDevice}) {
for (unsigned i = 0; i < args->count / 2; ++i) {
auto addressLo = static_cast<std::uint32_t>(args->submits[i].address);
auto addressHi = static_cast<std::uint32_t>(args->submits[i].address >> 32);
auto size = static_cast<std::uint32_t>(args->submits[i].size);

gpu.submitGfxCommand(gcFile->gfxPipe,
orbis::g_currentThread->tproc->vmId, {
{0xc0023f00, addressLo, addressHi, size}
});
}

gpu.waitForIdle();
} else {
return orbis::ErrorCode::BUSY;
}

args->status = 0;
return {};
}

case 0xc0108102: { // submit?
struct Args {
orbis::uint32_t arg0;
Expand Down
5 changes: 5 additions & 0 deletions rpcsx/iodev/icc_power.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,13 @@ static orbis::ErrorCode icc_power_ioctl(orbis::File *file,
return {};
}

orbis::ErrorCode icc_stat(orbis::File *file, orbis::Stat *sb, orbis::Thread *thread) {
return{};
}

static const orbis::FileOps fileOps = {
.ioctl = icc_power_ioctl,
.stat = icc_stat,
};

orbis::ErrorCode IccPowerDevice::open(orbis::Ref<orbis::File> *file,
Expand Down
25 changes: 25 additions & 0 deletions rpcsx/linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,9 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
std::unordered_map<std::uint64_t, std::size_t> idToModuleIndex;
std::unordered_map<std::uint64_t, std::size_t> idToLibraryIndex;

bool hasPs4Dyn = false;
bool hasPs5Dyn = false;

for (auto dyn : dyns) {
if (dyn.d_tag == kElfDynamicTypeSceModuleInfo ||
dyn.d_tag == kElfDynamicTypeSceModuleInfo1) {
Expand All @@ -686,6 +689,11 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,

if (dyn.d_tag == kElfDynamicTypeSceNeededModule ||
dyn.d_tag == kElfDynamicTypeSceNeededModule1) {
if (dyn.d_tag == kElfDynamicTypeSceNeededModule) {
hasPs4Dyn = true;
} else {
hasPs5Dyn = true;
}
auto [it, inserted] = idToModuleIndex.try_emplace(
dyn.d_un.d_val >> 48, result->neededModules.size());

Expand Down Expand Up @@ -713,6 +721,13 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
lib.name = strtab + static_cast<std::uint32_t>(dyn.d_un.d_val);
lib.isExport = dyn.d_tag == kElfDynamicTypeSceExportLib ||
dyn.d_tag == kElfDynamicTypeSceExportLib1;

if (dyn.d_tag == kElfDynamicTypeSceExportLib ||
dyn.d_tag == kElfDynamicTypeSceImportLib) {
hasPs4Dyn = true;
} else {
hasPs5Dyn = true;
}
} else if (dyn.d_tag == kElfDynamicTypeSceExportLibAttr ||
dyn.d_tag == kElfDynamicTypeSceImportLibAttr) {
auto [it, inserted] = idToLibraryIndex.try_emplace(
Expand Down Expand Up @@ -787,6 +802,16 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
}
}

if (hasPs4Dyn && hasPs5Dyn) {
std::fprintf(stderr, "unexpected import type\n");
std::abort();
}
if (hasPs4Dyn) {
result->dynType = orbis::DynType::Ps4;
} else if (hasPs5Dyn) {
result->dynType = orbis::DynType::Ps5;
}

if (symtab != nullptr && symtabSize > 0) {
auto sceSymtab = std::span(symtab, symtabSize);

Expand Down
Loading

0 comments on commit b6556e8

Please sign in to comment.