mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-22 16:40:57 +01:00
fix blockpool & dmem implementation modernize blockpool & dmem io devices use budgets per allocation add serialization support for MemoryTableWithPayload and AddressRange utils add format support for EnumBitSet util implemented trace formatter per syscall increased allowed reference count for Ref
143 lines
4.4 KiB
C++
143 lines
4.4 KiB
C++
#include "pmem.hpp"
|
|
#include "IoDevice.hpp"
|
|
#include "KernelAllocator.hpp"
|
|
#include "KernelObject.hpp"
|
|
#include "error.hpp"
|
|
#include "error/ErrorCode.hpp"
|
|
#include "file.hpp"
|
|
#include "kernel/KernelObject.hpp"
|
|
#include "kernel/MemoryResource.hpp"
|
|
#include "rx/AddressRange.hpp"
|
|
#include "rx/Rc.hpp"
|
|
#include "rx/print.hpp"
|
|
#include "vmem.hpp"
|
|
#include <cassert>
|
|
#include <rx/Mappable.hpp>
|
|
|
|
struct PhysicalMemoryAllocation {
|
|
bool allocated = false;
|
|
|
|
[[nodiscard]] bool isAllocated() const { return allocated; }
|
|
[[nodiscard]] bool isRelated(const PhysicalMemoryAllocation &left,
|
|
rx::AddressRange, rx::AddressRange) const {
|
|
return allocated == left.allocated;
|
|
}
|
|
|
|
[[nodiscard]] PhysicalMemoryAllocation
|
|
merge(const PhysicalMemoryAllocation &other, rx::AddressRange,
|
|
rx::AddressRange) const {
|
|
assert(other.allocated == allocated);
|
|
return other;
|
|
}
|
|
|
|
bool operator==(const PhysicalMemoryAllocation &) const = default;
|
|
};
|
|
|
|
using MappableMemoryResource =
|
|
kernel::MappableResource<decltype([](std::size_t size) {
|
|
return rx::Mappable::CreateMemory(size);
|
|
})>;
|
|
|
|
using PhysicalMemoryResource =
|
|
kernel::AllocableResource<PhysicalMemoryAllocation, orbis::kallocator,
|
|
MappableMemoryResource>;
|
|
|
|
static auto g_pmemInstance = orbis::createGlobalObject<
|
|
kernel::LockableKernelObject<PhysicalMemoryResource>>();
|
|
|
|
struct PhysicalMemory : orbis::IoDevice {
|
|
orbis::File file;
|
|
|
|
PhysicalMemory() {
|
|
incRef(); // do not delete global object
|
|
|
|
file.device = this;
|
|
file.incRef(); // do not delete property
|
|
}
|
|
|
|
orbis::ErrorCode open(rx::Ref<orbis::File> *file, const char *path,
|
|
std::uint32_t flags, std::uint32_t mode,
|
|
orbis::Thread *thread) override {
|
|
rx::die("open PhysicalMemory device");
|
|
}
|
|
|
|
orbis::ErrorCode map(rx::AddressRange range, std::int64_t offset,
|
|
rx::EnumBitSet<orbis::vmem::Protection> protection,
|
|
orbis::File *, orbis::Process *) override {
|
|
return orbis::pmem::map(
|
|
range.beginAddress(),
|
|
rx::AddressRange::fromBeginSize(offset, range.size()),
|
|
orbis::vmem::toCpuProtection(protection));
|
|
}
|
|
|
|
void serialize(rx::Serializer &s) const {}
|
|
void deserialize(rx::Deserializer &s) {}
|
|
};
|
|
|
|
static auto g_phyMemory = orbis::createGlobalObject<PhysicalMemory>();
|
|
|
|
orbis::ErrorCode orbis::pmem::initialize(std::uint64_t size) {
|
|
std::lock_guard lock(*g_pmemInstance);
|
|
rx::println("pmem: {:x}", size);
|
|
|
|
return toErrorCode(
|
|
g_pmemInstance->create(rx::AddressRange::fromBeginSize(0, size)));
|
|
}
|
|
|
|
void orbis::pmem::destroy() {
|
|
std::lock_guard lock(*g_pmemInstance);
|
|
g_pmemInstance->destroy();
|
|
}
|
|
|
|
std::pair<rx::AddressRange, orbis::ErrorCode>
|
|
orbis::pmem::allocate(std::uint64_t addressHint, std::uint64_t size,
|
|
rx::EnumBitSet<AllocationFlags> flags,
|
|
std::uint64_t alignment) {
|
|
std::lock_guard lock(*g_pmemInstance);
|
|
PhysicalMemoryAllocation allocation{.allocated = true};
|
|
auto [it, errc, range] =
|
|
g_pmemInstance->map(addressHint, size, allocation, flags, alignment);
|
|
|
|
if (errc != std::errc{}) {
|
|
return {{}, toErrorCode(errc)};
|
|
}
|
|
|
|
return {range, {}};
|
|
}
|
|
|
|
orbis::ErrorCode orbis::pmem::deallocate(rx::AddressRange range) {
|
|
std::lock_guard lock(*g_pmemInstance);
|
|
PhysicalMemoryAllocation allocation{};
|
|
auto [it, errc, _] =
|
|
g_pmemInstance->map(range.beginAddress(), range.size(), allocation,
|
|
AllocationFlags::Fixed, 1);
|
|
|
|
return toErrorCode(errc);
|
|
}
|
|
|
|
std::optional<rx::AddressRange> orbis::pmem::query(std::uint64_t address) {
|
|
std::lock_guard lock(*g_pmemInstance);
|
|
auto result = g_pmemInstance->query(address);
|
|
|
|
if (result == g_pmemInstance->end()) {
|
|
return {};
|
|
}
|
|
|
|
return result.range();
|
|
}
|
|
|
|
orbis::ErrorCode
|
|
orbis::pmem::map(std::uint64_t virtualAddress, rx::AddressRange range,
|
|
rx::EnumBitSet<rx::mem::Protection> protection) {
|
|
auto virtualRange =
|
|
rx::AddressRange::fromBeginSize(virtualAddress, range.size());
|
|
auto errc = g_pmemInstance->mappable.map(virtualRange, range.beginAddress(),
|
|
protection, vmem::kPageSize);
|
|
|
|
return toErrorCode(errc);
|
|
}
|
|
|
|
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; }
|