orbis: add pmem device query api

This commit is contained in:
DH 2026-01-06 07:52:33 +03:00
parent 733b8bf73f
commit 600512ee90
15 changed files with 191 additions and 146 deletions

View file

@ -77,6 +77,11 @@ struct IoDevice : rx::RcBase {
rx::EnumBitSet<vmem::Protection> protection, File *file,
Process *process);
virtual std::pair<rx::AddressRange, orbis::MemoryType>
getPmemRange(std::uint64_t offset, File *file) {
return {};
}
[[nodiscard]] virtual std::string toString() const;
};

View file

@ -69,6 +69,6 @@ ErrorCode protect(orbis::Process *process, unsigned dmemIndex,
rx::AddressRange range,
rx::EnumBitSet<vmem::Protection> prot);
std::pair<std::uint64_t, ErrorCode> getPmemOffset(unsigned dmemIndex,
std::uint64_t dmemOffset);
std::pair<rx::AddressRange, orbis::MemoryType>
getPmemRange(unsigned dmemIndex, std::uint64_t dmemOffset);
} // namespace orbis::dmem

View file

@ -22,6 +22,9 @@ ErrorCode deallocate(rx::AddressRange range);
std::optional<rx::AddressRange> query(std::uint64_t address);
ErrorCode map(std::uint64_t virtualAddress, rx::AddressRange range,
rx::EnumBitSet<rx::mem::Protection> protection);
void *mapInternal(rx::AddressRange range,
rx::EnumBitSet<rx::mem::Protection> protection);
void unmapInternal(void *data, std::size_t size);
std::size_t getSize();
IoDevice *getDevice();
File *getFile();

View file

@ -230,4 +230,6 @@ std::optional<QueryResult> query(Process *process, std::uint64_t address,
std::optional<MemoryProtection> queryProtection(Process *process,
std::uint64_t address,
bool lowerBound = false);
std::pair<rx::AddressRange, MemoryType> getPmemRange(Process *process,
std::uint64_t address);
} // namespace orbis::vmem

View file

@ -870,28 +870,31 @@ orbis::ErrorCode orbis::dmem::protect(orbis::Process *process,
return {};
}
std::pair<std::uint64_t, orbis::ErrorCode>
orbis::dmem::getPmemOffset(unsigned dmemIndex, std::uint64_t dmemOffset) {
std::pair<rx::AddressRange, orbis::MemoryType>
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()};
}

View file

@ -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 <cassert>
@ -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<rx::mem::Protection> 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<uintptr_t>(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; }

View file

@ -43,7 +43,7 @@ struct VirtualMemoryAllocation {
rx::EnumBitSet<orbis::vmem::BlockFlagsEx> flagsEx{};
rx::EnumBitSet<orbis::vmem::Protection> prot{};
orbis::MemoryType type = orbis::MemoryType::Invalid;
rx::Ref<orbis::IoDevice> device;
rx::Ref<orbis::File> 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<rx::AddressRange, VirtualMemoryAllocation>
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<rx::AddressRange, orbis::ErrorCode> 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<rx::AddressRange, orbis::ErrorCode> 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<rx::AddressRange, orbis::ErrorCode> 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<rx::AddressRange, orbis::ErrorCode> 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<rx::AddressRange, orbis::MemoryType>
orbis::vmem::getPmemRange(Process *process, std::uint64_t address) {
rx::Ref<File> 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());
}

View file

@ -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();

View file

@ -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<BlockPoolAllocation, orbis::kallocator>;
struct BlockPoolFile : public orbis::File {};
struct BlockPoolDevice
: orbis::IoDeviceWithIoctl<orbis::ioctl::group(BLOCKPOOL_IOCTL_EXPAND)> {
@ -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<orbis::ErrorCode, orbis::blockpool::BlockStats>

View file

@ -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<orbis::vmem::Protection> 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<orbis::File> *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<DceDevice>();
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<std::byte *>(vmem.beginAddress());
auto vmem = orbis::pmem::mapInternal(pmemRange, rx::mem::Protection::W);
auto dceControl = reinterpret_cast<std::byte *>(vmem);
*reinterpret_cast<orbis::uint64_t *>(dceControl + 0x130) = 0;
*reinterpret_cast<orbis::uint64_t *>(dceControl + 0x138) = 1;
*reinterpret_cast<orbis::uint16_t *>(dceControl + 0x140) =
orbis::kEvFiltDisplay;
orbis::vmem::unmap(process, vmem);
orbis::pmem::unmapInternal(vmem, pmemRange.size());
return result;
}

View file

@ -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<orbis::vmem::Protection> protection,
orbis::File *file, orbis::Process *process) override;
std::pair<rx::AddressRange, orbis::MemoryType>
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"; }
};

View file

@ -44,6 +44,11 @@ struct DmemDevice
rx::EnumBitSet<orbis::vmem::Protection> protection,
orbis::File *file, orbis::Process *process) override;
std::pair<rx::AddressRange, orbis::MemoryType>
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<orbis::vmem::Protection> 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 = {};

View file

@ -30,10 +30,9 @@ struct ComputeQueue {
struct GcDevice : public orbis::IoDevice {
rx::shared_mutex mtx;
rx::AddressRange dmemRange;
rx::AddressRange pmemRange;
orbis::kmap<orbis::pid_t, int> clients;
orbis::kmap<std::uint64_t, ComputeQueue> computeQueues;
orbis::uintptr_t submitArea = 0;
orbis::ErrorCode open(rx::Ref<orbis::File> *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<orbis::vmem::Protection> 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<rx::AddressRange, orbis::MemoryType>
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<orbis::uintptr_t *>(argp) = device->submitArea;
*reinterpret_cast<orbis::uintptr_t *>(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<GcDevice>();
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;
}

View file

@ -504,6 +504,16 @@ struct ElfDevice : orbis::IoDevice {
orbis::vmem::toCpuProtection(protection));
}
std::pair<rx::AddressRange, orbis::MemoryType>
getPmemRange(std::uint64_t offset, orbis::File *file) override {
auto elf = static_cast<ElfFile *>(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
}

View file

@ -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);