|
|
|
@ -9,6 +9,7 @@ |
|
|
|
#include "common/logging/log.h"
|
|
|
|
#include "core/arm/arm_interface.h"
|
|
|
|
#include "core/core.h"
|
|
|
|
#include "core/file_sys/program_metadata.h"
|
|
|
|
#include "core/hle/kernel/errors.h"
|
|
|
|
#include "core/hle/kernel/vm_manager.h"
|
|
|
|
#include "core/memory.h"
|
|
|
|
@ -54,30 +55,32 @@ bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { |
|
|
|
} |
|
|
|
|
|
|
|
VMManager::VMManager() { |
|
|
|
Reset(); |
|
|
|
// Default to assuming a 39-bit address space. This way we have a sane
|
|
|
|
// starting point with executables that don't provide metadata.
|
|
|
|
Reset(FileSys::ProgramAddressSpaceType::Is39Bit); |
|
|
|
} |
|
|
|
|
|
|
|
VMManager::~VMManager() { |
|
|
|
Reset(); |
|
|
|
Reset(FileSys::ProgramAddressSpaceType::Is39Bit); |
|
|
|
} |
|
|
|
|
|
|
|
void VMManager::Reset() { |
|
|
|
vma_map.clear(); |
|
|
|
void VMManager::Reset(FileSys::ProgramAddressSpaceType type) { |
|
|
|
Clear(); |
|
|
|
|
|
|
|
InitializeMemoryRegionRanges(type); |
|
|
|
|
|
|
|
page_table.Resize(address_space_width); |
|
|
|
|
|
|
|
// Initialize the map with a single free region covering the entire managed space.
|
|
|
|
VirtualMemoryArea initial_vma; |
|
|
|
initial_vma.size = MAX_ADDRESS; |
|
|
|
initial_vma.size = address_space_end; |
|
|
|
vma_map.emplace(initial_vma.base, initial_vma); |
|
|
|
|
|
|
|
page_table.pointers.fill(nullptr); |
|
|
|
page_table.special_regions.clear(); |
|
|
|
page_table.attributes.fill(Memory::PageType::Unmapped); |
|
|
|
|
|
|
|
UpdatePageTableForVMA(initial_vma); |
|
|
|
} |
|
|
|
|
|
|
|
VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { |
|
|
|
if (target >= MAX_ADDRESS) { |
|
|
|
if (target >= address_space_end) { |
|
|
|
return vma_map.end(); |
|
|
|
} else { |
|
|
|
return std::prev(vma_map.upper_bound(target)); |
|
|
|
@ -291,7 +294,7 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u64 size) { |
|
|
|
|
|
|
|
const VAddr target_end = target + size; |
|
|
|
ASSERT(target_end >= target); |
|
|
|
ASSERT(target_end <= MAX_ADDRESS); |
|
|
|
ASSERT(target_end <= address_space_end); |
|
|
|
ASSERT(size > 0); |
|
|
|
|
|
|
|
VMAIter begin_vma = StripIterConstness(FindVMA(target)); |
|
|
|
@ -382,6 +385,85 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType type) { |
|
|
|
u64 map_region_size = 0; |
|
|
|
u64 heap_region_size = 0; |
|
|
|
u64 new_map_region_size = 0; |
|
|
|
u64 tls_io_region_size = 0; |
|
|
|
|
|
|
|
switch (type) { |
|
|
|
case FileSys::ProgramAddressSpaceType::Is32Bit: |
|
|
|
address_space_width = 32; |
|
|
|
code_region_base = 0x200000; |
|
|
|
code_region_end = code_region_base + 0x3FE00000; |
|
|
|
map_region_size = 0x40000000; |
|
|
|
heap_region_size = 0x40000000; |
|
|
|
break; |
|
|
|
case FileSys::ProgramAddressSpaceType::Is36Bit: |
|
|
|
address_space_width = 36; |
|
|
|
code_region_base = 0x8000000; |
|
|
|
code_region_end = code_region_base + 0x78000000; |
|
|
|
map_region_size = 0x180000000; |
|
|
|
heap_region_size = 0x180000000; |
|
|
|
break; |
|
|
|
case FileSys::ProgramAddressSpaceType::Is32BitNoMap: |
|
|
|
address_space_width = 32; |
|
|
|
code_region_base = 0x200000; |
|
|
|
code_region_end = code_region_base + 0x3FE00000; |
|
|
|
map_region_size = 0; |
|
|
|
heap_region_size = 0x80000000; |
|
|
|
break; |
|
|
|
case FileSys::ProgramAddressSpaceType::Is39Bit: |
|
|
|
address_space_width = 39; |
|
|
|
code_region_base = 0x8000000; |
|
|
|
code_region_end = code_region_base + 0x80000000; |
|
|
|
map_region_size = 0x1000000000; |
|
|
|
heap_region_size = 0x180000000; |
|
|
|
new_map_region_size = 0x80000000; |
|
|
|
tls_io_region_size = 0x1000000000; |
|
|
|
break; |
|
|
|
default: |
|
|
|
UNREACHABLE_MSG("Invalid address space type specified: {}", static_cast<u32>(type)); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
address_space_base = 0; |
|
|
|
address_space_end = 1ULL << address_space_width; |
|
|
|
|
|
|
|
map_region_base = code_region_end; |
|
|
|
map_region_end = map_region_base + map_region_size; |
|
|
|
|
|
|
|
heap_region_base = map_region_end; |
|
|
|
heap_region_end = heap_region_base + heap_region_size; |
|
|
|
|
|
|
|
new_map_region_base = heap_region_end; |
|
|
|
new_map_region_end = new_map_region_base + new_map_region_size; |
|
|
|
|
|
|
|
tls_io_region_base = new_map_region_end; |
|
|
|
tls_io_region_end = tls_io_region_base + tls_io_region_size; |
|
|
|
|
|
|
|
if (new_map_region_size == 0) { |
|
|
|
new_map_region_base = address_space_base; |
|
|
|
new_map_region_end = address_space_end; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void VMManager::Clear() { |
|
|
|
ClearVMAMap(); |
|
|
|
ClearPageTable(); |
|
|
|
} |
|
|
|
|
|
|
|
void VMManager::ClearVMAMap() { |
|
|
|
vma_map.clear(); |
|
|
|
} |
|
|
|
|
|
|
|
void VMManager::ClearPageTable() { |
|
|
|
std::fill(page_table.pointers.begin(), page_table.pointers.end(), nullptr); |
|
|
|
page_table.special_regions.clear(); |
|
|
|
std::fill(page_table.attributes.begin(), page_table.attributes.end(), |
|
|
|
Memory::PageType::Unmapped); |
|
|
|
} |
|
|
|
|
|
|
|
u64 VMManager::GetTotalMemoryUsage() const { |
|
|
|
LOG_WARNING(Kernel, "(STUBBED) called"); |
|
|
|
return 0xF8000000; |
|
|
|
@ -392,14 +474,80 @@ u64 VMManager::GetTotalHeapUsage() const { |
|
|
|
return 0x0; |
|
|
|
} |
|
|
|
|
|
|
|
VAddr VMManager::GetAddressSpaceBaseAddr() const { |
|
|
|
LOG_WARNING(Kernel, "(STUBBED) called"); |
|
|
|
return 0x8000000; |
|
|
|
VAddr VMManager::GetAddressSpaceBaseAddress() const { |
|
|
|
return address_space_base; |
|
|
|
} |
|
|
|
|
|
|
|
VAddr VMManager::GetAddressSpaceEndAddress() const { |
|
|
|
return address_space_end; |
|
|
|
} |
|
|
|
|
|
|
|
u64 VMManager::GetAddressSpaceSize() const { |
|
|
|
LOG_WARNING(Kernel, "(STUBBED) called"); |
|
|
|
return MAX_ADDRESS; |
|
|
|
return address_space_end - address_space_base; |
|
|
|
} |
|
|
|
|
|
|
|
u64 VMManager::GetAddressSpaceWidth() const { |
|
|
|
return address_space_width; |
|
|
|
} |
|
|
|
|
|
|
|
VAddr VMManager::GetCodeRegionBaseAddress() const { |
|
|
|
return code_region_base; |
|
|
|
} |
|
|
|
|
|
|
|
VAddr VMManager::GetCodeRegionEndAddress() const { |
|
|
|
return code_region_end; |
|
|
|
} |
|
|
|
|
|
|
|
u64 VMManager::GetCodeRegionSize() const { |
|
|
|
return code_region_end - code_region_base; |
|
|
|
} |
|
|
|
|
|
|
|
VAddr VMManager::GetHeapRegionBaseAddress() const { |
|
|
|
return heap_region_base; |
|
|
|
} |
|
|
|
|
|
|
|
VAddr VMManager::GetHeapRegionEndAddress() const { |
|
|
|
return heap_region_end; |
|
|
|
} |
|
|
|
|
|
|
|
u64 VMManager::GetHeapRegionSize() const { |
|
|
|
return heap_region_end - heap_region_base; |
|
|
|
} |
|
|
|
|
|
|
|
VAddr VMManager::GetMapRegionBaseAddress() const { |
|
|
|
return map_region_base; |
|
|
|
} |
|
|
|
|
|
|
|
VAddr VMManager::GetMapRegionEndAddress() const { |
|
|
|
return map_region_end; |
|
|
|
} |
|
|
|
|
|
|
|
u64 VMManager::GetMapRegionSize() const { |
|
|
|
return map_region_end - map_region_base; |
|
|
|
} |
|
|
|
|
|
|
|
VAddr VMManager::GetNewMapRegionBaseAddress() const { |
|
|
|
return new_map_region_base; |
|
|
|
} |
|
|
|
|
|
|
|
VAddr VMManager::GetNewMapRegionEndAddress() const { |
|
|
|
return new_map_region_end; |
|
|
|
} |
|
|
|
|
|
|
|
u64 VMManager::GetNewMapRegionSize() const { |
|
|
|
return new_map_region_end - new_map_region_base; |
|
|
|
} |
|
|
|
|
|
|
|
VAddr VMManager::GetTLSIORegionBaseAddress() const { |
|
|
|
return tls_io_region_base; |
|
|
|
} |
|
|
|
|
|
|
|
VAddr VMManager::GetTLSIORegionEndAddress() const { |
|
|
|
return tls_io_region_end; |
|
|
|
} |
|
|
|
|
|
|
|
u64 VMManager::GetTLSIORegionSize() const { |
|
|
|
return tls_io_region_end - tls_io_region_base; |
|
|
|
} |
|
|
|
|
|
|
|
} // namespace Kernel
|