diff options
| author | 2022-10-02 14:26:30 -0700 | |
|---|---|---|
| committer | 2022-10-18 19:13:35 -0700 | |
| commit | abcc009dff5d98b5a04229f3a82baab23d568244 (patch) | |
| tree | e51f99cf493425a3cd331ffdaa1b984554e429aa | |
| parent | core: hle: kernel: k_interrupt_manager: HandleInterrupt should not depend on ... (diff) | |
| download | yuzu-abcc009dff5d98b5a04229f3a82baab23d568244.tar.gz yuzu-abcc009dff5d98b5a04229f3a82baab23d568244.tar.xz yuzu-abcc009dff5d98b5a04229f3a82baab23d568244.zip | |
core: hle: kernel: k_process: Improve management of page table & cleanup.
| -rw-r--r-- | src/core/hle/kernel/k_page_table.cpp | 23 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table.h | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.cpp | 62 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.h | 31 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 23 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 2 |
7 files changed, 92 insertions, 60 deletions
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index fcffc0b88..22098c056 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -256,16 +256,21 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type | |||
| 256 | m_mapped_physical_memory_size = 0; | 256 | m_mapped_physical_memory_size = 0; |
| 257 | m_memory_pool = pool; | 257 | m_memory_pool = pool; |
| 258 | 258 | ||
| 259 | m_page_table_impl.Resize(m_address_space_width, PageBits); | 259 | m_page_table_impl = std::make_unique<Common::PageTable>(); |
| 260 | m_page_table_impl->Resize(m_address_space_width, PageBits); | ||
| 260 | 261 | ||
| 261 | return m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, | 262 | return m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, |
| 262 | m_memory_block_slab_manager); | 263 | m_memory_block_slab_manager); |
| 263 | } | 264 | } |
| 264 | 265 | ||
| 265 | void KPageTable::Finalize() { | 266 | void KPageTable::Finalize() { |
| 267 | // Finalize memory blocks. | ||
| 266 | m_memory_block_manager.Finalize(m_memory_block_slab_manager, [&](VAddr addr, u64 size) { | 268 | m_memory_block_manager.Finalize(m_memory_block_slab_manager, [&](VAddr addr, u64 size) { |
| 267 | m_system.Memory().UnmapRegion(m_page_table_impl, addr, size); | 269 | m_system.Memory().UnmapRegion(*m_page_table_impl, addr, size); |
| 268 | }); | 270 | }); |
| 271 | |||
| 272 | // Close the backing page table, as the destructor is not called for guest objects. | ||
| 273 | m_page_table_impl.reset(); | ||
| 269 | } | 274 | } |
| 270 | 275 | ||
| 271 | Result KPageTable::MapProcessCode(VAddr addr, size_t num_pages, KMemoryState state, | 276 | Result KPageTable::MapProcessCode(VAddr addr, size_t num_pages, KMemoryState state, |
| @@ -514,7 +519,7 @@ Result KPageTable::MakePageGroup(KPageGroup& pg, VAddr addr, size_t num_pages) { | |||
| 514 | // Begin traversal. | 519 | // Begin traversal. |
| 515 | Common::PageTable::TraversalContext context; | 520 | Common::PageTable::TraversalContext context; |
| 516 | Common::PageTable::TraversalEntry next_entry; | 521 | Common::PageTable::TraversalEntry next_entry; |
| 517 | R_UNLESS(m_page_table_impl.BeginTraversal(next_entry, context, addr), | 522 | R_UNLESS(m_page_table_impl->BeginTraversal(next_entry, context, addr), |
| 518 | ResultInvalidCurrentMemory); | 523 | ResultInvalidCurrentMemory); |
| 519 | 524 | ||
| 520 | // Prepare tracking variables. | 525 | // Prepare tracking variables. |
| @@ -525,7 +530,7 @@ Result KPageTable::MakePageGroup(KPageGroup& pg, VAddr addr, size_t num_pages) { | |||
| 525 | // Iterate, adding to group as we go. | 530 | // Iterate, adding to group as we go. |
| 526 | const auto& memory_layout = m_system.Kernel().MemoryLayout(); | 531 | const auto& memory_layout = m_system.Kernel().MemoryLayout(); |
| 527 | while (tot_size < size) { | 532 | while (tot_size < size) { |
| 528 | R_UNLESS(m_page_table_impl.ContinueTraversal(next_entry, context), | 533 | R_UNLESS(m_page_table_impl->ContinueTraversal(next_entry, context), |
| 529 | ResultInvalidCurrentMemory); | 534 | ResultInvalidCurrentMemory); |
| 530 | 535 | ||
| 531 | if (next_entry.phys_addr != (cur_addr + cur_size)) { | 536 | if (next_entry.phys_addr != (cur_addr + cur_size)) { |
| @@ -588,7 +593,7 @@ bool KPageTable::IsValidPageGroup(const KPageGroup& pg_ll, VAddr addr, size_t nu | |||
| 588 | // Begin traversal. | 593 | // Begin traversal. |
| 589 | Common::PageTable::TraversalContext context; | 594 | Common::PageTable::TraversalContext context; |
| 590 | Common::PageTable::TraversalEntry next_entry; | 595 | Common::PageTable::TraversalEntry next_entry; |
| 591 | if (!m_page_table_impl.BeginTraversal(next_entry, context, addr)) { | 596 | if (!m_page_table_impl->BeginTraversal(next_entry, context, addr)) { |
| 592 | return false; | 597 | return false; |
| 593 | } | 598 | } |
| 594 | 599 | ||
| @@ -599,7 +604,7 @@ bool KPageTable::IsValidPageGroup(const KPageGroup& pg_ll, VAddr addr, size_t nu | |||
| 599 | 604 | ||
| 600 | // Iterate, comparing expected to actual. | 605 | // Iterate, comparing expected to actual. |
| 601 | while (tot_size < size) { | 606 | while (tot_size < size) { |
| 602 | if (!m_page_table_impl.ContinueTraversal(next_entry, context)) { | 607 | if (!m_page_table_impl->ContinueTraversal(next_entry, context)) { |
| 603 | return false; | 608 | return false; |
| 604 | } | 609 | } |
| 605 | 610 | ||
| @@ -2042,7 +2047,7 @@ Result KPageTable::Operate(VAddr addr, size_t num_pages, const KPageGroup& page_ | |||
| 2042 | 2047 | ||
| 2043 | switch (operation) { | 2048 | switch (operation) { |
| 2044 | case OperationType::MapGroup: | 2049 | case OperationType::MapGroup: |
| 2045 | m_system.Memory().MapMemoryRegion(m_page_table_impl, addr, size, node.GetAddress()); | 2050 | m_system.Memory().MapMemoryRegion(*m_page_table_impl, addr, size, node.GetAddress()); |
| 2046 | break; | 2051 | break; |
| 2047 | default: | 2052 | default: |
| 2048 | ASSERT(false); | 2053 | ASSERT(false); |
| @@ -2064,12 +2069,12 @@ Result KPageTable::Operate(VAddr addr, size_t num_pages, KMemoryPermission perm, | |||
| 2064 | 2069 | ||
| 2065 | switch (operation) { | 2070 | switch (operation) { |
| 2066 | case OperationType::Unmap: | 2071 | case OperationType::Unmap: |
| 2067 | m_system.Memory().UnmapRegion(m_page_table_impl, addr, num_pages * PageSize); | 2072 | m_system.Memory().UnmapRegion(*m_page_table_impl, addr, num_pages * PageSize); |
| 2068 | break; | 2073 | break; |
| 2069 | case OperationType::Map: { | 2074 | case OperationType::Map: { |
| 2070 | ASSERT(map_addr); | 2075 | ASSERT(map_addr); |
| 2071 | ASSERT(Common::IsAligned(map_addr, PageSize)); | 2076 | ASSERT(Common::IsAligned(map_addr, PageSize)); |
| 2072 | m_system.Memory().MapMemoryRegion(m_page_table_impl, addr, num_pages * PageSize, map_addr); | 2077 | m_system.Memory().MapMemoryRegion(*m_page_table_impl, addr, num_pages * PageSize, map_addr); |
| 2073 | break; | 2078 | break; |
| 2074 | } | 2079 | } |
| 2075 | case OperationType::ChangePermissions: | 2080 | case OperationType::ChangePermissions: |
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index 225854319..1811d3e2d 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h | |||
| @@ -88,11 +88,11 @@ public: | |||
| 88 | KMemoryAttribute attr_mask, KMemoryAttribute attr); | 88 | KMemoryAttribute attr_mask, KMemoryAttribute attr); |
| 89 | 89 | ||
| 90 | Common::PageTable& PageTableImpl() { | 90 | Common::PageTable& PageTableImpl() { |
| 91 | return m_page_table_impl; | 91 | return *m_page_table_impl; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | const Common::PageTable& PageTableImpl() const { | 94 | const Common::PageTable& PageTableImpl() const { |
| 95 | return m_page_table_impl; | 95 | return *m_page_table_impl; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | bool CanContain(VAddr addr, size_t size, KMemoryState state) const; | 98 | bool CanContain(VAddr addr, size_t size, KMemoryState state) const; |
| @@ -303,7 +303,7 @@ public: | |||
| 303 | return IsKernel() ? 1 : 4; | 303 | return IsKernel() ? 1 : 4; |
| 304 | } | 304 | } |
| 305 | PAddr GetPhysicalAddr(VAddr addr) const { | 305 | PAddr GetPhysicalAddr(VAddr addr) const { |
| 306 | const auto backing_addr = m_page_table_impl.backing_addr[addr >> PageBits]; | 306 | const auto backing_addr = m_page_table_impl->backing_addr[addr >> PageBits]; |
| 307 | ASSERT(backing_addr); | 307 | ASSERT(backing_addr); |
| 308 | return backing_addr + addr; | 308 | return backing_addr + addr; |
| 309 | } | 309 | } |
| @@ -365,7 +365,7 @@ private: | |||
| 365 | KMemoryManager::Pool m_memory_pool{KMemoryManager::Pool::Application}; | 365 | KMemoryManager::Pool m_memory_pool{KMemoryManager::Pool::Application}; |
| 366 | KMemoryManager::Direction m_allocation_option{KMemoryManager::Direction::FromFront}; | 366 | KMemoryManager::Direction m_allocation_option{KMemoryManager::Direction::FromFront}; |
| 367 | 367 | ||
| 368 | Common::PageTable m_page_table_impl; | 368 | std::unique_ptr<Common::PageTable> m_page_table_impl; |
| 369 | 369 | ||
| 370 | Core::System& m_system; | 370 | Core::System& m_system; |
| 371 | }; | 371 | }; |
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index abc2115bd..1a0aec56a 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -72,6 +72,7 @@ Result KProcess::Initialize(KProcess* process, Core::System& system, std::string | |||
| 72 | 72 | ||
| 73 | process->name = std::move(process_name); | 73 | process->name = std::move(process_name); |
| 74 | process->resource_limit = res_limit; | 74 | process->resource_limit = res_limit; |
| 75 | process->system_resource_address = 0; | ||
| 75 | process->state = State::Created; | 76 | process->state = State::Created; |
| 76 | process->program_id = 0; | 77 | process->program_id = 0; |
| 77 | process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() | 78 | process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() |
| @@ -92,6 +93,7 @@ Result KProcess::Initialize(KProcess* process, Core::System& system, std::string | |||
| 92 | process->exception_thread = nullptr; | 93 | process->exception_thread = nullptr; |
| 93 | process->is_suspended = false; | 94 | process->is_suspended = false; |
| 94 | process->schedule_count = 0; | 95 | process->schedule_count = 0; |
| 96 | process->is_handle_table_initialized = false; | ||
| 95 | 97 | ||
| 96 | // Open a reference to the resource limit. | 98 | // Open a reference to the resource limit. |
| 97 | process->resource_limit->Open(); | 99 | process->resource_limit->Open(); |
| @@ -121,9 +123,9 @@ void KProcess::DecrementRunningThreadCount() { | |||
| 121 | } | 123 | } |
| 122 | } | 124 | } |
| 123 | 125 | ||
| 124 | u64 KProcess::GetTotalPhysicalMemoryAvailable() const { | 126 | u64 KProcess::GetTotalPhysicalMemoryAvailable() { |
| 125 | const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + | 127 | const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + |
| 126 | page_table->GetNormalMemorySize() + GetSystemResourceSize() + image_size + | 128 | page_table.GetNormalMemorySize() + GetSystemResourceSize() + image_size + |
| 127 | main_thread_stack_size}; | 129 | main_thread_stack_size}; |
| 128 | if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application); | 130 | if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application); |
| 129 | capacity != pool_size) { | 131 | capacity != pool_size) { |
| @@ -135,16 +137,16 @@ u64 KProcess::GetTotalPhysicalMemoryAvailable() const { | |||
| 135 | return memory_usage_capacity; | 137 | return memory_usage_capacity; |
| 136 | } | 138 | } |
| 137 | 139 | ||
| 138 | u64 KProcess::GetTotalPhysicalMemoryAvailableWithoutSystemResource() const { | 140 | u64 KProcess::GetTotalPhysicalMemoryAvailableWithoutSystemResource() { |
| 139 | return GetTotalPhysicalMemoryAvailable() - GetSystemResourceSize(); | 141 | return GetTotalPhysicalMemoryAvailable() - GetSystemResourceSize(); |
| 140 | } | 142 | } |
| 141 | 143 | ||
| 142 | u64 KProcess::GetTotalPhysicalMemoryUsed() const { | 144 | u64 KProcess::GetTotalPhysicalMemoryUsed() { |
| 143 | return image_size + main_thread_stack_size + page_table->GetNormalMemorySize() + | 145 | return image_size + main_thread_stack_size + page_table.GetNormalMemorySize() + |
| 144 | GetSystemResourceSize(); | 146 | GetSystemResourceSize(); |
| 145 | } | 147 | } |
| 146 | 148 | ||
| 147 | u64 KProcess::GetTotalPhysicalMemoryUsedWithoutSystemResource() const { | 149 | u64 KProcess::GetTotalPhysicalMemoryUsedWithoutSystemResource() { |
| 148 | return GetTotalPhysicalMemoryUsed() - GetSystemResourceUsage(); | 150 | return GetTotalPhysicalMemoryUsed() - GetSystemResourceUsage(); |
| 149 | } | 151 | } |
| 150 | 152 | ||
| @@ -348,6 +350,9 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: | |||
| 348 | system_resource_size = metadata.GetSystemResourceSize(); | 350 | system_resource_size = metadata.GetSystemResourceSize(); |
| 349 | image_size = code_size; | 351 | image_size = code_size; |
| 350 | 352 | ||
| 353 | // We currently do not support process-specific system resource | ||
| 354 | UNIMPLEMENTED_IF(system_resource_size != 0); | ||
| 355 | |||
| 351 | KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, | 356 | KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, |
| 352 | code_size + system_resource_size); | 357 | code_size + system_resource_size); |
| 353 | if (!memory_reservation.Succeeded()) { | 358 | if (!memory_reservation.Succeeded()) { |
| @@ -356,7 +361,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: | |||
| 356 | return ResultLimitReached; | 361 | return ResultLimitReached; |
| 357 | } | 362 | } |
| 358 | // Initialize proces address space | 363 | // Initialize proces address space |
| 359 | if (const Result result{page_table->InitializeForProcess( | 364 | if (const Result result{page_table.InitializeForProcess( |
| 360 | metadata.GetAddressSpaceType(), false, 0x8000000, code_size, | 365 | metadata.GetAddressSpaceType(), false, 0x8000000, code_size, |
| 361 | &kernel.GetApplicationMemoryBlockManager(), KMemoryManager::Pool::Application)}; | 366 | &kernel.GetApplicationMemoryBlockManager(), KMemoryManager::Pool::Application)}; |
| 362 | result.IsError()) { | 367 | result.IsError()) { |
| @@ -364,9 +369,9 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: | |||
| 364 | } | 369 | } |
| 365 | 370 | ||
| 366 | // Map process code region | 371 | // Map process code region |
| 367 | if (const Result result{page_table->MapProcessCode(page_table->GetCodeRegionStart(), | 372 | if (const Result result{page_table.MapProcessCode(page_table.GetCodeRegionStart(), |
| 368 | code_size / PageSize, KMemoryState::Code, | 373 | code_size / PageSize, KMemoryState::Code, |
| 369 | KMemoryPermission::None)}; | 374 | KMemoryPermission::None)}; |
| 370 | result.IsError()) { | 375 | result.IsError()) { |
| 371 | return result; | 376 | return result; |
| 372 | } | 377 | } |
| @@ -374,7 +379,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: | |||
| 374 | // Initialize process capabilities | 379 | // Initialize process capabilities |
| 375 | const auto& caps{metadata.GetKernelCapabilities()}; | 380 | const auto& caps{metadata.GetKernelCapabilities()}; |
| 376 | if (const Result result{ | 381 | if (const Result result{ |
| 377 | capabilities.InitializeForUserProcess(caps.data(), caps.size(), *page_table)}; | 382 | capabilities.InitializeForUserProcess(caps.data(), caps.size(), page_table)}; |
| 378 | result.IsError()) { | 383 | result.IsError()) { |
| 379 | return result; | 384 | return result; |
| 380 | } | 385 | } |
| @@ -384,12 +389,12 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: | |||
| 384 | case FileSys::ProgramAddressSpaceType::Is32Bit: | 389 | case FileSys::ProgramAddressSpaceType::Is32Bit: |
| 385 | case FileSys::ProgramAddressSpaceType::Is36Bit: | 390 | case FileSys::ProgramAddressSpaceType::Is36Bit: |
| 386 | case FileSys::ProgramAddressSpaceType::Is39Bit: | 391 | case FileSys::ProgramAddressSpaceType::Is39Bit: |
| 387 | memory_usage_capacity = page_table->GetHeapRegionEnd() - page_table->GetHeapRegionStart(); | 392 | memory_usage_capacity = page_table.GetHeapRegionEnd() - page_table.GetHeapRegionStart(); |
| 388 | break; | 393 | break; |
| 389 | 394 | ||
| 390 | case FileSys::ProgramAddressSpaceType::Is32BitNoMap: | 395 | case FileSys::ProgramAddressSpaceType::Is32BitNoMap: |
| 391 | memory_usage_capacity = page_table->GetHeapRegionEnd() - page_table->GetHeapRegionStart() + | 396 | memory_usage_capacity = page_table.GetHeapRegionEnd() - page_table.GetHeapRegionStart() + |
| 392 | page_table->GetAliasRegionEnd() - page_table->GetAliasRegionStart(); | 397 | page_table.GetAliasRegionEnd() - page_table.GetAliasRegionStart(); |
| 393 | break; | 398 | break; |
| 394 | 399 | ||
| 395 | default: | 400 | default: |
| @@ -397,7 +402,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: | |||
| 397 | } | 402 | } |
| 398 | 403 | ||
| 399 | // Create TLS region | 404 | // Create TLS region |
| 400 | R_TRY(this->CreateThreadLocalRegion(std::addressof(tls_region_address))); | 405 | R_TRY(this->CreateThreadLocalRegion(std::addressof(plr_address))); |
| 401 | memory_reservation.Commit(); | 406 | memory_reservation.Commit(); |
| 402 | 407 | ||
| 403 | return handle_table.Initialize(capabilities.GetHandleTableSize()); | 408 | return handle_table.Initialize(capabilities.GetHandleTableSize()); |
| @@ -409,7 +414,7 @@ void KProcess::Run(s32 main_thread_priority, u64 stack_size) { | |||
| 409 | resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size); | 414 | resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size); |
| 410 | 415 | ||
| 411 | const std::size_t heap_capacity{memory_usage_capacity - (main_thread_stack_size + image_size)}; | 416 | const std::size_t heap_capacity{memory_usage_capacity - (main_thread_stack_size + image_size)}; |
| 412 | ASSERT(!page_table->SetMaxHeapSize(heap_capacity).IsError()); | 417 | ASSERT(!page_table.SetMaxHeapSize(heap_capacity).IsError()); |
| 413 | 418 | ||
| 414 | ChangeState(State::Running); | 419 | ChangeState(State::Running); |
| 415 | 420 | ||
| @@ -437,8 +442,8 @@ void KProcess::PrepareForTermination() { | |||
| 437 | 442 | ||
| 438 | stop_threads(kernel.System().GlobalSchedulerContext().GetThreadList()); | 443 | stop_threads(kernel.System().GlobalSchedulerContext().GetThreadList()); |
| 439 | 444 | ||
| 440 | this->DeleteThreadLocalRegion(tls_region_address); | 445 | this->DeleteThreadLocalRegion(plr_address); |
| 441 | tls_region_address = 0; | 446 | plr_address = 0; |
| 442 | 447 | ||
| 443 | if (resource_limit) { | 448 | if (resource_limit) { |
| 444 | resource_limit->Release(LimitableResource::PhysicalMemory, | 449 | resource_limit->Release(LimitableResource::PhysicalMemory, |
| @@ -474,7 +479,7 @@ void KProcess::Finalize() { | |||
| 474 | } | 479 | } |
| 475 | 480 | ||
| 476 | // Finalize the page table. | 481 | // Finalize the page table. |
| 477 | page_table.reset(); | 482 | page_table.Finalize(); |
| 478 | 483 | ||
| 479 | // Perform inherited finalization. | 484 | // Perform inherited finalization. |
| 480 | KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask>::Finalize(); | 485 | KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask>::Finalize(); |
| @@ -628,7 +633,7 @@ bool KProcess::RemoveWatchpoint(Core::System& system, VAddr addr, u64 size, | |||
| 628 | void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) { | 633 | void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) { |
| 629 | const auto ReprotectSegment = [&](const CodeSet::Segment& segment, | 634 | const auto ReprotectSegment = [&](const CodeSet::Segment& segment, |
| 630 | Svc::MemoryPermission permission) { | 635 | Svc::MemoryPermission permission) { |
| 631 | page_table->SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission); | 636 | page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission); |
| 632 | }; | 637 | }; |
| 633 | 638 | ||
| 634 | kernel.System().Memory().WriteBlock(*this, base_addr, code_set.memory.data(), | 639 | kernel.System().Memory().WriteBlock(*this, base_addr, code_set.memory.data(), |
| @@ -645,8 +650,7 @@ bool KProcess::IsSignaled() const { | |||
| 645 | } | 650 | } |
| 646 | 651 | ||
| 647 | KProcess::KProcess(KernelCore& kernel_) | 652 | KProcess::KProcess(KernelCore& kernel_) |
| 648 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, page_table{std::make_unique<KPageTable>( | 653 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, page_table{kernel_.System()}, |
| 649 | kernel_.System())}, | ||
| 650 | handle_table{kernel_}, address_arbiter{kernel_.System()}, condition_var{kernel_.System()}, | 654 | handle_table{kernel_}, address_arbiter{kernel_.System()}, condition_var{kernel_.System()}, |
| 651 | state_lock{kernel_}, list_lock{kernel_} {} | 655 | state_lock{kernel_}, list_lock{kernel_} {} |
| 652 | 656 | ||
| @@ -668,11 +672,11 @@ Result KProcess::AllocateMainThreadStack(std::size_t stack_size) { | |||
| 668 | // The kernel always ensures that the given stack size is page aligned. | 672 | // The kernel always ensures that the given stack size is page aligned. |
| 669 | main_thread_stack_size = Common::AlignUp(stack_size, PageSize); | 673 | main_thread_stack_size = Common::AlignUp(stack_size, PageSize); |
| 670 | 674 | ||
| 671 | const VAddr start{page_table->GetStackRegionStart()}; | 675 | const VAddr start{page_table.GetStackRegionStart()}; |
| 672 | const std::size_t size{page_table->GetStackRegionEnd() - start}; | 676 | const std::size_t size{page_table.GetStackRegionEnd() - start}; |
| 673 | 677 | ||
| 674 | CASCADE_RESULT(main_thread_stack_top, | 678 | CASCADE_RESULT(main_thread_stack_top, |
| 675 | page_table->AllocateAndMapMemory( | 679 | page_table.AllocateAndMapMemory( |
| 676 | main_thread_stack_size / PageSize, PageSize, false, start, size / PageSize, | 680 | main_thread_stack_size / PageSize, PageSize, false, start, size / PageSize, |
| 677 | KMemoryState::Stack, KMemoryPermission::UserReadWrite)); | 681 | KMemoryState::Stack, KMemoryPermission::UserReadWrite)); |
| 678 | 682 | ||
| @@ -681,4 +685,12 @@ Result KProcess::AllocateMainThreadStack(std::size_t stack_size) { | |||
| 681 | return ResultSuccess; | 685 | return ResultSuccess; |
| 682 | } | 686 | } |
| 683 | 687 | ||
| 688 | void KProcess::FinalizeHandleTable() { | ||
| 689 | // Finalize the table. | ||
| 690 | handle_table.Finalize(); | ||
| 691 | |||
| 692 | // Note that the table is finalized. | ||
| 693 | is_handle_table_initialized = false; | ||
| 694 | } | ||
| 695 | |||
| 684 | } // namespace Kernel | 696 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index b1c7da454..fcc2897f9 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "core/hle/kernel/k_auto_object.h" | 13 | #include "core/hle/kernel/k_auto_object.h" |
| 14 | #include "core/hle/kernel/k_condition_variable.h" | 14 | #include "core/hle/kernel/k_condition_variable.h" |
| 15 | #include "core/hle/kernel/k_handle_table.h" | 15 | #include "core/hle/kernel/k_handle_table.h" |
| 16 | #include "core/hle/kernel/k_page_table.h" | ||
| 16 | #include "core/hle/kernel/k_synchronization_object.h" | 17 | #include "core/hle/kernel/k_synchronization_object.h" |
| 17 | #include "core/hle/kernel/k_thread_local_page.h" | 18 | #include "core/hle/kernel/k_thread_local_page.h" |
| 18 | #include "core/hle/kernel/k_worker_task.h" | 19 | #include "core/hle/kernel/k_worker_task.h" |
| @@ -31,7 +32,6 @@ class ProgramMetadata; | |||
| 31 | namespace Kernel { | 32 | namespace Kernel { |
| 32 | 33 | ||
| 33 | class KernelCore; | 34 | class KernelCore; |
| 34 | class KPageTable; | ||
| 35 | class KResourceLimit; | 35 | class KResourceLimit; |
| 36 | class KThread; | 36 | class KThread; |
| 37 | class KSharedMemoryInfo; | 37 | class KSharedMemoryInfo; |
| @@ -107,12 +107,12 @@ public: | |||
| 107 | 107 | ||
| 108 | /// Gets a reference to the process' page table. | 108 | /// Gets a reference to the process' page table. |
| 109 | KPageTable& PageTable() { | 109 | KPageTable& PageTable() { |
| 110 | return *page_table; | 110 | return page_table; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | /// Gets const a reference to the process' page table. | 113 | /// Gets const a reference to the process' page table. |
| 114 | const KPageTable& PageTable() const { | 114 | const KPageTable& PageTable() const { |
| 115 | return *page_table; | 115 | return page_table; |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | /// Gets a reference to the process' handle table. | 118 | /// Gets a reference to the process' handle table. |
| @@ -150,9 +150,8 @@ public: | |||
| 150 | return address_arbiter.WaitForAddress(address, arb_type, value, timeout); | 150 | return address_arbiter.WaitForAddress(address, arb_type, value, timeout); |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | /// Gets the address to the process' dedicated TLS region. | 153 | VAddr GetProcessLocalRegionAddress() const { |
| 154 | VAddr GetTLSRegionAddress() const { | 154 | return plr_address; |
| 155 | return tls_region_address; | ||
| 156 | } | 155 | } |
| 157 | 156 | ||
| 158 | /// Gets the current status of the process | 157 | /// Gets the current status of the process |
| @@ -279,18 +278,18 @@ public: | |||
| 279 | } | 278 | } |
| 280 | 279 | ||
| 281 | /// Retrieves the total physical memory available to this process in bytes. | 280 | /// Retrieves the total physical memory available to this process in bytes. |
| 282 | u64 GetTotalPhysicalMemoryAvailable() const; | 281 | u64 GetTotalPhysicalMemoryAvailable(); |
| 283 | 282 | ||
| 284 | /// Retrieves the total physical memory available to this process in bytes, | 283 | /// Retrieves the total physical memory available to this process in bytes, |
| 285 | /// without the size of the personal system resource heap added to it. | 284 | /// without the size of the personal system resource heap added to it. |
| 286 | u64 GetTotalPhysicalMemoryAvailableWithoutSystemResource() const; | 285 | u64 GetTotalPhysicalMemoryAvailableWithoutSystemResource(); |
| 287 | 286 | ||
| 288 | /// Retrieves the total physical memory used by this process in bytes. | 287 | /// Retrieves the total physical memory used by this process in bytes. |
| 289 | u64 GetTotalPhysicalMemoryUsed() const; | 288 | u64 GetTotalPhysicalMemoryUsed(); |
| 290 | 289 | ||
| 291 | /// Retrieves the total physical memory used by this process in bytes, | 290 | /// Retrieves the total physical memory used by this process in bytes, |
| 292 | /// without the size of the personal system resource heap added to it. | 291 | /// without the size of the personal system resource heap added to it. |
| 293 | u64 GetTotalPhysicalMemoryUsedWithoutSystemResource() const; | 292 | u64 GetTotalPhysicalMemoryUsedWithoutSystemResource(); |
| 294 | 293 | ||
| 295 | /// Gets the list of all threads created with this process as their owner. | 294 | /// Gets the list of all threads created with this process as their owner. |
| 296 | std::list<KThread*>& GetThreadList() { | 295 | std::list<KThread*>& GetThreadList() { |
| @@ -413,8 +412,10 @@ private: | |||
| 413 | /// Allocates the main thread stack for the process, given the stack size in bytes. | 412 | /// Allocates the main thread stack for the process, given the stack size in bytes. |
| 414 | Result AllocateMainThreadStack(std::size_t stack_size); | 413 | Result AllocateMainThreadStack(std::size_t stack_size); |
| 415 | 414 | ||
| 415 | void FinalizeHandleTable(); | ||
| 416 | |||
| 416 | /// Memory manager for this process | 417 | /// Memory manager for this process |
| 417 | std::unique_ptr<KPageTable> page_table; | 418 | KPageTable page_table; |
| 418 | 419 | ||
| 419 | /// Current status of the process | 420 | /// Current status of the process |
| 420 | State state{}; | 421 | State state{}; |
| @@ -433,6 +434,8 @@ private: | |||
| 433 | /// Resource limit descriptor for this process | 434 | /// Resource limit descriptor for this process |
| 434 | KResourceLimit* resource_limit{}; | 435 | KResourceLimit* resource_limit{}; |
| 435 | 436 | ||
| 437 | VAddr system_resource_address{}; | ||
| 438 | |||
| 436 | /// The ideal CPU core for this process, threads are scheduled on this core by default. | 439 | /// The ideal CPU core for this process, threads are scheduled on this core by default. |
| 437 | u8 ideal_core = 0; | 440 | u8 ideal_core = 0; |
| 438 | 441 | ||
| @@ -459,7 +462,7 @@ private: | |||
| 459 | KConditionVariable condition_var; | 462 | KConditionVariable condition_var; |
| 460 | 463 | ||
| 461 | /// Address indicating the location of the process' dedicated TLS region. | 464 | /// Address indicating the location of the process' dedicated TLS region. |
| 462 | VAddr tls_region_address = 0; | 465 | VAddr plr_address = 0; |
| 463 | 466 | ||
| 464 | /// Random values for svcGetInfo RandomEntropy | 467 | /// Random values for svcGetInfo RandomEntropy |
| 465 | std::array<u64, RANDOM_ENTROPY_SIZE> random_entropy{}; | 468 | std::array<u64, RANDOM_ENTROPY_SIZE> random_entropy{}; |
| @@ -485,8 +488,12 @@ private: | |||
| 485 | /// Schedule count of this process | 488 | /// Schedule count of this process |
| 486 | s64 schedule_count{}; | 489 | s64 schedule_count{}; |
| 487 | 490 | ||
| 491 | size_t memory_release_hint{}; | ||
| 492 | |||
| 488 | bool is_signaled{}; | 493 | bool is_signaled{}; |
| 489 | bool is_suspended{}; | 494 | bool is_suspended{}; |
| 495 | bool is_immortal{}; | ||
| 496 | bool is_handle_table_initialized{}; | ||
| 490 | bool is_initialized{}; | 497 | bool is_initialized{}; |
| 491 | 498 | ||
| 492 | std::atomic<u16> num_running_threads{}; | 499 | std::atomic<u16> num_running_threads{}; |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b6bbd4984..6879de9ef 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -95,6 +95,15 @@ struct KernelCore::Impl { | |||
| 95 | } | 95 | } |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | void CloseCurrentProcess() { | ||
| 99 | (*current_process).Finalize(); | ||
| 100 | // current_process->Close(); | ||
| 101 | // TODO: The current process should be destroyed based on accurate ref counting after | ||
| 102 | // calling Close(). Adding a manual Destroy() call instead to avoid a memory leak. | ||
| 103 | (*current_process).Destroy(); | ||
| 104 | current_process = nullptr; | ||
| 105 | } | ||
| 106 | |||
| 98 | void Shutdown() { | 107 | void Shutdown() { |
| 99 | is_shutting_down.store(true, std::memory_order_relaxed); | 108 | is_shutting_down.store(true, std::memory_order_relaxed); |
| 100 | SCOPE_EXIT({ is_shutting_down.store(false, std::memory_order_relaxed); }); | 109 | SCOPE_EXIT({ is_shutting_down.store(false, std::memory_order_relaxed); }); |
| @@ -157,15 +166,7 @@ struct KernelCore::Impl { | |||
| 157 | } | 166 | } |
| 158 | } | 167 | } |
| 159 | 168 | ||
| 160 | // Shutdown all processes. | 169 | CloseCurrentProcess(); |
| 161 | if (current_process) { | ||
| 162 | (*current_process).Finalize(); | ||
| 163 | // current_process->Close(); | ||
| 164 | // TODO: The current process should be destroyed based on accurate ref counting after | ||
| 165 | // calling Close(). Adding a manual Destroy() call instead to avoid a memory leak. | ||
| 166 | (*current_process).Destroy(); | ||
| 167 | current_process = nullptr; | ||
| 168 | } | ||
| 169 | 170 | ||
| 170 | // Track kernel objects that were not freed on shutdown | 171 | // Track kernel objects that were not freed on shutdown |
| 171 | { | 172 | { |
| @@ -870,6 +871,10 @@ const KProcess* KernelCore::CurrentProcess() const { | |||
| 870 | return impl->current_process; | 871 | return impl->current_process; |
| 871 | } | 872 | } |
| 872 | 873 | ||
| 874 | void KernelCore::CloseCurrentProcess() { | ||
| 875 | impl->CloseCurrentProcess(); | ||
| 876 | } | ||
| 877 | |||
| 873 | const std::vector<KProcess*>& KernelCore::GetProcessList() const { | 878 | const std::vector<KProcess*>& KernelCore::GetProcessList() const { |
| 874 | return impl->process_list; | 879 | return impl->process_list; |
| 875 | } | 880 | } |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 79e66483e..6eded9539 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -131,6 +131,9 @@ public: | |||
| 131 | /// Retrieves a const pointer to the current process. | 131 | /// Retrieves a const pointer to the current process. |
| 132 | const KProcess* CurrentProcess() const; | 132 | const KProcess* CurrentProcess() const; |
| 133 | 133 | ||
| 134 | /// Closes the current process. | ||
| 135 | void CloseCurrentProcess(); | ||
| 136 | |||
| 134 | /// Retrieves the list of processes. | 137 | /// Retrieves the list of processes. |
| 135 | const std::vector<KProcess*>& GetProcessList() const; | 138 | const std::vector<KProcess*>& GetProcessList() const; |
| 136 | 139 | ||
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index bac61fd09..b07ae3f02 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -933,7 +933,7 @@ static Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle han | |||
| 933 | return ResultSuccess; | 933 | return ResultSuccess; |
| 934 | 934 | ||
| 935 | case GetInfoType::UserExceptionContextAddr: | 935 | case GetInfoType::UserExceptionContextAddr: |
| 936 | *result = process->GetTLSRegionAddress(); | 936 | *result = process->GetProcessLocalRegionAddress(); |
| 937 | return ResultSuccess; | 937 | return ResultSuccess; |
| 938 | 938 | ||
| 939 | case GetInfoType::TotalPhysicalMemoryAvailableWithoutSystemResource: | 939 | case GetInfoType::TotalPhysicalMemoryAvailableWithoutSystemResource: |