mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #4616 from wwylele/core-global-clean
Cleanup System::GetInstance reference - Part 1
This commit is contained in:
		
						commit
						c265f3f507
					
				
					 34 changed files with 234 additions and 160 deletions
				
			
		|  | @ -73,7 +73,7 @@ class DynarmicUserCallbacks final : public Dynarmic::A32::UserCallbacks { | |||
| public: | ||||
|     explicit DynarmicUserCallbacks(ARM_Dynarmic& parent) | ||||
|         : parent(parent), timing(parent.system.CoreTiming()), svc_context(parent.system), | ||||
|           memory(parent.system.Memory()) {} | ||||
|           memory(parent.memory) {} | ||||
|     ~DynarmicUserCallbacks() = default; | ||||
| 
 | ||||
|     std::uint8_t MemoryRead8(VAddr vaddr) override { | ||||
|  | @ -163,9 +163,10 @@ public: | |||
|     Memory::MemorySystem& memory; | ||||
| }; | ||||
| 
 | ||||
| ARM_Dynarmic::ARM_Dynarmic(Core::System& system, PrivilegeMode initial_mode) | ||||
|     : system(system), cb(std::make_unique<DynarmicUserCallbacks>(*this)) { | ||||
|     interpreter_state = std::make_shared<ARMul_State>(system, initial_mode); | ||||
| ARM_Dynarmic::ARM_Dynarmic(Core::System* system, Memory::MemorySystem& memory, | ||||
|                            PrivilegeMode initial_mode) | ||||
|     : system(*system), memory(memory), cb(std::make_unique<DynarmicUserCallbacks>(*this)) { | ||||
|     interpreter_state = std::make_shared<ARMul_State>(system, memory, initial_mode); | ||||
|     PageTableChanged(); | ||||
| } | ||||
| 
 | ||||
|  | @ -174,7 +175,7 @@ ARM_Dynarmic::~ARM_Dynarmic() = default; | |||
| MICROPROFILE_DEFINE(ARM_Jit, "ARM JIT", "ARM JIT", MP_RGB(255, 64, 64)); | ||||
| 
 | ||||
| void ARM_Dynarmic::Run() { | ||||
|     ASSERT(system.Memory().GetCurrentPageTable() == current_page_table); | ||||
|     ASSERT(memory.GetCurrentPageTable() == current_page_table); | ||||
|     MICROPROFILE_SCOPE(ARM_Jit); | ||||
| 
 | ||||
|     jit->Run(); | ||||
|  | @ -281,7 +282,7 @@ void ARM_Dynarmic::InvalidateCacheRange(u32 start_address, std::size_t length) { | |||
| } | ||||
| 
 | ||||
| void ARM_Dynarmic::PageTableChanged() { | ||||
|     current_page_table = system.Memory().GetCurrentPageTable(); | ||||
|     current_page_table = memory.GetCurrentPageTable(); | ||||
| 
 | ||||
|     auto iter = jits.find(current_page_table); | ||||
|     if (iter != jits.end()) { | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ | |||
| 
 | ||||
| namespace Memory { | ||||
| struct PageTable; | ||||
| class MemorySystem; | ||||
| } // namespace Memory
 | ||||
| 
 | ||||
| namespace Core { | ||||
|  | @ -23,7 +24,7 @@ class DynarmicUserCallbacks; | |||
| 
 | ||||
| class ARM_Dynarmic final : public ARM_Interface { | ||||
| public: | ||||
|     ARM_Dynarmic(Core::System& system, PrivilegeMode initial_mode); | ||||
|     ARM_Dynarmic(Core::System* system, Memory::MemorySystem& memory, PrivilegeMode initial_mode); | ||||
|     ~ARM_Dynarmic(); | ||||
| 
 | ||||
|     void Run() override; | ||||
|  | @ -55,6 +56,7 @@ public: | |||
| private: | ||||
|     friend class DynarmicUserCallbacks; | ||||
|     Core::System& system; | ||||
|     Memory::MemorySystem& memory; | ||||
|     std::unique_ptr<DynarmicUserCallbacks> cb; | ||||
|     std::unique_ptr<Dynarmic::A32::Jit> MakeJit(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -68,14 +68,17 @@ private: | |||
|     u32 fpexc; | ||||
| }; | ||||
| 
 | ||||
| ARM_DynCom::ARM_DynCom(Core::System& system, PrivilegeMode initial_mode) : system(system) { | ||||
|     state = std::make_unique<ARMul_State>(system, initial_mode); | ||||
| ARM_DynCom::ARM_DynCom(Core::System* system, Memory::MemorySystem& memory, | ||||
|                        PrivilegeMode initial_mode) | ||||
|     : system(system) { | ||||
|     state = std::make_unique<ARMul_State>(system, memory, initial_mode); | ||||
| } | ||||
| 
 | ||||
| ARM_DynCom::~ARM_DynCom() {} | ||||
| 
 | ||||
| void ARM_DynCom::Run() { | ||||
|     ExecuteInstructions(std::max<s64>(system.CoreTiming().GetDowncount(), 0)); | ||||
|     DEBUG_ASSERT(system != nullptr); | ||||
|     ExecuteInstructions(std::max<s64>(system->CoreTiming().GetDowncount(), 0)); | ||||
| } | ||||
| 
 | ||||
| void ARM_DynCom::Step() { | ||||
|  | @ -146,7 +149,9 @@ void ARM_DynCom::SetCP15Register(CP15Register reg, u32 value) { | |||
| void ARM_DynCom::ExecuteInstructions(u64 num_instructions) { | ||||
|     state->NumInstrsToExecute = num_instructions; | ||||
|     unsigned ticks_executed = InterpreterMainLoop(state.get()); | ||||
|     system.CoreTiming().AddTicks(ticks_executed); | ||||
|     if (system != nullptr) { | ||||
|         system->CoreTiming().AddTicks(ticks_executed); | ||||
|     } | ||||
|     state->ServeBreak(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,9 +14,14 @@ namespace Core { | |||
| struct System; | ||||
| } | ||||
| 
 | ||||
| namespace Memory { | ||||
| class MemorySystem; | ||||
| } | ||||
| 
 | ||||
| class ARM_DynCom final : public ARM_Interface { | ||||
| public: | ||||
|     explicit ARM_DynCom(Core::System& system, PrivilegeMode initial_mode); | ||||
|     explicit ARM_DynCom(Core::System* system, Memory::MemorySystem& memory, | ||||
|                         PrivilegeMode initial_mode); | ||||
|     ~ARM_DynCom(); | ||||
| 
 | ||||
|     void Run() override; | ||||
|  | @ -48,6 +53,6 @@ public: | |||
| private: | ||||
|     void ExecuteInstructions(u64 num_instructions); | ||||
| 
 | ||||
|     Core::System& system; | ||||
|     Core::System* system; | ||||
|     std::unique_ptr<ARMul_State> state; | ||||
| }; | ||||
|  |  | |||
|  | @ -811,7 +811,7 @@ MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64)); | |||
| static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, | ||||
|                                                     ARM_INST_PTR& inst_base) { | ||||
|     u32 inst_size = 4; | ||||
|     u32 inst = cpu->system.Memory().Read32(phys_addr & 0xFFFFFFFC); | ||||
|     u32 inst = cpu->memory.Read32(phys_addr & 0xFFFFFFFC); | ||||
| 
 | ||||
|     // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM
 | ||||
|     // instruction
 | ||||
|  | @ -3859,12 +3859,13 @@ SUB_INST : { | |||
| } | ||||
| SWI_INST : { | ||||
|     if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||||
|         DEBUG_ASSERT(cpu->system != nullptr); | ||||
|         swi_inst* const inst_cream = (swi_inst*)inst_base->component; | ||||
|         cpu->system.CoreTiming().AddTicks(num_instrs); | ||||
|         cpu->system->CoreTiming().AddTicks(num_instrs); | ||||
|         cpu->NumInstrsToExecute = | ||||
|             num_instrs >= cpu->NumInstrsToExecute ? 0 : cpu->NumInstrsToExecute - num_instrs; | ||||
|         num_instrs = 0; | ||||
|         Kernel::SVCContext{cpu->system}.CallSVC(inst_cream->num & 0xFFFF); | ||||
|         Kernel::SVCContext{*cpu->system}.CallSVC(inst_cream->num & 0xFFFF); | ||||
|         // The kernel would call ERET to get here, which clears exclusive memory state.
 | ||||
|         cpu->UnsetExclusiveMemoryAddress(); | ||||
|     } | ||||
|  |  | |||
|  | @ -10,7 +10,9 @@ | |||
| #include "core/core.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| ARMul_State::ARMul_State(Core::System& system, PrivilegeMode initial_mode) : system(system) { | ||||
| ARMul_State::ARMul_State(Core::System* system, Memory::MemorySystem& memory, | ||||
|                          PrivilegeMode initial_mode) | ||||
|     : system(system), memory(memory) { | ||||
|     Reset(); | ||||
|     ChangePrivilegeMode(initial_mode); | ||||
| } | ||||
|  | @ -191,13 +193,13 @@ static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) { | |||
| u8 ARMul_State::ReadMemory8(u32 address) const { | ||||
|     CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); | ||||
| 
 | ||||
|     return system.Memory().Read8(address); | ||||
|     return memory.Read8(address); | ||||
| } | ||||
| 
 | ||||
| u16 ARMul_State::ReadMemory16(u32 address) const { | ||||
|     CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); | ||||
| 
 | ||||
|     u16 data = system.Memory().Read16(address); | ||||
|     u16 data = memory.Read16(address); | ||||
| 
 | ||||
|     if (InBigEndianMode()) | ||||
|         data = Common::swap16(data); | ||||
|  | @ -208,7 +210,7 @@ u16 ARMul_State::ReadMemory16(u32 address) const { | |||
| u32 ARMul_State::ReadMemory32(u32 address) const { | ||||
|     CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); | ||||
| 
 | ||||
|     u32 data = system.Memory().Read32(address); | ||||
|     u32 data = memory.Read32(address); | ||||
| 
 | ||||
|     if (InBigEndianMode()) | ||||
|         data = Common::swap32(data); | ||||
|  | @ -219,7 +221,7 @@ u32 ARMul_State::ReadMemory32(u32 address) const { | |||
| u64 ARMul_State::ReadMemory64(u32 address) const { | ||||
|     CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); | ||||
| 
 | ||||
|     u64 data = system.Memory().Read64(address); | ||||
|     u64 data = memory.Read64(address); | ||||
| 
 | ||||
|     if (InBigEndianMode()) | ||||
|         data = Common::swap64(data); | ||||
|  | @ -230,7 +232,7 @@ u64 ARMul_State::ReadMemory64(u32 address) const { | |||
| void ARMul_State::WriteMemory8(u32 address, u8 data) { | ||||
|     CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); | ||||
| 
 | ||||
|     system.Memory().Write8(address, data); | ||||
|     memory.Write8(address, data); | ||||
| } | ||||
| 
 | ||||
| void ARMul_State::WriteMemory16(u32 address, u16 data) { | ||||
|  | @ -239,7 +241,7 @@ void ARMul_State::WriteMemory16(u32 address, u16 data) { | |||
|     if (InBigEndianMode()) | ||||
|         data = Common::swap16(data); | ||||
| 
 | ||||
|     system.Memory().Write16(address, data); | ||||
|     memory.Write16(address, data); | ||||
| } | ||||
| 
 | ||||
| void ARMul_State::WriteMemory32(u32 address, u32 data) { | ||||
|  | @ -248,7 +250,7 @@ void ARMul_State::WriteMemory32(u32 address, u32 data) { | |||
|     if (InBigEndianMode()) | ||||
|         data = Common::swap32(data); | ||||
| 
 | ||||
|     system.Memory().Write32(address, data); | ||||
|     memory.Write32(address, data); | ||||
| } | ||||
| 
 | ||||
| void ARMul_State::WriteMemory64(u32 address, u64 data) { | ||||
|  | @ -257,7 +259,7 @@ void ARMul_State::WriteMemory64(u32 address, u64 data) { | |||
|     if (InBigEndianMode()) | ||||
|         data = Common::swap64(data); | ||||
| 
 | ||||
|     system.Memory().Write64(address, data); | ||||
|     memory.Write64(address, data); | ||||
| } | ||||
| 
 | ||||
| // Reads from the CP15 registers. Used with implementation of the MRC instruction.
 | ||||
|  | @ -603,8 +605,9 @@ void ARMul_State::ServeBreak() { | |||
|     if (last_bkpt_hit) { | ||||
|         Reg[15] = last_bkpt.address; | ||||
|     } | ||||
|     Kernel::Thread* thread = system.Kernel().GetThreadManager().GetCurrentThread(); | ||||
|     system.CPU().SaveContext(thread->context); | ||||
|     DEBUG_ASSERT(system != nullptr); | ||||
|     Kernel::Thread* thread = system->Kernel().GetThreadManager().GetCurrentThread(); | ||||
|     system->CPU().SaveContext(thread->context); | ||||
|     if (last_bkpt_hit || GDBStub::GetCpuStepFlag()) { | ||||
|         last_bkpt_hit = false; | ||||
|         GDBStub::Break(); | ||||
|  |  | |||
|  | @ -27,6 +27,10 @@ namespace Core { | |||
| class System; | ||||
| } | ||||
| 
 | ||||
| namespace Memory { | ||||
| class MemorySystem; | ||||
| } | ||||
| 
 | ||||
| // Signal levels
 | ||||
| enum { LOW = 0, HIGH = 1, LOWHIGH = 1, HIGHLOW = 2 }; | ||||
| 
 | ||||
|  | @ -143,7 +147,8 @@ enum { | |||
| 
 | ||||
| struct ARMul_State final { | ||||
| public: | ||||
|     explicit ARMul_State(Core::System& system, PrivilegeMode initial_mode); | ||||
|     explicit ARMul_State(Core::System* system, Memory::MemorySystem& memory, | ||||
|                          PrivilegeMode initial_mode); | ||||
| 
 | ||||
|     void ChangePrivilegeMode(u32 new_mode); | ||||
|     void Reset(); | ||||
|  | @ -201,7 +206,8 @@ public: | |||
| 
 | ||||
|     void ServeBreak(); | ||||
| 
 | ||||
|     Core::System& system; | ||||
|     Core::System* system; | ||||
|     Memory::MemorySystem& memory; | ||||
| 
 | ||||
|     std::array<u32, 16> Reg{}; // The current register file
 | ||||
|     std::array<u32, 2> Reg_usr{}; | ||||
|  |  | |||
|  | @ -174,19 +174,23 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) { | |||
| 
 | ||||
|     timing = std::make_unique<Timing>(); | ||||
| 
 | ||||
|     kernel = std::make_unique<Kernel::KernelSystem>(*memory, system_mode); | ||||
|     kernel = std::make_unique<Kernel::KernelSystem>(*memory, *timing, | ||||
|                                                     [this] { PrepareReschedule(); }, system_mode); | ||||
| 
 | ||||
|     if (Settings::values.use_cpu_jit) { | ||||
| #ifdef ARCHITECTURE_x86_64 | ||||
|         cpu_core = std::make_unique<ARM_Dynarmic>(*this, USER32MODE); | ||||
|         cpu_core = std::make_unique<ARM_Dynarmic>(this, *memory, USER32MODE); | ||||
| #else | ||||
|         cpu_core = std::make_unique<ARM_DynCom>(*this, USER32MODE); | ||||
|         cpu_core = std::make_unique<ARM_DynCom>(this, *memory, USER32MODE); | ||||
|         LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); | ||||
| #endif | ||||
|     } else { | ||||
|         cpu_core = std::make_unique<ARM_DynCom>(*this, USER32MODE); | ||||
|         cpu_core = std::make_unique<ARM_DynCom>(this, *memory, USER32MODE); | ||||
|     } | ||||
| 
 | ||||
|     kernel->GetThreadManager().SetCPU(*cpu_core); | ||||
|     memory->SetCPU(*cpu_core); | ||||
| 
 | ||||
|     if (Settings::values.enable_dsp_lle) { | ||||
|         dsp_core = std::make_unique<AudioCore::DspLle>(*memory, | ||||
|                                                        Settings::values.enable_dsp_lle_multithread); | ||||
|  |  | |||
|  | @ -270,8 +270,6 @@ private: | |||
| 
 | ||||
|     std::unique_ptr<Service::FS::ArchiveManager> archive_manager; | ||||
| 
 | ||||
| public: // HACK: this is temporary exposed for tests,
 | ||||
|         // due to WIP kernel refactor causing desync state in memory
 | ||||
|     std::unique_ptr<Memory::MemorySystem> memory; | ||||
|     std::unique_ptr<Kernel::KernelSystem> kernel; | ||||
|     std::unique_ptr<Timing> timing; | ||||
|  |  | |||
|  | @ -16,11 +16,11 @@ | |||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread> dst_thread, | ||||
|                                   VAddr src_address, VAddr dst_address, | ||||
| ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, SharedPtr<Thread> src_thread, | ||||
|                                   SharedPtr<Thread> dst_thread, VAddr src_address, | ||||
|                                   VAddr dst_address, | ||||
|                                   std::vector<MappedBufferContext>& mapped_buffer_context, | ||||
|                                   bool reply) { | ||||
|     Memory::MemorySystem& memory = Core::System::GetInstance().Memory(); | ||||
|     auto& src_process = src_thread->owner_process; | ||||
|     auto& dst_process = dst_thread->owner_process; | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,6 +10,10 @@ | |||
| #include "core/hle/ipc.h" | ||||
| #include "core/hle/kernel/thread.h" | ||||
| 
 | ||||
| namespace Memory { | ||||
| class MemorySystem; | ||||
| } | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| struct MappedBufferContext { | ||||
|  | @ -23,8 +27,9 @@ struct MappedBufferContext { | |||
| }; | ||||
| 
 | ||||
| /// Performs IPC command buffer translation from one process to another.
 | ||||
| ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread> dst_thread, | ||||
|                                   VAddr src_address, VAddr dst_address, | ||||
| ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, SharedPtr<Thread> src_thread, | ||||
|                                   SharedPtr<Thread> dst_thread, VAddr src_address, | ||||
|                                   VAddr dst_address, | ||||
|                                   std::vector<MappedBufferContext>& mapped_buffer_context, | ||||
|                                   bool reply); | ||||
| } // namespace Kernel
 | ||||
|  |  | |||
|  | @ -16,12 +16,15 @@ | |||
| namespace Kernel { | ||||
| 
 | ||||
| /// Initialize the kernel
 | ||||
| KernelSystem::KernelSystem(Memory::MemorySystem& memory, u32 system_mode) : memory(memory) { | ||||
| KernelSystem::KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing, | ||||
|                            std::function<void()> prepare_reschedule_callback, u32 system_mode) | ||||
|     : memory(memory), timing(timing), | ||||
|       prepare_reschedule_callback(std::move(prepare_reschedule_callback)) { | ||||
|     MemoryInit(system_mode); | ||||
| 
 | ||||
|     resource_limits = std::make_unique<ResourceLimitList>(*this); | ||||
|     thread_manager = std::make_unique<ThreadManager>(*this); | ||||
|     timer_manager = std::make_unique<TimerManager>(); | ||||
|     timer_manager = std::make_unique<TimerManager>(timing); | ||||
| } | ||||
| 
 | ||||
| /// Shutdown the kernel
 | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| 
 | ||||
| #include <array> | ||||
| #include <atomic> | ||||
| #include <functional> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <unordered_map> | ||||
|  | @ -27,6 +28,10 @@ namespace Memory { | |||
| class MemorySystem; | ||||
| } | ||||
| 
 | ||||
| namespace Core { | ||||
| class Timing; | ||||
| } | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| class AddressArbiter; | ||||
|  | @ -78,7 +83,8 @@ using SharedPtr = boost::intrusive_ptr<T>; | |||
| 
 | ||||
| class KernelSystem { | ||||
| public: | ||||
|     explicit KernelSystem(Memory::MemorySystem& memory, u32 system_mode); | ||||
|     explicit KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing, | ||||
|                           std::function<void()> prepare_reschedule_callback, u32 system_mode); | ||||
|     ~KernelSystem(); | ||||
| 
 | ||||
|     /**
 | ||||
|  | @ -224,14 +230,22 @@ public: | |||
|     /// Adds a port to the named port table
 | ||||
|     void AddNamedPort(std::string name, SharedPtr<ClientPort> port); | ||||
| 
 | ||||
|     void PrepareReschedule() { | ||||
|         prepare_reschedule_callback(); | ||||
|     } | ||||
| 
 | ||||
|     /// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort
 | ||||
|     std::unordered_map<std::string, SharedPtr<ClientPort>> named_ports; | ||||
| 
 | ||||
|     Memory::MemorySystem& memory; | ||||
| 
 | ||||
|     Core::Timing& timing; | ||||
| 
 | ||||
| private: | ||||
|     void MemoryInit(u32 mem_type); | ||||
| 
 | ||||
|     std::function<void()> prepare_reschedule_callback; | ||||
| 
 | ||||
|     std::unique_ptr<ResourceLimitList> resource_limits; | ||||
|     std::atomic<u32> next_object_id{0}; | ||||
| 
 | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ void KernelSystem::MemoryInit(u32 mem_type) { | |||
|     config_mem.sys_mem_alloc = memory_regions[1].size; | ||||
|     config_mem.base_mem_alloc = memory_regions[2].size; | ||||
| 
 | ||||
|     shared_page_handler = std::make_unique<SharedPage::Handler>(); | ||||
|     shared_page_handler = std::make_unique<SharedPage::Handler>(timing); | ||||
| } | ||||
| 
 | ||||
| MemoryRegionInfo* KernelSystem::GetMemoryRegion(MemoryRegion region) { | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ void ReleaseThreadMutexes(Thread* thread) { | |||
|     thread->held_mutexes.clear(); | ||||
| } | ||||
| 
 | ||||
| Mutex::Mutex(KernelSystem& kernel) : WaitObject(kernel) {} | ||||
| Mutex::Mutex(KernelSystem& kernel) : WaitObject(kernel), kernel(kernel) {} | ||||
| Mutex::~Mutex() {} | ||||
| 
 | ||||
| SharedPtr<Mutex> KernelSystem::CreateMutex(bool initial_locked, std::string name) { | ||||
|  | @ -54,7 +54,7 @@ void Mutex::Acquire(Thread* thread) { | |||
|         thread->held_mutexes.insert(this); | ||||
|         holding_thread = thread; | ||||
|         thread->UpdatePriority(); | ||||
|         Core::System::GetInstance().PrepareReschedule(); | ||||
|         kernel.PrepareReschedule(); | ||||
|     } | ||||
| 
 | ||||
|     lock_count++; | ||||
|  | @ -87,7 +87,7 @@ ResultCode Mutex::Release(Thread* thread) { | |||
|         holding_thread->UpdatePriority(); | ||||
|         holding_thread = nullptr; | ||||
|         WakeupAllWaitingThreads(); | ||||
|         Core::System::GetInstance().PrepareReschedule(); | ||||
|         kernel.PrepareReschedule(); | ||||
|     } | ||||
| 
 | ||||
|     return RESULT_SUCCESS; | ||||
|  |  | |||
|  | @ -57,6 +57,7 @@ private: | |||
|     ~Mutex() override; | ||||
| 
 | ||||
|     friend class KernelSystem; | ||||
|     KernelSystem& kernel; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ static std::chrono::seconds GetInitTime() { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| Handler::Handler() { | ||||
| Handler::Handler(Core::Timing& timing) : timing(timing) { | ||||
|     std::memset(&shared_page, 0, sizeof(shared_page)); | ||||
| 
 | ||||
|     shared_page.running_hw = 0x1; // product
 | ||||
|  | @ -54,9 +54,9 @@ Handler::Handler() { | |||
|     init_time = GetInitTime(); | ||||
| 
 | ||||
|     using namespace std::placeholders; | ||||
|     update_time_event = Core::System::GetInstance().CoreTiming().RegisterEvent( | ||||
|         "SharedPage::UpdateTimeCallback", std::bind(&Handler::UpdateTimeCallback, this, _1, _2)); | ||||
|     Core::System::GetInstance().CoreTiming().ScheduleEvent(0, update_time_event); | ||||
|     update_time_event = timing.RegisterEvent("SharedPage::UpdateTimeCallback", | ||||
|                                              std::bind(&Handler::UpdateTimeCallback, this, _1, _2)); | ||||
|     timing.ScheduleEvent(0, update_time_event); | ||||
| 
 | ||||
|     float slidestate = | ||||
|         Settings::values.toggle_3d ? (float_le)Settings::values.factor_3d / 100 : 0.0f; | ||||
|  | @ -66,8 +66,7 @@ Handler::Handler() { | |||
| /// Gets system time in 3DS format. The epoch is Jan 1900, and the unit is millisecond.
 | ||||
| u64 Handler::GetSystemTime() const { | ||||
|     std::chrono::milliseconds now = | ||||
|         init_time + std::chrono::duration_cast<std::chrono::milliseconds>( | ||||
|                         Core::System::GetInstance().CoreTiming().GetGlobalTimeUs()); | ||||
|         init_time + std::chrono::duration_cast<std::chrono::milliseconds>(timing.GetGlobalTimeUs()); | ||||
| 
 | ||||
|     // 3DS system does't allow user to set a time before Jan 1 2000,
 | ||||
|     // so we use it as an auxiliary epoch to calculate the console time.
 | ||||
|  | @ -98,15 +97,14 @@ void Handler::UpdateTimeCallback(u64 userdata, int cycles_late) { | |||
|         shared_page.date_time_counter % 2 ? shared_page.date_time_0 : shared_page.date_time_1; | ||||
| 
 | ||||
|     date_time.date_time = GetSystemTime(); | ||||
|     date_time.update_tick = Core::System::GetInstance().CoreTiming().GetTicks(); | ||||
|     date_time.update_tick = timing.GetTicks(); | ||||
|     date_time.tick_to_second_coefficient = BASE_CLOCK_RATE_ARM11; | ||||
|     date_time.tick_offset = 0; | ||||
| 
 | ||||
|     ++shared_page.date_time_counter; | ||||
| 
 | ||||
|     // system time is updated hourly
 | ||||
|     Core::System::GetInstance().CoreTiming().ScheduleEvent(msToCycles(60 * 60 * 1000) - cycles_late, | ||||
|                                                            update_time_event); | ||||
|     timing.ScheduleEvent(msToCycles(60 * 60 * 1000) - cycles_late, update_time_event); | ||||
| } | ||||
| 
 | ||||
| void Handler::SetMacAddress(const MacAddress& addr) { | ||||
|  |  | |||
|  | @ -23,7 +23,8 @@ | |||
| 
 | ||||
| namespace Core { | ||||
| struct TimingEventType; | ||||
| } | ||||
| class Timing; | ||||
| } // namespace Core
 | ||||
| 
 | ||||
| namespace SharedPage { | ||||
| 
 | ||||
|  | @ -83,7 +84,7 @@ static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, | |||
| 
 | ||||
| class Handler { | ||||
| public: | ||||
|     Handler(); | ||||
|     Handler(Core::Timing& timing); | ||||
| 
 | ||||
|     void SetMacAddress(const MacAddress&); | ||||
| 
 | ||||
|  | @ -98,6 +99,7 @@ public: | |||
| private: | ||||
|     u64 GetSystemTime() const; | ||||
|     void UpdateTimeCallback(u64 userdata, int cycles_late); | ||||
|     Core::Timing& timing; | ||||
|     Core::TimingEventType* update_time_event; | ||||
|     std::chrono::seconds init_time; | ||||
| 
 | ||||
|  |  | |||
|  | @ -592,7 +592,8 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle | |||
|     } | ||||
| } | ||||
| 
 | ||||
| static ResultCode ReceiveIPCRequest(SharedPtr<ServerSession> server_session, | ||||
| static ResultCode ReceiveIPCRequest(Memory::MemorySystem& memory, | ||||
|                                     SharedPtr<ServerSession> server_session, | ||||
|                                     SharedPtr<Thread> thread) { | ||||
|     if (server_session->parent->client == nullptr) { | ||||
|         return ERR_SESSION_CLOSED_BY_REMOTE; | ||||
|  | @ -602,7 +603,7 @@ static ResultCode ReceiveIPCRequest(SharedPtr<ServerSession> server_session, | |||
|     VAddr source_address = server_session->currently_handling->GetCommandBufferAddress(); | ||||
| 
 | ||||
|     ResultCode translation_result = | ||||
|         TranslateCommandBuffer(server_session->currently_handling, thread, source_address, | ||||
|         TranslateCommandBuffer(memory, server_session->currently_handling, thread, source_address, | ||||
|                                target_address, server_session->mapped_buffer_context, false); | ||||
| 
 | ||||
|     // If a translation error occurred, immediately resume the client thread.
 | ||||
|  | @ -669,7 +670,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co | |||
|         VAddr target_address = request_thread->GetCommandBufferAddress(); | ||||
| 
 | ||||
|         ResultCode translation_result = | ||||
|             TranslateCommandBuffer(thread, request_thread, source_address, target_address, | ||||
|             TranslateCommandBuffer(memory, thread, request_thread, source_address, target_address, | ||||
|                                    session->mapped_buffer_context, true); | ||||
| 
 | ||||
|         // Note: The real kernel seems to always panic if the Server->Client buffer translation
 | ||||
|  | @ -705,7 +706,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co | |||
|             return RESULT_SUCCESS; | ||||
| 
 | ||||
|         auto server_session = static_cast<ServerSession*>(object); | ||||
|         return ReceiveIPCRequest(server_session, thread); | ||||
|         return ReceiveIPCRequest(memory, server_session, thread); | ||||
|     } | ||||
| 
 | ||||
|     // No objects were ready to be acquired, prepare to suspend the thread.
 | ||||
|  | @ -721,8 +722,9 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co | |||
| 
 | ||||
|     thread->wait_objects = std::move(objects); | ||||
| 
 | ||||
|     thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread, | ||||
|                                  SharedPtr<WaitObject> object) { | ||||
|     thread->wakeup_callback = [& memory = this->memory](ThreadWakeupReason reason, | ||||
|                                                         SharedPtr<Thread> thread, | ||||
|                                                         SharedPtr<WaitObject> object) { | ||||
|         ASSERT(thread->status == ThreadStatus::WaitSynchAny); | ||||
|         ASSERT(reason == ThreadWakeupReason::Signal); | ||||
| 
 | ||||
|  | @ -730,7 +732,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co | |||
| 
 | ||||
|         if (object->GetHandleType() == HandleType::ServerSession) { | ||||
|             auto server_session = DynamicObjectCast<ServerSession>(object); | ||||
|             result = ReceiveIPCRequest(server_session, thread); | ||||
|             result = ReceiveIPCRequest(memory, server_session, thread); | ||||
|         } | ||||
| 
 | ||||
|         thread->SetWaitSynchronizationResult(result); | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ u32 ThreadManager::NewThreadId() { | |||
| } | ||||
| 
 | ||||
| Thread::Thread(KernelSystem& kernel) | ||||
|     : WaitObject(kernel), context(Core::CPU().NewContext()), | ||||
|     : WaitObject(kernel), context(kernel.GetThreadManager().NewContext()), | ||||
|       thread_manager(kernel.GetThreadManager()) {} | ||||
| Thread::~Thread() {} | ||||
| 
 | ||||
|  | @ -48,8 +48,7 @@ Thread* ThreadManager::GetCurrentThread() const { | |||
| 
 | ||||
| void Thread::Stop() { | ||||
|     // Cancel any outstanding wakeup events for this thread
 | ||||
|     Core::System::GetInstance().CoreTiming().UnscheduleEvent(thread_manager.ThreadWakeupEventType, | ||||
|                                                              thread_id); | ||||
|     thread_manager.kernel.timing.UnscheduleEvent(thread_manager.ThreadWakeupEventType, thread_id); | ||||
|     thread_manager.wakeup_callback_table.erase(thread_id); | ||||
| 
 | ||||
|     // Clean up thread from ready queue
 | ||||
|  | @ -81,12 +80,12 @@ void Thread::Stop() { | |||
| void ThreadManager::SwitchContext(Thread* new_thread) { | ||||
|     Thread* previous_thread = GetCurrentThread(); | ||||
| 
 | ||||
|     Core::Timing& timing = Core::System::GetInstance().CoreTiming(); | ||||
|     Core::Timing& timing = kernel.timing; | ||||
| 
 | ||||
|     // Save context for previous thread
 | ||||
|     if (previous_thread) { | ||||
|         previous_thread->last_running_ticks = timing.GetTicks(); | ||||
|         Core::CPU().SaveContext(previous_thread->context); | ||||
|         cpu->SaveContext(previous_thread->context); | ||||
| 
 | ||||
|         if (previous_thread->status == ThreadStatus::Running) { | ||||
|             // This is only the case when a reschedule is triggered without the current thread
 | ||||
|  | @ -117,8 +116,8 @@ void ThreadManager::SwitchContext(Thread* new_thread) { | |||
|                 ¤t_thread->owner_process->vm_manager.page_table); | ||||
|         } | ||||
| 
 | ||||
|         Core::CPU().LoadContext(new_thread->context); | ||||
|         Core::CPU().SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress()); | ||||
|         cpu->LoadContext(new_thread->context); | ||||
|         cpu->SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress()); | ||||
|     } else { | ||||
|         current_thread = nullptr; | ||||
|         // Note: We do not reset the current process and current page table when idling because
 | ||||
|  | @ -186,8 +185,8 @@ void Thread::WakeAfterDelay(s64 nanoseconds) { | |||
|     if (nanoseconds == -1) | ||||
|         return; | ||||
| 
 | ||||
|     Core::System::GetInstance().CoreTiming().ScheduleEvent( | ||||
|         nsToCycles(nanoseconds), thread_manager.ThreadWakeupEventType, thread_id); | ||||
|     thread_manager.kernel.timing.ScheduleEvent(nsToCycles(nanoseconds), | ||||
|                                                thread_manager.ThreadWakeupEventType, thread_id); | ||||
| } | ||||
| 
 | ||||
| void Thread::ResumeFromWait() { | ||||
|  | @ -225,7 +224,7 @@ void Thread::ResumeFromWait() { | |||
| 
 | ||||
|     thread_manager.ready_queue.push_back(current_priority, this); | ||||
|     status = ThreadStatus::Ready; | ||||
|     Core::System::GetInstance().PrepareReschedule(); | ||||
|     thread_manager.kernel.PrepareReschedule(); | ||||
| } | ||||
| 
 | ||||
| void ThreadManager::DebugThreadQueue() { | ||||
|  | @ -320,7 +319,7 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr | |||
|     thread->entry_point = entry_point; | ||||
|     thread->stack_top = stack_top; | ||||
|     thread->nominal_priority = thread->current_priority = priority; | ||||
|     thread->last_running_ticks = Core::System::GetInstance().CoreTiming().GetTicks(); | ||||
|     thread->last_running_ticks = timing.GetTicks(); | ||||
|     thread->processor_id = processor_id; | ||||
|     thread->wait_objects.clear(); | ||||
|     thread->wait_address = 0; | ||||
|  | @ -462,9 +461,10 @@ VAddr Thread::GetCommandBufferAddress() const { | |||
| } | ||||
| 
 | ||||
| ThreadManager::ThreadManager(Kernel::KernelSystem& kernel) : kernel(kernel) { | ||||
|     ThreadWakeupEventType = Core::System::GetInstance().CoreTiming().RegisterEvent( | ||||
|         "ThreadWakeupCallback", | ||||
|         [this](u64 thread_id, s64 cycle_late) { ThreadWakeupCallback(thread_id, cycle_late); }); | ||||
|     ThreadWakeupEventType = | ||||
|         kernel.timing.RegisterEvent("ThreadWakeupCallback", [this](u64 thread_id, s64 cycle_late) { | ||||
|             ThreadWakeupCallback(thread_id, cycle_late); | ||||
|         }); | ||||
| } | ||||
| 
 | ||||
| ThreadManager::~ThreadManager() { | ||||
|  |  | |||
|  | @ -101,6 +101,14 @@ public: | |||
|      */ | ||||
|     const std::vector<SharedPtr<Thread>>& GetThreadList(); | ||||
| 
 | ||||
|     void SetCPU(ARM_Interface& cpu) { | ||||
|         this->cpu = &cpu; | ||||
|     } | ||||
| 
 | ||||
|     std::unique_ptr<ARM_Interface::ThreadContext> NewContext() { | ||||
|         return cpu->NewContext(); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     /**
 | ||||
|      * Switches the CPU's active thread context to that of the specified thread | ||||
|  | @ -122,6 +130,7 @@ private: | |||
|     void ThreadWakeupCallback(u64 thread_id, s64 cycles_late); | ||||
| 
 | ||||
|     Kernel::KernelSystem& kernel; | ||||
|     ARM_Interface* cpu; | ||||
| 
 | ||||
|     u32 next_thread_id = 1; | ||||
|     SharedPtr<Thread> current_thread; | ||||
|  |  | |||
|  | @ -14,7 +14,8 @@ | |||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| Timer::Timer(KernelSystem& kernel) : WaitObject(kernel), timer_manager(kernel.GetTimerManager()) {} | ||||
| Timer::Timer(KernelSystem& kernel) | ||||
|     : WaitObject(kernel), kernel(kernel), timer_manager(kernel.GetTimerManager()) {} | ||||
| Timer::~Timer() { | ||||
|     Cancel(); | ||||
|     timer_manager.timer_callback_table.erase(callback_id); | ||||
|  | @ -56,14 +57,13 @@ void Timer::Set(s64 initial, s64 interval) { | |||
|         // Immediately invoke the callback
 | ||||
|         Signal(0); | ||||
|     } else { | ||||
|         Core::System::GetInstance().CoreTiming().ScheduleEvent( | ||||
|             nsToCycles(initial), timer_manager.timer_callback_event_type, callback_id); | ||||
|         kernel.timing.ScheduleEvent(nsToCycles(initial), timer_manager.timer_callback_event_type, | ||||
|                                     callback_id); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Timer::Cancel() { | ||||
|     Core::System::GetInstance().CoreTiming().UnscheduleEvent( | ||||
|         timer_manager.timer_callback_event_type, callback_id); | ||||
|     kernel.timing.UnscheduleEvent(timer_manager.timer_callback_event_type, callback_id); | ||||
| } | ||||
| 
 | ||||
| void Timer::Clear() { | ||||
|  | @ -87,9 +87,8 @@ void Timer::Signal(s64 cycles_late) { | |||
| 
 | ||||
|     if (interval_delay != 0) { | ||||
|         // Reschedule the timer with the interval delay
 | ||||
|         Core::System::GetInstance().CoreTiming().ScheduleEvent( | ||||
|             nsToCycles(interval_delay) - cycles_late, timer_manager.timer_callback_event_type, | ||||
|             callback_id); | ||||
|         kernel.timing.ScheduleEvent(nsToCycles(interval_delay) - cycles_late, | ||||
|                                     timer_manager.timer_callback_event_type, callback_id); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -105,10 +104,11 @@ void TimerManager::TimerCallback(u64 callback_id, s64 cycles_late) { | |||
|     timer->Signal(cycles_late); | ||||
| } | ||||
| 
 | ||||
| TimerManager::TimerManager() { | ||||
|     timer_callback_event_type = Core::System::GetInstance().CoreTiming().RegisterEvent( | ||||
|         "TimerCallback", | ||||
|         [this](u64 thread_id, s64 cycle_late) { TimerCallback(thread_id, cycle_late); }); | ||||
| TimerManager::TimerManager(Core::Timing& timing) : timing(timing) { | ||||
|     timer_callback_event_type = | ||||
|         timing.RegisterEvent("TimerCallback", [this](u64 thread_id, s64 cycle_late) { | ||||
|             TimerCallback(thread_id, cycle_late); | ||||
|         }); | ||||
| } | ||||
| 
 | ||||
| } // namespace Kernel
 | ||||
|  |  | |||
|  | @ -9,16 +9,22 @@ | |||
| #include "core/hle/kernel/object.h" | ||||
| #include "core/hle/kernel/wait_object.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| class Timing; | ||||
| } | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| class TimerManager { | ||||
| public: | ||||
|     TimerManager(); | ||||
|     TimerManager(Core::Timing& timing); | ||||
| 
 | ||||
| private: | ||||
|     /// The timer callback event, called when a timer is fired
 | ||||
|     void TimerCallback(u64 callback_id, s64 cycles_late); | ||||
| 
 | ||||
|     Core::Timing& timing; | ||||
| 
 | ||||
|     /// The event type of the generic timer callback event
 | ||||
|     Core::TimingEventType* timer_callback_event_type = nullptr; | ||||
| 
 | ||||
|  | @ -93,6 +99,7 @@ private: | |||
|     /// ID used as userdata to reference this object when inserting into the CoreTiming queue.
 | ||||
|     u64 callback_id; | ||||
| 
 | ||||
|     KernelSystem& kernel; | ||||
|     TimerManager& timer_manager; | ||||
| 
 | ||||
|     friend class KernelSystem; | ||||
|  |  | |||
|  | @ -72,11 +72,11 @@ ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType reloc | |||
|     case RelocationType::AbsoluteAddress: | ||||
|     case RelocationType::AbsoluteAddress2: | ||||
|         memory.Write32(target_address, symbol_address + addend); | ||||
|         Core::CPU().InvalidateCacheRange(target_address, sizeof(u32)); | ||||
|         cpu.InvalidateCacheRange(target_address, sizeof(u32)); | ||||
|         break; | ||||
|     case RelocationType::RelativeAddress: | ||||
|         memory.Write32(target_address, symbol_address + addend - target_future_address); | ||||
|         Core::CPU().InvalidateCacheRange(target_address, sizeof(u32)); | ||||
|         cpu.InvalidateCacheRange(target_address, sizeof(u32)); | ||||
|         break; | ||||
|     case RelocationType::ThumbBranch: | ||||
|     case RelocationType::ArmBranch: | ||||
|  | @ -99,7 +99,7 @@ ResultCode CROHelper::ClearRelocation(VAddr target_address, RelocationType reloc | |||
|     case RelocationType::AbsoluteAddress2: | ||||
|     case RelocationType::RelativeAddress: | ||||
|         memory.Write32(target_address, 0); | ||||
|         Core::CPU().InvalidateCacheRange(target_address, sizeof(u32)); | ||||
|         cpu.InvalidateCacheRange(target_address, sizeof(u32)); | ||||
|         break; | ||||
|     case RelocationType::ThumbBranch: | ||||
|     case RelocationType::ArmBranch: | ||||
|  | @ -548,7 +548,7 @@ ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) { | |||
|         static_relocation_table_offset + | ||||
|         GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry); | ||||
| 
 | ||||
|     CROHelper crs(crs_address, process, memory); | ||||
|     CROHelper crs(crs_address, process, memory, cpu); | ||||
|     u32 offset_export_num = GetField(StaticAnonymousSymbolNum); | ||||
|     LOG_INFO(Service_LDR, "CRO \"{}\" exports {} static anonymous symbols", ModuleName(), | ||||
|              offset_export_num); | ||||
|  | @ -759,7 +759,7 @@ ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) { | |||
| 
 | ||||
|         if (!relocation_entry.is_batch_resolved) { | ||||
|             ResultCode result = ForEachAutoLinkCRO( | ||||
|                 process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> { | ||||
|                 process, memory, cpu, crs_address, [&](CROHelper source) -> ResultVal<bool> { | ||||
|                     std::string symbol_name = | ||||
|                         memory.ReadCString(entry.name_offset, import_strings_size); | ||||
|                     u32 symbol_address = source.FindExportNamedSymbol(symbol_name); | ||||
|  | @ -861,7 +861,7 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) { | |||
|         std::string want_cro_name = memory.ReadCString(entry.name_offset, import_strings_size); | ||||
| 
 | ||||
|         ResultCode result = ForEachAutoLinkCRO( | ||||
|             process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> { | ||||
|             process, memory, cpu, crs_address, [&](CROHelper source) -> ResultVal<bool> { | ||||
|                 if (want_cro_name == source.ModuleName()) { | ||||
|                     LOG_INFO(Service_LDR, "CRO \"{}\" imports {} indexed symbols from \"{}\"", | ||||
|                              ModuleName(), entry.import_indexed_symbol_num, source.ModuleName()); | ||||
|  | @ -1071,7 +1071,7 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) { | |||
| 
 | ||||
|         if (memory.ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") { | ||||
|             ResultCode result = ForEachAutoLinkCRO( | ||||
|                 process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> { | ||||
|                 process, memory, cpu, crs_address, [&](CROHelper source) -> ResultVal<bool> { | ||||
|                     u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_"); | ||||
| 
 | ||||
|                     if (symbol_address != 0) { | ||||
|  | @ -1301,7 +1301,7 @@ ResultCode CROHelper::Link(VAddr crs_address, bool link_on_load_bug_fix) { | |||
|     } | ||||
| 
 | ||||
|     // Exports symbols to other modules
 | ||||
|     result = ForEachAutoLinkCRO(process, memory, crs_address, | ||||
|     result = ForEachAutoLinkCRO(process, memory, cpu, crs_address, | ||||
|                                 [this](CROHelper target) -> ResultVal<bool> { | ||||
|                                     ResultCode result = ApplyExportNamedSymbol(target); | ||||
|                                     if (result.IsError()) | ||||
|  | @ -1346,7 +1346,7 @@ ResultCode CROHelper::Unlink(VAddr crs_address) { | |||
| 
 | ||||
|     // Resets all symbols in other modules imported from this module
 | ||||
|     // Note: the RO service seems only searching in auto-link modules
 | ||||
|     result = ForEachAutoLinkCRO(process, memory, crs_address, | ||||
|     result = ForEachAutoLinkCRO(process, memory, cpu, crs_address, | ||||
|                                 [this](CROHelper target) -> ResultVal<bool> { | ||||
|                                     ResultCode result = ResetExportNamedSymbol(target); | ||||
|                                     if (result.IsError()) | ||||
|  | @ -1387,13 +1387,13 @@ void CROHelper::InitCRS() { | |||
| } | ||||
| 
 | ||||
| void CROHelper::Register(VAddr crs_address, bool auto_link) { | ||||
|     CROHelper crs(crs_address, process, memory); | ||||
|     CROHelper head(auto_link ? crs.NextModule() : crs.PreviousModule(), process, memory); | ||||
|     CROHelper crs(crs_address, process, memory, cpu); | ||||
|     CROHelper head(auto_link ? crs.NextModule() : crs.PreviousModule(), process, memory, cpu); | ||||
| 
 | ||||
|     if (head.module_address) { | ||||
|         // there are already CROs registered
 | ||||
|         // register as the new tail
 | ||||
|         CROHelper tail(head.PreviousModule(), process, memory); | ||||
|         CROHelper tail(head.PreviousModule(), process, memory, cpu); | ||||
| 
 | ||||
|         // link with the old tail
 | ||||
|         ASSERT(tail.NextModule() == 0); | ||||
|  | @ -1419,11 +1419,11 @@ void CROHelper::Register(VAddr crs_address, bool auto_link) { | |||
| } | ||||
| 
 | ||||
| void CROHelper::Unregister(VAddr crs_address) { | ||||
|     CROHelper crs(crs_address, process, memory); | ||||
|     CROHelper next_head(crs.NextModule(), process, memory); | ||||
|     CROHelper previous_head(crs.PreviousModule(), process, memory); | ||||
|     CROHelper next(NextModule(), process, memory); | ||||
|     CROHelper previous(PreviousModule(), process, memory); | ||||
|     CROHelper crs(crs_address, process, memory, cpu); | ||||
|     CROHelper next_head(crs.NextModule(), process, memory, cpu); | ||||
|     CROHelper previous_head(crs.PreviousModule(), process, memory, cpu); | ||||
|     CROHelper next(NextModule(), process, memory, cpu); | ||||
|     CROHelper previous(PreviousModule(), process, memory, cpu); | ||||
| 
 | ||||
|     if (module_address == next_head.module_address || | ||||
|         module_address == previous_head.module_address) { | ||||
|  |  | |||
|  | @ -15,6 +15,8 @@ namespace Kernel { | |||
| class Process; | ||||
| } | ||||
| 
 | ||||
| class ARM_Interface; | ||||
| 
 | ||||
| namespace Service::LDR { | ||||
| 
 | ||||
| #define ASSERT_CRO_STRUCT(name, size)                                                              \ | ||||
|  | @ -31,8 +33,9 @@ static constexpr u32 CRO_HASH_SIZE = 0x80; | |||
| class CROHelper final { | ||||
| public: | ||||
|     // TODO (wwylele): pass in the process handle for memory access
 | ||||
|     explicit CROHelper(VAddr cro_address, Kernel::Process& process, Memory::MemorySystem& memory) | ||||
|         : module_address(cro_address), process(process), memory(memory) {} | ||||
|     explicit CROHelper(VAddr cro_address, Kernel::Process& process, Memory::MemorySystem& memory, | ||||
|                        ARM_Interface& cpu) | ||||
|         : module_address(cro_address), process(process), memory(memory), cpu(cpu) {} | ||||
| 
 | ||||
|     std::string ModuleName() const { | ||||
|         return memory.ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize)); | ||||
|  | @ -142,6 +145,7 @@ private: | |||
|     const VAddr module_address; ///< the virtual address of this module
 | ||||
|     Kernel::Process& process;   ///< the owner process of this module
 | ||||
|     Memory::MemorySystem& memory; | ||||
|     ARM_Interface& cpu; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Each item in this enum represents a u32 field in the header begin from address+0x80, | ||||
|  | @ -471,10 +475,11 @@ private: | |||
|      */ | ||||
|     template <typename FunctionObject> | ||||
|     static ResultCode ForEachAutoLinkCRO(Kernel::Process& process, Memory::MemorySystem& memory, | ||||
|                                          VAddr crs_address, FunctionObject func) { | ||||
|                                          ARM_Interface& cpu, VAddr crs_address, | ||||
|                                          FunctionObject func) { | ||||
|         VAddr current = crs_address; | ||||
|         while (current != 0) { | ||||
|             CROHelper cro(current, process, memory); | ||||
|             CROHelper cro(current, process, memory, cpu); | ||||
|             CASCADE_RESULT(bool next, func(cro)); | ||||
|             if (!next) | ||||
|                 break; | ||||
|  |  | |||
|  | @ -115,7 +115,7 @@ void RO::Initialize(Kernel::HLERequestContext& ctx) { | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     CROHelper crs(crs_address, *process, system.Memory()); | ||||
|     CROHelper crs(crs_address, *process, system.Memory(), system.CPU()); | ||||
|     crs.InitCRS(); | ||||
| 
 | ||||
|     result = crs.Rebase(0, crs_size, 0, 0, 0, 0, true); | ||||
|  | @ -249,7 +249,7 @@ void RO::LoadCRO(Kernel::HLERequestContext& ctx, bool link_on_load_bug_fix) { | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     CROHelper cro(cro_address, *process, system.Memory()); | ||||
|     CROHelper cro(cro_address, *process, system.Memory(), system.CPU()); | ||||
| 
 | ||||
|     result = cro.VerifyHash(cro_size, crr_address); | ||||
|     if (result.IsError()) { | ||||
|  | @ -313,7 +313,7 @@ void RO::LoadCRO(Kernel::HLERequestContext& ctx, bool link_on_load_bug_fix) { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Core::CPU().InvalidateCacheRange(cro_address, cro_size); | ||||
|     system.CPU().InvalidateCacheRange(cro_address, cro_size); | ||||
| 
 | ||||
|     LOG_INFO(Service_LDR, "CRO \"{}\" loaded at 0x{:08X}, fixed_end=0x{:08X}", cro.ModuleName(), | ||||
|              cro_address, cro_address + fix_size); | ||||
|  | @ -331,7 +331,7 @@ void RO::UnloadCRO(Kernel::HLERequestContext& ctx) { | |||
|     LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}, zero={}, cro_buffer_ptr=0x{:08X}", | ||||
|               cro_address, zero, cro_buffer_ptr); | ||||
| 
 | ||||
|     CROHelper cro(cro_address, *process, system.Memory()); | ||||
|     CROHelper cro(cro_address, *process, system.Memory(), system.CPU()); | ||||
| 
 | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||
| 
 | ||||
|  | @ -386,7 +386,7 @@ void RO::UnloadCRO(Kernel::HLERequestContext& ctx) { | |||
|         LOG_ERROR(Service_LDR, "Error unmapping CRO {:08X}", result.raw); | ||||
|     } | ||||
| 
 | ||||
|     Core::CPU().InvalidateCacheRange(cro_address, fixed_size); | ||||
|     system.CPU().InvalidateCacheRange(cro_address, fixed_size); | ||||
| 
 | ||||
|     rb.Push(result); | ||||
| } | ||||
|  | @ -398,7 +398,7 @@ void RO::LinkCRO(Kernel::HLERequestContext& ctx) { | |||
| 
 | ||||
|     LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}", cro_address); | ||||
| 
 | ||||
|     CROHelper cro(cro_address, *process, system.Memory()); | ||||
|     CROHelper cro(cro_address, *process, system.Memory(), system.CPU()); | ||||
| 
 | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||
| 
 | ||||
|  | @ -438,7 +438,7 @@ void RO::UnlinkCRO(Kernel::HLERequestContext& ctx) { | |||
| 
 | ||||
|     LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}", cro_address); | ||||
| 
 | ||||
|     CROHelper cro(cro_address, *process, system.Memory()); | ||||
|     CROHelper cro(cro_address, *process, system.Memory(), system.CPU()); | ||||
| 
 | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||
| 
 | ||||
|  | @ -487,7 +487,7 @@ void RO::Shutdown(Kernel::HLERequestContext& ctx) { | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     CROHelper crs(slot->loaded_crs, *process, system.Memory()); | ||||
|     CROHelper crs(slot->loaded_crs, *process, system.Memory(), system.CPU()); | ||||
|     crs.Unrebase(true); | ||||
| 
 | ||||
|     ResultCode result = RESULT_SUCCESS; | ||||
|  |  | |||
|  | @ -65,15 +65,21 @@ public: | |||
|     PageTable* current_page_table = nullptr; | ||||
|     RasterizerCacheMarker cache_marker; | ||||
|     std::vector<PageTable*> page_table_list; | ||||
| 
 | ||||
|     ARM_Interface* cpu = nullptr; | ||||
| }; | ||||
| 
 | ||||
| MemorySystem::MemorySystem() : impl(std::make_unique<Impl>()) {} | ||||
| MemorySystem::~MemorySystem() = default; | ||||
| 
 | ||||
| void MemorySystem::SetCPU(ARM_Interface& cpu) { | ||||
|     impl->cpu = &cpu; | ||||
| } | ||||
| 
 | ||||
| void MemorySystem::SetCurrentPageTable(PageTable* page_table) { | ||||
|     impl->current_page_table = page_table; | ||||
|     if (Core::System::GetInstance().IsPoweredOn()) { | ||||
|         Core::CPU().PageTableChanged(); | ||||
|     if (impl->cpu != nullptr) { | ||||
|         impl->cpu->PageTableChanged(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,6 +12,8 @@ | |||
| #include "common/common_types.h" | ||||
| #include "core/mmio.h" | ||||
| 
 | ||||
| class ARM_Interface; | ||||
| 
 | ||||
| namespace Kernel { | ||||
| class Process; | ||||
| } | ||||
|  | @ -214,6 +216,9 @@ public: | |||
|     MemorySystem(); | ||||
|     ~MemorySystem(); | ||||
| 
 | ||||
|     /// Sets CPU to notify page table change
 | ||||
|     void SetCPU(ARM_Interface& cpu); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Maps an allocated buffer onto a region of the emulated process address space. | ||||
|      * | ||||
|  |  | |||
|  | @ -20,17 +20,13 @@ | |||
| #include "audio_fixures.h" | ||||
| 
 | ||||
| TEST_CASE("DSP HLE Audio Decoder", "[audio_core]") { | ||||
|     // HACK: see comments of member timing
 | ||||
|     Core::System::GetInstance().timing = std::make_unique<Core::Timing>(); | ||||
|     Core::System::GetInstance().memory = std::make_unique<Memory::MemorySystem>(); | ||||
|     Kernel::KernelSystem kernel(*Core::System::GetInstance().memory, 0); | ||||
|     Memory::MemorySystem memory; | ||||
|     SECTION("decoder should produce correct samples") { | ||||
|         auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0)); | ||||
|         auto decoder = | ||||
| #ifdef HAVE_MF | ||||
|             std::make_unique<AudioCore::HLE::WMFDecoder>(*Core::System::GetInstance().memory); | ||||
|             std::make_unique<AudioCore::HLE::WMFDecoder>(memory); | ||||
| #elif HAVE_FFMPEG | ||||
|             std::make_unique<AudioCore::HLE::FFMPEGDecoder>(*Core::System::GetInstance().memory); | ||||
|             std::make_unique<AudioCore::HLE::FFMPEGDecoder>(memory); | ||||
| #endif | ||||
|         AudioCore::HLE::BinaryRequest request; | ||||
| 
 | ||||
|  | @ -40,7 +36,7 @@ TEST_CASE("DSP HLE Audio Decoder", "[audio_core]") { | |||
|         std::optional<AudioCore::HLE::BinaryResponse> response = decoder->ProcessRequest(request); | ||||
| 
 | ||||
|         request.cmd = AudioCore::HLE::DecoderCommand::Decode; | ||||
|         u8* fcram = Core::System::GetInstance().memory->GetFCRAMPointer(0); | ||||
|         u8* fcram = memory.GetFCRAMPointer(0); | ||||
| 
 | ||||
|         memcpy(fcram, fixure_buffer, fixure_buffer_size); | ||||
|         request.src_addr = Memory::FCRAM_PADDR; | ||||
|  |  | |||
|  | @ -15,14 +15,9 @@ static Memory::PageTable* page_table = nullptr; | |||
| TestEnvironment::TestEnvironment(bool mutable_memory_) | ||||
|     : mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) { | ||||
| 
 | ||||
|     // HACK: some memory functions are currently referring kernel from the global instance,
 | ||||
|     //       so we need to create the kernel object there.
 | ||||
|     //       Change this when all global states are eliminated.
 | ||||
|     Core::System::GetInstance().timing = std::make_unique<Core::Timing>(); | ||||
|     Core::System::GetInstance().memory = std::make_unique<Memory::MemorySystem>(); | ||||
|     Memory::MemorySystem& memory = *Core::System::GetInstance().memory; | ||||
|     Core::System::GetInstance().kernel = std::make_unique<Kernel::KernelSystem>(memory, 0); | ||||
|     kernel = Core::System::GetInstance().kernel.get(); | ||||
|     timing = std::make_unique<Core::Timing>(); | ||||
|     memory = std::make_unique<Memory::MemorySystem>(); | ||||
|     kernel = std::make_unique<Kernel::KernelSystem>(*memory, *timing, [] {}, 0); | ||||
| 
 | ||||
|     kernel->SetCurrentProcess(kernel->CreateProcess(kernel->CreateCodeSet("", 0))); | ||||
|     page_table = &kernel->GetCurrentProcess()->vm_manager.page_table; | ||||
|  | @ -30,17 +25,15 @@ TestEnvironment::TestEnvironment(bool mutable_memory_) | |||
|     page_table->pointers.fill(nullptr); | ||||
|     page_table->attributes.fill(Memory::PageType::Unmapped); | ||||
| 
 | ||||
|     memory.MapIoRegion(*page_table, 0x00000000, 0x80000000, test_memory); | ||||
|     memory.MapIoRegion(*page_table, 0x80000000, 0x80000000, test_memory); | ||||
|     memory->MapIoRegion(*page_table, 0x00000000, 0x80000000, test_memory); | ||||
|     memory->MapIoRegion(*page_table, 0x80000000, 0x80000000, test_memory); | ||||
| 
 | ||||
|     memory.SetCurrentPageTable(page_table); | ||||
|     memory->SetCurrentPageTable(page_table); | ||||
| } | ||||
| 
 | ||||
| TestEnvironment::~TestEnvironment() { | ||||
|     Memory::MemorySystem& memory = *Core::System::GetInstance().memory; | ||||
|     memory.UnmapRegion(*page_table, 0x80000000, 0x80000000); | ||||
|     memory.UnmapRegion(*page_table, 0x00000000, 0x80000000); | ||||
|     Core::System::GetInstance().kernel.reset(); | ||||
|     memory->UnmapRegion(*page_table, 0x80000000, 0x80000000); | ||||
|     memory->UnmapRegion(*page_table, 0x00000000, 0x80000000); | ||||
| } | ||||
| 
 | ||||
| void TestEnvironment::SetMemory64(VAddr vaddr, u64 value) { | ||||
|  |  | |||
|  | @ -49,6 +49,10 @@ public: | |||
|     /// Empties the internal write-record store.
 | ||||
|     void ClearWriteRecords(); | ||||
| 
 | ||||
|     Memory::MemorySystem& GetMemory() { | ||||
|         return *memory; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     friend struct TestMemory; | ||||
|     struct TestMemory final : Memory::MMIORegion { | ||||
|  | @ -80,7 +84,9 @@ private: | |||
|     std::shared_ptr<TestMemory> test_memory; | ||||
|     std::vector<WriteRecord> write_records; | ||||
| 
 | ||||
|     Kernel::KernelSystem* kernel; | ||||
|     std::unique_ptr<Core::Timing> timing; | ||||
|     std::unique_ptr<Memory::MemorySystem> memory; | ||||
|     std::unique_ptr<Kernel::KernelSystem> kernel; | ||||
| }; | ||||
| 
 | ||||
| } // namespace ArmTests
 | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ TEST_CASE("ARM_DynCom (vfp): vadd", "[arm_dyncom]") { | |||
|     test_env.SetMemory32(0, 0xEE321A03); // vadd.f32 s2, s4, s6
 | ||||
|     test_env.SetMemory32(4, 0xEAFFFFFE); // b +#0
 | ||||
| 
 | ||||
|     ARM_DynCom dyncom(Core::System::GetInstance(), USER32MODE); | ||||
|     ARM_DynCom dyncom(nullptr, test_env.GetMemory(), USER32MODE); | ||||
| 
 | ||||
|     std::vector<VfpTestCase> test_cases{{ | ||||
| #include "vfp_vadd_f32.inc" | ||||
|  |  | |||
|  | @ -21,10 +21,9 @@ static SharedPtr<Object> MakeObject(Kernel::KernelSystem& kernel) { | |||
| } | ||||
| 
 | ||||
| TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel]") { | ||||
|     // HACK: see comments of member timing
 | ||||
|     Core::System::GetInstance().timing = std::make_unique<Core::Timing>(); | ||||
|     auto memory = std::make_unique<Memory::MemorySystem>(); | ||||
|     Kernel::KernelSystem kernel(*memory, 0); | ||||
|     Core::Timing timing; | ||||
|     Memory::MemorySystem memory; | ||||
|     Kernel::KernelSystem kernel(memory, timing, [] {}, 0); | ||||
|     auto session = std::get<SharedPtr<ServerSession>>(kernel.CreateSessionPair()); | ||||
|     HLERequestContext context(std::move(session)); | ||||
| 
 | ||||
|  | @ -234,10 +233,9 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
| } | ||||
| 
 | ||||
| TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { | ||||
|     // HACK: see comments of member timing
 | ||||
|     Core::System::GetInstance().timing = std::make_unique<Core::Timing>(); | ||||
|     auto memory = std::make_unique<Memory::MemorySystem>(); | ||||
|     Kernel::KernelSystem kernel(*memory, 0); | ||||
|     Core::Timing timing; | ||||
|     Memory::MemorySystem memory; | ||||
|     Kernel::KernelSystem kernel(memory, timing, [] {}, 0); | ||||
|     auto session = std::get<SharedPtr<ServerSession>>(kernel.CreateSessionPair()); | ||||
|     HLERequestContext context(std::move(session)); | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,10 +11,9 @@ | |||
| #include "core/memory.h" | ||||
| 
 | ||||
| TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") { | ||||
|     // HACK: see comments of member timing
 | ||||
|     Core::System::GetInstance().timing = std::make_unique<Core::Timing>(); | ||||
|     Core::System::GetInstance().memory = std::make_unique<Memory::MemorySystem>(); | ||||
|     Kernel::KernelSystem kernel(*Core::System::GetInstance().memory, 0); | ||||
|     Core::Timing timing; | ||||
|     Memory::MemorySystem memory; | ||||
|     Kernel::KernelSystem kernel(memory, timing, [] {}, 0); | ||||
|     SECTION("these regions should not be mapped on an empty process") { | ||||
|         auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0)); | ||||
|         CHECK(Memory::IsValidVirtualAddress(*process, Memory::PROCESS_IMAGE_VADDR) == false); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue