|
@@ -9,6 +9,7 @@
|
|
|
#include "common/logging/log.h"
|
|
#include "common/logging/log.h"
|
|
|
#include "core/arm/arm_interface.h"
|
|
#include "core/arm/arm_interface.h"
|
|
|
#include "core/core.h"
|
|
#include "core/core.h"
|
|
|
|
|
+#include "core/file_sys/program_metadata.h"
|
|
|
#include "core/hle/kernel/errors.h"
|
|
#include "core/hle/kernel/errors.h"
|
|
|
#include "core/hle/kernel/vm_manager.h"
|
|
#include "core/hle/kernel/vm_manager.h"
|
|
|
#include "core/memory.h"
|
|
#include "core/memory.h"
|
|
@@ -54,30 +55,32 @@ bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VMManager::VMManager() {
|
|
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() {
|
|
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.
|
|
// Initialize the map with a single free region covering the entire managed space.
|
|
|
VirtualMemoryArea initial_vma;
|
|
VirtualMemoryArea initial_vma;
|
|
|
- initial_vma.size = MAX_ADDRESS;
|
|
|
|
|
|
|
+ initial_vma.size = address_space_end;
|
|
|
vma_map.emplace(initial_vma.base, initial_vma);
|
|
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);
|
|
UpdatePageTableForVMA(initial_vma);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VMManager::VMAHandle VMManager::FindVMA(VAddr target) const {
|
|
VMManager::VMAHandle VMManager::FindVMA(VAddr target) const {
|
|
|
- if (target >= MAX_ADDRESS) {
|
|
|
|
|
|
|
+ if (target >= address_space_end) {
|
|
|
return vma_map.end();
|
|
return vma_map.end();
|
|
|
} else {
|
|
} else {
|
|
|
return std::prev(vma_map.upper_bound(target));
|
|
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;
|
|
const VAddr target_end = target + size;
|
|
|
ASSERT(target_end >= target);
|
|
ASSERT(target_end >= target);
|
|
|
- ASSERT(target_end <= MAX_ADDRESS);
|
|
|
|
|
|
|
+ ASSERT(target_end <= address_space_end);
|
|
|
ASSERT(size > 0);
|
|
ASSERT(size > 0);
|
|
|
|
|
|
|
|
VMAIter begin_vma = StripIterConstness(FindVMA(target));
|
|
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 {
|
|
u64 VMManager::GetTotalMemoryUsage() const {
|
|
|
LOG_WARNING(Kernel, "(STUBBED) called");
|
|
LOG_WARNING(Kernel, "(STUBBED) called");
|
|
|
return 0xF8000000;
|
|
return 0xF8000000;
|
|
@@ -392,14 +474,80 @@ u64 VMManager::GetTotalHeapUsage() const {
|
|
|
return 0x0;
|
|
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 {
|
|
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
|
|
} // namespace Kernel
|