mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-22 00:20:40 +01:00
orbis: add pmem device query api
This commit is contained in:
parent
733b8bf73f
commit
600512ee90
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 = {};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue