diff options
| author | 2018-09-29 10:54:39 -0400 | |
|---|---|---|
| committer | 2018-09-29 10:54:39 -0400 | |
| commit | f7b69d61f2a871e8afcd9819b014e873f6e0b80d (patch) | |
| tree | ab6fa797e0a0edd41cc84138ac56aaba0c5238fe /src/core/hle/kernel | |
| parent | Merge pull request #1360 from FearlessTobi/port-3979 (diff) | |
| parent | memory: Dehardcode the use of fixed memory range constants (diff) | |
| download | yuzu-f7b69d61f2a871e8afcd9819b014e873f6e0b80d.tar.gz yuzu-f7b69d61f2a871e8afcd9819b014e873f6e0b80d.tar.xz yuzu-f7b69d61f2a871e8afcd9819b014e873f6e0b80d.zip | |
Merge pull request #1395 from lioncash/vm
process/vm_manager: Initial modifications to load NPDM metadata
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 28 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 12 | ||||
| -rw-r--r-- | src/core/hle/kernel/shared_memory.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 45 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.cpp | 180 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.h | 100 |
7 files changed, 319 insertions, 53 deletions
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 121f741fd..a8e3098ca 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "common/common_funcs.h" | 8 | #include "common/common_funcs.h" |
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/file_sys/program_metadata.h" | ||
| 11 | #include "core/hle/kernel/errors.h" | 12 | #include "core/hle/kernel/errors.h" |
| 12 | #include "core/hle/kernel/kernel.h" | 13 | #include "core/hle/kernel/kernel.h" |
| 13 | #include "core/hle/kernel/process.h" | 14 | #include "core/hle/kernel/process.h" |
| @@ -34,14 +35,21 @@ SharedPtr<Process> Process::Create(KernelCore& kernel, std::string&& name) { | |||
| 34 | process->name = std::move(name); | 35 | process->name = std::move(name); |
| 35 | process->flags.raw = 0; | 36 | process->flags.raw = 0; |
| 36 | process->flags.memory_region.Assign(MemoryRegion::APPLICATION); | 37 | process->flags.memory_region.Assign(MemoryRegion::APPLICATION); |
| 38 | process->resource_limit = kernel.ResourceLimitForCategory(ResourceLimitCategory::APPLICATION); | ||
| 37 | process->status = ProcessStatus::Created; | 39 | process->status = ProcessStatus::Created; |
| 38 | process->program_id = 0; | 40 | process->program_id = 0; |
| 39 | process->process_id = kernel.CreateNewProcessID(); | 41 | process->process_id = kernel.CreateNewProcessID(); |
| 42 | process->svc_access_mask.set(); | ||
| 40 | 43 | ||
| 41 | kernel.AppendNewProcess(process); | 44 | kernel.AppendNewProcess(process); |
| 42 | return process; | 45 | return process; |
| 43 | } | 46 | } |
| 44 | 47 | ||
| 48 | void Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) { | ||
| 49 | program_id = metadata.GetTitleID(); | ||
| 50 | vm_manager.Reset(metadata.GetAddressSpaceType()); | ||
| 51 | } | ||
| 52 | |||
| 45 | void Process::ParseKernelCaps(const u32* kernel_caps, std::size_t len) { | 53 | void Process::ParseKernelCaps(const u32* kernel_caps, std::size_t len) { |
| 46 | for (std::size_t i = 0; i < len; ++i) { | 54 | for (std::size_t i = 0; i < len; ++i) { |
| 47 | u32 descriptor = kernel_caps[i]; | 55 | u32 descriptor = kernel_caps[i]; |
| @@ -119,7 +127,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { | |||
| 119 | // TODO(bunnei): This is heap area that should be allocated by the kernel and not mapped as part | 127 | // TODO(bunnei): This is heap area that should be allocated by the kernel and not mapped as part |
| 120 | // of the user address space. | 128 | // of the user address space. |
| 121 | vm_manager | 129 | vm_manager |
| 122 | .MapMemoryBlock(Memory::STACK_AREA_VADDR_END - stack_size, | 130 | .MapMemoryBlock(vm_manager.GetTLSIORegionEndAddress() - stack_size, |
| 123 | std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, | 131 | std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, |
| 124 | MemoryState::Mapped) | 132 | MemoryState::Mapped) |
| 125 | .Unwrap(); | 133 | .Unwrap(); |
| @@ -185,6 +193,7 @@ static std::tuple<std::size_t, std::size_t, bool> FindFreeThreadLocalSlot( | |||
| 185 | 193 | ||
| 186 | VAddr Process::MarkNextAvailableTLSSlotAsUsed(Thread& thread) { | 194 | VAddr Process::MarkNextAvailableTLSSlotAsUsed(Thread& thread) { |
| 187 | auto [available_page, available_slot, needs_allocation] = FindFreeThreadLocalSlot(tls_slots); | 195 | auto [available_page, available_slot, needs_allocation] = FindFreeThreadLocalSlot(tls_slots); |
| 196 | const VAddr tls_begin = vm_manager.GetTLSIORegionBaseAddress(); | ||
| 188 | 197 | ||
| 189 | if (needs_allocation) { | 198 | if (needs_allocation) { |
| 190 | tls_slots.emplace_back(0); // The page is completely available at the start | 199 | tls_slots.emplace_back(0); // The page is completely available at the start |
| @@ -197,18 +206,17 @@ VAddr Process::MarkNextAvailableTLSSlotAsUsed(Thread& thread) { | |||
| 197 | 206 | ||
| 198 | vm_manager.RefreshMemoryBlockMappings(tls_memory.get()); | 207 | vm_manager.RefreshMemoryBlockMappings(tls_memory.get()); |
| 199 | 208 | ||
| 200 | vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, | 209 | vm_manager.MapMemoryBlock(tls_begin + available_page * Memory::PAGE_SIZE, tls_memory, 0, |
| 201 | tls_memory, 0, Memory::PAGE_SIZE, MemoryState::ThreadLocal); | 210 | Memory::PAGE_SIZE, MemoryState::ThreadLocal); |
| 202 | } | 211 | } |
| 203 | 212 | ||
| 204 | tls_slots[available_page].set(available_slot); | 213 | tls_slots[available_page].set(available_slot); |
| 205 | 214 | ||
| 206 | return Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE + | 215 | return tls_begin + available_page * Memory::PAGE_SIZE + available_slot * Memory::TLS_ENTRY_SIZE; |
| 207 | available_slot * Memory::TLS_ENTRY_SIZE; | ||
| 208 | } | 216 | } |
| 209 | 217 | ||
| 210 | void Process::FreeTLSSlot(VAddr tls_address) { | 218 | void Process::FreeTLSSlot(VAddr tls_address) { |
| 211 | const VAddr tls_base = tls_address - Memory::TLS_AREA_VADDR; | 219 | const VAddr tls_base = tls_address - vm_manager.GetTLSIORegionBaseAddress(); |
| 212 | const VAddr tls_page = tls_base / Memory::PAGE_SIZE; | 220 | const VAddr tls_page = tls_base / Memory::PAGE_SIZE; |
| 213 | const VAddr tls_slot = (tls_base % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; | 221 | const VAddr tls_slot = (tls_base % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; |
| 214 | 222 | ||
| @@ -232,8 +240,8 @@ void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) { | |||
| 232 | } | 240 | } |
| 233 | 241 | ||
| 234 | ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { | 242 | ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { |
| 235 | if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || | 243 | if (target < vm_manager.GetHeapRegionBaseAddress() || |
| 236 | target + size < target) { | 244 | target + size > vm_manager.GetHeapRegionEndAddress() || target + size < target) { |
| 237 | return ERR_INVALID_ADDRESS; | 245 | return ERR_INVALID_ADDRESS; |
| 238 | } | 246 | } |
| 239 | 247 | ||
| @@ -268,8 +276,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission per | |||
| 268 | } | 276 | } |
| 269 | 277 | ||
| 270 | ResultCode Process::HeapFree(VAddr target, u32 size) { | 278 | ResultCode Process::HeapFree(VAddr target, u32 size) { |
| 271 | if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || | 279 | if (target < vm_manager.GetHeapRegionBaseAddress() || |
| 272 | target + size < target) { | 280 | target + size > vm_manager.GetHeapRegionEndAddress() || target + size < target) { |
| 273 | return ERR_INVALID_ADDRESS; | 281 | return ERR_INVALID_ADDRESS; |
| 274 | } | 282 | } |
| 275 | 283 | ||
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 04d74e572..adb03c228 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -17,6 +17,10 @@ | |||
| 17 | #include "core/hle/kernel/thread.h" | 17 | #include "core/hle/kernel/thread.h" |
| 18 | #include "core/hle/kernel/vm_manager.h" | 18 | #include "core/hle/kernel/vm_manager.h" |
| 19 | 19 | ||
| 20 | namespace FileSys { | ||
| 21 | class ProgramMetadata; | ||
| 22 | } | ||
| 23 | |||
| 20 | namespace Kernel { | 24 | namespace Kernel { |
| 21 | 25 | ||
| 22 | class KernelCore; | 26 | class KernelCore; |
| @@ -141,6 +145,14 @@ public: | |||
| 141 | return process_id; | 145 | return process_id; |
| 142 | } | 146 | } |
| 143 | 147 | ||
| 148 | /** | ||
| 149 | * Loads process-specifics configuration info with metadata provided | ||
| 150 | * by an executable. | ||
| 151 | * | ||
| 152 | * @param metadata The provided metadata to load process specific info. | ||
| 153 | */ | ||
| 154 | void LoadFromMetadata(const FileSys::ProgramMetadata& metadata); | ||
| 155 | |||
| 144 | /// Title ID corresponding to the process | 156 | /// Title ID corresponding to the process |
| 145 | u64 program_id; | 157 | u64 program_id; |
| 146 | 158 | ||
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index abb1d09cd..9b78c8cb5 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/hle/kernel/errors.h" | 10 | #include "core/hle/kernel/errors.h" |
| 11 | #include "core/hle/kernel/kernel.h" | ||
| 11 | #include "core/hle/kernel/shared_memory.h" | 12 | #include "core/hle/kernel/shared_memory.h" |
| 12 | #include "core/memory.h" | 13 | #include "core/memory.h" |
| 13 | 14 | ||
| @@ -71,7 +72,8 @@ SharedPtr<SharedMemory> SharedMemory::CreateForApplet( | |||
| 71 | shared_memory->other_permissions = other_permissions; | 72 | shared_memory->other_permissions = other_permissions; |
| 72 | shared_memory->backing_block = std::move(heap_block); | 73 | shared_memory->backing_block = std::move(heap_block); |
| 73 | shared_memory->backing_block_offset = offset; | 74 | shared_memory->backing_block_offset = offset; |
| 74 | shared_memory->base_address = Memory::HEAP_VADDR + offset; | 75 | shared_memory->base_address = |
| 76 | kernel.CurrentProcess()->vm_manager.GetHeapRegionBaseAddress() + offset; | ||
| 75 | 77 | ||
| 76 | return shared_memory; | 78 | return shared_memory; |
| 77 | } | 79 | } |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index c9d212a4c..44bbaf0c8 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -51,8 +51,9 @@ static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) { | |||
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | auto& process = *Core::CurrentProcess(); | 53 | auto& process = *Core::CurrentProcess(); |
| 54 | const VAddr heap_base = process.vm_manager.GetHeapRegionBaseAddress(); | ||
| 54 | CASCADE_RESULT(*heap_addr, | 55 | CASCADE_RESULT(*heap_addr, |
| 55 | process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite)); | 56 | process.HeapAllocate(heap_base, heap_size, VMAPermission::ReadWrite)); |
| 56 | return RESULT_SUCCESS; | 57 | return RESULT_SUCCESS; |
| 57 | } | 58 | } |
| 58 | 59 | ||
| @@ -325,26 +326,27 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 325 | LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id, | 326 | LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id, |
| 326 | info_sub_id, handle); | 327 | info_sub_id, handle); |
| 327 | 328 | ||
| 328 | const auto& vm_manager = Core::CurrentProcess()->vm_manager; | 329 | const auto& current_process = Core::CurrentProcess(); |
| 330 | const auto& vm_manager = current_process->vm_manager; | ||
| 329 | 331 | ||
| 330 | switch (static_cast<GetInfoType>(info_id)) { | 332 | switch (static_cast<GetInfoType>(info_id)) { |
| 331 | case GetInfoType::AllowedCpuIdBitmask: | 333 | case GetInfoType::AllowedCpuIdBitmask: |
| 332 | *result = Core::CurrentProcess()->allowed_processor_mask; | 334 | *result = current_process->allowed_processor_mask; |
| 333 | break; | 335 | break; |
| 334 | case GetInfoType::AllowedThreadPrioBitmask: | 336 | case GetInfoType::AllowedThreadPrioBitmask: |
| 335 | *result = Core::CurrentProcess()->allowed_thread_priority_mask; | 337 | *result = current_process->allowed_thread_priority_mask; |
| 336 | break; | 338 | break; |
| 337 | case GetInfoType::MapRegionBaseAddr: | 339 | case GetInfoType::MapRegionBaseAddr: |
| 338 | *result = Memory::MAP_REGION_VADDR; | 340 | *result = vm_manager.GetMapRegionBaseAddress(); |
| 339 | break; | 341 | break; |
| 340 | case GetInfoType::MapRegionSize: | 342 | case GetInfoType::MapRegionSize: |
| 341 | *result = Memory::MAP_REGION_SIZE; | 343 | *result = vm_manager.GetMapRegionSize(); |
| 342 | break; | 344 | break; |
| 343 | case GetInfoType::HeapRegionBaseAddr: | 345 | case GetInfoType::HeapRegionBaseAddr: |
| 344 | *result = Memory::HEAP_VADDR; | 346 | *result = vm_manager.GetHeapRegionBaseAddress(); |
| 345 | break; | 347 | break; |
| 346 | case GetInfoType::HeapRegionSize: | 348 | case GetInfoType::HeapRegionSize: |
| 347 | *result = Memory::HEAP_SIZE; | 349 | *result = vm_manager.GetHeapRegionSize(); |
| 348 | break; | 350 | break; |
| 349 | case GetInfoType::TotalMemoryUsage: | 351 | case GetInfoType::TotalMemoryUsage: |
| 350 | *result = vm_manager.GetTotalMemoryUsage(); | 352 | *result = vm_manager.GetTotalMemoryUsage(); |
| @@ -359,22 +361,35 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 359 | *result = 0; | 361 | *result = 0; |
| 360 | break; | 362 | break; |
| 361 | case GetInfoType::AddressSpaceBaseAddr: | 363 | case GetInfoType::AddressSpaceBaseAddr: |
| 362 | *result = vm_manager.GetAddressSpaceBaseAddr(); | 364 | *result = vm_manager.GetCodeRegionBaseAddress(); |
| 363 | break; | 365 | break; |
| 364 | case GetInfoType::AddressSpaceSize: | 366 | case GetInfoType::AddressSpaceSize: { |
| 365 | *result = vm_manager.GetAddressSpaceSize(); | 367 | const u64 width = vm_manager.GetAddressSpaceWidth(); |
| 368 | |||
| 369 | switch (width) { | ||
| 370 | case 32: | ||
| 371 | *result = 0xFFE00000; | ||
| 372 | break; | ||
| 373 | case 36: | ||
| 374 | *result = 0xFF8000000; | ||
| 375 | break; | ||
| 376 | case 39: | ||
| 377 | *result = 0x7FF8000000; | ||
| 378 | break; | ||
| 379 | } | ||
| 366 | break; | 380 | break; |
| 381 | } | ||
| 367 | case GetInfoType::NewMapRegionBaseAddr: | 382 | case GetInfoType::NewMapRegionBaseAddr: |
| 368 | *result = Memory::NEW_MAP_REGION_VADDR; | 383 | *result = vm_manager.GetNewMapRegionBaseAddress(); |
| 369 | break; | 384 | break; |
| 370 | case GetInfoType::NewMapRegionSize: | 385 | case GetInfoType::NewMapRegionSize: |
| 371 | *result = Memory::NEW_MAP_REGION_SIZE; | 386 | *result = vm_manager.GetNewMapRegionSize(); |
| 372 | break; | 387 | break; |
| 373 | case GetInfoType::IsVirtualAddressMemoryEnabled: | 388 | case GetInfoType::IsVirtualAddressMemoryEnabled: |
| 374 | *result = Core::CurrentProcess()->is_virtual_address_memory_enabled; | 389 | *result = current_process->is_virtual_address_memory_enabled; |
| 375 | break; | 390 | break; |
| 376 | case GetInfoType::TitleId: | 391 | case GetInfoType::TitleId: |
| 377 | *result = Core::CurrentProcess()->program_id; | 392 | *result = current_process->program_id; |
| 378 | break; | 393 | break; |
| 379 | case GetInfoType::PrivilegedProcessId: | 394 | case GetInfoType::PrivilegedProcessId: |
| 380 | LOG_WARNING(Kernel_SVC, | 395 | LOG_WARNING(Kernel_SVC, |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 315f65338..064ed908d 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -262,8 +262,9 @@ SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 pri | |||
| 262 | SetCurrentPageTable(&owner_process.vm_manager.page_table); | 262 | SetCurrentPageTable(&owner_process.vm_manager.page_table); |
| 263 | 263 | ||
| 264 | // Initialize new "main" thread | 264 | // Initialize new "main" thread |
| 265 | const VAddr stack_top = owner_process.vm_manager.GetTLSIORegionEndAddress(); | ||
| 265 | auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, THREADPROCESSORID_0, | 266 | auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, THREADPROCESSORID_0, |
| 266 | Memory::STACK_AREA_VADDR_END, &owner_process); | 267 | stack_top, &owner_process); |
| 267 | 268 | ||
| 268 | SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); | 269 | SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); |
| 269 | 270 | ||
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 608cbd57b..e412309fd 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "core/arm/arm_interface.h" | 10 | #include "core/arm/arm_interface.h" |
| 11 | #include "core/core.h" | 11 | #include "core/core.h" |
| 12 | #include "core/file_sys/program_metadata.h" | ||
| 12 | #include "core/hle/kernel/errors.h" | 13 | #include "core/hle/kernel/errors.h" |
| 13 | #include "core/hle/kernel/vm_manager.h" | 14 | #include "core/hle/kernel/vm_manager.h" |
| 14 | #include "core/memory.h" | 15 | #include "core/memory.h" |
| @@ -54,30 +55,32 @@ bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { | |||
| 54 | } | 55 | } |
| 55 | 56 | ||
| 56 | VMManager::VMManager() { | 57 | VMManager::VMManager() { |
| 57 | Reset(); | 58 | // Default to assuming a 39-bit address space. This way we have a sane |
| 59 | // starting point with executables that don't provide metadata. | ||
| 60 | Reset(FileSys::ProgramAddressSpaceType::Is39Bit); | ||
| 58 | } | 61 | } |
| 59 | 62 | ||
| 60 | VMManager::~VMManager() { | 63 | VMManager::~VMManager() { |
| 61 | Reset(); | 64 | Reset(FileSys::ProgramAddressSpaceType::Is39Bit); |
| 62 | } | 65 | } |
| 63 | 66 | ||
| 64 | void VMManager::Reset() { | 67 | void VMManager::Reset(FileSys::ProgramAddressSpaceType type) { |
| 65 | vma_map.clear(); | 68 | Clear(); |
| 69 | |||
| 70 | InitializeMemoryRegionRanges(type); | ||
| 71 | |||
| 72 | page_table.Resize(address_space_width); | ||
| 66 | 73 | ||
| 67 | // Initialize the map with a single free region covering the entire managed space. | 74 | // Initialize the map with a single free region covering the entire managed space. |
| 68 | VirtualMemoryArea initial_vma; | 75 | VirtualMemoryArea initial_vma; |
| 69 | initial_vma.size = MAX_ADDRESS; | 76 | initial_vma.size = address_space_end; |
| 70 | vma_map.emplace(initial_vma.base, initial_vma); | 77 | vma_map.emplace(initial_vma.base, initial_vma); |
| 71 | 78 | ||
| 72 | page_table.pointers.fill(nullptr); | ||
| 73 | page_table.special_regions.clear(); | ||
| 74 | page_table.attributes.fill(Memory::PageType::Unmapped); | ||
| 75 | |||
| 76 | UpdatePageTableForVMA(initial_vma); | 79 | UpdatePageTableForVMA(initial_vma); |
| 77 | } | 80 | } |
| 78 | 81 | ||
| 79 | VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { | 82 | VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { |
| 80 | if (target >= MAX_ADDRESS) { | 83 | if (target >= address_space_end) { |
| 81 | return vma_map.end(); | 84 | return vma_map.end(); |
| 82 | } else { | 85 | } else { |
| 83 | return std::prev(vma_map.upper_bound(target)); | 86 | return std::prev(vma_map.upper_bound(target)); |
| @@ -291,7 +294,7 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u64 size) { | |||
| 291 | 294 | ||
| 292 | const VAddr target_end = target + size; | 295 | const VAddr target_end = target + size; |
| 293 | ASSERT(target_end >= target); | 296 | ASSERT(target_end >= target); |
| 294 | ASSERT(target_end <= MAX_ADDRESS); | 297 | ASSERT(target_end <= address_space_end); |
| 295 | ASSERT(size > 0); | 298 | ASSERT(size > 0); |
| 296 | 299 | ||
| 297 | VMAIter begin_vma = StripIterConstness(FindVMA(target)); | 300 | VMAIter begin_vma = StripIterConstness(FindVMA(target)); |
| @@ -382,6 +385,85 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) { | |||
| 382 | } | 385 | } |
| 383 | } | 386 | } |
| 384 | 387 | ||
| 388 | void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType type) { | ||
| 389 | u64 map_region_size = 0; | ||
| 390 | u64 heap_region_size = 0; | ||
| 391 | u64 new_map_region_size = 0; | ||
| 392 | u64 tls_io_region_size = 0; | ||
| 393 | |||
| 394 | switch (type) { | ||
| 395 | case FileSys::ProgramAddressSpaceType::Is32Bit: | ||
| 396 | address_space_width = 32; | ||
| 397 | code_region_base = 0x200000; | ||
| 398 | code_region_end = code_region_base + 0x3FE00000; | ||
| 399 | map_region_size = 0x40000000; | ||
| 400 | heap_region_size = 0x40000000; | ||
| 401 | break; | ||
| 402 | case FileSys::ProgramAddressSpaceType::Is36Bit: | ||
| 403 | address_space_width = 36; | ||
| 404 | code_region_base = 0x8000000; | ||
| 405 | code_region_end = code_region_base + 0x78000000; | ||
| 406 | map_region_size = 0x180000000; | ||
| 407 | heap_region_size = 0x180000000; | ||
| 408 | break; | ||
| 409 | case FileSys::ProgramAddressSpaceType::Is32BitNoMap: | ||
| 410 | address_space_width = 32; | ||
| 411 | code_region_base = 0x200000; | ||
| 412 | code_region_end = code_region_base + 0x3FE00000; | ||
| 413 | map_region_size = 0; | ||
| 414 | heap_region_size = 0x80000000; | ||
| 415 | break; | ||
| 416 | case FileSys::ProgramAddressSpaceType::Is39Bit: | ||
| 417 | address_space_width = 39; | ||
| 418 | code_region_base = 0x8000000; | ||
| 419 | code_region_end = code_region_base + 0x80000000; | ||
| 420 | map_region_size = 0x1000000000; | ||
| 421 | heap_region_size = 0x180000000; | ||
| 422 | new_map_region_size = 0x80000000; | ||
| 423 | tls_io_region_size = 0x1000000000; | ||
| 424 | break; | ||
| 425 | default: | ||
| 426 | UNREACHABLE_MSG("Invalid address space type specified: {}", static_cast<u32>(type)); | ||
| 427 | return; | ||
| 428 | } | ||
| 429 | |||
| 430 | address_space_base = 0; | ||
| 431 | address_space_end = 1ULL << address_space_width; | ||
| 432 | |||
| 433 | map_region_base = code_region_end; | ||
| 434 | map_region_end = map_region_base + map_region_size; | ||
| 435 | |||
| 436 | heap_region_base = map_region_end; | ||
| 437 | heap_region_end = heap_region_base + heap_region_size; | ||
| 438 | |||
| 439 | new_map_region_base = heap_region_end; | ||
| 440 | new_map_region_end = new_map_region_base + new_map_region_size; | ||
| 441 | |||
| 442 | tls_io_region_base = new_map_region_end; | ||
| 443 | tls_io_region_end = tls_io_region_base + tls_io_region_size; | ||
| 444 | |||
| 445 | if (new_map_region_size == 0) { | ||
| 446 | new_map_region_base = address_space_base; | ||
| 447 | new_map_region_end = address_space_end; | ||
| 448 | } | ||
| 449 | } | ||
| 450 | |||
| 451 | void VMManager::Clear() { | ||
| 452 | ClearVMAMap(); | ||
| 453 | ClearPageTable(); | ||
| 454 | } | ||
| 455 | |||
| 456 | void VMManager::ClearVMAMap() { | ||
| 457 | vma_map.clear(); | ||
| 458 | } | ||
| 459 | |||
| 460 | void VMManager::ClearPageTable() { | ||
| 461 | std::fill(page_table.pointers.begin(), page_table.pointers.end(), nullptr); | ||
| 462 | page_table.special_regions.clear(); | ||
| 463 | std::fill(page_table.attributes.begin(), page_table.attributes.end(), | ||
| 464 | Memory::PageType::Unmapped); | ||
| 465 | } | ||
| 466 | |||
| 385 | u64 VMManager::GetTotalMemoryUsage() const { | 467 | u64 VMManager::GetTotalMemoryUsage() const { |
| 386 | LOG_WARNING(Kernel, "(STUBBED) called"); | 468 | LOG_WARNING(Kernel, "(STUBBED) called"); |
| 387 | return 0xF8000000; | 469 | return 0xF8000000; |
| @@ -392,14 +474,80 @@ u64 VMManager::GetTotalHeapUsage() const { | |||
| 392 | return 0x0; | 474 | return 0x0; |
| 393 | } | 475 | } |
| 394 | 476 | ||
| 395 | VAddr VMManager::GetAddressSpaceBaseAddr() const { | 477 | VAddr VMManager::GetAddressSpaceBaseAddress() const { |
| 396 | LOG_WARNING(Kernel, "(STUBBED) called"); | 478 | return address_space_base; |
| 397 | return 0x8000000; | 479 | } |
| 480 | |||
| 481 | VAddr VMManager::GetAddressSpaceEndAddress() const { | ||
| 482 | return address_space_end; | ||
| 398 | } | 483 | } |
| 399 | 484 | ||
| 400 | u64 VMManager::GetAddressSpaceSize() const { | 485 | u64 VMManager::GetAddressSpaceSize() const { |
| 401 | LOG_WARNING(Kernel, "(STUBBED) called"); | 486 | return address_space_end - address_space_base; |
| 402 | return MAX_ADDRESS; | 487 | } |
| 488 | |||
| 489 | u64 VMManager::GetAddressSpaceWidth() const { | ||
| 490 | return address_space_width; | ||
| 491 | } | ||
| 492 | |||
| 493 | VAddr VMManager::GetCodeRegionBaseAddress() const { | ||
| 494 | return code_region_base; | ||
| 495 | } | ||
| 496 | |||
| 497 | VAddr VMManager::GetCodeRegionEndAddress() const { | ||
| 498 | return code_region_end; | ||
| 499 | } | ||
| 500 | |||
| 501 | u64 VMManager::GetCodeRegionSize() const { | ||
| 502 | return code_region_end - code_region_base; | ||
| 503 | } | ||
| 504 | |||
| 505 | VAddr VMManager::GetHeapRegionBaseAddress() const { | ||
| 506 | return heap_region_base; | ||
| 507 | } | ||
| 508 | |||
| 509 | VAddr VMManager::GetHeapRegionEndAddress() const { | ||
| 510 | return heap_region_end; | ||
| 511 | } | ||
| 512 | |||
| 513 | u64 VMManager::GetHeapRegionSize() const { | ||
| 514 | return heap_region_end - heap_region_base; | ||
| 515 | } | ||
| 516 | |||
| 517 | VAddr VMManager::GetMapRegionBaseAddress() const { | ||
| 518 | return map_region_base; | ||
| 519 | } | ||
| 520 | |||
| 521 | VAddr VMManager::GetMapRegionEndAddress() const { | ||
| 522 | return map_region_end; | ||
| 523 | } | ||
| 524 | |||
| 525 | u64 VMManager::GetMapRegionSize() const { | ||
| 526 | return map_region_end - map_region_base; | ||
| 527 | } | ||
| 528 | |||
| 529 | VAddr VMManager::GetNewMapRegionBaseAddress() const { | ||
| 530 | return new_map_region_base; | ||
| 531 | } | ||
| 532 | |||
| 533 | VAddr VMManager::GetNewMapRegionEndAddress() const { | ||
| 534 | return new_map_region_end; | ||
| 535 | } | ||
| 536 | |||
| 537 | u64 VMManager::GetNewMapRegionSize() const { | ||
| 538 | return new_map_region_end - new_map_region_base; | ||
| 539 | } | ||
| 540 | |||
| 541 | VAddr VMManager::GetTLSIORegionBaseAddress() const { | ||
| 542 | return tls_io_region_base; | ||
| 543 | } | ||
| 544 | |||
| 545 | VAddr VMManager::GetTLSIORegionEndAddress() const { | ||
| 546 | return tls_io_region_end; | ||
| 547 | } | ||
| 548 | |||
| 549 | u64 VMManager::GetTLSIORegionSize() const { | ||
| 550 | return tls_io_region_end - tls_io_region_base; | ||
| 403 | } | 551 | } |
| 404 | 552 | ||
| 405 | } // namespace Kernel | 553 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index de75036c0..015559a64 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h | |||
| @@ -12,6 +12,10 @@ | |||
| 12 | #include "core/memory.h" | 12 | #include "core/memory.h" |
| 13 | #include "core/memory_hook.h" | 13 | #include "core/memory_hook.h" |
| 14 | 14 | ||
| 15 | namespace FileSys { | ||
| 16 | enum class ProgramAddressSpaceType : u8; | ||
| 17 | } | ||
| 18 | |||
| 15 | namespace Kernel { | 19 | namespace Kernel { |
| 16 | 20 | ||
| 17 | enum class VMAType : u8 { | 21 | enum class VMAType : u8 { |
| @@ -111,12 +115,6 @@ struct VirtualMemoryArea { | |||
| 111 | class VMManager final { | 115 | class VMManager final { |
| 112 | public: | 116 | public: |
| 113 | /** | 117 | /** |
| 114 | * The maximum amount of address space managed by the kernel. | ||
| 115 | * @todo This was selected arbitrarily, and should be verified for Switch OS. | ||
| 116 | */ | ||
| 117 | static constexpr VAddr MAX_ADDRESS{0x1000000000ULL}; | ||
| 118 | |||
| 119 | /** | ||
| 120 | * A map covering the entirety of the managed address space, keyed by the `base` field of each | 118 | * A map covering the entirety of the managed address space, keyed by the `base` field of each |
| 121 | * VMA. It must always be modified by splitting or merging VMAs, so that the invariant | 119 | * VMA. It must always be modified by splitting or merging VMAs, so that the invariant |
| 122 | * `elem.base + elem.size == next.base` is preserved, and mergeable regions must always be | 120 | * `elem.base + elem.size == next.base` is preserved, and mergeable regions must always be |
| @@ -130,7 +128,7 @@ public: | |||
| 130 | ~VMManager(); | 128 | ~VMManager(); |
| 131 | 129 | ||
| 132 | /// Clears the address space map, re-initializing with a single free area. | 130 | /// Clears the address space map, re-initializing with a single free area. |
| 133 | void Reset(); | 131 | void Reset(FileSys::ProgramAddressSpaceType type); |
| 134 | 132 | ||
| 135 | /// Finds the VMA in which the given address is included in, or `vma_map.end()`. | 133 | /// Finds the VMA in which the given address is included in, or `vma_map.end()`. |
| 136 | VMAHandle FindVMA(VAddr target) const; | 134 | VMAHandle FindVMA(VAddr target) const; |
| @@ -195,12 +193,63 @@ public: | |||
| 195 | /// Gets the total heap usage, used by svcGetInfo | 193 | /// Gets the total heap usage, used by svcGetInfo |
| 196 | u64 GetTotalHeapUsage() const; | 194 | u64 GetTotalHeapUsage() const; |
| 197 | 195 | ||
| 198 | /// Gets the total address space base address, used by svcGetInfo | 196 | /// Gets the address space base address |
| 199 | VAddr GetAddressSpaceBaseAddr() const; | 197 | VAddr GetAddressSpaceBaseAddress() const; |
| 200 | 198 | ||
| 201 | /// Gets the total address space address size, used by svcGetInfo | 199 | /// Gets the address space end address |
| 200 | VAddr GetAddressSpaceEndAddress() const; | ||
| 201 | |||
| 202 | /// Gets the total address space address size in bytes | ||
| 202 | u64 GetAddressSpaceSize() const; | 203 | u64 GetAddressSpaceSize() const; |
| 203 | 204 | ||
| 205 | /// Gets the address space width in bits. | ||
| 206 | u64 GetAddressSpaceWidth() const; | ||
| 207 | |||
| 208 | /// Gets the base address of the code region. | ||
| 209 | VAddr GetCodeRegionBaseAddress() const; | ||
| 210 | |||
| 211 | /// Gets the end address of the code region. | ||
| 212 | VAddr GetCodeRegionEndAddress() const; | ||
| 213 | |||
| 214 | /// Gets the total size of the code region in bytes. | ||
| 215 | u64 GetCodeRegionSize() const; | ||
| 216 | |||
| 217 | /// Gets the base address of the heap region. | ||
| 218 | VAddr GetHeapRegionBaseAddress() const; | ||
| 219 | |||
| 220 | /// Gets the end address of the heap region; | ||
| 221 | VAddr GetHeapRegionEndAddress() const; | ||
| 222 | |||
| 223 | /// Gets the total size of the heap region in bytes. | ||
| 224 | u64 GetHeapRegionSize() const; | ||
| 225 | |||
| 226 | /// Gets the base address of the map region. | ||
| 227 | VAddr GetMapRegionBaseAddress() const; | ||
| 228 | |||
| 229 | /// Gets the end address of the map region. | ||
| 230 | VAddr GetMapRegionEndAddress() const; | ||
| 231 | |||
| 232 | /// Gets the total size of the map region in bytes. | ||
| 233 | u64 GetMapRegionSize() const; | ||
| 234 | |||
| 235 | /// Gets the base address of the new map region. | ||
| 236 | VAddr GetNewMapRegionBaseAddress() const; | ||
| 237 | |||
| 238 | /// Gets the end address of the new map region. | ||
| 239 | VAddr GetNewMapRegionEndAddress() const; | ||
| 240 | |||
| 241 | /// Gets the total size of the new map region in bytes. | ||
| 242 | u64 GetNewMapRegionSize() const; | ||
| 243 | |||
| 244 | /// Gets the base address of the TLS IO region. | ||
| 245 | VAddr GetTLSIORegionBaseAddress() const; | ||
| 246 | |||
| 247 | /// Gets the end address of the TLS IO region. | ||
| 248 | VAddr GetTLSIORegionEndAddress() const; | ||
| 249 | |||
| 250 | /// Gets the total size of the TLS IO region in bytes. | ||
| 251 | u64 GetTLSIORegionSize() const; | ||
| 252 | |||
| 204 | /// Each VMManager has its own page table, which is set as the main one when the owning process | 253 | /// Each VMManager has its own page table, which is set as the main one when the owning process |
| 205 | /// is scheduled. | 254 | /// is scheduled. |
| 206 | Memory::PageTable page_table; | 255 | Memory::PageTable page_table; |
| @@ -240,5 +289,36 @@ private: | |||
| 240 | 289 | ||
| 241 | /// Updates the pages corresponding to this VMA so they match the VMA's attributes. | 290 | /// Updates the pages corresponding to this VMA so they match the VMA's attributes. |
| 242 | void UpdatePageTableForVMA(const VirtualMemoryArea& vma); | 291 | void UpdatePageTableForVMA(const VirtualMemoryArea& vma); |
| 292 | |||
| 293 | /// Initializes memory region ranges to adhere to a given address space type. | ||
| 294 | void InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType type); | ||
| 295 | |||
| 296 | /// Clears the underlying map and page table. | ||
| 297 | void Clear(); | ||
| 298 | |||
| 299 | /// Clears out the VMA map, unmapping any previously mapped ranges. | ||
| 300 | void ClearVMAMap(); | ||
| 301 | |||
| 302 | /// Clears out the page table | ||
| 303 | void ClearPageTable(); | ||
| 304 | |||
| 305 | u32 address_space_width = 0; | ||
| 306 | VAddr address_space_base = 0; | ||
| 307 | VAddr address_space_end = 0; | ||
| 308 | |||
| 309 | VAddr code_region_base = 0; | ||
| 310 | VAddr code_region_end = 0; | ||
| 311 | |||
| 312 | VAddr heap_region_base = 0; | ||
| 313 | VAddr heap_region_end = 0; | ||
| 314 | |||
| 315 | VAddr map_region_base = 0; | ||
| 316 | VAddr map_region_end = 0; | ||
| 317 | |||
| 318 | VAddr new_map_region_base = 0; | ||
| 319 | VAddr new_map_region_end = 0; | ||
| 320 | |||
| 321 | VAddr tls_io_region_base = 0; | ||
| 322 | VAddr tls_io_region_end = 0; | ||
| 243 | }; | 323 | }; |
| 244 | } // namespace Kernel | 324 | } // namespace Kernel |