diff options
| author | 2017-09-29 14:58:42 -0400 | |
|---|---|---|
| committer | 2017-09-29 14:58:42 -0400 | |
| commit | b07af7dda822898e9c8f231c5ddcd1741d93dbef (patch) | |
| tree | d41c9221d6065b8cf9e6a2405565b675a9c83c51 | |
| parent | Merge pull request #2907 from Subv/warnings3 (diff) | |
| parent | Loaders: Don't automatically set the current process every time we load an ap... (diff) | |
| download | yuzu-b07af7dda822898e9c8f231c5ddcd1741d93dbef.tar.gz yuzu-b07af7dda822898e9c8f231c5ddcd1741d93dbef.tar.xz yuzu-b07af7dda822898e9c8f231c5ddcd1741d93dbef.zip | |
Merge pull request #2961 from Subv/load_titles
Loaders: Don't automatically set the current process every time we load an application.
Diffstat (limited to '')
| -rw-r--r-- | src/core/core.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 17 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 15 | ||||
| -rw-r--r-- | src/core/hle/svc.cpp | 5 | ||||
| -rw-r--r-- | src/core/loader/3dsx.cpp | 15 | ||||
| -rw-r--r-- | src/core/loader/3dsx.h | 2 | ||||
| -rw-r--r-- | src/core/loader/elf.cpp | 15 | ||||
| -rw-r--r-- | src/core/loader/elf.h | 2 | ||||
| -rw-r--r-- | src/core/loader/loader.h | 13 | ||||
| -rw-r--r-- | src/core/loader/ncch.cpp | 19 | ||||
| -rw-r--r-- | src/core/loader/ncch.h | 5 | ||||
| -rw-r--r-- | src/core/memory.cpp | 25 | ||||
| -rw-r--r-- | src/core/memory.h | 7 | ||||
| -rw-r--r-- | src/tests/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/tests/core/arm/arm_test_common.cpp | 22 | ||||
| -rw-r--r-- | src/tests/core/memory/memory.cpp | 56 |
17 files changed, 157 insertions, 70 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 59b8768e7..0c7a72987 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "core/core_timing.h" | 13 | #include "core/core_timing.h" |
| 14 | #include "core/gdbstub/gdbstub.h" | 14 | #include "core/gdbstub/gdbstub.h" |
| 15 | #include "core/hle/kernel/kernel.h" | 15 | #include "core/hle/kernel/kernel.h" |
| 16 | #include "core/hle/kernel/process.h" | ||
| 16 | #include "core/hle/kernel/thread.h" | 17 | #include "core/hle/kernel/thread.h" |
| 17 | #include "core/hle/service/service.h" | 18 | #include "core/hle/service/service.h" |
| 18 | #include "core/hw/hw.h" | 19 | #include "core/hw/hw.h" |
| @@ -100,7 +101,7 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file | |||
| 100 | return init_result; | 101 | return init_result; |
| 101 | } | 102 | } |
| 102 | 103 | ||
| 103 | const Loader::ResultStatus load_result{app_loader->Load()}; | 104 | const Loader::ResultStatus load_result{app_loader->Load(Kernel::g_current_process)}; |
| 104 | if (Loader::ResultStatus::Success != load_result) { | 105 | if (Loader::ResultStatus::Success != load_result) { |
| 105 | LOG_CRITICAL(Core, "Failed to load ROM (Error %i)!", load_result); | 106 | LOG_CRITICAL(Core, "Failed to load ROM (Error %i)!", load_result); |
| 106 | System::Shutdown(); | 107 | System::Shutdown(); |
| @@ -114,6 +115,7 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file | |||
| 114 | return ResultStatus::ErrorLoader; | 115 | return ResultStatus::ErrorLoader; |
| 115 | } | 116 | } |
| 116 | } | 117 | } |
| 118 | Memory::SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table); | ||
| 117 | status = ResultStatus::Success; | 119 | status = ResultStatus::Success; |
| 118 | return status; | 120 | return status; |
| 119 | } | 121 | } |
| @@ -196,4 +198,4 @@ void System::Shutdown() { | |||
| 196 | LOG_DEBUG(Core, "Shutdown OK"); | 198 | LOG_DEBUG(Core, "Shutdown OK"); |
| 197 | } | 199 | } |
| 198 | 200 | ||
| 199 | } // namespace | 201 | } // namespace Core |
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 522ad2333..cf3163e0f 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -147,7 +147,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { | |||
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | vm_manager.LogLayout(Log::Level::Debug); | 149 | vm_manager.LogLayout(Log::Level::Debug); |
| 150 | Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); | 150 | Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority, this); |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | VAddr Process::GetLinearHeapAreaAddress() const { | 153 | VAddr Process::GetLinearHeapAreaAddress() const { |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 61378211f..1033f8552 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -361,7 +361,8 @@ static void ResetThreadContext(ARM_Interface::ThreadContext& context, u32 stack_ | |||
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, u32 priority, | 363 | ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, u32 priority, |
| 364 | u32 arg, s32 processor_id, VAddr stack_top) { | 364 | u32 arg, s32 processor_id, VAddr stack_top, |
| 365 | SharedPtr<Process> owner_process) { | ||
| 365 | // Check if priority is in ranged. Lowest priority -> highest priority id. | 366 | // Check if priority is in ranged. Lowest priority -> highest priority id. |
| 366 | if (priority > THREADPRIO_LOWEST) { | 367 | if (priority > THREADPRIO_LOWEST) { |
| 367 | LOG_ERROR(Kernel_SVC, "Invalid thread priority: %d", priority); | 368 | LOG_ERROR(Kernel_SVC, "Invalid thread priority: %d", priority); |
| @@ -375,7 +376,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 375 | 376 | ||
| 376 | // TODO(yuriks): Other checks, returning 0xD9001BEA | 377 | // TODO(yuriks): Other checks, returning 0xD9001BEA |
| 377 | 378 | ||
| 378 | if (!Memory::IsValidVirtualAddress(entry_point)) { | 379 | if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) { |
| 379 | LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); | 380 | LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); |
| 380 | // TODO: Verify error | 381 | // TODO: Verify error |
| 381 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, | 382 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, |
| @@ -399,10 +400,10 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 399 | thread->wait_address = 0; | 400 | thread->wait_address = 0; |
| 400 | thread->name = std::move(name); | 401 | thread->name = std::move(name); |
| 401 | thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); | 402 | thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); |
| 402 | thread->owner_process = g_current_process; | 403 | thread->owner_process = owner_process; |
| 403 | 404 | ||
| 404 | // Find the next available TLS index, and mark it as used | 405 | // Find the next available TLS index, and mark it as used |
| 405 | auto& tls_slots = Kernel::g_current_process->tls_slots; | 406 | auto& tls_slots = owner_process->tls_slots; |
| 406 | bool needs_allocation = true; | 407 | bool needs_allocation = true; |
| 407 | u32 available_page; // Which allocated page has free space | 408 | u32 available_page; // Which allocated page has free space |
| 408 | u32 available_slot; // Which slot within the page is free | 409 | u32 available_slot; // Which slot within the page is free |
| @@ -426,13 +427,13 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 426 | // Allocate some memory from the end of the linear heap for this region. | 427 | // Allocate some memory from the end of the linear heap for this region. |
| 427 | linheap_memory->insert(linheap_memory->end(), Memory::PAGE_SIZE, 0); | 428 | linheap_memory->insert(linheap_memory->end(), Memory::PAGE_SIZE, 0); |
| 428 | memory_region->used += Memory::PAGE_SIZE; | 429 | memory_region->used += Memory::PAGE_SIZE; |
| 429 | Kernel::g_current_process->linear_heap_used += Memory::PAGE_SIZE; | 430 | owner_process->linear_heap_used += Memory::PAGE_SIZE; |
| 430 | 431 | ||
| 431 | tls_slots.emplace_back(0); // The page is completely available at the start | 432 | tls_slots.emplace_back(0); // The page is completely available at the start |
| 432 | available_page = tls_slots.size() - 1; | 433 | available_page = tls_slots.size() - 1; |
| 433 | available_slot = 0; // Use the first slot in the new page | 434 | available_slot = 0; // Use the first slot in the new page |
| 434 | 435 | ||
| 435 | auto& vm_manager = Kernel::g_current_process->vm_manager; | 436 | auto& vm_manager = owner_process->vm_manager; |
| 436 | vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); | 437 | vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); |
| 437 | 438 | ||
| 438 | // Map the page to the current process' address space. | 439 | // Map the page to the current process' address space. |
| @@ -486,10 +487,10 @@ void Thread::BoostPriority(s32 priority) { | |||
| 486 | current_priority = priority; | 487 | current_priority = priority; |
| 487 | } | 488 | } |
| 488 | 489 | ||
| 489 | SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { | 490 | SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority, SharedPtr<Process> owner_process) { |
| 490 | // Initialize new "main" thread | 491 | // Initialize new "main" thread |
| 491 | auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0, | 492 | auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0, |
| 492 | Memory::HEAP_VADDR_END); | 493 | Memory::HEAP_VADDR_END, owner_process); |
| 493 | 494 | ||
| 494 | SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); | 495 | SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); |
| 495 | 496 | ||
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 6a3566f15..ddc0d15c5 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -56,10 +56,12 @@ public: | |||
| 56 | * @param arg User data to pass to the thread | 56 | * @param arg User data to pass to the thread |
| 57 | * @param processor_id The ID(s) of the processors on which the thread is desired to be run | 57 | * @param processor_id The ID(s) of the processors on which the thread is desired to be run |
| 58 | * @param stack_top The address of the thread's stack top | 58 | * @param stack_top The address of the thread's stack top |
| 59 | * @param owner_process The parent process for the thread | ||
| 59 | * @return A shared pointer to the newly created thread | 60 | * @return A shared pointer to the newly created thread |
| 60 | */ | 61 | */ |
| 61 | static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, u32 priority, | 62 | static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, u32 priority, |
| 62 | u32 arg, s32 processor_id, VAddr stack_top); | 63 | u32 arg, s32 processor_id, VAddr stack_top, |
| 64 | SharedPtr<Process> owner_process); | ||
| 63 | 65 | ||
| 64 | std::string GetName() const override { | 66 | std::string GetName() const override { |
| 65 | return name; | 67 | return name; |
| @@ -116,9 +118,9 @@ public: | |||
| 116 | void ResumeFromWait(); | 118 | void ResumeFromWait(); |
| 117 | 119 | ||
| 118 | /** | 120 | /** |
| 119 | * Schedules an event to wake up the specified thread after the specified delay | 121 | * Schedules an event to wake up the specified thread after the specified delay |
| 120 | * @param nanoseconds The time this thread will be allowed to sleep for | 122 | * @param nanoseconds The time this thread will be allowed to sleep for |
| 121 | */ | 123 | */ |
| 122 | void WakeAfterDelay(s64 nanoseconds); | 124 | void WakeAfterDelay(s64 nanoseconds); |
| 123 | 125 | ||
| 124 | /** | 126 | /** |
| @@ -214,9 +216,10 @@ private: | |||
| 214 | * Sets up the primary application thread | 216 | * Sets up the primary application thread |
| 215 | * @param entry_point The address at which the thread should start execution | 217 | * @param entry_point The address at which the thread should start execution |
| 216 | * @param priority The priority to give the main thread | 218 | * @param priority The priority to give the main thread |
| 219 | * @param owner_process The parent process for the main thread | ||
| 217 | * @return A shared pointer to the main thread | 220 | * @return A shared pointer to the main thread |
| 218 | */ | 221 | */ |
| 219 | SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority); | 222 | SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority, SharedPtr<Process> owner_process); |
| 220 | 223 | ||
| 221 | /** | 224 | /** |
| 222 | * Returns whether there are any threads that are ready to run. | 225 | * Returns whether there are any threads that are ready to run. |
| @@ -276,4 +279,4 @@ void ThreadingShutdown(); | |||
| 276 | */ | 279 | */ |
| 277 | const std::vector<SharedPtr<Thread>>& GetThreadList(); | 280 | const std::vector<SharedPtr<Thread>>& GetThreadList(); |
| 278 | 281 | ||
| 279 | } // namespace | 282 | } // namespace Kernel |
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index dfc36748c..05c6897bf 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -656,8 +656,9 @@ static ResultCode CreateThread(Kernel::Handle* out_handle, u32 priority, u32 ent | |||
| 656 | "Newly created thread must run in the SysCore (Core1), unimplemented."); | 656 | "Newly created thread must run in the SysCore (Core1), unimplemented."); |
| 657 | } | 657 | } |
| 658 | 658 | ||
| 659 | CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create(name, entry_point, priority, | 659 | CASCADE_RESULT(SharedPtr<Thread> thread, |
| 660 | arg, processor_id, stack_top)); | 660 | Kernel::Thread::Create(name, entry_point, priority, arg, processor_id, stack_top, |
| 661 | Kernel::g_current_process)); | ||
| 661 | 662 | ||
| 662 | thread->context.fpscr = | 663 | thread->context.fpscr = |
| 663 | FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000 | 664 | FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000 |
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index 5ad5c5287..918038f1e 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp | |||
| @@ -91,8 +91,8 @@ static u32 TranslateAddr(u32 addr, const THREEloadinfo* loadinfo, u32* offsets) | |||
| 91 | return loadinfo->seg_addrs[2] + addr - offsets[1]; | 91 | return loadinfo->seg_addrs[2] + addr - offsets[1]; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | using Kernel::SharedPtr; | ||
| 95 | using Kernel::CodeSet; | 94 | using Kernel::CodeSet; |
| 95 | using Kernel::SharedPtr; | ||
| 96 | 96 | ||
| 97 | static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, | 97 | static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, |
| 98 | SharedPtr<CodeSet>* out_codeset) { | 98 | SharedPtr<CodeSet>* out_codeset) { |
| @@ -255,7 +255,7 @@ FileType AppLoader_THREEDSX::IdentifyType(FileUtil::IOFile& file) { | |||
| 255 | return FileType::Error; | 255 | return FileType::Error; |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | ResultStatus AppLoader_THREEDSX::Load() { | 258 | ResultStatus AppLoader_THREEDSX::Load(Kernel::SharedPtr<Kernel::Process>& process) { |
| 259 | if (is_loaded) | 259 | if (is_loaded) |
| 260 | return ResultStatus::ErrorAlreadyLoaded; | 260 | return ResultStatus::ErrorAlreadyLoaded; |
| 261 | 261 | ||
| @@ -267,16 +267,15 @@ ResultStatus AppLoader_THREEDSX::Load() { | |||
| 267 | return ResultStatus::Error; | 267 | return ResultStatus::Error; |
| 268 | codeset->name = filename; | 268 | codeset->name = filename; |
| 269 | 269 | ||
| 270 | Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); | 270 | process = Kernel::Process::Create(std::move(codeset)); |
| 271 | Kernel::g_current_process->svc_access_mask.set(); | 271 | process->svc_access_mask.set(); |
| 272 | Kernel::g_current_process->address_mappings = default_address_mappings; | 272 | process->address_mappings = default_address_mappings; |
| 273 | Memory::SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table); | ||
| 274 | 273 | ||
| 275 | // Attach the default resource limit (APPLICATION) to the process | 274 | // Attach the default resource limit (APPLICATION) to the process |
| 276 | Kernel::g_current_process->resource_limit = | 275 | process->resource_limit = |
| 277 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 276 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); |
| 278 | 277 | ||
| 279 | Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); | 278 | process->Run(48, Kernel::DEFAULT_STACK_SIZE); |
| 280 | 279 | ||
| 281 | Service::FS::RegisterSelfNCCH(*this); | 280 | Service::FS::RegisterSelfNCCH(*this); |
| 282 | 281 | ||
diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h index 3f376778a..1e59bbb9d 100644 --- a/src/core/loader/3dsx.h +++ b/src/core/loader/3dsx.h | |||
| @@ -31,7 +31,7 @@ public: | |||
| 31 | return IdentifyType(file); | 31 | return IdentifyType(file); |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | ResultStatus Load() override; | 34 | ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override; |
| 35 | 35 | ||
| 36 | ResultStatus ReadIcon(std::vector<u8>& buffer) override; | 36 | ResultStatus ReadIcon(std::vector<u8>& buffer) override; |
| 37 | 37 | ||
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 2de1f4e81..e36e42120 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | #include "core/loader/elf.h" | 13 | #include "core/loader/elf.h" |
| 14 | #include "core/memory.h" | 14 | #include "core/memory.h" |
| 15 | 15 | ||
| 16 | using Kernel::SharedPtr; | ||
| 17 | using Kernel::CodeSet; | 16 | using Kernel::CodeSet; |
| 17 | using Kernel::SharedPtr; | ||
| 18 | 18 | ||
| 19 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 19 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 20 | // ELF Header Constants | 20 | // ELF Header Constants |
| @@ -375,7 +375,7 @@ FileType AppLoader_ELF::IdentifyType(FileUtil::IOFile& file) { | |||
| 375 | return FileType::Error; | 375 | return FileType::Error; |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | ResultStatus AppLoader_ELF::Load() { | 378 | ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) { |
| 379 | if (is_loaded) | 379 | if (is_loaded) |
| 380 | return ResultStatus::ErrorAlreadyLoaded; | 380 | return ResultStatus::ErrorAlreadyLoaded; |
| 381 | 381 | ||
| @@ -394,16 +394,15 @@ ResultStatus AppLoader_ELF::Load() { | |||
| 394 | SharedPtr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR); | 394 | SharedPtr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR); |
| 395 | codeset->name = filename; | 395 | codeset->name = filename; |
| 396 | 396 | ||
| 397 | Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); | 397 | process = Kernel::Process::Create(std::move(codeset)); |
| 398 | Kernel::g_current_process->svc_access_mask.set(); | 398 | process->svc_access_mask.set(); |
| 399 | Kernel::g_current_process->address_mappings = default_address_mappings; | 399 | process->address_mappings = default_address_mappings; |
| 400 | Memory::SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table); | ||
| 401 | 400 | ||
| 402 | // Attach the default resource limit (APPLICATION) to the process | 401 | // Attach the default resource limit (APPLICATION) to the process |
| 403 | Kernel::g_current_process->resource_limit = | 402 | process->resource_limit = |
| 404 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 403 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); |
| 405 | 404 | ||
| 406 | Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); | 405 | process->Run(48, Kernel::DEFAULT_STACK_SIZE); |
| 407 | 406 | ||
| 408 | is_loaded = true; | 407 | is_loaded = true; |
| 409 | return ResultStatus::Success; | 408 | return ResultStatus::Success; |
diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index 862aa90d8..113da5917 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h | |||
| @@ -30,7 +30,7 @@ public: | |||
| 30 | return IdentifyType(file); | 30 | return IdentifyType(file); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | ResultStatus Load() override; | 33 | ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override; |
| 34 | 34 | ||
| 35 | private: | 35 | private: |
| 36 | std::string filename; | 36 | std::string filename; |
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 3160fd2fd..82b2be6a3 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h | |||
| @@ -13,10 +13,12 @@ | |||
| 13 | #include <boost/optional.hpp> | 13 | #include <boost/optional.hpp> |
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "common/file_util.h" | 15 | #include "common/file_util.h" |
| 16 | #include "core/hle/kernel/kernel.h" | ||
| 16 | 17 | ||
| 17 | namespace Kernel { | 18 | namespace Kernel { |
| 18 | struct AddressMapping; | 19 | struct AddressMapping; |
| 19 | } | 20 | class Process; |
| 21 | } // namespace Kernel | ||
| 20 | 22 | ||
| 21 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 23 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 22 | // Loader namespace | 24 | // Loader namespace |
| @@ -92,10 +94,11 @@ public: | |||
| 92 | virtual FileType GetFileType() = 0; | 94 | virtual FileType GetFileType() = 0; |
| 93 | 95 | ||
| 94 | /** | 96 | /** |
| 95 | * Load the application | 97 | * Load the application and return the created Process instance |
| 96 | * @return ResultStatus result of function | 98 | * @param process The newly created process. |
| 99 | * @return The status result of the operation. | ||
| 97 | */ | 100 | */ |
| 98 | virtual ResultStatus Load() = 0; | 101 | virtual ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) = 0; |
| 99 | 102 | ||
| 100 | /** | 103 | /** |
| 101 | * Loads the system mode that this application needs. | 104 | * Loads the system mode that this application needs. |
| @@ -206,4 +209,4 @@ extern const std::initializer_list<Kernel::AddressMapping> default_address_mappi | |||
| 206 | */ | 209 | */ |
| 207 | std::unique_ptr<AppLoader> GetLoader(const std::string& filename); | 210 | std::unique_ptr<AppLoader> GetLoader(const std::string& filename); |
| 208 | 211 | ||
| 209 | } // namespace | 212 | } // namespace Loader |
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 5107135f9..66bc5823d 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp | |||
| @@ -67,9 +67,9 @@ std::pair<boost::optional<u32>, ResultStatus> AppLoader_NCCH::LoadKernelSystemMo | |||
| 67 | ResultStatus::Success); | 67 | ResultStatus::Success); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | ResultStatus AppLoader_NCCH::LoadExec() { | 70 | ResultStatus AppLoader_NCCH::LoadExec(Kernel::SharedPtr<Kernel::Process>& process) { |
| 71 | using Kernel::SharedPtr; | ||
| 72 | using Kernel::CodeSet; | 71 | using Kernel::CodeSet; |
| 72 | using Kernel::SharedPtr; | ||
| 73 | 73 | ||
| 74 | if (!is_loaded) | 74 | if (!is_loaded) |
| 75 | return ResultStatus::ErrorNotLoaded; | 75 | return ResultStatus::ErrorNotLoaded; |
| @@ -107,16 +107,15 @@ ResultStatus AppLoader_NCCH::LoadExec() { | |||
| 107 | codeset->entrypoint = codeset->code.addr; | 107 | codeset->entrypoint = codeset->code.addr; |
| 108 | codeset->memory = std::make_shared<std::vector<u8>>(std::move(code)); | 108 | codeset->memory = std::make_shared<std::vector<u8>>(std::move(code)); |
| 109 | 109 | ||
| 110 | Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); | 110 | process = Kernel::Process::Create(std::move(codeset)); |
| 111 | Memory::SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table); | ||
| 112 | 111 | ||
| 113 | // Attach a resource limit to the process based on the resource limit category | 112 | // Attach a resource limit to the process based on the resource limit category |
| 114 | Kernel::g_current_process->resource_limit = | 113 | process->resource_limit = |
| 115 | Kernel::ResourceLimit::GetForCategory(static_cast<Kernel::ResourceLimitCategory>( | 114 | Kernel::ResourceLimit::GetForCategory(static_cast<Kernel::ResourceLimitCategory>( |
| 116 | overlay_ncch->exheader_header.arm11_system_local_caps.resource_limit_category)); | 115 | overlay_ncch->exheader_header.arm11_system_local_caps.resource_limit_category)); |
| 117 | 116 | ||
| 118 | // Set the default CPU core for this process | 117 | // Set the default CPU core for this process |
| 119 | Kernel::g_current_process->ideal_processor = | 118 | process->ideal_processor = |
| 120 | overlay_ncch->exheader_header.arm11_system_local_caps.ideal_processor; | 119 | overlay_ncch->exheader_header.arm11_system_local_caps.ideal_processor; |
| 121 | 120 | ||
| 122 | // Copy data while converting endianness | 121 | // Copy data while converting endianness |
| @@ -124,11 +123,11 @@ ResultStatus AppLoader_NCCH::LoadExec() { | |||
| 124 | kernel_caps; | 123 | kernel_caps; |
| 125 | std::copy_n(overlay_ncch->exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), | 124 | std::copy_n(overlay_ncch->exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), |
| 126 | begin(kernel_caps)); | 125 | begin(kernel_caps)); |
| 127 | Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size()); | 126 | process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size()); |
| 128 | 127 | ||
| 129 | s32 priority = overlay_ncch->exheader_header.arm11_system_local_caps.priority; | 128 | s32 priority = overlay_ncch->exheader_header.arm11_system_local_caps.priority; |
| 130 | u32 stack_size = overlay_ncch->exheader_header.codeset_info.stack_size; | 129 | u32 stack_size = overlay_ncch->exheader_header.codeset_info.stack_size; |
| 131 | Kernel::g_current_process->Run(priority, stack_size); | 130 | process->Run(priority, stack_size); |
| 132 | return ResultStatus::Success; | 131 | return ResultStatus::Success; |
| 133 | } | 132 | } |
| 134 | return ResultStatus::Error; | 133 | return ResultStatus::Error; |
| @@ -151,7 +150,7 @@ void AppLoader_NCCH::ParseRegionLockoutInfo() { | |||
| 151 | } | 150 | } |
| 152 | } | 151 | } |
| 153 | 152 | ||
| 154 | ResultStatus AppLoader_NCCH::Load() { | 153 | ResultStatus AppLoader_NCCH::Load(Kernel::SharedPtr<Kernel::Process>& process) { |
| 155 | u64_le ncch_program_id; | 154 | u64_le ncch_program_id; |
| 156 | 155 | ||
| 157 | if (is_loaded) | 156 | if (is_loaded) |
| @@ -183,7 +182,7 @@ ResultStatus AppLoader_NCCH::Load() { | |||
| 183 | 182 | ||
| 184 | is_loaded = true; // Set state to loaded | 183 | is_loaded = true; // Set state to loaded |
| 185 | 184 | ||
| 186 | result = LoadExec(); // Load the executable into memory for booting | 185 | result = LoadExec(process); // Load the executable into memory for booting |
| 187 | if (ResultStatus::Success != result) | 186 | if (ResultStatus::Success != result) |
| 188 | return result; | 187 | return result; |
| 189 | 188 | ||
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index 9b56465cb..09230ae33 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h | |||
| @@ -33,7 +33,7 @@ public: | |||
| 33 | return IdentifyType(file); | 33 | return IdentifyType(file); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | ResultStatus Load() override; | 36 | ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override; |
| 37 | 37 | ||
| 38 | /** | 38 | /** |
| 39 | * Loads the Exheader and returns the system mode for this application. | 39 | * Loads the Exheader and returns the system mode for this application. |
| @@ -62,9 +62,10 @@ public: | |||
| 62 | private: | 62 | private: |
| 63 | /** | 63 | /** |
| 64 | * Loads .code section into memory for booting | 64 | * Loads .code section into memory for booting |
| 65 | * @param process The newly created process | ||
| 65 | * @return ResultStatus result of function | 66 | * @return ResultStatus result of function |
| 66 | */ | 67 | */ |
| 67 | ResultStatus LoadExec(); | 68 | ResultStatus LoadExec(Kernel::SharedPtr<Kernel::Process>& process); |
| 68 | 69 | ||
| 69 | /// Reads the region lockout info in the SMDH and send it to CFG service | 70 | /// Reads the region lockout info in the SMDH and send it to CFG service |
| 70 | void ParseRegionLockoutInfo(); | 71 | void ParseRegionLockoutInfo(); |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 9b394f84b..5ea0694a9 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -110,8 +110,8 @@ static u8* GetPointerFromVMA(VAddr vaddr) { | |||
| 110 | /** | 110 | /** |
| 111 | * This function should only be called for virtual addreses with attribute `PageType::Special`. | 111 | * This function should only be called for virtual addreses with attribute `PageType::Special`. |
| 112 | */ | 112 | */ |
| 113 | static MMIORegionPointer GetMMIOHandler(VAddr vaddr) { | 113 | static MMIORegionPointer GetMMIOHandler(const PageTable& page_table, VAddr vaddr) { |
| 114 | for (const auto& region : current_page_table->special_regions) { | 114 | for (const auto& region : page_table.special_regions) { |
| 115 | if (vaddr >= region.base && vaddr < (region.base + region.size)) { | 115 | if (vaddr >= region.base && vaddr < (region.base + region.size)) { |
| 116 | return region.handler; | 116 | return region.handler; |
| 117 | } | 117 | } |
| @@ -120,6 +120,11 @@ static MMIORegionPointer GetMMIOHandler(VAddr vaddr) { | |||
| 120 | return nullptr; // Should never happen | 120 | return nullptr; // Should never happen |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | static MMIORegionPointer GetMMIOHandler(VAddr vaddr) { | ||
| 124 | const PageTable& page_table = Kernel::g_current_process->vm_manager.page_table; | ||
| 125 | return GetMMIOHandler(page_table, vaddr); | ||
| 126 | } | ||
| 127 | |||
| 123 | template <typename T> | 128 | template <typename T> |
| 124 | T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); | 129 | T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); |
| 125 | 130 | ||
| @@ -204,18 +209,20 @@ void Write(const VAddr vaddr, const T data) { | |||
| 204 | } | 209 | } |
| 205 | } | 210 | } |
| 206 | 211 | ||
| 207 | bool IsValidVirtualAddress(const VAddr vaddr) { | 212 | bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) { |
| 208 | const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | 213 | auto& page_table = process.vm_manager.page_table; |
| 214 | |||
| 215 | const u8* page_pointer = page_table.pointers[vaddr >> PAGE_BITS]; | ||
| 209 | if (page_pointer) | 216 | if (page_pointer) |
| 210 | return true; | 217 | return true; |
| 211 | 218 | ||
| 212 | if (current_page_table->attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory) | 219 | if (page_table.attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory) |
| 213 | return true; | 220 | return true; |
| 214 | 221 | ||
| 215 | if (current_page_table->attributes[vaddr >> PAGE_BITS] != PageType::Special) | 222 | if (page_table.attributes[vaddr >> PAGE_BITS] != PageType::Special) |
| 216 | return false; | 223 | return false; |
| 217 | 224 | ||
| 218 | MMIORegionPointer mmio_region = GetMMIOHandler(vaddr); | 225 | MMIORegionPointer mmio_region = GetMMIOHandler(page_table, vaddr); |
| 219 | if (mmio_region) { | 226 | if (mmio_region) { |
| 220 | return mmio_region->IsValidAddress(vaddr); | 227 | return mmio_region->IsValidAddress(vaddr); |
| 221 | } | 228 | } |
| @@ -223,6 +230,10 @@ bool IsValidVirtualAddress(const VAddr vaddr) { | |||
| 223 | return false; | 230 | return false; |
| 224 | } | 231 | } |
| 225 | 232 | ||
| 233 | bool IsValidVirtualAddress(const VAddr vaddr) { | ||
| 234 | return IsValidVirtualAddress(*Kernel::g_current_process, vaddr); | ||
| 235 | } | ||
| 236 | |||
| 226 | bool IsValidPhysicalAddress(const PAddr paddr) { | 237 | bool IsValidPhysicalAddress(const PAddr paddr) { |
| 227 | return GetPhysicalPointer(paddr) != nullptr; | 238 | return GetPhysicalPointer(paddr) != nullptr; |
| 228 | } | 239 | } |
diff --git a/src/core/memory.h b/src/core/memory.h index 1865bfea0..347c08c78 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -12,6 +12,10 @@ | |||
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "core/mmio.h" | 13 | #include "core/mmio.h" |
| 14 | 14 | ||
| 15 | namespace Kernel { | ||
| 16 | class Process; | ||
| 17 | } | ||
| 18 | |||
| 15 | namespace Memory { | 19 | namespace Memory { |
| 16 | 20 | ||
| 17 | /** | 21 | /** |
| @@ -185,7 +189,10 @@ enum : VAddr { | |||
| 185 | void SetCurrentPageTable(PageTable* page_table); | 189 | void SetCurrentPageTable(PageTable* page_table); |
| 186 | PageTable* GetCurrentPageTable(); | 190 | PageTable* GetCurrentPageTable(); |
| 187 | 191 | ||
| 192 | /// Determines if the given VAddr is valid for the specified process. | ||
| 193 | bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr); | ||
| 188 | bool IsValidVirtualAddress(const VAddr addr); | 194 | bool IsValidVirtualAddress(const VAddr addr); |
| 195 | |||
| 189 | bool IsValidPhysicalAddress(const PAddr addr); | 196 | bool IsValidPhysicalAddress(const PAddr addr); |
| 190 | 197 | ||
| 191 | u8 Read8(VAddr addr); | 198 | u8 Read8(VAddr addr); |
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 5e9c4c2bf..1aac0daa2 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt | |||
| @@ -4,6 +4,7 @@ set(SRCS | |||
| 4 | core/arm/dyncom/arm_dyncom_vfp_tests.cpp | 4 | core/arm/dyncom/arm_dyncom_vfp_tests.cpp |
| 5 | core/file_sys/path_parser.cpp | 5 | core/file_sys/path_parser.cpp |
| 6 | core/hle/kernel/hle_ipc.cpp | 6 | core/hle/kernel/hle_ipc.cpp |
| 7 | core/memory/memory.cpp | ||
| 7 | glad.cpp | 8 | glad.cpp |
| 8 | tests.cpp | 9 | tests.cpp |
| 9 | ) | 10 | ) |
diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp index cfe0d503a..484713a92 100644 --- a/src/tests/core/arm/arm_test_common.cpp +++ b/src/tests/core/arm/arm_test_common.cpp | |||
| @@ -3,30 +3,34 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hle/kernel/process.h" | ||
| 6 | #include "core/memory.h" | 7 | #include "core/memory.h" |
| 7 | #include "core/memory_setup.h" | 8 | #include "core/memory_setup.h" |
| 8 | #include "tests/core/arm/arm_test_common.h" | 9 | #include "tests/core/arm/arm_test_common.h" |
| 9 | 10 | ||
| 10 | namespace ArmTests { | 11 | namespace ArmTests { |
| 11 | 12 | ||
| 12 | static Memory::PageTable page_table; | 13 | static Memory::PageTable* page_table = nullptr; |
| 13 | 14 | ||
| 14 | TestEnvironment::TestEnvironment(bool mutable_memory_) | 15 | TestEnvironment::TestEnvironment(bool mutable_memory_) |
| 15 | : mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) { | 16 | : mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) { |
| 16 | 17 | ||
| 17 | page_table.pointers.fill(nullptr); | 18 | Kernel::g_current_process = Kernel::Process::Create(Kernel::CodeSet::Create("", 0)); |
| 18 | page_table.attributes.fill(Memory::PageType::Unmapped); | 19 | page_table = &Kernel::g_current_process->vm_manager.page_table; |
| 19 | page_table.cached_res_count.fill(0); | ||
| 20 | 20 | ||
| 21 | Memory::MapIoRegion(page_table, 0x00000000, 0x80000000, test_memory); | 21 | page_table->pointers.fill(nullptr); |
| 22 | Memory::MapIoRegion(page_table, 0x80000000, 0x80000000, test_memory); | 22 | page_table->attributes.fill(Memory::PageType::Unmapped); |
| 23 | page_table->cached_res_count.fill(0); | ||
| 23 | 24 | ||
| 24 | Memory::SetCurrentPageTable(&page_table); | 25 | Memory::MapIoRegion(*page_table, 0x00000000, 0x80000000, test_memory); |
| 26 | Memory::MapIoRegion(*page_table, 0x80000000, 0x80000000, test_memory); | ||
| 27 | |||
| 28 | Memory::SetCurrentPageTable(page_table); | ||
| 25 | } | 29 | } |
| 26 | 30 | ||
| 27 | TestEnvironment::~TestEnvironment() { | 31 | TestEnvironment::~TestEnvironment() { |
| 28 | Memory::UnmapRegion(page_table, 0x80000000, 0x80000000); | 32 | Memory::UnmapRegion(*page_table, 0x80000000, 0x80000000); |
| 29 | Memory::UnmapRegion(page_table, 0x00000000, 0x80000000); | 33 | Memory::UnmapRegion(*page_table, 0x00000000, 0x80000000); |
| 30 | } | 34 | } |
| 31 | 35 | ||
| 32 | void TestEnvironment::SetMemory64(VAddr vaddr, u64 value) { | 36 | void TestEnvironment::SetMemory64(VAddr vaddr, u64 value) { |
diff --git a/src/tests/core/memory/memory.cpp b/src/tests/core/memory/memory.cpp new file mode 100644 index 000000000..a01b896f7 --- /dev/null +++ b/src/tests/core/memory/memory.cpp | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <catch.hpp> | ||
| 6 | #include "core/hle/kernel/memory.h" | ||
| 7 | #include "core/hle/kernel/process.h" | ||
| 8 | #include "core/memory.h" | ||
| 9 | |||
| 10 | TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") { | ||
| 11 | SECTION("these regions should not be mapped on an empty process") { | ||
| 12 | auto process = Kernel::Process::Create(Kernel::CodeSet::Create("", 0)); | ||
| 13 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::PROCESS_IMAGE_VADDR) == false); | ||
| 14 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::HEAP_VADDR) == false); | ||
| 15 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::LINEAR_HEAP_VADDR) == false); | ||
| 16 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::VRAM_VADDR) == false); | ||
| 17 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == false); | ||
| 18 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::SHARED_PAGE_VADDR) == false); | ||
| 19 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::TLS_AREA_VADDR) == false); | ||
| 20 | } | ||
| 21 | |||
| 22 | SECTION("CONFIG_MEMORY_VADDR and SHARED_PAGE_VADDR should be valid after mapping them") { | ||
| 23 | auto process = Kernel::Process::Create(Kernel::CodeSet::Create("", 0)); | ||
| 24 | Kernel::MapSharedPages(process->vm_manager); | ||
| 25 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == true); | ||
| 26 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::SHARED_PAGE_VADDR) == true); | ||
| 27 | } | ||
| 28 | |||
| 29 | SECTION("special regions should be valid after mapping them") { | ||
| 30 | auto process = Kernel::Process::Create(Kernel::CodeSet::Create("", 0)); | ||
| 31 | SECTION("VRAM") { | ||
| 32 | Kernel::HandleSpecialMapping(process->vm_manager, | ||
| 33 | {Memory::VRAM_VADDR, Memory::VRAM_SIZE, false, false}); | ||
| 34 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::VRAM_VADDR) == true); | ||
| 35 | } | ||
| 36 | |||
| 37 | SECTION("IO (Not yet implemented)") { | ||
| 38 | Kernel::HandleSpecialMapping( | ||
| 39 | process->vm_manager, {Memory::IO_AREA_VADDR, Memory::IO_AREA_SIZE, false, false}); | ||
| 40 | CHECK_FALSE(Memory::IsValidVirtualAddress(*process, Memory::IO_AREA_VADDR) == true); | ||
| 41 | } | ||
| 42 | |||
| 43 | SECTION("DSP") { | ||
| 44 | Kernel::HandleSpecialMapping( | ||
| 45 | process->vm_manager, {Memory::DSP_RAM_VADDR, Memory::DSP_RAM_SIZE, false, false}); | ||
| 46 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::DSP_RAM_VADDR) == true); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | SECTION("Unmapping a VAddr should make it invalid") { | ||
| 51 | auto process = Kernel::Process::Create(Kernel::CodeSet::Create("", 0)); | ||
| 52 | Kernel::MapSharedPages(process->vm_manager); | ||
| 53 | process->vm_manager.UnmapRange(Memory::CONFIG_MEMORY_VADDR, Memory::CONFIG_MEMORY_SIZE); | ||
| 54 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == false); | ||
| 55 | } | ||
| 56 | } | ||