diff options
| author | 2019-04-19 19:09:20 -0400 | |
|---|---|---|
| committer | 2019-04-19 19:09:20 -0400 | |
| commit | 40dc893c372c81c687eca2d0b964220a8f8aeab4 (patch) | |
| tree | 1c05675d446978752a749f2cb18a797c6b737998 | |
| parent | Merge pull request #2397 from lioncash/thread-unused (diff) | |
| parent | core/core: Move process execution start to System's Load() (diff) | |
| download | yuzu-40dc893c372c81c687eca2d0b964220a8f8aeab4.tar.gz yuzu-40dc893c372c81c687eca2d0b964220a8f8aeab4.tar.xz yuzu-40dc893c372c81c687eca2d0b964220a8f8aeab4.zip | |
Merge pull request #2374 from lioncash/pagetable
core: Reorganize boot order
38 files changed, 253 insertions, 177 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 4dfd41b43..978b1518f 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h | |||
| @@ -7,6 +7,10 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | 9 | ||
| 10 | namespace Common { | ||
| 11 | struct PageTable; | ||
| 12 | } | ||
| 13 | |||
| 10 | namespace Kernel { | 14 | namespace Kernel { |
| 11 | enum class VMAPermission : u8; | 15 | enum class VMAPermission : u8; |
| 12 | } | 16 | } |
| @@ -49,8 +53,14 @@ public: | |||
| 49 | /// Clear all instruction cache | 53 | /// Clear all instruction cache |
| 50 | virtual void ClearInstructionCache() = 0; | 54 | virtual void ClearInstructionCache() = 0; |
| 51 | 55 | ||
| 52 | /// Notify CPU emulation that page tables have changed | 56 | /// Notifies CPU emulation that the current page table has changed. |
| 53 | virtual void PageTableChanged() = 0; | 57 | /// |
| 58 | /// @param new_page_table The new page table. | ||
| 59 | /// @param new_address_space_size_in_bits The new usable size of the address space in bits. | ||
| 60 | /// This can be either 32, 36, or 39 on official software. | ||
| 61 | /// | ||
| 62 | virtual void PageTableChanged(Common::PageTable& new_page_table, | ||
| 63 | std::size_t new_address_space_size_in_bits) = 0; | ||
| 54 | 64 | ||
| 55 | /** | 65 | /** |
| 56 | * Set the Program Counter to an address | 66 | * Set the Program Counter to an address |
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index dc96e35d5..44307fa19 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | #include "core/core_timing.h" | 14 | #include "core/core_timing.h" |
| 15 | #include "core/core_timing_util.h" | 15 | #include "core/core_timing_util.h" |
| 16 | #include "core/gdbstub/gdbstub.h" | 16 | #include "core/gdbstub/gdbstub.h" |
| 17 | #include "core/hle/kernel/kernel.h" | ||
| 18 | #include "core/hle/kernel/process.h" | 17 | #include "core/hle/kernel/process.h" |
| 19 | #include "core/hle/kernel/svc.h" | 18 | #include "core/hle/kernel/svc.h" |
| 20 | #include "core/hle/kernel/vm_manager.h" | 19 | #include "core/hle/kernel/vm_manager.h" |
| @@ -129,18 +128,16 @@ public: | |||
| 129 | u64 tpidr_el0 = 0; | 128 | u64 tpidr_el0 = 0; |
| 130 | }; | 129 | }; |
| 131 | 130 | ||
| 132 | std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const { | 131 | std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& page_table, |
| 133 | auto* current_process = system.Kernel().CurrentProcess(); | 132 | std::size_t address_space_bits) const { |
| 134 | auto** const page_table = current_process->VMManager().page_table.pointers.data(); | ||
| 135 | |||
| 136 | Dynarmic::A64::UserConfig config; | 133 | Dynarmic::A64::UserConfig config; |
| 137 | 134 | ||
| 138 | // Callbacks | 135 | // Callbacks |
| 139 | config.callbacks = cb.get(); | 136 | config.callbacks = cb.get(); |
| 140 | 137 | ||
| 141 | // Memory | 138 | // Memory |
| 142 | config.page_table = reinterpret_cast<void**>(page_table); | 139 | config.page_table = reinterpret_cast<void**>(page_table.pointers.data()); |
| 143 | config.page_table_address_space_bits = current_process->VMManager().GetAddressSpaceWidth(); | 140 | config.page_table_address_space_bits = address_space_bits; |
| 144 | config.silently_mirror_page_table = false; | 141 | config.silently_mirror_page_table = false; |
| 145 | 142 | ||
| 146 | // Multi-process state | 143 | // Multi-process state |
| @@ -176,12 +173,7 @@ ARM_Dynarmic::ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor, | |||
| 176 | std::size_t core_index) | 173 | std::size_t core_index) |
| 177 | : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), inner_unicorn{system}, | 174 | : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), inner_unicorn{system}, |
| 178 | core_index{core_index}, system{system}, | 175 | core_index{core_index}, system{system}, |
| 179 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} { | 176 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} |
| 180 | ThreadContext ctx{}; | ||
| 181 | inner_unicorn.SaveContext(ctx); | ||
| 182 | PageTableChanged(); | ||
| 183 | LoadContext(ctx); | ||
| 184 | } | ||
| 185 | 177 | ||
| 186 | ARM_Dynarmic::~ARM_Dynarmic() = default; | 178 | ARM_Dynarmic::~ARM_Dynarmic() = default; |
| 187 | 179 | ||
| @@ -276,8 +268,9 @@ void ARM_Dynarmic::ClearExclusiveState() { | |||
| 276 | jit->ClearExclusiveState(); | 268 | jit->ClearExclusiveState(); |
| 277 | } | 269 | } |
| 278 | 270 | ||
| 279 | void ARM_Dynarmic::PageTableChanged() { | 271 | void ARM_Dynarmic::PageTableChanged(Common::PageTable& page_table, |
| 280 | jit = MakeJit(); | 272 | std::size_t new_address_space_size_in_bits) { |
| 273 | jit = MakeJit(page_table, new_address_space_size_in_bits); | ||
| 281 | } | 274 | } |
| 282 | 275 | ||
| 283 | DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(std::size_t core_count) : monitor(core_count) {} | 276 | DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(std::size_t core_count) : monitor(core_count) {} |
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index c1db254e8..b701e97a3 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h | |||
| @@ -48,10 +48,12 @@ public: | |||
| 48 | void ClearExclusiveState() override; | 48 | void ClearExclusiveState() override; |
| 49 | 49 | ||
| 50 | void ClearInstructionCache() override; | 50 | void ClearInstructionCache() override; |
| 51 | void PageTableChanged() override; | 51 | void PageTableChanged(Common::PageTable& new_page_table, |
| 52 | std::size_t new_address_space_size_in_bits) override; | ||
| 52 | 53 | ||
| 53 | private: | 54 | private: |
| 54 | std::unique_ptr<Dynarmic::A64::Jit> MakeJit() const; | 55 | std::unique_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable& page_table, |
| 56 | std::size_t address_space_bits) const; | ||
| 55 | 57 | ||
| 56 | friend class ARM_Dynarmic_Callbacks; | 58 | friend class ARM_Dynarmic_Callbacks; |
| 57 | std::unique_ptr<ARM_Dynarmic_Callbacks> cb; | 59 | std::unique_ptr<ARM_Dynarmic_Callbacks> cb; |
diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h index 209fc16ad..34e974b4d 100644 --- a/src/core/arm/unicorn/arm_unicorn.h +++ b/src/core/arm/unicorn/arm_unicorn.h | |||
| @@ -41,7 +41,7 @@ public: | |||
| 41 | void Run() override; | 41 | void Run() override; |
| 42 | void Step() override; | 42 | void Step() override; |
| 43 | void ClearInstructionCache() override; | 43 | void ClearInstructionCache() override; |
| 44 | void PageTableChanged() override{}; | 44 | void PageTableChanged(Common::PageTable&, std::size_t) override {} |
| 45 | void RecordBreak(GDBStub::BreakpointAddress bkpt); | 45 | void RecordBreak(GDBStub::BreakpointAddress bkpt); |
| 46 | 46 | ||
| 47 | private: | 47 | private: |
diff --git a/src/core/core.cpp b/src/core/core.cpp index bc9e887b6..175a5f2ea 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -3,9 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <array> | 5 | #include <array> |
| 6 | #include <map> | ||
| 7 | #include <memory> | 6 | #include <memory> |
| 8 | #include <thread> | ||
| 9 | #include <utility> | 7 | #include <utility> |
| 10 | 8 | ||
| 11 | #include "common/file_util.h" | 9 | #include "common/file_util.h" |
| @@ -38,8 +36,6 @@ | |||
| 38 | #include "frontend/applets/software_keyboard.h" | 36 | #include "frontend/applets/software_keyboard.h" |
| 39 | #include "frontend/applets/web_browser.h" | 37 | #include "frontend/applets/web_browser.h" |
| 40 | #include "video_core/debug_utils/debug_utils.h" | 38 | #include "video_core/debug_utils/debug_utils.h" |
| 41 | #include "video_core/gpu_asynch.h" | ||
| 42 | #include "video_core/gpu_synch.h" | ||
| 43 | #include "video_core/renderer_base.h" | 39 | #include "video_core/renderer_base.h" |
| 44 | #include "video_core/video_core.h" | 40 | #include "video_core/video_core.h" |
| 45 | 41 | ||
| @@ -81,7 +77,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | |||
| 81 | return vfs->OpenFile(path, FileSys::Mode::Read); | 77 | return vfs->OpenFile(path, FileSys::Mode::Read); |
| 82 | } | 78 | } |
| 83 | struct System::Impl { | 79 | struct System::Impl { |
| 84 | explicit Impl(System& system) : kernel{system} {} | 80 | explicit Impl(System& system) : kernel{system}, cpu_core_manager{system} {} |
| 85 | 81 | ||
| 86 | Cpu& CurrentCpuCore() { | 82 | Cpu& CurrentCpuCore() { |
| 87 | return cpu_core_manager.GetCurrentCore(); | 83 | return cpu_core_manager.GetCurrentCore(); |
| @@ -99,6 +95,7 @@ struct System::Impl { | |||
| 99 | LOG_DEBUG(HW_Memory, "initialized OK"); | 95 | LOG_DEBUG(HW_Memory, "initialized OK"); |
| 100 | 96 | ||
| 101 | core_timing.Initialize(); | 97 | core_timing.Initialize(); |
| 98 | cpu_core_manager.Initialize(); | ||
| 102 | kernel.Initialize(); | 99 | kernel.Initialize(); |
| 103 | 100 | ||
| 104 | const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( | 101 | const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( |
| @@ -120,9 +117,6 @@ struct System::Impl { | |||
| 120 | if (web_browser == nullptr) | 117 | if (web_browser == nullptr) |
| 121 | web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>(); | 118 | web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>(); |
| 122 | 119 | ||
| 123 | auto main_process = Kernel::Process::Create(system, "main"); | ||
| 124 | kernel.MakeCurrentProcess(main_process.get()); | ||
| 125 | |||
| 126 | telemetry_session = std::make_unique<Core::TelemetrySession>(); | 120 | telemetry_session = std::make_unique<Core::TelemetrySession>(); |
| 127 | service_manager = std::make_shared<Service::SM::ServiceManager>(); | 121 | service_manager = std::make_shared<Service::SM::ServiceManager>(); |
| 128 | 122 | ||
| @@ -134,15 +128,9 @@ struct System::Impl { | |||
| 134 | return ResultStatus::ErrorVideoCore; | 128 | return ResultStatus::ErrorVideoCore; |
| 135 | } | 129 | } |
| 136 | 130 | ||
| 137 | is_powered_on = true; | 131 | gpu_core = VideoCore::CreateGPU(system); |
| 138 | |||
| 139 | if (Settings::values.use_asynchronous_gpu_emulation) { | ||
| 140 | gpu_core = std::make_unique<VideoCommon::GPUAsynch>(system, *renderer); | ||
| 141 | } else { | ||
| 142 | gpu_core = std::make_unique<VideoCommon::GPUSynch>(system, *renderer); | ||
| 143 | } | ||
| 144 | 132 | ||
| 145 | cpu_core_manager.Initialize(system); | 133 | is_powered_on = true; |
| 146 | 134 | ||
| 147 | LOG_DEBUG(Core, "Initialized OK"); | 135 | LOG_DEBUG(Core, "Initialized OK"); |
| 148 | 136 | ||
| @@ -179,7 +167,8 @@ struct System::Impl { | |||
| 179 | return init_result; | 167 | return init_result; |
| 180 | } | 168 | } |
| 181 | 169 | ||
| 182 | const Loader::ResultStatus load_result{app_loader->Load(*kernel.CurrentProcess())}; | 170 | auto main_process = Kernel::Process::Create(system, "main"); |
| 171 | const auto [load_result, load_parameters] = app_loader->Load(*main_process); | ||
| 183 | if (load_result != Loader::ResultStatus::Success) { | 172 | if (load_result != Loader::ResultStatus::Success) { |
| 184 | LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result)); | 173 | LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result)); |
| 185 | Shutdown(); | 174 | Shutdown(); |
| @@ -187,6 +176,16 @@ struct System::Impl { | |||
| 187 | return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) + | 176 | return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) + |
| 188 | static_cast<u32>(load_result)); | 177 | static_cast<u32>(load_result)); |
| 189 | } | 178 | } |
| 179 | kernel.MakeCurrentProcess(main_process.get()); | ||
| 180 | |||
| 181 | // Main process has been loaded and been made current. | ||
| 182 | // Begin GPU and CPU execution. | ||
| 183 | gpu_core->Start(); | ||
| 184 | cpu_core_manager.StartThreads(); | ||
| 185 | |||
| 186 | // All threads are started, begin main process execution, now that we're in the clear. | ||
| 187 | main_process->Run(load_parameters->main_thread_priority, | ||
| 188 | load_parameters->main_thread_stack_size); | ||
| 190 | 189 | ||
| 191 | status = ResultStatus::Success; | 190 | status = ResultStatus::Success; |
| 192 | return status; | 191 | return status; |
diff --git a/src/core/cpu_core_manager.cpp b/src/core/cpu_core_manager.cpp index 93bc5619c..8fcb4eeb1 100644 --- a/src/core/cpu_core_manager.cpp +++ b/src/core/cpu_core_manager.cpp | |||
| @@ -19,17 +19,19 @@ void RunCpuCore(const System& system, Cpu& cpu_state) { | |||
| 19 | } | 19 | } |
| 20 | } // Anonymous namespace | 20 | } // Anonymous namespace |
| 21 | 21 | ||
| 22 | CpuCoreManager::CpuCoreManager() = default; | 22 | CpuCoreManager::CpuCoreManager(System& system) : system{system} {} |
| 23 | CpuCoreManager::~CpuCoreManager() = default; | 23 | CpuCoreManager::~CpuCoreManager() = default; |
| 24 | 24 | ||
| 25 | void CpuCoreManager::Initialize(System& system) { | 25 | void CpuCoreManager::Initialize() { |
| 26 | barrier = std::make_unique<CpuBarrier>(); | 26 | barrier = std::make_unique<CpuBarrier>(); |
| 27 | exclusive_monitor = Cpu::MakeExclusiveMonitor(cores.size()); | 27 | exclusive_monitor = Cpu::MakeExclusiveMonitor(cores.size()); |
| 28 | 28 | ||
| 29 | for (std::size_t index = 0; index < cores.size(); ++index) { | 29 | for (std::size_t index = 0; index < cores.size(); ++index) { |
| 30 | cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index); | 30 | cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index); |
| 31 | } | 31 | } |
| 32 | } | ||
| 32 | 33 | ||
| 34 | void CpuCoreManager::StartThreads() { | ||
| 33 | // Create threads for CPU cores 1-3, and build thread_to_cpu map | 35 | // Create threads for CPU cores 1-3, and build thread_to_cpu map |
| 34 | // CPU core 0 is run on the main thread | 36 | // CPU core 0 is run on the main thread |
| 35 | thread_to_cpu[std::this_thread::get_id()] = cores[0].get(); | 37 | thread_to_cpu[std::this_thread::get_id()] = cores[0].get(); |
diff --git a/src/core/cpu_core_manager.h b/src/core/cpu_core_manager.h index a4d70ec56..2cbbf8216 100644 --- a/src/core/cpu_core_manager.h +++ b/src/core/cpu_core_manager.h | |||
| @@ -18,7 +18,7 @@ class System; | |||
| 18 | 18 | ||
| 19 | class CpuCoreManager { | 19 | class CpuCoreManager { |
| 20 | public: | 20 | public: |
| 21 | CpuCoreManager(); | 21 | explicit CpuCoreManager(System& system); |
| 22 | CpuCoreManager(const CpuCoreManager&) = delete; | 22 | CpuCoreManager(const CpuCoreManager&) = delete; |
| 23 | CpuCoreManager(CpuCoreManager&&) = delete; | 23 | CpuCoreManager(CpuCoreManager&&) = delete; |
| 24 | 24 | ||
| @@ -27,7 +27,8 @@ public: | |||
| 27 | CpuCoreManager& operator=(const CpuCoreManager&) = delete; | 27 | CpuCoreManager& operator=(const CpuCoreManager&) = delete; |
| 28 | CpuCoreManager& operator=(CpuCoreManager&&) = delete; | 28 | CpuCoreManager& operator=(CpuCoreManager&&) = delete; |
| 29 | 29 | ||
| 30 | void Initialize(System& system); | 30 | void Initialize(); |
| 31 | void StartThreads(); | ||
| 31 | void Shutdown(); | 32 | void Shutdown(); |
| 32 | 33 | ||
| 33 | Cpu& GetCore(std::size_t index); | 34 | Cpu& GetCore(std::size_t index); |
| @@ -54,6 +55,8 @@ private: | |||
| 54 | 55 | ||
| 55 | /// Map of guest threads to CPU cores | 56 | /// Map of guest threads to CPU cores |
| 56 | std::map<std::thread::id, Cpu*> thread_to_cpu; | 57 | std::map<std::thread::id, Cpu*> thread_to_cpu; |
| 58 | |||
| 59 | System& system; | ||
| 57 | }; | 60 | }; |
| 58 | 61 | ||
| 59 | } // namespace Core | 62 | } // namespace Core |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 4d58e7c69..8539fabe4 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -182,7 +182,12 @@ void KernelCore::AppendNewProcess(SharedPtr<Process> process) { | |||
| 182 | 182 | ||
| 183 | void KernelCore::MakeCurrentProcess(Process* process) { | 183 | void KernelCore::MakeCurrentProcess(Process* process) { |
| 184 | impl->current_process = process; | 184 | impl->current_process = process; |
| 185 | Memory::SetCurrentPageTable(&process->VMManager().page_table); | 185 | |
| 186 | if (process == nullptr) { | ||
| 187 | return; | ||
| 188 | } | ||
| 189 | |||
| 190 | Memory::SetCurrentPageTable(*process); | ||
| 186 | } | 191 | } |
| 187 | 192 | ||
| 188 | Process* KernelCore::CurrentProcess() { | 193 | Process* KernelCore::CurrentProcess() { |
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 8b2b3877d..6d7a7e754 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -28,12 +28,12 @@ namespace { | |||
| 28 | * | 28 | * |
| 29 | * @param owner_process The parent process for the main thread | 29 | * @param owner_process The parent process for the main thread |
| 30 | * @param kernel The kernel instance to create the main thread under. | 30 | * @param kernel The kernel instance to create the main thread under. |
| 31 | * @param entry_point The address at which the thread should start execution | ||
| 32 | * @param priority The priority to give the main thread | 31 | * @param priority The priority to give the main thread |
| 33 | */ | 32 | */ |
| 34 | void SetupMainThread(Process& owner_process, KernelCore& kernel, VAddr entry_point, u32 priority) { | 33 | void SetupMainThread(Process& owner_process, KernelCore& kernel, u32 priority) { |
| 35 | // Initialize new "main" thread | 34 | const auto& vm_manager = owner_process.VMManager(); |
| 36 | const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress(); | 35 | const VAddr entry_point = vm_manager.GetCodeRegionBaseAddress(); |
| 36 | const VAddr stack_top = vm_manager.GetTLSIORegionEndAddress(); | ||
| 37 | auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, | 37 | auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, |
| 38 | owner_process.GetIdealCore(), stack_top, owner_process); | 38 | owner_process.GetIdealCore(), stack_top, owner_process); |
| 39 | 39 | ||
| @@ -105,8 +105,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) { | |||
| 105 | is_64bit_process = metadata.Is64BitProgram(); | 105 | is_64bit_process = metadata.Is64BitProgram(); |
| 106 | 106 | ||
| 107 | vm_manager.Reset(metadata.GetAddressSpaceType()); | 107 | vm_manager.Reset(metadata.GetAddressSpaceType()); |
| 108 | // Ensure that the potentially resized page table is seen by CPU backends. | ||
| 109 | Memory::SetCurrentPageTable(&vm_manager.page_table); | ||
| 110 | 108 | ||
| 111 | const auto& caps = metadata.GetKernelCapabilities(); | 109 | const auto& caps = metadata.GetKernelCapabilities(); |
| 112 | const auto capability_init_result = | 110 | const auto capability_init_result = |
| @@ -118,7 +116,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) { | |||
| 118 | return handle_table.SetSize(capabilities.GetHandleTableSize()); | 116 | return handle_table.SetSize(capabilities.GetHandleTableSize()); |
| 119 | } | 117 | } |
| 120 | 118 | ||
| 121 | void Process::Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size) { | 119 | void Process::Run(s32 main_thread_priority, u64 stack_size) { |
| 122 | // The kernel always ensures that the given stack size is page aligned. | 120 | // The kernel always ensures that the given stack size is page aligned. |
| 123 | main_thread_stack_size = Common::AlignUp(stack_size, Memory::PAGE_SIZE); | 121 | main_thread_stack_size = Common::AlignUp(stack_size, Memory::PAGE_SIZE); |
| 124 | 122 | ||
| @@ -134,7 +132,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size) { | |||
| 134 | vm_manager.LogLayout(); | 132 | vm_manager.LogLayout(); |
| 135 | ChangeStatus(ProcessStatus::Running); | 133 | ChangeStatus(ProcessStatus::Running); |
| 136 | 134 | ||
| 137 | SetupMainThread(*this, kernel, entry_point, main_thread_priority); | 135 | SetupMainThread(*this, kernel, main_thread_priority); |
| 138 | } | 136 | } |
| 139 | 137 | ||
| 140 | void Process::PrepareForTermination() { | 138 | void Process::PrepareForTermination() { |
| @@ -241,9 +239,6 @@ void Process::LoadModule(CodeSet module_, VAddr base_addr) { | |||
| 241 | MapSegment(module_.DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeData); | 239 | MapSegment(module_.DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeData); |
| 242 | 240 | ||
| 243 | code_memory_size += module_.memory.size(); | 241 | code_memory_size += module_.memory.size(); |
| 244 | |||
| 245 | // Clear instruction cache in CPU JIT | ||
| 246 | system.InvalidateCpuInstructionCaches(); | ||
| 247 | } | 242 | } |
| 248 | 243 | ||
| 249 | Process::Process(Core::System& system) | 244 | Process::Process(Core::System& system) |
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index dda52f4c0..bf3b7eef3 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -225,9 +225,12 @@ public: | |||
| 225 | ResultCode LoadFromMetadata(const FileSys::ProgramMetadata& metadata); | 225 | ResultCode LoadFromMetadata(const FileSys::ProgramMetadata& metadata); |
| 226 | 226 | ||
| 227 | /** | 227 | /** |
| 228 | * Applies address space changes and launches the process main thread. | 228 | * Starts the main application thread for this process. |
| 229 | * | ||
| 230 | * @param main_thread_priority The priority for the main thread. | ||
| 231 | * @param stack_size The stack size for the main thread in bytes. | ||
| 229 | */ | 232 | */ |
| 230 | void Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size); | 233 | void Run(s32 main_thread_priority, u64 stack_size); |
| 231 | 234 | ||
| 232 | /** | 235 | /** |
| 233 | * Prepares a process for termination by stopping all of its threads | 236 | * Prepares a process for termination by stopping all of its threads |
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 07aa7a1cd..10b13fb1d 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp | |||
| @@ -86,25 +86,29 @@ FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::Virtua | |||
| 86 | return FileType::Error; | 86 | return FileType::Error; |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process) { | 89 | AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirectory::Load( |
| 90 | Kernel::Process& process) { | ||
| 90 | if (is_loaded) { | 91 | if (is_loaded) { |
| 91 | return ResultStatus::ErrorAlreadyLoaded; | 92 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 92 | } | 93 | } |
| 93 | 94 | ||
| 94 | if (dir == nullptr) { | 95 | if (dir == nullptr) { |
| 95 | if (file == nullptr) | 96 | if (file == nullptr) { |
| 96 | return ResultStatus::ErrorNullFile; | 97 | return {ResultStatus::ErrorNullFile, {}}; |
| 98 | } | ||
| 99 | |||
| 97 | dir = file->GetContainingDirectory(); | 100 | dir = file->GetContainingDirectory(); |
| 98 | } | 101 | } |
| 99 | 102 | ||
| 100 | // Read meta to determine title ID | 103 | // Read meta to determine title ID |
| 101 | FileSys::VirtualFile npdm = dir->GetFile("main.npdm"); | 104 | FileSys::VirtualFile npdm = dir->GetFile("main.npdm"); |
| 102 | if (npdm == nullptr) | 105 | if (npdm == nullptr) { |
| 103 | return ResultStatus::ErrorMissingNPDM; | 106 | return {ResultStatus::ErrorMissingNPDM, {}}; |
| 107 | } | ||
| 104 | 108 | ||
| 105 | ResultStatus result = metadata.Load(npdm); | 109 | const ResultStatus result = metadata.Load(npdm); |
| 106 | if (result != ResultStatus::Success) { | 110 | if (result != ResultStatus::Success) { |
| 107 | return result; | 111 | return {result, {}}; |
| 108 | } | 112 | } |
| 109 | 113 | ||
| 110 | if (override_update) { | 114 | if (override_update) { |
| @@ -114,23 +118,24 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process) | |||
| 114 | 118 | ||
| 115 | // Reread in case PatchExeFS affected the main.npdm | 119 | // Reread in case PatchExeFS affected the main.npdm |
| 116 | npdm = dir->GetFile("main.npdm"); | 120 | npdm = dir->GetFile("main.npdm"); |
| 117 | if (npdm == nullptr) | 121 | if (npdm == nullptr) { |
| 118 | return ResultStatus::ErrorMissingNPDM; | 122 | return {ResultStatus::ErrorMissingNPDM, {}}; |
| 123 | } | ||
| 119 | 124 | ||
| 120 | ResultStatus result2 = metadata.Load(npdm); | 125 | const ResultStatus result2 = metadata.Load(npdm); |
| 121 | if (result2 != ResultStatus::Success) { | 126 | if (result2 != ResultStatus::Success) { |
| 122 | return result2; | 127 | return {result2, {}}; |
| 123 | } | 128 | } |
| 124 | metadata.Print(); | 129 | metadata.Print(); |
| 125 | 130 | ||
| 126 | const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()}; | 131 | const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()}; |
| 127 | if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit || | 132 | if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit || |
| 128 | arch_bits == FileSys::ProgramAddressSpaceType::Is32BitNoMap) { | 133 | arch_bits == FileSys::ProgramAddressSpaceType::Is32BitNoMap) { |
| 129 | return ResultStatus::Error32BitISA; | 134 | return {ResultStatus::Error32BitISA, {}}; |
| 130 | } | 135 | } |
| 131 | 136 | ||
| 132 | if (process.LoadFromMetadata(metadata).IsError()) { | 137 | if (process.LoadFromMetadata(metadata).IsError()) { |
| 133 | return ResultStatus::ErrorUnableToParseKernelMetadata; | 138 | return {ResultStatus::ErrorUnableToParseKernelMetadata, {}}; |
| 134 | } | 139 | } |
| 135 | 140 | ||
| 136 | const FileSys::PatchManager pm(metadata.GetTitleID()); | 141 | const FileSys::PatchManager pm(metadata.GetTitleID()); |
| @@ -150,7 +155,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process) | |||
| 150 | const auto tentative_next_load_addr = | 155 | const auto tentative_next_load_addr = |
| 151 | AppLoader_NSO::LoadModule(process, *module_file, load_addr, should_pass_arguments, pm); | 156 | AppLoader_NSO::LoadModule(process, *module_file, load_addr, should_pass_arguments, pm); |
| 152 | if (!tentative_next_load_addr) { | 157 | if (!tentative_next_load_addr) { |
| 153 | return ResultStatus::ErrorLoadingNSO; | 158 | return {ResultStatus::ErrorLoadingNSO, {}}; |
| 154 | } | 159 | } |
| 155 | 160 | ||
| 156 | next_load_addr = *tentative_next_load_addr; | 161 | next_load_addr = *tentative_next_load_addr; |
| @@ -159,8 +164,6 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process) | |||
| 159 | GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false); | 164 | GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false); |
| 160 | } | 165 | } |
| 161 | 166 | ||
| 162 | process.Run(base_address, metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()); | ||
| 163 | |||
| 164 | // Find the RomFS by searching for a ".romfs" file in this directory | 167 | // Find the RomFS by searching for a ".romfs" file in this directory |
| 165 | const auto& files = dir->GetFiles(); | 168 | const auto& files = dir->GetFiles(); |
| 166 | const auto romfs_iter = | 169 | const auto romfs_iter = |
| @@ -175,7 +178,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process) | |||
| 175 | } | 178 | } |
| 176 | 179 | ||
| 177 | is_loaded = true; | 180 | is_loaded = true; |
| 178 | return ResultStatus::Success; | 181 | return {ResultStatus::Success, |
| 182 | LoadParameters{metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()}}; | ||
| 179 | } | 183 | } |
| 180 | 184 | ||
| 181 | ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile& dir) { | 185 | ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile& dir) { |
diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h index 1615cb5a8..1a65c16a4 100644 --- a/src/core/loader/deconstructed_rom_directory.h +++ b/src/core/loader/deconstructed_rom_directory.h | |||
| @@ -37,7 +37,7 @@ public: | |||
| 37 | return IdentifyType(file); | 37 | return IdentifyType(file); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | ResultStatus Load(Kernel::Process& process) override; | 40 | LoadResult Load(Kernel::Process& process) override; |
| 41 | 41 | ||
| 42 | ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; | 42 | ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; |
| 43 | ResultStatus ReadIcon(std::vector<u8>& buffer) override; | 43 | ResultStatus ReadIcon(std::vector<u8>& buffer) override; |
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 46ac372f6..6d4b02375 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp | |||
| @@ -382,13 +382,15 @@ FileType AppLoader_ELF::IdentifyType(const FileSys::VirtualFile& file) { | |||
| 382 | return FileType::Error; | 382 | return FileType::Error; |
| 383 | } | 383 | } |
| 384 | 384 | ||
| 385 | ResultStatus AppLoader_ELF::Load(Kernel::Process& process) { | 385 | AppLoader_ELF::LoadResult AppLoader_ELF::Load(Kernel::Process& process) { |
| 386 | if (is_loaded) | 386 | if (is_loaded) { |
| 387 | return ResultStatus::ErrorAlreadyLoaded; | 387 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 388 | } | ||
| 388 | 389 | ||
| 389 | std::vector<u8> buffer = file->ReadAllBytes(); | 390 | std::vector<u8> buffer = file->ReadAllBytes(); |
| 390 | if (buffer.size() != file->GetSize()) | 391 | if (buffer.size() != file->GetSize()) { |
| 391 | return ResultStatus::ErrorIncorrectELFFileSize; | 392 | return {ResultStatus::ErrorIncorrectELFFileSize, {}}; |
| 393 | } | ||
| 392 | 394 | ||
| 393 | const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); | 395 | const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); |
| 394 | ElfReader elf_reader(&buffer[0]); | 396 | ElfReader elf_reader(&buffer[0]); |
| @@ -396,10 +398,9 @@ ResultStatus AppLoader_ELF::Load(Kernel::Process& process) { | |||
| 396 | const VAddr entry_point = codeset.entrypoint; | 398 | const VAddr entry_point = codeset.entrypoint; |
| 397 | 399 | ||
| 398 | process.LoadModule(std::move(codeset), entry_point); | 400 | process.LoadModule(std::move(codeset), entry_point); |
| 399 | process.Run(entry_point, 48, Memory::DEFAULT_STACK_SIZE); | ||
| 400 | 401 | ||
| 401 | is_loaded = true; | 402 | is_loaded = true; |
| 402 | return ResultStatus::Success; | 403 | return {ResultStatus::Success, LoadParameters{48, Memory::DEFAULT_STACK_SIZE}}; |
| 403 | } | 404 | } |
| 404 | 405 | ||
| 405 | } // namespace Loader | 406 | } // namespace Loader |
diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index a2d33021c..7ef7770a6 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h | |||
| @@ -26,7 +26,7 @@ public: | |||
| 26 | return IdentifyType(file); | 26 | return IdentifyType(file); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | ResultStatus Load(Kernel::Process& process) override; | 29 | LoadResult Load(Kernel::Process& process) override; |
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| 32 | } // namespace Loader | 32 | } // namespace Loader |
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index bb925f4a6..f7846db52 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h | |||
| @@ -131,6 +131,12 @@ std::ostream& operator<<(std::ostream& os, ResultStatus status); | |||
| 131 | /// Interface for loading an application | 131 | /// Interface for loading an application |
| 132 | class AppLoader : NonCopyable { | 132 | class AppLoader : NonCopyable { |
| 133 | public: | 133 | public: |
| 134 | struct LoadParameters { | ||
| 135 | s32 main_thread_priority; | ||
| 136 | u64 main_thread_stack_size; | ||
| 137 | }; | ||
| 138 | using LoadResult = std::pair<ResultStatus, std::optional<LoadParameters>>; | ||
| 139 | |||
| 134 | explicit AppLoader(FileSys::VirtualFile file); | 140 | explicit AppLoader(FileSys::VirtualFile file); |
| 135 | virtual ~AppLoader(); | 141 | virtual ~AppLoader(); |
| 136 | 142 | ||
| @@ -145,7 +151,7 @@ public: | |||
| 145 | * @param process The newly created process. | 151 | * @param process The newly created process. |
| 146 | * @return The status result of the operation. | 152 | * @return The status result of the operation. |
| 147 | */ | 153 | */ |
| 148 | virtual ResultStatus Load(Kernel::Process& process) = 0; | 154 | virtual LoadResult Load(Kernel::Process& process) = 0; |
| 149 | 155 | ||
| 150 | /** | 156 | /** |
| 151 | * Loads the system mode that this application needs. | 157 | * Loads the system mode that this application needs. |
diff --git a/src/core/loader/nax.cpp b/src/core/loader/nax.cpp index 93a970d10..34efef09a 100644 --- a/src/core/loader/nax.cpp +++ b/src/core/loader/nax.cpp | |||
| @@ -41,31 +41,37 @@ FileType AppLoader_NAX::GetFileType() const { | |||
| 41 | return IdentifyTypeImpl(*nax); | 41 | return IdentifyTypeImpl(*nax); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | ResultStatus AppLoader_NAX::Load(Kernel::Process& process) { | 44 | AppLoader_NAX::LoadResult AppLoader_NAX::Load(Kernel::Process& process) { |
| 45 | if (is_loaded) { | 45 | if (is_loaded) { |
| 46 | return ResultStatus::ErrorAlreadyLoaded; | 46 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | if (nax->GetStatus() != ResultStatus::Success) | 49 | const auto nax_status = nax->GetStatus(); |
| 50 | return nax->GetStatus(); | 50 | if (nax_status != ResultStatus::Success) { |
| 51 | return {nax_status, {}}; | ||
| 52 | } | ||
| 51 | 53 | ||
| 52 | const auto nca = nax->AsNCA(); | 54 | const auto nca = nax->AsNCA(); |
| 53 | if (nca == nullptr) { | 55 | if (nca == nullptr) { |
| 54 | if (!Core::Crypto::KeyManager::KeyFileExists(false)) | 56 | if (!Core::Crypto::KeyManager::KeyFileExists(false)) { |
| 55 | return ResultStatus::ErrorMissingProductionKeyFile; | 57 | return {ResultStatus::ErrorMissingProductionKeyFile, {}}; |
| 56 | return ResultStatus::ErrorNAXInconvertibleToNCA; | 58 | } |
| 59 | |||
| 60 | return {ResultStatus::ErrorNAXInconvertibleToNCA, {}}; | ||
| 57 | } | 61 | } |
| 58 | 62 | ||
| 59 | if (nca->GetStatus() != ResultStatus::Success) | 63 | const auto nca_status = nca->GetStatus(); |
| 60 | return nca->GetStatus(); | 64 | if (nca_status != ResultStatus::Success) { |
| 65 | return {nca_status, {}}; | ||
| 66 | } | ||
| 61 | 67 | ||
| 62 | const auto result = nca_loader->Load(process); | 68 | const auto result = nca_loader->Load(process); |
| 63 | if (result != ResultStatus::Success) | 69 | if (result.first != ResultStatus::Success) { |
| 64 | return result; | 70 | return result; |
| 71 | } | ||
| 65 | 72 | ||
| 66 | is_loaded = true; | 73 | is_loaded = true; |
| 67 | 74 | return result; | |
| 68 | return ResultStatus::Success; | ||
| 69 | } | 75 | } |
| 70 | 76 | ||
| 71 | ResultStatus AppLoader_NAX::ReadRomFS(FileSys::VirtualFile& dir) { | 77 | ResultStatus AppLoader_NAX::ReadRomFS(FileSys::VirtualFile& dir) { |
diff --git a/src/core/loader/nax.h b/src/core/loader/nax.h index f40079574..00f1659c1 100644 --- a/src/core/loader/nax.h +++ b/src/core/loader/nax.h | |||
| @@ -33,7 +33,7 @@ public: | |||
| 33 | 33 | ||
| 34 | FileType GetFileType() const override; | 34 | FileType GetFileType() const override; |
| 35 | 35 | ||
| 36 | ResultStatus Load(Kernel::Process& process) override; | 36 | LoadResult Load(Kernel::Process& process) override; |
| 37 | 37 | ||
| 38 | ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; | 38 | ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; |
| 39 | u64 ReadRomFSIVFCOffset() const override; | 39 | u64 ReadRomFSIVFCOffset() const override; |
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp index ce8196fcf..b3f8f1083 100644 --- a/src/core/loader/nca.cpp +++ b/src/core/loader/nca.cpp | |||
| @@ -30,36 +30,38 @@ FileType AppLoader_NCA::IdentifyType(const FileSys::VirtualFile& file) { | |||
| 30 | return FileType::Error; | 30 | return FileType::Error; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | ResultStatus AppLoader_NCA::Load(Kernel::Process& process) { | 33 | AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::Process& process) { |
| 34 | if (is_loaded) { | 34 | if (is_loaded) { |
| 35 | return ResultStatus::ErrorAlreadyLoaded; | 35 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | const auto result = nca->GetStatus(); | 38 | const auto result = nca->GetStatus(); |
| 39 | if (result != ResultStatus::Success) { | 39 | if (result != ResultStatus::Success) { |
| 40 | return result; | 40 | return {result, {}}; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | if (nca->GetType() != FileSys::NCAContentType::Program) | 43 | if (nca->GetType() != FileSys::NCAContentType::Program) { |
| 44 | return ResultStatus::ErrorNCANotProgram; | 44 | return {ResultStatus::ErrorNCANotProgram, {}}; |
| 45 | } | ||
| 45 | 46 | ||
| 46 | const auto exefs = nca->GetExeFS(); | 47 | const auto exefs = nca->GetExeFS(); |
| 47 | 48 | if (exefs == nullptr) { | |
| 48 | if (exefs == nullptr) | 49 | return {ResultStatus::ErrorNoExeFS, {}}; |
| 49 | return ResultStatus::ErrorNoExeFS; | 50 | } |
| 50 | 51 | ||
| 51 | directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs, true); | 52 | directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs, true); |
| 52 | 53 | ||
| 53 | const auto load_result = directory_loader->Load(process); | 54 | const auto load_result = directory_loader->Load(process); |
| 54 | if (load_result != ResultStatus::Success) | 55 | if (load_result.first != ResultStatus::Success) { |
| 55 | return load_result; | 56 | return load_result; |
| 57 | } | ||
| 56 | 58 | ||
| 57 | if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0) | 59 | if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0) { |
| 58 | Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this)); | 60 | Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this)); |
| 61 | } | ||
| 59 | 62 | ||
| 60 | is_loaded = true; | 63 | is_loaded = true; |
| 61 | 64 | return load_result; | |
| 62 | return ResultStatus::Success; | ||
| 63 | } | 65 | } |
| 64 | 66 | ||
| 65 | ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) { | 67 | ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) { |
diff --git a/src/core/loader/nca.h b/src/core/loader/nca.h index b9f077468..94f0ed677 100644 --- a/src/core/loader/nca.h +++ b/src/core/loader/nca.h | |||
| @@ -33,7 +33,7 @@ public: | |||
| 33 | return IdentifyType(file); | 33 | return IdentifyType(file); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | ResultStatus Load(Kernel::Process& process) override; | 36 | LoadResult Load(Kernel::Process& process) override; |
| 37 | 37 | ||
| 38 | ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; | 38 | ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; |
| 39 | u64 ReadRomFSIVFCOffset() const override; | 39 | u64 ReadRomFSIVFCOffset() const override; |
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 31e4a0c84..6a0ca389b 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp | |||
| @@ -201,25 +201,25 @@ bool AppLoader_NRO::LoadNro(Kernel::Process& process, const FileSys::VfsFile& fi | |||
| 201 | return LoadNroImpl(process, file.ReadAllBytes(), file.GetName(), load_base); | 201 | return LoadNroImpl(process, file.ReadAllBytes(), file.GetName(), load_base); |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | ResultStatus AppLoader_NRO::Load(Kernel::Process& process) { | 204 | AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::Process& process) { |
| 205 | if (is_loaded) { | 205 | if (is_loaded) { |
| 206 | return ResultStatus::ErrorAlreadyLoaded; | 206 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | // Load NRO | 209 | // Load NRO |
| 210 | const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); | 210 | const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); |
| 211 | 211 | ||
| 212 | if (!LoadNro(process, *file, base_address)) { | 212 | if (!LoadNro(process, *file, base_address)) { |
| 213 | return ResultStatus::ErrorLoadingNRO; | 213 | return {ResultStatus::ErrorLoadingNRO, {}}; |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | if (romfs != nullptr) | 216 | if (romfs != nullptr) { |
| 217 | Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this)); | 217 | Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this)); |
| 218 | 218 | } | |
| 219 | process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); | ||
| 220 | 219 | ||
| 221 | is_loaded = true; | 220 | is_loaded = true; |
| 222 | return ResultStatus::Success; | 221 | return {ResultStatus::Success, |
| 222 | LoadParameters{Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE}}; | ||
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | ResultStatus AppLoader_NRO::ReadIcon(std::vector<u8>& buffer) { | 225 | ResultStatus AppLoader_NRO::ReadIcon(std::vector<u8>& buffer) { |
diff --git a/src/core/loader/nro.h b/src/core/loader/nro.h index 85b0ed644..1ffdae805 100644 --- a/src/core/loader/nro.h +++ b/src/core/loader/nro.h | |||
| @@ -37,7 +37,7 @@ public: | |||
| 37 | return IdentifyType(file); | 37 | return IdentifyType(file); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | ResultStatus Load(Kernel::Process& process) override; | 40 | LoadResult Load(Kernel::Process& process) override; |
| 41 | 41 | ||
| 42 | ResultStatus ReadIcon(std::vector<u8>& buffer) override; | 42 | ResultStatus ReadIcon(std::vector<u8>& buffer) override; |
| 43 | ResultStatus ReadProgramId(u64& out_program_id) override; | 43 | ResultStatus ReadProgramId(u64& out_program_id) override; |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index d7c47c197..a86653204 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -169,22 +169,21 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, | |||
| 169 | return load_base + image_size; | 169 | return load_base + image_size; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | ResultStatus AppLoader_NSO::Load(Kernel::Process& process) { | 172 | AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process) { |
| 173 | if (is_loaded) { | 173 | if (is_loaded) { |
| 174 | return ResultStatus::ErrorAlreadyLoaded; | 174 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | // Load module | 177 | // Load module |
| 178 | const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); | 178 | const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); |
| 179 | if (!LoadModule(process, *file, base_address, true)) { | 179 | if (!LoadModule(process, *file, base_address, true)) { |
| 180 | return ResultStatus::ErrorLoadingNSO; | 180 | return {ResultStatus::ErrorLoadingNSO, {}}; |
| 181 | } | 181 | } |
| 182 | LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address); | 182 | LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address); |
| 183 | 183 | ||
| 184 | process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); | ||
| 185 | |||
| 186 | is_loaded = true; | 184 | is_loaded = true; |
| 187 | return ResultStatus::Success; | 185 | return {ResultStatus::Success, |
| 186 | LoadParameters{Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE}}; | ||
| 188 | } | 187 | } |
| 189 | 188 | ||
| 190 | } // namespace Loader | 189 | } // namespace Loader |
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h index 4674c3724..fdce9191c 100644 --- a/src/core/loader/nso.h +++ b/src/core/loader/nso.h | |||
| @@ -84,7 +84,7 @@ public: | |||
| 84 | VAddr load_base, bool should_pass_arguments, | 84 | VAddr load_base, bool should_pass_arguments, |
| 85 | std::optional<FileSys::PatchManager> pm = {}); | 85 | std::optional<FileSys::PatchManager> pm = {}); |
| 86 | 86 | ||
| 87 | ResultStatus Load(Kernel::Process& process) override; | 87 | LoadResult Load(Kernel::Process& process) override; |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| 90 | } // namespace Loader | 90 | } // namespace Loader |
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp index 7da1f8960..ad56bbb38 100644 --- a/src/core/loader/nsp.cpp +++ b/src/core/loader/nsp.cpp | |||
| @@ -72,37 +72,45 @@ FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& file) { | |||
| 72 | return FileType::Error; | 72 | return FileType::Error; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | ResultStatus AppLoader_NSP::Load(Kernel::Process& process) { | 75 | AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process) { |
| 76 | if (is_loaded) { | 76 | if (is_loaded) { |
| 77 | return ResultStatus::ErrorAlreadyLoaded; | 77 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | if (title_id == 0) | 80 | if (title_id == 0) { |
| 81 | return ResultStatus::ErrorNSPMissingProgramNCA; | 81 | return {ResultStatus::ErrorNSPMissingProgramNCA, {}}; |
| 82 | } | ||
| 82 | 83 | ||
| 83 | if (nsp->GetStatus() != ResultStatus::Success) | 84 | const auto nsp_status = nsp->GetStatus(); |
| 84 | return nsp->GetStatus(); | 85 | if (nsp_status != ResultStatus::Success) { |
| 86 | return {nsp_status, {}}; | ||
| 87 | } | ||
| 85 | 88 | ||
| 86 | if (nsp->GetProgramStatus(title_id) != ResultStatus::Success) | 89 | const auto nsp_program_status = nsp->GetProgramStatus(title_id); |
| 87 | return nsp->GetProgramStatus(title_id); | 90 | if (nsp_program_status != ResultStatus::Success) { |
| 91 | return {nsp_program_status, {}}; | ||
| 92 | } | ||
| 88 | 93 | ||
| 89 | if (nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) { | 94 | if (nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) { |
| 90 | if (!Core::Crypto::KeyManager::KeyFileExists(false)) | 95 | if (!Core::Crypto::KeyManager::KeyFileExists(false)) { |
| 91 | return ResultStatus::ErrorMissingProductionKeyFile; | 96 | return {ResultStatus::ErrorMissingProductionKeyFile, {}}; |
| 92 | return ResultStatus::ErrorNSPMissingProgramNCA; | 97 | } |
| 98 | |||
| 99 | return {ResultStatus::ErrorNSPMissingProgramNCA, {}}; | ||
| 93 | } | 100 | } |
| 94 | 101 | ||
| 95 | const auto result = secondary_loader->Load(process); | 102 | const auto result = secondary_loader->Load(process); |
| 96 | if (result != ResultStatus::Success) | 103 | if (result.first != ResultStatus::Success) { |
| 97 | return result; | 104 | return result; |
| 105 | } | ||
| 98 | 106 | ||
| 99 | FileSys::VirtualFile update_raw; | 107 | FileSys::VirtualFile update_raw; |
| 100 | if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) | 108 | if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) { |
| 101 | Service::FileSystem::SetPackedUpdate(std::move(update_raw)); | 109 | Service::FileSystem::SetPackedUpdate(std::move(update_raw)); |
| 110 | } | ||
| 102 | 111 | ||
| 103 | is_loaded = true; | 112 | is_loaded = true; |
| 104 | 113 | return result; | |
| 105 | return ResultStatus::Success; | ||
| 106 | } | 114 | } |
| 107 | 115 | ||
| 108 | ResultStatus AppLoader_NSP::ReadRomFS(FileSys::VirtualFile& file) { | 116 | ResultStatus AppLoader_NSP::ReadRomFS(FileSys::VirtualFile& file) { |
diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h index 953a1b508..85e870bdf 100644 --- a/src/core/loader/nsp.h +++ b/src/core/loader/nsp.h | |||
| @@ -35,7 +35,7 @@ public: | |||
| 35 | return IdentifyType(file); | 35 | return IdentifyType(file); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | ResultStatus Load(Kernel::Process& process) override; | 38 | LoadResult Load(Kernel::Process& process) override; |
| 39 | 39 | ||
| 40 | ResultStatus ReadRomFS(FileSys::VirtualFile& file) override; | 40 | ResultStatus ReadRomFS(FileSys::VirtualFile& file) override; |
| 41 | u64 ReadRomFSIVFCOffset() const override; | 41 | u64 ReadRomFSIVFCOffset() const override; |
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp index 89f7bbf77..1e285a053 100644 --- a/src/core/loader/xci.cpp +++ b/src/core/loader/xci.cpp | |||
| @@ -48,31 +48,35 @@ FileType AppLoader_XCI::IdentifyType(const FileSys::VirtualFile& file) { | |||
| 48 | return FileType::Error; | 48 | return FileType::Error; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | ResultStatus AppLoader_XCI::Load(Kernel::Process& process) { | 51 | AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::Process& process) { |
| 52 | if (is_loaded) { | 52 | if (is_loaded) { |
| 53 | return ResultStatus::ErrorAlreadyLoaded; | 53 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | if (xci->GetStatus() != ResultStatus::Success) | 56 | if (xci->GetStatus() != ResultStatus::Success) { |
| 57 | return xci->GetStatus(); | 57 | return {xci->GetStatus(), {}}; |
| 58 | } | ||
| 58 | 59 | ||
| 59 | if (xci->GetProgramNCAStatus() != ResultStatus::Success) | 60 | if (xci->GetProgramNCAStatus() != ResultStatus::Success) { |
| 60 | return xci->GetProgramNCAStatus(); | 61 | return {xci->GetProgramNCAStatus(), {}}; |
| 62 | } | ||
| 61 | 63 | ||
| 62 | if (!xci->HasProgramNCA() && !Core::Crypto::KeyManager::KeyFileExists(false)) | 64 | if (!xci->HasProgramNCA() && !Core::Crypto::KeyManager::KeyFileExists(false)) { |
| 63 | return ResultStatus::ErrorMissingProductionKeyFile; | 65 | return {ResultStatus::ErrorMissingProductionKeyFile, {}}; |
| 66 | } | ||
| 64 | 67 | ||
| 65 | const auto result = nca_loader->Load(process); | 68 | const auto result = nca_loader->Load(process); |
| 66 | if (result != ResultStatus::Success) | 69 | if (result.first != ResultStatus::Success) { |
| 67 | return result; | 70 | return result; |
| 71 | } | ||
| 68 | 72 | ||
| 69 | FileSys::VirtualFile update_raw; | 73 | FileSys::VirtualFile update_raw; |
| 70 | if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) | 74 | if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) { |
| 71 | Service::FileSystem::SetPackedUpdate(std::move(update_raw)); | 75 | Service::FileSystem::SetPackedUpdate(std::move(update_raw)); |
| 76 | } | ||
| 72 | 77 | ||
| 73 | is_loaded = true; | 78 | is_loaded = true; |
| 74 | 79 | return result; | |
| 75 | return ResultStatus::Success; | ||
| 76 | } | 80 | } |
| 77 | 81 | ||
| 78 | ResultStatus AppLoader_XCI::ReadRomFS(FileSys::VirtualFile& file) { | 82 | ResultStatus AppLoader_XCI::ReadRomFS(FileSys::VirtualFile& file) { |
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h index 436f7387c..ae7145b14 100644 --- a/src/core/loader/xci.h +++ b/src/core/loader/xci.h | |||
| @@ -35,7 +35,7 @@ public: | |||
| 35 | return IdentifyType(file); | 35 | return IdentifyType(file); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | ResultStatus Load(Kernel::Process& process) override; | 38 | LoadResult Load(Kernel::Process& process) override; |
| 39 | 39 | ||
| 40 | ResultStatus ReadRomFS(FileSys::VirtualFile& file) override; | 40 | ResultStatus ReadRomFS(FileSys::VirtualFile& file) override; |
| 41 | u64 ReadRomFSIVFCOffset() const override; | 41 | u64 ReadRomFSIVFCOffset() const override; |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 4e0538bc2..f18f6226b 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -26,16 +26,16 @@ namespace Memory { | |||
| 26 | 26 | ||
| 27 | static Common::PageTable* current_page_table = nullptr; | 27 | static Common::PageTable* current_page_table = nullptr; |
| 28 | 28 | ||
| 29 | void SetCurrentPageTable(Common::PageTable* page_table) { | 29 | void SetCurrentPageTable(Kernel::Process& process) { |
| 30 | current_page_table = page_table; | 30 | current_page_table = &process.VMManager().page_table; |
| 31 | |||
| 32 | const std::size_t address_space_width = process.VMManager().GetAddressSpaceWidth(); | ||
| 31 | 33 | ||
| 32 | auto& system = Core::System::GetInstance(); | 34 | auto& system = Core::System::GetInstance(); |
| 33 | if (system.IsPoweredOn()) { | 35 | system.ArmInterface(0).PageTableChanged(*current_page_table, address_space_width); |
| 34 | system.ArmInterface(0).PageTableChanged(); | 36 | system.ArmInterface(1).PageTableChanged(*current_page_table, address_space_width); |
| 35 | system.ArmInterface(1).PageTableChanged(); | 37 | system.ArmInterface(2).PageTableChanged(*current_page_table, address_space_width); |
| 36 | system.ArmInterface(2).PageTableChanged(); | 38 | system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width); |
| 37 | system.ArmInterface(3).PageTableChanged(); | ||
| 38 | } | ||
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | static void MapPages(Common::PageTable& page_table, VAddr base, u64 size, u8* memory, | 41 | static void MapPages(Common::PageTable& page_table, VAddr base, u64 size, u8* memory, |
diff --git a/src/core/memory.h b/src/core/memory.h index 6845f5fe1..b9fa18b1d 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -40,8 +40,9 @@ enum : VAddr { | |||
| 40 | KERNEL_REGION_END = KERNEL_REGION_VADDR + KERNEL_REGION_SIZE, | 40 | KERNEL_REGION_END = KERNEL_REGION_VADDR + KERNEL_REGION_SIZE, |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | /// Changes the currently active page table. | 43 | /// Changes the currently active page table to that of |
| 44 | void SetCurrentPageTable(Common::PageTable* page_table); | 44 | /// the given process instance. |
| 45 | void SetCurrentPageTable(Kernel::Process& process); | ||
| 45 | 46 | ||
| 46 | /// Determines if the given VAddr is valid for the specified process. | 47 | /// Determines if the given VAddr is valid for the specified process. |
| 47 | bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr); | 48 | bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr); |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index de30ea354..fe6628923 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -207,6 +207,11 @@ public: | |||
| 207 | }; | 207 | }; |
| 208 | } regs{}; | 208 | } regs{}; |
| 209 | 209 | ||
| 210 | /// Performs any additional setup necessary in order to begin GPU emulation. | ||
| 211 | /// This can be used to launch any necessary threads and register any necessary | ||
| 212 | /// core timing events. | ||
| 213 | virtual void Start() = 0; | ||
| 214 | |||
| 210 | /// Push GPU command entries to be processed | 215 | /// Push GPU command entries to be processed |
| 211 | virtual void PushGPUEntries(Tegra::CommandList&& entries) = 0; | 216 | virtual void PushGPUEntries(Tegra::CommandList&& entries) = 0; |
| 212 | 217 | ||
diff --git a/src/video_core/gpu_asynch.cpp b/src/video_core/gpu_asynch.cpp index db507cf04..d4e2553a9 100644 --- a/src/video_core/gpu_asynch.cpp +++ b/src/video_core/gpu_asynch.cpp | |||
| @@ -9,10 +9,14 @@ | |||
| 9 | namespace VideoCommon { | 9 | namespace VideoCommon { |
| 10 | 10 | ||
| 11 | GPUAsynch::GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer) | 11 | GPUAsynch::GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer) |
| 12 | : Tegra::GPU(system, renderer), gpu_thread{system, renderer, *dma_pusher} {} | 12 | : GPU(system, renderer), gpu_thread{system} {} |
| 13 | 13 | ||
| 14 | GPUAsynch::~GPUAsynch() = default; | 14 | GPUAsynch::~GPUAsynch() = default; |
| 15 | 15 | ||
| 16 | void GPUAsynch::Start() { | ||
| 17 | gpu_thread.StartThread(renderer, *dma_pusher); | ||
| 18 | } | ||
| 19 | |||
| 16 | void GPUAsynch::PushGPUEntries(Tegra::CommandList&& entries) { | 20 | void GPUAsynch::PushGPUEntries(Tegra::CommandList&& entries) { |
| 17 | gpu_thread.SubmitList(std::move(entries)); | 21 | gpu_thread.SubmitList(std::move(entries)); |
| 18 | } | 22 | } |
diff --git a/src/video_core/gpu_asynch.h b/src/video_core/gpu_asynch.h index 1dcc61a6c..30be74cba 100644 --- a/src/video_core/gpu_asynch.h +++ b/src/video_core/gpu_asynch.h | |||
| @@ -13,16 +13,13 @@ class RendererBase; | |||
| 13 | 13 | ||
| 14 | namespace VideoCommon { | 14 | namespace VideoCommon { |
| 15 | 15 | ||
| 16 | namespace GPUThread { | ||
| 17 | class ThreadManager; | ||
| 18 | } // namespace GPUThread | ||
| 19 | |||
| 20 | /// Implementation of GPU interface that runs the GPU asynchronously | 16 | /// Implementation of GPU interface that runs the GPU asynchronously |
| 21 | class GPUAsynch : public Tegra::GPU { | 17 | class GPUAsynch : public Tegra::GPU { |
| 22 | public: | 18 | public: |
| 23 | explicit GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer); | 19 | explicit GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer); |
| 24 | ~GPUAsynch() override; | 20 | ~GPUAsynch() override; |
| 25 | 21 | ||
| 22 | void Start() override; | ||
| 26 | void PushGPUEntries(Tegra::CommandList&& entries) override; | 23 | void PushGPUEntries(Tegra::CommandList&& entries) override; |
| 27 | void SwapBuffers( | 24 | void SwapBuffers( |
| 28 | std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) override; | 25 | std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) override; |
diff --git a/src/video_core/gpu_synch.cpp b/src/video_core/gpu_synch.cpp index 2cfc900ed..45e43b1dc 100644 --- a/src/video_core/gpu_synch.cpp +++ b/src/video_core/gpu_synch.cpp | |||
| @@ -8,10 +8,12 @@ | |||
| 8 | namespace VideoCommon { | 8 | namespace VideoCommon { |
| 9 | 9 | ||
| 10 | GPUSynch::GPUSynch(Core::System& system, VideoCore::RendererBase& renderer) | 10 | GPUSynch::GPUSynch(Core::System& system, VideoCore::RendererBase& renderer) |
| 11 | : Tegra::GPU(system, renderer) {} | 11 | : GPU(system, renderer) {} |
| 12 | 12 | ||
| 13 | GPUSynch::~GPUSynch() = default; | 13 | GPUSynch::~GPUSynch() = default; |
| 14 | 14 | ||
| 15 | void GPUSynch::Start() {} | ||
| 16 | |||
| 15 | void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { | 17 | void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { |
| 16 | dma_pusher->Push(std::move(entries)); | 18 | dma_pusher->Push(std::move(entries)); |
| 17 | dma_pusher->DispatchCalls(); | 19 | dma_pusher->DispatchCalls(); |
diff --git a/src/video_core/gpu_synch.h b/src/video_core/gpu_synch.h index 766b5631c..3031fcf72 100644 --- a/src/video_core/gpu_synch.h +++ b/src/video_core/gpu_synch.h | |||
| @@ -18,6 +18,7 @@ public: | |||
| 18 | explicit GPUSynch(Core::System& system, VideoCore::RendererBase& renderer); | 18 | explicit GPUSynch(Core::System& system, VideoCore::RendererBase& renderer); |
| 19 | ~GPUSynch() override; | 19 | ~GPUSynch() override; |
| 20 | 20 | ||
| 21 | void Start() override; | ||
| 21 | void PushGPUEntries(Tegra::CommandList&& entries) override; | 22 | void PushGPUEntries(Tegra::CommandList&& entries) override; |
| 22 | void SwapBuffers( | 23 | void SwapBuffers( |
| 23 | std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) override; | 24 | std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) override; |
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index cc56cf467..c9a2077de 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp | |||
| @@ -55,19 +55,24 @@ static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_p | |||
| 55 | } | 55 | } |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | ThreadManager::ThreadManager(Core::System& system, VideoCore::RendererBase& renderer, | 58 | ThreadManager::ThreadManager(Core::System& system) : system{system} {} |
| 59 | Tegra::DmaPusher& dma_pusher) | ||
| 60 | : system{system}, thread{RunThread, std::ref(renderer), std::ref(dma_pusher), std::ref(state)} { | ||
| 61 | synchronization_event = system.CoreTiming().RegisterEvent( | ||
| 62 | "GPUThreadSynch", [this](u64 fence, s64) { state.WaitForSynchronization(fence); }); | ||
| 63 | } | ||
| 64 | 59 | ||
| 65 | ThreadManager::~ThreadManager() { | 60 | ThreadManager::~ThreadManager() { |
| 61 | if (!thread.joinable()) { | ||
| 62 | return; | ||
| 63 | } | ||
| 64 | |||
| 66 | // Notify GPU thread that a shutdown is pending | 65 | // Notify GPU thread that a shutdown is pending |
| 67 | PushCommand(EndProcessingCommand()); | 66 | PushCommand(EndProcessingCommand()); |
| 68 | thread.join(); | 67 | thread.join(); |
| 69 | } | 68 | } |
| 70 | 69 | ||
| 70 | void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher) { | ||
| 71 | thread = std::thread{RunThread, std::ref(renderer), std::ref(dma_pusher), std::ref(state)}; | ||
| 72 | synchronization_event = system.CoreTiming().RegisterEvent( | ||
| 73 | "GPUThreadSynch", [this](u64 fence, s64) { state.WaitForSynchronization(fence); }); | ||
| 74 | } | ||
| 75 | |||
| 71 | void ThreadManager::SubmitList(Tegra::CommandList&& entries) { | 76 | void ThreadManager::SubmitList(Tegra::CommandList&& entries) { |
| 72 | const u64 fence{PushCommand(SubmitListCommand(std::move(entries)))}; | 77 | const u64 fence{PushCommand(SubmitListCommand(std::move(entries)))}; |
| 73 | const s64 synchronization_ticks{Core::Timing::usToCycles(9000)}; | 78 | const s64 synchronization_ticks{Core::Timing::usToCycles(9000)}; |
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 62bcea5bb..cc14527c7 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h | |||
| @@ -138,10 +138,12 @@ struct SynchState final { | |||
| 138 | /// Class used to manage the GPU thread | 138 | /// Class used to manage the GPU thread |
| 139 | class ThreadManager final { | 139 | class ThreadManager final { |
| 140 | public: | 140 | public: |
| 141 | explicit ThreadManager(Core::System& system, VideoCore::RendererBase& renderer, | 141 | explicit ThreadManager(Core::System& system); |
| 142 | Tegra::DmaPusher& dma_pusher); | ||
| 143 | ~ThreadManager(); | 142 | ~ThreadManager(); |
| 144 | 143 | ||
| 144 | /// Creates and starts the GPU thread. | ||
| 145 | void StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher); | ||
| 146 | |||
| 145 | /// Push GPU command entries to be processed | 147 | /// Push GPU command entries to be processed |
| 146 | void SubmitList(Tegra::CommandList&& entries); | 148 | void SubmitList(Tegra::CommandList&& entries); |
| 147 | 149 | ||
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index cb82ecf3f..60cda0ca3 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/settings.h" | 7 | #include "core/settings.h" |
| 8 | #include "video_core/gpu_asynch.h" | ||
| 9 | #include "video_core/gpu_synch.h" | ||
| 8 | #include "video_core/renderer_base.h" | 10 | #include "video_core/renderer_base.h" |
| 9 | #include "video_core/renderer_opengl/renderer_opengl.h" | 11 | #include "video_core/renderer_opengl/renderer_opengl.h" |
| 10 | #include "video_core/video_core.h" | 12 | #include "video_core/video_core.h" |
| @@ -16,6 +18,14 @@ std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_wind | |||
| 16 | return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system); | 18 | return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system); |
| 17 | } | 19 | } |
| 18 | 20 | ||
| 21 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::System& system) { | ||
| 22 | if (Settings::values.use_asynchronous_gpu_emulation) { | ||
| 23 | return std::make_unique<VideoCommon::GPUAsynch>(system, system.Renderer()); | ||
| 24 | } | ||
| 25 | |||
| 26 | return std::make_unique<VideoCommon::GPUSynch>(system, system.Renderer()); | ||
| 27 | } | ||
| 28 | |||
| 19 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { | 29 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { |
| 20 | return static_cast<u16>( | 30 | return static_cast<u16>( |
| 21 | Settings::values.resolution_factor | 31 | Settings::values.resolution_factor |
diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index 3c583f195..b8e0ac372 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h | |||
| @@ -14,6 +14,10 @@ namespace Core::Frontend { | |||
| 14 | class EmuWindow; | 14 | class EmuWindow; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | namespace Tegra { | ||
| 18 | class GPU; | ||
| 19 | } | ||
| 20 | |||
| 17 | namespace VideoCore { | 21 | namespace VideoCore { |
| 18 | 22 | ||
| 19 | class RendererBase; | 23 | class RendererBase; |
| @@ -27,6 +31,9 @@ class RendererBase; | |||
| 27 | std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, | 31 | std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, |
| 28 | Core::System& system); | 32 | Core::System& system); |
| 29 | 33 | ||
| 34 | /// Creates an emulated GPU instance using the given system context. | ||
| 35 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::System& system); | ||
| 36 | |||
| 30 | u16 GetResolutionScaleFactor(const RendererBase& renderer); | 37 | u16 GetResolutionScaleFactor(const RendererBase& renderer); |
| 31 | 38 | ||
| 32 | } // namespace VideoCore | 39 | } // namespace VideoCore |