From 600512ee908d2d7e4f3683505d4702cae1f9208b Mon Sep 17 00:00:00 2001 From: DH Date: Tue, 6 Jan 2026 07:52:33 +0300 Subject: [PATCH] orbis: add pmem device query api --- kernel/orbis/include/orbis/IoDevice.hpp | 5 ++ kernel/orbis/include/orbis/dmem.hpp | 4 +- kernel/orbis/include/orbis/pmem.hpp | 3 + kernel/orbis/include/orbis/vmem.hpp | 2 + kernel/orbis/src/dmem.cpp | 17 ++--- kernel/orbis/src/pmem.cpp | 17 +++++ kernel/orbis/src/vmem.cpp | 77 ++++++++++++++++++----- rpcsx/io-devices.hpp | 4 +- rpcsx/iodev/blockpool.cpp | 29 ++------- rpcsx/iodev/dce.cpp | 52 ++++++---------- rpcsx/iodev/dce.hpp | 12 +++- rpcsx/iodev/dmem.cpp | 20 ++---- rpcsx/iodev/gc.cpp | 83 +++++++++++-------------- rpcsx/linker.cpp | 10 +++ rpcsx/main.cpp | 2 +- 15 files changed, 191 insertions(+), 146 deletions(-) diff --git a/kernel/orbis/include/orbis/IoDevice.hpp b/kernel/orbis/include/orbis/IoDevice.hpp index e02e22644..9db01b036 100644 --- a/kernel/orbis/include/orbis/IoDevice.hpp +++ b/kernel/orbis/include/orbis/IoDevice.hpp @@ -77,6 +77,11 @@ struct IoDevice : rx::RcBase { rx::EnumBitSet protection, File *file, Process *process); + virtual std::pair + getPmemRange(std::uint64_t offset, File *file) { + return {}; + } + [[nodiscard]] virtual std::string toString() const; }; diff --git a/kernel/orbis/include/orbis/dmem.hpp b/kernel/orbis/include/orbis/dmem.hpp index 65caf883c..951be392d 100644 --- a/kernel/orbis/include/orbis/dmem.hpp +++ b/kernel/orbis/include/orbis/dmem.hpp @@ -69,6 +69,6 @@ ErrorCode protect(orbis::Process *process, unsigned dmemIndex, rx::AddressRange range, rx::EnumBitSet prot); -std::pair getPmemOffset(unsigned dmemIndex, - std::uint64_t dmemOffset); +std::pair +getPmemRange(unsigned dmemIndex, std::uint64_t dmemOffset); } // namespace orbis::dmem diff --git a/kernel/orbis/include/orbis/pmem.hpp b/kernel/orbis/include/orbis/pmem.hpp index bc641d966..5950ab178 100644 --- a/kernel/orbis/include/orbis/pmem.hpp +++ b/kernel/orbis/include/orbis/pmem.hpp @@ -22,6 +22,9 @@ ErrorCode deallocate(rx::AddressRange range); std::optional query(std::uint64_t address); ErrorCode map(std::uint64_t virtualAddress, rx::AddressRange range, rx::EnumBitSet protection); +void *mapInternal(rx::AddressRange range, + rx::EnumBitSet protection); +void unmapInternal(void *data, std::size_t size); std::size_t getSize(); IoDevice *getDevice(); File *getFile(); diff --git a/kernel/orbis/include/orbis/vmem.hpp b/kernel/orbis/include/orbis/vmem.hpp index 000ff4bfb..d4ce67c72 100644 --- a/kernel/orbis/include/orbis/vmem.hpp +++ b/kernel/orbis/include/orbis/vmem.hpp @@ -230,4 +230,6 @@ std::optional query(Process *process, std::uint64_t address, std::optional queryProtection(Process *process, std::uint64_t address, bool lowerBound = false); +std::pair getPmemRange(Process *process, + std::uint64_t address); } // namespace orbis::vmem diff --git a/kernel/orbis/src/dmem.cpp b/kernel/orbis/src/dmem.cpp index 9fc22b865..9c7e92264 100644 --- a/kernel/orbis/src/dmem.cpp +++ b/kernel/orbis/src/dmem.cpp @@ -870,28 +870,31 @@ orbis::ErrorCode orbis::dmem::protect(orbis::Process *process, return {}; } -std::pair -orbis::dmem::getPmemOffset(unsigned dmemIndex, std::uint64_t dmemOffset) { +std::pair +orbis::dmem::getPmemRange(unsigned dmemIndex, std::uint64_t dmemOffset) { if (dmemIndex > std::size(g_dmemPools)) { - return {{}, ErrorCode::INVAL}; + return {}; } auto dmem = g_dmemPools[dmemIndex]; std::lock_guard lock(*dmem); if (dmemOffset >= dmem->dmemTotalSize) { - return {{}, orbis::ErrorCode::INVAL}; + return {}; } if (dmemOffset >= dmem->dmemTotalSize - dmem->dmemReservedSize) { - return {{}, orbis::ErrorCode::ACCES}; + return {}; } auto allocationInfoIt = dmem->query(dmemOffset); if (allocationInfoIt == dmem->end() || !allocationInfoIt->isAllocated()) { - return {{}, orbis::ErrorCode::ACCES}; + return {}; } - return {dmem->pmemOffset + dmemOffset, {}}; + auto range = rx::AddressRange::fromBeginEnd( + dmem->pmemOffset + dmemOffset, + dmem->pmemOffset + allocationInfoIt.endAddress()); + return {range, allocationInfoIt->getMemoryType()}; } diff --git a/kernel/orbis/src/pmem.cpp b/kernel/orbis/src/pmem.cpp index 256b6889e..c782a8041 100644 --- a/kernel/orbis/src/pmem.cpp +++ b/kernel/orbis/src/pmem.cpp @@ -9,6 +9,7 @@ #include "kernel/MemoryResource.hpp" #include "rx/AddressRange.hpp" #include "rx/Rc.hpp" +#include "rx/mem.hpp" #include "rx/print.hpp" #include "vmem.hpp" #include @@ -151,6 +152,22 @@ orbis::pmem::map(std::uint64_t virtualAddress, rx::AddressRange range, return toErrorCode(errc); } +void *orbis::pmem::mapInternal(rx::AddressRange range, + rx::EnumBitSet protection) { + auto [pointer, errc] = g_pmemInstance->mappable.map( + range.size(), range.beginAddress(), protection); + if (errc != std::errc{}) { + return nullptr; + } + + return pointer; +} + +void orbis::pmem::unmapInternal(void *data, std::size_t size) { + auto address = std::bit_cast(data); + rx::mem::release(rx::AddressRange::fromBeginSize(address, size), 0); +} + std::size_t orbis::pmem::getSize() { return g_pmemInstance->size; } orbis::IoDevice *orbis::pmem::getDevice() { return g_phyMemory.get(); } orbis::File *orbis::pmem::getFile() { return &g_phyMemory->file; } diff --git a/kernel/orbis/src/vmem.cpp b/kernel/orbis/src/vmem.cpp index 0af0d1984..4ea7fa959 100644 --- a/kernel/orbis/src/vmem.cpp +++ b/kernel/orbis/src/vmem.cpp @@ -43,7 +43,7 @@ struct VirtualMemoryAllocation { rx::EnumBitSet flagsEx{}; rx::EnumBitSet prot{}; orbis::MemoryType type = orbis::MemoryType::Invalid; - rx::Ref device; + rx::Ref file; std::uint64_t deviceOffset = 0; std::uint64_t callerAddress = 0; rx::StaticString<31> name; @@ -57,7 +57,7 @@ struct VirtualMemoryAllocation { isRelated(const VirtualMemoryAllocation &other, rx::AddressRange selfRange, [[maybe_unused]] rx::AddressRange rightRange) const { if (flags != other.flags || flagsEx != other.flagsEx || - prot != other.prot || type != other.type || device != other.device || + prot != other.prot || type != other.type || file != other.file || callerAddress != other.callerAddress) { return false; } @@ -70,7 +70,7 @@ struct VirtualMemoryAllocation { return false; } - if (device == nullptr || flags == orbis::vmem::BlockFlags::PooledMemory) { + if (file == nullptr || flags == orbis::vmem::BlockFlags::PooledMemory) { return true; } @@ -86,7 +86,7 @@ struct VirtualMemoryAllocation { [[nodiscard]] std::pair truncate(rx::AddressRange selfRange, rx::AddressRange leftRange, rx::AddressRange rightRange) const { - if (!rightRange.isValid() || device == nullptr) { + if (!rightRange.isValid() || file == nullptr) { return {}; } @@ -270,7 +270,7 @@ static void release(orbis::Process *process, decltype(g_vmInstance)::type *vmem, auto gpuProt = orbis::vmem::toGpuProtection(it->prot); if (it->flags & orbis::vmem::BlockFlags::FlexibleMemory) { - if (it->device == nullptr && gpuProt) { + if (it->file == nullptr && gpuProt) { amdgpu::unmapMemory(process->pid, blockRange); orbis::fmem::deallocate(blockRange); } @@ -333,7 +333,7 @@ static decltype(g_vmInstance)::type::iterator modifyRange( } else { auto allocInfo = it.get(); - if (allocInfo.device != nullptr && + if (allocInfo.file != nullptr && !(allocInfo.flags & orbis::vmem::BlockFlags::PooledMemory)) { allocInfo.deviceOffset += mapRange.beginAddress() - it.beginAddress(); } @@ -514,7 +514,7 @@ std::pair orbis::vmem::mapFile( } allocationInfo.flagsEx = blockFlagsEx | BlockFlagsEx::Allocated; - allocationInfo.device = file->device; + allocationInfo.file = file; allocationInfo.prot = prot; allocationInfo.deviceOffset = fileOffset; allocationInfo.setName(process, name); @@ -652,7 +652,14 @@ std::pair orbis::vmem::mapFile( rx::dieIf(errc != std::errc{}, "failed to commit virtual memory {}", errc); } - vmemDump(process, rx::format("mapped {:x}-{:x} {}", range.beginAddress(), + if (auto [pmemRange, memoryType] = + file->device->getPmemRange(fileOffset, file); + pmemRange.isValid()) { + amdgpu::mapMemory(process->pid, range, type, prot, + pmemRange.beginAddress()); + } + + vmemDump(process, rx::format("file mapped {:x}-{:x} {}", range.beginAddress(), range.endAddress(), prot)); return {range, {}}; @@ -692,7 +699,7 @@ std::pair orbis::vmem::mapDirect( allocationInfo.flags = BlockFlags::DirectMemory; allocationInfo.flagsEx = BlockFlagsEx::Allocated; allocationInfo.prot = prot; - allocationInfo.device = g_context->dmem->device; + allocationInfo.file = g_context->dmem; allocationInfo.deviceOffset = directRange.beginAddress(); allocationInfo.type = type; allocationInfo.setName(process, name); @@ -757,11 +764,14 @@ std::pair orbis::vmem::mapDirect( dmemResource.commit(); - auto [pmemOffset, errc] = dmem::getPmemOffset(0, directRange.beginAddress()); - rx::dieIf(errc != ErrorCode{}, - "mapDirect: failed to query physical offset {}", errc); + auto [pmemRange, pmemType] = + dmem::getPmemRange(0, directRange.beginAddress()); + rx::dieIf(!pmemRange.isValid(), "mapDirect: failed to query physical offset"); + rx::dieIf(pmemType != type, + "mapDirect: unexpected queried pmem type. mapped {}, queried {}", + type, pmemType); - amdgpu::mapMemory(process->pid, range, type, prot, pmemOffset); + amdgpu::mapMemory(process->pid, range, type, prot, pmemRange.beginAddress()); vmemDump(process, rx::format("mapped dmem {:x}-{:x}", range.beginAddress(), range.endAddress())); @@ -1192,7 +1202,7 @@ orbis::ErrorCode orbis::vmem::protect(Process *process, rx::AddressRange range, } if (!alloc.isVoid()) { - if (alloc.isFlex() && alloc.device == nullptr) { + if (alloc.isFlex() && alloc.file == nullptr) { if (blockProt && !alloc.prot) { auto [pmemRange, errc] = fmem::allocate(range.size()); rx::dieIf(errc != ErrorCode{}, @@ -1231,7 +1241,7 @@ orbis::ErrorCode orbis::vmem::protect(Process *process, rx::AddressRange range, if (sdkVersion > 0x1500000) { if (alloc.isDirect() || alloc.isPooled() || - (alloc.isFlex() && alloc.device != nullptr)) { + (alloc.isFlex() && alloc.file != nullptr)) { blockProt &= ~Protection::CpuExec; } } @@ -1252,7 +1262,7 @@ orbis::ErrorCode orbis::vmem::protect(Process *process, rx::AddressRange range, } if (alloc.isDirect() || alloc.isPooled() || - (alloc.isFlex() && alloc.device != nullptr)) { + (alloc.isFlex() && alloc.file != nullptr)) { blockProt &= ~Protection::CpuExec; } @@ -1458,7 +1468,7 @@ orbis::vmem::query(Process *process, std::uint64_t address, bool lowerBound) { result.start = it.beginAddress(); result.end = it.endAddress(); - if (!(it->flags & BlockFlags::FlexibleMemory) || it->device != nullptr) { + if (!(it->flags & BlockFlags::FlexibleMemory) || it->file != nullptr) { result.offset = it->deviceOffset; } @@ -1512,3 +1522,36 @@ orbis::vmem::queryProtection(Process *process, std::uint64_t address, result.prot = it->prot; return result; } + +std::pair +orbis::vmem::getPmemRange(Process *process, std::uint64_t address) { + rx::Ref file; + std::uint64_t deviceOffset; + { + auto vmem = process->get(g_vmInstance); + std::lock_guard lock(*vmem); + + auto it = vmem->query(address); + + if (it == vmem->end()) { + return {}; + } + + auto disp = address - it.beginAddress(); + + if (it->isFlexCommited()) { + return {rx::AddressRange::fromBeginSize(it->deviceOffset + disp, + it.size() - disp), + orbis::MemoryType::WbOnion}; + } + + if (it->file == nullptr) { + return {}; + } + + file = it->file; + deviceOffset = it->deviceOffset + disp; + } + + return file->device->getPmemRange(deviceOffset, file.get()); +} diff --git a/rpcsx/io-devices.hpp b/rpcsx/io-devices.hpp index 05e55d31f..de58d8e00 100644 --- a/rpcsx/io-devices.hpp +++ b/rpcsx/io-devices.hpp @@ -6,9 +6,9 @@ namespace orbis { struct IoDevice; struct Process; -} +} // namespace orbis -orbis::IoDevice *createDceCharacterDevice(orbis::Process *process); +orbis::IoDevice *createDceCharacterDevice(); orbis::IoDevice *createDipswCharacterDevice(); orbis::IoDevice *createDmemCharacterDevice(int index); orbis::IoDevice *createGcCharacterDevice(); diff --git a/rpcsx/iodev/blockpool.cpp b/rpcsx/iodev/blockpool.cpp index c5424c5ed..f17b4a0a8 100644 --- a/rpcsx/iodev/blockpool.cpp +++ b/rpcsx/iodev/blockpool.cpp @@ -14,27 +14,6 @@ enum { BLOCKPOOL_IOCTL_GET_BLOCK_STATS = 0x4010a802, }; -struct BlockPoolAllocation { - bool allocated = false; - - [[nodiscard]] bool isAllocated() const { return allocated; } - [[nodiscard]] bool isRelated(const BlockPoolAllocation &, rx::AddressRange, - rx::AddressRange) const { - return true; - } - - [[nodiscard]] BlockPoolAllocation merge(const BlockPoolAllocation &other, - rx::AddressRange, - rx::AddressRange) const { - return other; - } - - bool operator==(const BlockPoolAllocation &) const = default; -}; - -using DirectMemoryResource = - kernel::AllocableResource; - struct BlockPoolFile : public orbis::File {}; struct BlockPoolDevice : orbis::IoDeviceWithIoctl { @@ -86,15 +65,15 @@ static orbis::ErrorCode blockpool_ioctl_expand(orbis::Thread *thread, return dmemErrc; } - auto [pmemOffset, pmemErrc] = orbis::dmem::getPmemOffset(0, dmemOffset); + auto [range, memoryType] = orbis::dmem::getPmemRange(0, dmemOffset); - if (pmemErrc != orbis::ErrorCode{}) { - return pmemErrc; + if (range.isValid()) { + return orbis::ErrorCode::ACCES; } args.searchStart = dmemOffset; return orbis::blockpool::expand( - rx::AddressRange::fromBeginSize(pmemOffset, args.len)); + rx::AddressRange::fromBeginSize(range.beginAddress(), args.len)); } static std::pair diff --git a/rpcsx/iodev/dce.cpp b/rpcsx/iodev/dce.cpp index a2a696988..6c00ca1d6 100644 --- a/rpcsx/iodev/dce.cpp +++ b/rpcsx/iodev/dce.cpp @@ -278,15 +278,13 @@ static orbis::ErrorCode dce_ioctl(orbis::File *file, std::uint64_t request, args->arg2, args->ptr, args->size, args->arg5, args->arg6); - auto [range, errc] = orbis::vmem::mapDirect( - thread->tproc, 0, - rx::AddressRange::fromBeginSize(device->dmemRange.beginAddress(), - orbis::vmem::kPageSize), - orbis::vmem::Protection::CpuRead | - orbis::vmem::Protection::CpuWrite | - orbis::vmem::Protection::GpuRead | - orbis::vmem::Protection::GpuWrite, - {}, "DCE"); + auto [range, errc] = + orbis::vmem::mapFile(thread->tproc, 0, orbis::vmem::kPageSize, {}, + orbis::vmem::Protection::CpuRead | + orbis::vmem::Protection::CpuWrite | + orbis::vmem::Protection::GpuRead | + orbis::vmem::Protection::GpuWrite, + {}, {}, file, 0, "DCE"); if (errc != orbis::ErrorCode{}) { return errc; @@ -587,22 +585,18 @@ orbis::ErrorCode DceDevice::map(rx::AddressRange range, std::int64_t offset, rx::EnumBitSet protection, orbis::File *, orbis::Process *process) { - if (offset + range.size() > dmemRange.size()) { + if (offset + range.size() > pmemRange.size()) { return orbis::ErrorCode::INVAL; } rx::println(stderr, "map dce {:x}-{:x} {:04x} {}", range.beginAddress(), range.endAddress(), offset, protection); - auto result = - orbis::dmem::map(process, 0, range, dmemRange.beginAddress() + offset, protection); + auto pmemMapRange = rx::AddressRange::fromBeginSize( + pmemRange.beginAddress() + offset, range.size()); - if (result == orbis::ErrorCode{}) { - amdgpu::mapMemory(process->pid, range, orbis::MemoryType::WcGarlic, - protection, dmemRange.beginAddress() + offset); - } - - return result; + return orbis::pmem::map(range.beginAddress(), pmemMapRange, + orbis::vmem::toCpuProtection(protection)); } static const orbis::FileOps ops = { @@ -624,7 +618,7 @@ static void createGpu() { } } -DceDevice::~DceDevice() { orbis::dmem::release(0, dmemRange); } +DceDevice::~DceDevice() { orbis::pmem::deallocate(pmemRange); } orbis::ErrorCode DceDevice::open(rx::Ref *file, const char *path, std::uint32_t flags, std::uint32_t mode, @@ -653,28 +647,22 @@ void DceDevice::initializeProcess(orbis::Process *process) { } } -orbis::IoDevice *createDceCharacterDevice(orbis::Process *process) { +orbis::IoDevice *createDceCharacterDevice() { auto result = orbis::knew(); - auto dmemSize = orbis::dmem::getSize(0); - auto [dmemOffset, errc] = orbis::dmem::allocate( - 0, - rx::AddressRange::fromBeginEnd(dmemSize - orbis::dmem::kPageSize * 2, - dmemSize), - orbis::dmem::kPageSize, orbis::MemoryType::WcGarlic); + auto [pmemRange, errc] = orbis::pmem::allocate(0, orbis::dmem::kPageSize, {}, + orbis::dmem::kPageSize); rx::dieIf(errc != orbis::ErrorCode{}, "failed to allocate DCE memory, error {}", errc); - result->dmemRange = - rx::AddressRange::fromBeginSize(dmemOffset, orbis::dmem::kPageSize); + result->pmemRange = pmemRange; - auto [vmem, mapErrc] = orbis::vmem::mapDirect( - process, 0, result->dmemRange, orbis::vmem::Protection::CpuWrite, {}); - auto dceControl = reinterpret_cast(vmem.beginAddress()); + auto vmem = orbis::pmem::mapInternal(pmemRange, rx::mem::Protection::W); + auto dceControl = reinterpret_cast(vmem); *reinterpret_cast(dceControl + 0x130) = 0; *reinterpret_cast(dceControl + 0x138) = 1; *reinterpret_cast(dceControl + 0x140) = orbis::kEvFiltDisplay; - orbis::vmem::unmap(process, vmem); + orbis::pmem::unmapInternal(vmem, pmemRange.size()); return result; } diff --git a/rpcsx/iodev/dce.hpp b/rpcsx/iodev/dce.hpp index 1af40a03a..f1e57565f 100644 --- a/rpcsx/iodev/dce.hpp +++ b/rpcsx/iodev/dce.hpp @@ -12,7 +12,7 @@ static constexpr auto kVmIdCount = 6; struct DceDevice : orbis::IoDevice { rx::shared_mutex mtx; - rx::AddressRange dmemRange; + rx::AddressRange pmemRange; std::uint32_t eopCount = 0; std::uint32_t freeVmIds = (1 << (kVmIdCount + 1)) - 1; @@ -25,7 +25,17 @@ struct DceDevice : orbis::IoDevice { orbis::ErrorCode map(rx::AddressRange range, std::int64_t offset, rx::EnumBitSet protection, orbis::File *file, orbis::Process *process) override; + std::pair + getPmemRange(std::uint64_t offset, orbis::File *) override { + auto range = rx::AddressRange::fromBeginEnd( + pmemRange.beginAddress() + offset, pmemRange.endAddress()); + + return {range, orbis::MemoryType::WcGarlic}; + } + int allocateVmId(); void deallocateVmId(int vmId); void initializeProcess(orbis::Process *process); + + std::string toString() const override { return "dce"; } }; diff --git a/rpcsx/iodev/dmem.cpp b/rpcsx/iodev/dmem.cpp index d4978f211..9742f5a08 100644 --- a/rpcsx/iodev/dmem.cpp +++ b/rpcsx/iodev/dmem.cpp @@ -44,6 +44,11 @@ struct DmemDevice rx::EnumBitSet protection, orbis::File *file, orbis::Process *process) override; + std::pair + getPmemRange(std::uint64_t offset, orbis::File *) override { + return orbis::dmem::getPmemRange(index, offset); + } + [[nodiscard]] std::string toString() const override { return "dmem" + std::to_string(index); } @@ -357,20 +362,7 @@ orbis::ErrorCode DmemDevice::map(rx::AddressRange range, std::int64_t offset, rx::EnumBitSet protection, orbis::File *, orbis::Process *process) { - auto result = orbis::dmem::map(process, index, range, offset, protection); - - if (result == orbis::ErrorCode{}) { - if (auto dmemType = orbis::dmem::query(0, offset)) { - auto [pmemOffset, errc] = orbis::dmem::getPmemOffset(0, offset); - rx::dieIf(errc != orbis::ErrorCode{}, "failed to query dmem type {}", - errc); - - amdgpu::mapMemory(process->pid, range, dmemType->memoryType, protection, - pmemOffset); - } - } - - return result; + return orbis::dmem::map(process, index, range, offset, protection); } static const orbis::FileOps ops = {}; diff --git a/rpcsx/iodev/gc.cpp b/rpcsx/iodev/gc.cpp index 9bad3835a..a789e0b6f 100644 --- a/rpcsx/iodev/gc.cpp +++ b/rpcsx/iodev/gc.cpp @@ -30,10 +30,9 @@ struct ComputeQueue { struct GcDevice : public orbis::IoDevice { rx::shared_mutex mtx; - rx::AddressRange dmemRange; + rx::AddressRange pmemRange; orbis::kmap clients; orbis::kmap computeQueues; - orbis::uintptr_t submitArea = 0; orbis::ErrorCode open(rx::Ref *file, const char *path, std::uint32_t flags, std::uint32_t mode, orbis::Thread *thread) override; @@ -43,30 +42,31 @@ struct GcDevice : public orbis::IoDevice { GcDevice() { blockFlags = orbis::vmem::BlockFlags::DirectMemory; } - ~GcDevice() { orbis::pmem::deallocate(dmemRange); } + ~GcDevice() { orbis::pmem::deallocate(pmemRange); } orbis::ErrorCode map(rx::AddressRange range, std::int64_t offset, rx::EnumBitSet protection, orbis::File *file, orbis::Process *process) override { - if (offset + range.size() > dmemRange.size()) { + if (offset + range.size() > pmemRange.size()) { return orbis::ErrorCode::INVAL; } rx::println(stderr, "map gc {:x}-{:x} {:04x} {}", range.beginAddress(), range.endAddress(), offset, protection); - auto result = - orbis::pmem::map(range.beginAddress(), - rx::AddressRange::fromBeginSize( - dmemRange.beginAddress() + offset, range.size()), - orbis::vmem::toCpuProtection(protection)); + return orbis::pmem::map( + range.beginAddress(), + rx::AddressRange::fromBeginSize(pmemRange.beginAddress() + offset, + range.size()), + orbis::vmem::toCpuProtection(protection)); + } - if (result == orbis::ErrorCode{}) { - amdgpu::mapMemory(process->pid, range, orbis::MemoryType::WbOnion, - protection, dmemRange.beginAddress() + offset); - } + std::pair + getPmemRange(std::uint64_t offset, orbis::File *) override { + auto range = rx::AddressRange::fromBeginEnd( + pmemRange.beginAddress() + offset, pmemRange.endAddress()); - return result; + return {range, orbis::MemoryType::WcGarlic}; } }; @@ -87,37 +87,34 @@ static orbis::ErrorCode gc_ioctl(orbis::File *file, std::uint64_t request, std::lock_guard lock(device->mtx); switch (request) { - case 0xc008811b: // get submit done flag ptr? - if (device->submitArea == 0) { - auto [dmemOffset, dmemErrc] = orbis::dmem::allocate( - 0, rx::AddressRange::fromBeginEnd(0, 0), orbis::dmem::kPageSize, - orbis::MemoryType::WcGarlic); + case 0xc008811b: { // get submit done flag ptr? + auto [dmemOffset, dmemErrc] = orbis::dmem::allocate( + 0, rx::AddressRange::fromBeginEnd(0, 0), orbis::dmem::kPageSize, + orbis::MemoryType::WcGarlic); - if (dmemErrc != orbis::ErrorCode{}) { - return dmemErrc; - } + if (dmemErrc != orbis::ErrorCode{}) { + return dmemErrc; + } - auto directRange = - rx::AddressRange::fromBeginSize(dmemOffset, orbis::dmem::kPageSize); + auto directRange = + rx::AddressRange::fromBeginSize(dmemOffset, orbis::dmem::kPageSize); - auto [vmemRange, vmemErrc] = orbis::vmem::mapDirect( - thread->tproc, 0xfe0100000, directRange, - orbis::vmem::Protection::CpuRead | orbis::vmem::Protection::CpuWrite | - orbis::vmem::Protection::GpuRead | - orbis::vmem::Protection::GpuWrite, - {}); + auto [vmemRange, vmemErrc] = orbis::vmem::mapFile( + thread->tproc, 0xfe0100000, orbis::dmem::kPageSize, {}, + orbis::vmem::Protection::CpuRead | orbis::vmem::Protection::CpuWrite | + orbis::vmem::Protection::GpuRead | + orbis::vmem::Protection::GpuWrite, + {}, {}, file, orbis::dmem::kPageSize, "GC"); - if (vmemErrc != orbis::ErrorCode{}) { - orbis::dmem::release(0, directRange); - return vmemErrc; - } - - device->submitArea = vmemRange.beginAddress(); + if (vmemErrc != orbis::ErrorCode{}) { + orbis::dmem::release(0, directRange); + return vmemErrc; } ORBIS_LOG_ERROR("gc ioctl 0xc008811b", *(std::uint64_t *)argp); - *reinterpret_cast(argp) = device->submitArea; + *reinterpret_cast(argp) = vmemRange.beginAddress(); break; + } case 0xc004812e: { if (orbis::g_context->fwType != orbis::FwType::Ps5) { @@ -534,16 +531,12 @@ void GcDevice::removeClient(orbis::Process *process) { orbis::IoDevice *createGcCharacterDevice() { auto result = orbis::knew(); - auto dmemSize = orbis::dmem::getSize(0); - auto [dmemOffset, errc] = orbis::dmem::allocate( - 0, - rx::AddressRange::fromBeginEnd(dmemSize - orbis::dmem::kPageSize * 2, - dmemSize), - orbis::dmem::kPageSize, orbis::MemoryType::WcGarlic); + auto [pmemRange, errc] = orbis::pmem::allocate(0, orbis::dmem::kPageSize * 2, + {}, orbis::dmem::kPageSize); rx::dieIf(errc != orbis::ErrorCode{}, "failed to allocate GC memory, error {}", errc); - result->dmemRange = - rx::AddressRange::fromBeginSize(dmemOffset, orbis::dmem::kPageSize); + + result->pmemRange = pmemRange; return result; } diff --git a/rpcsx/linker.cpp b/rpcsx/linker.cpp index 72ae3264e..91234f646 100644 --- a/rpcsx/linker.cpp +++ b/rpcsx/linker.cpp @@ -504,6 +504,16 @@ struct ElfDevice : orbis::IoDevice { orbis::vmem::toCpuProtection(protection)); } + std::pair + getPmemRange(std::uint64_t offset, orbis::File *file) override { + auto elf = static_cast(file); + auto range = rx::AddressRange::fromBeginEnd( + elf->physicalMemory.beginAddress() + offset, + elf->physicalMemory.endAddress()); + + return {range, orbis::MemoryType::WbOnion}; + } + void serialize(rx::Serializer &s) const { // FIXME: implement } diff --git a/rpcsx/main.cpp b/rpcsx/main.cpp index 63d60e368..7411b7128 100644 --- a/rpcsx/main.cpp +++ b/rpcsx/main.cpp @@ -362,7 +362,7 @@ static void guestInitDev(orbis::Thread *thread, int stdinFd, int stdoutFd, auto dmem0 = createDmemCharacterDevice(0); dmem0->open(&orbis::g_context->dmem, "", 0, 0, thread); - auto dce = createDceCharacterDevice(thread->tproc); + auto dce = createDceCharacterDevice(); orbis::g_context->dceDevice = dce; auto consoleDev = createConsoleCharacterDevice(stdinFd, stdoutFd);