Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebase of "Handle munmap over multiple VMAs" #2233

Merged
merged 6 commits into from
Jan 24, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions src/core/memory.cpp
Original file line number Diff line number Diff line change
@@ -389,32 +389,29 @@ s32 MemoryManager::UnmapMemory(VAddr virtual_addr, size_t size) {
return UnmapMemoryImpl(virtual_addr, size);
}

s32 MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, size_t size) {
const auto it = FindVMA(virtual_addr);
const auto& vma_base = it->second;
ASSERT_MSG(vma_base.Contains(virtual_addr, size),
"Existing mapping does not contain requested unmap range");

const auto type = vma_base.type;
if (type == VMAType::Free) {
return ORBIS_OK;
}

u64 MemoryManager::UnmapBytesFromEntry(VAddr virtual_addr, VirtualMemoryArea vma_base, u64 size) {
const auto vma_base_addr = vma_base.base;
const auto vma_base_size = vma_base.size;
const auto type = vma_base.type;
const auto phys_base = vma_base.phys_base;
const bool is_exec = vma_base.is_exec;
const auto start_in_vma = virtual_addr - vma_base_addr;
const auto adjusted_size =
vma_base_size - start_in_vma < size ? vma_base_size - start_in_vma : size;
const bool has_backing = type == VMAType::Direct || type == VMAType::File;

if (type == VMAType::Free) {
return adjusted_size;
}
if (type == VMAType::Direct || type == VMAType::Pooled) {
rasterizer->UnmapMemory(virtual_addr, size);
rasterizer->UnmapMemory(virtual_addr, adjusted_size);
}
if (type == VMAType::Flexible) {
flexible_usage -= size;
flexible_usage -= adjusted_size;
}

// Mark region as free and attempt to coalesce it with neighbours.
const auto new_it = CarveVMA(virtual_addr, size);
const auto new_it = CarveVMA(virtual_addr, adjusted_size);
auto& vma = new_it->second;
vma.type = VMAType::Free;
vma.prot = MemoryProt::NoAccess;
@@ -423,13 +420,25 @@ s32 MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, size_t size) {
vma.name = "";
MergeAdjacent(vma_map, new_it);
bool readonly_file = vma.prot == MemoryProt::CpuRead && type == VMAType::File;

if (type != VMAType::Reserved && type != VMAType::PoolReserved) {
// Unmap the memory region.
impl.Unmap(vma_base_addr, vma_base_size, start_in_vma, start_in_vma + size, phys_base,
is_exec, has_backing, readonly_file);
impl.Unmap(vma_base_addr, vma_base_size, start_in_vma, start_in_vma + adjusted_size,
phys_base, is_exec, has_backing, readonly_file);
TRACK_FREE(virtual_addr, "VMEM");
}
return adjusted_size;
}

s32 MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, u64 size) {
u64 unmapped_bytes = 0;
do {
auto it = FindVMA(virtual_addr + unmapped_bytes);
auto& vma_base = it->second;
auto unmapped =
UnmapBytesFromEntry(virtual_addr + unmapped_bytes, vma_base, size - unmapped_bytes);
ASSERT_MSG(unmapped > 0, "Failed to unmap memory, progress is impossible");
unmapped_bytes += unmapped;
} while (unmapped_bytes < size);

return ORBIS_OK;
}
@@ -651,6 +660,12 @@ MemoryManager::VMAHandle MemoryManager::CarveVMA(VAddr virtual_addr, size_t size

const VAddr start_in_vma = virtual_addr - vma.base;
const VAddr end_in_vma = start_in_vma + size;

if (start_in_vma == 0 && size == vma.size) {
// if requsting the whole VMA, return it
return vma_handle;
}

ASSERT_MSG(end_in_vma <= vma.size, "Mapping cannot fit inside free region");

if (end_in_vma != vma.size) {
4 changes: 3 additions & 1 deletion src/core/memory.h
Original file line number Diff line number Diff line change
@@ -252,7 +252,9 @@ class MemoryManager {

DMemHandle Split(DMemHandle dmem_handle, size_t offset_in_area);

s32 UnmapMemoryImpl(VAddr virtual_addr, size_t size);
u64 UnmapBytesFromEntry(VAddr virtual_addr, VirtualMemoryArea vma_base, u64 size);

s32 UnmapMemoryImpl(VAddr virtual_addr, u64 size);

private:
AddressSpace impl;