core: Rework memory manager

This commit is contained in:
raphaelthegreat 2024-06-10 02:13:44 +03:00
parent 623b1d6837
commit fc887bf3f5
10 changed files with 339 additions and 179 deletions

View file

@ -4,6 +4,7 @@
#pragma once
#include <functional>
#include <mutex>
#include <string_view>
#include <vector>
#include <boost/icl/split_interval_map.hpp>
@ -11,6 +12,7 @@
#include "common/singleton.h"
#include "common/types.h"
#include "core/address_space.h"
#include "core/libraries/kernel/memory_management.h"
#include "video_core/renderer_vulkan/vk_common.h"
namespace Vulkan {
@ -47,12 +49,28 @@ enum class VMAType : u32 {
Flexible = 3,
Pooled = 4,
Stack = 5,
Code = 6,
};
struct DirectMemoryArea {
PAddr base = 0;
size_t size = 0;
int memory_type = 0;
bool is_free = true;
PAddr GetEnd() const {
return base + size;
}
bool CanMergeWith(const DirectMemoryArea& next) const {
if (base + size != next.base) {
return false;
}
if (is_free != next.is_free) {
return false;
}
return true;
}
};
struct VirtualMemoryArea {
@ -81,14 +99,10 @@ struct VirtualMemoryArea {
}
};
constexpr VAddr SYSTEM_RESERVED = 0x800000000ULL;
constexpr VAddr CODE_BASE_OFFSET = 0x100000000ULL;
constexpr VAddr SYSTEM_MANAGED_MIN = 0x0000040000ULL;
constexpr VAddr SYSTEM_MANAGED_MAX = 0x07FFFFBFFFULL;
constexpr VAddr USER_MIN = 0x1000000000ULL;
constexpr VAddr USER_MAX = 0xFBFFFFFFFFULL;
class MemoryManager {
using DMemMap = std::map<PAddr, DirectMemoryArea>;
using DMemHandle = DMemMap::iterator;
using VMAMap = std::map<VAddr, VirtualMemoryArea>;
using VMAHandle = VMAMap::iterator;
@ -107,35 +121,57 @@ public:
int MapMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
MemoryMapFlags flags, VMAType type, std::string_view name = "",
PAddr phys_addr = -1, u64 alignment = 0);
bool is_exec = false, PAddr phys_addr = -1, u64 alignment = 0);
void UnmapMemory(VAddr virtual_addr, size_t size);
int QueryProtection(VAddr addr, void** start, void** end, u32* prot);
int VirtualQuery(VAddr addr, int flags, Libraries::Kernel::OrbisVirtualQueryInfo* info);
int DirectMemoryQuery(PAddr addr, bool find_next, Libraries::Kernel::OrbisQueryInfo* out_info);
VAddr Reserve(size_t size, u64 alignment) {
return reinterpret_cast<VAddr>(impl.Reserve(size, alignment));
}
int DirectQueryAvailable(PAddr search_start, PAddr search_end, size_t alignment,
PAddr* phys_addr_out, size_t* size_out);
std::pair<vk::Buffer, size_t> GetVulkanBuffer(VAddr addr);
private:
VMAHandle FindVMA(VAddr target) {
// Return first the VMA with base >= target.
const auto it = vma_map.lower_bound(target);
if (it != vma_map.end() && it->first == target) {
return it;
return std::prev(vma_map.upper_bound(target));
}
DMemHandle FindDmemArea(PAddr target) {
return std::prev(dmem_map.upper_bound(target));
}
template <typename Handle>
Handle MergeAdjacent(auto& handle_map, Handle iter) {
const auto next_vma = std::next(iter);
if (next_vma != handle_map.end() && iter->second.CanMergeWith(next_vma->second)) {
iter->second.size += next_vma->second.size;
handle_map.erase(next_vma);
}
return std::prev(it);
if (iter != handle_map.begin()) {
auto prev_vma = std::prev(iter);
if (prev_vma->second.CanMergeWith(iter->second)) {
prev_vma->second.size += iter->second.size;
handle_map.erase(iter);
iter = prev_vma;
}
}
return iter;
}
VirtualMemoryArea& AddMapping(VAddr virtual_addr, size_t size);
DirectMemoryArea& AddDmemAllocation(PAddr addr, size_t size);
VMAHandle Split(VMAHandle vma_handle, size_t offset_in_vma);
VMAHandle MergeAdjacent(VMAHandle iter);
DMemHandle Split(DMemHandle dmem_handle, size_t offset_in_area);
void MapVulkanMemory(VAddr addr, size_t size);
@ -143,8 +179,9 @@ private:
private:
AddressSpace impl;
std::vector<DirectMemoryArea> allocations;
DMemMap dmem_map;
VMAMap vma_map;
std::recursive_mutex mutex;
struct MappedMemory {
vk::UniqueBuffer buffer;