diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/arm_interface.h | 14 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic.cpp | 23 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic.h | 6 | ||||
| -rw-r--r-- | src/core/arm/unicorn/arm_unicorn.h | 2 | ||||
| -rw-r--r-- | src/core/core.cpp | 9 | ||||
| -rw-r--r-- | src/core/cpu_core_manager.cpp | 6 | ||||
| -rw-r--r-- | src/core/cpu_core_manager.h | 7 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 7 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 2 | ||||
| -rw-r--r-- | src/core/memory.cpp | 16 | ||||
| -rw-r--r-- | src/core/memory.h | 5 |
11 files changed, 58 insertions, 39 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..2b8ec3ca7 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -81,7 +81,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | |||
| 81 | return vfs->OpenFile(path, FileSys::Mode::Read); | 81 | return vfs->OpenFile(path, FileSys::Mode::Read); |
| 82 | } | 82 | } |
| 83 | struct System::Impl { | 83 | struct System::Impl { |
| 84 | explicit Impl(System& system) : kernel{system} {} | 84 | explicit Impl(System& system) : kernel{system}, cpu_core_manager{system} {} |
| 85 | 85 | ||
| 86 | Cpu& CurrentCpuCore() { | 86 | Cpu& CurrentCpuCore() { |
| 87 | return cpu_core_manager.GetCurrentCore(); | 87 | return cpu_core_manager.GetCurrentCore(); |
| @@ -99,6 +99,7 @@ struct System::Impl { | |||
| 99 | LOG_DEBUG(HW_Memory, "initialized OK"); | 99 | LOG_DEBUG(HW_Memory, "initialized OK"); |
| 100 | 100 | ||
| 101 | core_timing.Initialize(); | 101 | core_timing.Initialize(); |
| 102 | cpu_core_manager.Initialize(); | ||
| 102 | kernel.Initialize(); | 103 | kernel.Initialize(); |
| 103 | 104 | ||
| 104 | const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( | 105 | const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( |
| @@ -142,8 +143,6 @@ struct System::Impl { | |||
| 142 | gpu_core = std::make_unique<VideoCommon::GPUSynch>(system, *renderer); | 143 | gpu_core = std::make_unique<VideoCommon::GPUSynch>(system, *renderer); |
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | cpu_core_manager.Initialize(system); | ||
| 146 | |||
| 147 | LOG_DEBUG(Core, "Initialized OK"); | 146 | LOG_DEBUG(Core, "Initialized OK"); |
| 148 | 147 | ||
| 149 | // Reset counters and set time origin to current frame | 148 | // Reset counters and set time origin to current frame |
| @@ -188,6 +187,10 @@ struct System::Impl { | |||
| 188 | static_cast<u32>(load_result)); | 187 | static_cast<u32>(load_result)); |
| 189 | } | 188 | } |
| 190 | 189 | ||
| 190 | // Main process has been loaded and been made current. | ||
| 191 | // Begin CPU execution. | ||
| 192 | cpu_core_manager.StartThreads(); | ||
| 193 | |||
| 191 | status = ResultStatus::Success; | 194 | status = ResultStatus::Success; |
| 192 | return status; | 195 | return status; |
| 193 | } | 196 | } |
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 4e94048da..94d196e5c 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -107,7 +107,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) { | |||
| 107 | 107 | ||
| 108 | vm_manager.Reset(metadata.GetAddressSpaceType()); | 108 | vm_manager.Reset(metadata.GetAddressSpaceType()); |
| 109 | // Ensure that the potentially resized page table is seen by CPU backends. | 109 | // Ensure that the potentially resized page table is seen by CPU backends. |
| 110 | Memory::SetCurrentPageTable(&vm_manager.page_table); | 110 | Memory::SetCurrentPageTable(*this); |
| 111 | 111 | ||
| 112 | const auto& caps = metadata.GetKernelCapabilities(); | 112 | const auto& caps = metadata.GetKernelCapabilities(); |
| 113 | const auto capability_init_result = | 113 | const auto capability_init_result = |
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); |