From b9f6bd927867448a7c23be573b3be66c873ddd38 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Fri, 1 Feb 2019 11:09:37 -0500 Subject: [PATCH 1/8] ldr_ro: replace usage of Core::CPU() --- src/core/hle/service/ldr_ro/cro_helper.cpp | 34 +++++++++++----------- src/core/hle/service/ldr_ro/cro_helper.h | 13 ++++++--- src/core/hle/service/ldr_ro/ldr_ro.cpp | 16 +++++----- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/core/hle/service/ldr_ro/cro_helper.cpp b/src/core/hle/service/ldr_ro/cro_helper.cpp index 755614662..86600e7a9 100644 --- a/src/core/hle/service/ldr_ro/cro_helper.cpp +++ b/src/core/hle/service/ldr_ro/cro_helper.cpp @@ -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 { + process, memory, cpu, crs_address, [&](CROHelper source) -> ResultVal { 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 { + process, memory, cpu, crs_address, [&](CROHelper source) -> ResultVal { 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 { + process, memory, cpu, crs_address, [&](CROHelper source) -> ResultVal { 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 { 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 { 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) { diff --git a/src/core/hle/service/ldr_ro/cro_helper.h b/src/core/hle/service/ldr_ro/cro_helper.h index c9b1c7993..62d72dae6 100644 --- a/src/core/hle/service/ldr_ro/cro_helper.h +++ b/src/core/hle/service/ldr_ro/cro_helper.h @@ -15,6 +15,8 @@ namespace Kernel { class Process; } +class ARM_Interface; + namespace Service::LDR { // GCC versions < 5.0 do not implement std::is_trivially_copyable. @@ -40,8 +42,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)); @@ -151,6 +154,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, @@ -480,10 +484,11 @@ private: */ template 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; diff --git a/src/core/hle/service/ldr_ro/ldr_ro.cpp b/src/core/hle/service/ldr_ro/ldr_ro.cpp index 1b56c0629..caa063593 100644 --- a/src/core/hle/service/ldr_ro/ldr_ro.cpp +++ b/src/core/hle/service/ldr_ro/ldr_ro.cpp @@ -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; From 276ca88c9e854f461823d873a4673d15a11773f3 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Fri, 1 Feb 2019 11:23:39 -0500 Subject: [PATCH 2/8] kernel/thread: replace usage of Core::CPU() --- src/core/core.cpp | 2 ++ src/core/hle/kernel/thread.cpp | 8 ++++---- src/core/hle/kernel/thread.h | 9 +++++++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 671363169..f44836236 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -187,6 +187,8 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) { cpu_core = std::make_unique(*this, USER32MODE); } + kernel->GetThreadManager().SetCPU(*cpu_core); + if (Settings::values.enable_dsp_lle) { dsp_core = std::make_unique(*memory, Settings::values.enable_dsp_lle_multithread); diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 4f4c9b174..994beef4e 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -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() {} @@ -86,7 +86,7 @@ void ThreadManager::SwitchContext(Thread* new_thread) { // 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 +117,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 diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index e0af473e0..8f5da92c7 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -101,6 +101,14 @@ public: */ const std::vector>& GetThreadList(); + void SetCPU(ARM_Interface& cpu) { + this->cpu = &cpu; + } + + std::unique_ptr 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 current_thread; From eb050b8403c55db1a284b272b93e650ff544a397 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Fri, 1 Feb 2019 11:54:52 -0500 Subject: [PATCH 3/8] Kernel: replace usage of Core::System::GetInstance()::Timing() --- src/core/core.cpp | 2 +- src/core/hle/kernel/kernel.cpp | 5 +++-- src/core/hle/kernel/kernel.h | 8 +++++++- src/core/hle/kernel/memory.cpp | 2 +- src/core/hle/kernel/shared_page.cpp | 16 +++++++--------- src/core/hle/kernel/shared_page.h | 6 ++++-- src/core/hle/kernel/thread.cpp | 18 +++++++++--------- src/core/hle/kernel/timer.cpp | 24 ++++++++++++------------ src/core/hle/kernel/timer.h | 9 ++++++++- src/tests/core/arm/arm_test_common.cpp | 3 ++- src/tests/core/hle/kernel/hle_ipc.cpp | 4 ++-- src/tests/core/memory/memory.cpp | 3 ++- 12 files changed, 58 insertions(+), 42 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index f44836236..9cc23c75d 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -174,7 +174,7 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) { timing = std::make_unique(); - kernel = std::make_unique(*memory, system_mode); + kernel = std::make_unique(*memory, *timing, system_mode); if (Settings::values.use_cpu_jit) { #ifdef ARCHITECTURE_x86_64 diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index f60611dcc..b2a5a9d45 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -16,12 +16,13 @@ namespace Kernel { /// Initialize the kernel -KernelSystem::KernelSystem(Memory::MemorySystem& memory, u32 system_mode) : memory(memory) { +KernelSystem::KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing, u32 system_mode) + : memory(memory), timing(timing) { MemoryInit(system_mode); resource_limits = std::make_unique(*this); thread_manager = std::make_unique(*this); - timer_manager = std::make_unique(); + timer_manager = std::make_unique(timing); } /// Shutdown the kernel diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 0a4aefec0..dfb87b906 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -27,6 +27,10 @@ namespace Memory { class MemorySystem; } +namespace Core { +class Timing; +} + namespace Kernel { class AddressArbiter; @@ -78,7 +82,7 @@ using SharedPtr = boost::intrusive_ptr; class KernelSystem { public: - explicit KernelSystem(Memory::MemorySystem& memory, u32 system_mode); + explicit KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing, u32 system_mode); ~KernelSystem(); /** @@ -229,6 +233,8 @@ public: Memory::MemorySystem& memory; + Core::Timing& timing; + private: void MemoryInit(u32 mem_type); diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp index 16d497b7a..e4aae5d13 100644 --- a/src/core/hle/kernel/memory.cpp +++ b/src/core/hle/kernel/memory.cpp @@ -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(); + shared_page_handler = std::make_unique(timing); } MemoryRegionInfo* KernelSystem::GetMemoryRegion(MemoryRegion region) { diff --git a/src/core/hle/kernel/shared_page.cpp b/src/core/hle/kernel/shared_page.cpp index caf073658..c0d9387db 100644 --- a/src/core/hle/kernel/shared_page.cpp +++ b/src/core/hle/kernel/shared_page.cpp @@ -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( - Core::System::GetInstance().CoreTiming().GetGlobalTimeUs()); + init_time + std::chrono::duration_cast(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) { diff --git a/src/core/hle/kernel/shared_page.h b/src/core/hle/kernel/shared_page.h index 8ea114a4e..ab88c27a3 100644 --- a/src/core/hle/kernel/shared_page.h +++ b/src/core/hle/kernel/shared_page.h @@ -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; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 994beef4e..403879248 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -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,7 +80,7 @@ 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) { @@ -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() { @@ -320,7 +319,7 @@ ResultVal> 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() { diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index 98e180aa6..08f21479f 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp @@ -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 diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h index 3e446675c..be11ab16c 100644 --- a/src/core/hle/kernel/timer.h +++ b/src/core/hle/kernel/timer.h @@ -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; diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp index acadf4d53..07da6b2b9 100644 --- a/src/tests/core/arm/arm_test_common.cpp +++ b/src/tests/core/arm/arm_test_common.cpp @@ -21,7 +21,8 @@ TestEnvironment::TestEnvironment(bool mutable_memory_) Core::System::GetInstance().timing = std::make_unique(); Core::System::GetInstance().memory = std::make_unique(); Memory::MemorySystem& memory = *Core::System::GetInstance().memory; - Core::System::GetInstance().kernel = std::make_unique(memory, 0); + Core::System::GetInstance().kernel = + std::make_unique(memory, *Core::System::GetInstance().timing, 0); kernel = Core::System::GetInstance().kernel.get(); kernel->SetCurrentProcess(kernel->CreateProcess(kernel->CreateCodeSet("", 0))); diff --git a/src/tests/core/hle/kernel/hle_ipc.cpp b/src/tests/core/hle/kernel/hle_ipc.cpp index c22c66837..062a8d8ee 100644 --- a/src/tests/core/hle/kernel/hle_ipc.cpp +++ b/src/tests/core/hle/kernel/hle_ipc.cpp @@ -24,7 +24,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel // HACK: see comments of member timing Core::System::GetInstance().timing = std::make_unique(); auto memory = std::make_unique(); - Kernel::KernelSystem kernel(*memory, 0); + Kernel::KernelSystem kernel(*memory, *Core::System::GetInstance().timing, 0); auto session = std::get>(kernel.CreateSessionPair()); HLERequestContext context(std::move(session)); @@ -237,7 +237,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { // HACK: see comments of member timing Core::System::GetInstance().timing = std::make_unique(); auto memory = std::make_unique(); - Kernel::KernelSystem kernel(*memory, 0); + Kernel::KernelSystem kernel(*memory, *Core::System::GetInstance().timing, 0); auto session = std::get>(kernel.CreateSessionPair()); HLERequestContext context(std::move(session)); diff --git a/src/tests/core/memory/memory.cpp b/src/tests/core/memory/memory.cpp index ee795e63d..a36571193 100644 --- a/src/tests/core/memory/memory.cpp +++ b/src/tests/core/memory/memory.cpp @@ -14,7 +14,8 @@ TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") { // HACK: see comments of member timing Core::System::GetInstance().timing = std::make_unique(); Core::System::GetInstance().memory = std::make_unique(); - Kernel::KernelSystem kernel(*Core::System::GetInstance().memory, 0); + Kernel::KernelSystem kernel(*Core::System::GetInstance().memory, + *Core::System::GetInstance().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); From 20f47583f6ce93aca40f5d5c282d886b09c3623e Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Fri, 1 Feb 2019 12:19:20 -0500 Subject: [PATCH 4/8] Kernel: replace usage of Core::System::GetInstance().PrepareReschedule() with callback --- src/core/core.cpp | 3 ++- src/core/hle/kernel/kernel.cpp | 6 ++++-- src/core/hle/kernel/kernel.h | 10 +++++++++- src/core/hle/kernel/mutex.cpp | 6 +++--- src/core/hle/kernel/mutex.h | 1 + src/core/hle/kernel/thread.cpp | 2 +- src/tests/core/arm/arm_test_common.cpp | 4 ++-- src/tests/core/hle/kernel/hle_ipc.cpp | 4 ++-- src/tests/core/memory/memory.cpp | 2 +- 9 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 9cc23c75d..f5c640fe5 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -174,7 +174,8 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) { timing = std::make_unique(); - kernel = std::make_unique(*memory, *timing, system_mode); + kernel = std::make_unique(*memory, *timing, + [this] { PrepareReschedule(); }, system_mode); if (Settings::values.use_cpu_jit) { #ifdef ARCHITECTURE_x86_64 diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b2a5a9d45..e5bb44f0a 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -16,8 +16,10 @@ namespace Kernel { /// Initialize the kernel -KernelSystem::KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing, u32 system_mode) - : memory(memory), timing(timing) { +KernelSystem::KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing, + std::function 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(*this); diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index dfb87b906..0fe29af92 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -82,7 +83,8 @@ using SharedPtr = boost::intrusive_ptr; class KernelSystem { public: - explicit KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing, u32 system_mode); + explicit KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing, + std::function prepare_reschedule_callback, u32 system_mode); ~KernelSystem(); /** @@ -228,6 +230,10 @@ public: /// Adds a port to the named port table void AddNamedPort(std::string name, SharedPtr port); + void PrepareReschedule() { + prepare_reschedule_callback(); + } + /// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort std::unordered_map> named_ports; @@ -238,6 +244,8 @@ public: private: void MemoryInit(u32 mem_type); + std::function prepare_reschedule_callback; + std::unique_ptr resource_limits; std::atomic next_object_id{0}; diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 88d03d8f2..9bc0505f5 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -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 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; diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index ec0e3f794..aff2f3986 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -57,6 +57,7 @@ private: ~Mutex() override; friend class KernelSystem; + KernelSystem& kernel; }; /** diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 403879248..c3ad3d054 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -224,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() { diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp index 07da6b2b9..e1ef67a52 100644 --- a/src/tests/core/arm/arm_test_common.cpp +++ b/src/tests/core/arm/arm_test_common.cpp @@ -21,8 +21,8 @@ TestEnvironment::TestEnvironment(bool mutable_memory_) Core::System::GetInstance().timing = std::make_unique(); Core::System::GetInstance().memory = std::make_unique(); Memory::MemorySystem& memory = *Core::System::GetInstance().memory; - Core::System::GetInstance().kernel = - std::make_unique(memory, *Core::System::GetInstance().timing, 0); + Core::System::GetInstance().kernel = std::make_unique( + memory, *Core::System::GetInstance().timing, [] {}, 0); kernel = Core::System::GetInstance().kernel.get(); kernel->SetCurrentProcess(kernel->CreateProcess(kernel->CreateCodeSet("", 0))); diff --git a/src/tests/core/hle/kernel/hle_ipc.cpp b/src/tests/core/hle/kernel/hle_ipc.cpp index 062a8d8ee..3df0a4468 100644 --- a/src/tests/core/hle/kernel/hle_ipc.cpp +++ b/src/tests/core/hle/kernel/hle_ipc.cpp @@ -24,7 +24,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel // HACK: see comments of member timing Core::System::GetInstance().timing = std::make_unique(); auto memory = std::make_unique(); - Kernel::KernelSystem kernel(*memory, *Core::System::GetInstance().timing, 0); + Kernel::KernelSystem kernel(*memory, *Core::System::GetInstance().timing, [] {}, 0); auto session = std::get>(kernel.CreateSessionPair()); HLERequestContext context(std::move(session)); @@ -237,7 +237,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { // HACK: see comments of member timing Core::System::GetInstance().timing = std::make_unique(); auto memory = std::make_unique(); - Kernel::KernelSystem kernel(*memory, *Core::System::GetInstance().timing, 0); + Kernel::KernelSystem kernel(*memory, *Core::System::GetInstance().timing, [] {}, 0); auto session = std::get>(kernel.CreateSessionPair()); HLERequestContext context(std::move(session)); diff --git a/src/tests/core/memory/memory.cpp b/src/tests/core/memory/memory.cpp index a36571193..9ccfe4587 100644 --- a/src/tests/core/memory/memory.cpp +++ b/src/tests/core/memory/memory.cpp @@ -15,7 +15,7 @@ TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") { Core::System::GetInstance().timing = std::make_unique(); Core::System::GetInstance().memory = std::make_unique(); Kernel::KernelSystem kernel(*Core::System::GetInstance().memory, - *Core::System::GetInstance().timing, 0); + *Core::System::GetInstance().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); From 5f6d9f1915620a115d9580fbf5647222ef108ed0 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Fri, 1 Feb 2019 12:32:49 -0500 Subject: [PATCH 5/8] Kernel/IPC: use MemorySystem from parameter --- src/core/hle/kernel/ipc.cpp | 6 +++--- src/core/hle/kernel/ipc.h | 9 +++++++-- src/core/hle/kernel/svc.cpp | 16 +++++++++------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/core/hle/kernel/ipc.cpp b/src/core/hle/kernel/ipc.cpp index 7eb16ba9e..25676ee56 100644 --- a/src/core/hle/kernel/ipc.cpp +++ b/src/core/hle/kernel/ipc.cpp @@ -16,11 +16,11 @@ namespace Kernel { -ResultCode TranslateCommandBuffer(SharedPtr src_thread, SharedPtr dst_thread, - VAddr src_address, VAddr dst_address, +ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, SharedPtr src_thread, + SharedPtr dst_thread, VAddr src_address, + VAddr dst_address, std::vector& 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; diff --git a/src/core/hle/kernel/ipc.h b/src/core/hle/kernel/ipc.h index 9f2d57a96..55488bc72 100644 --- a/src/core/hle/kernel/ipc.h +++ b/src/core/hle/kernel/ipc.h @@ -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 src_thread, SharedPtr dst_thread, - VAddr src_address, VAddr dst_address, +ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, SharedPtr src_thread, + SharedPtr dst_thread, VAddr src_address, + VAddr dst_address, std::vector& mapped_buffer_context, bool reply); } // namespace Kernel diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index f28717570..892aa0dc1 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -592,7 +592,8 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle } } -static ResultCode ReceiveIPCRequest(SharedPtr server_session, +static ResultCode ReceiveIPCRequest(Memory::MemorySystem& memory, + SharedPtr server_session, SharedPtr thread) { if (server_session->parent->client == nullptr) { return ERR_SESSION_CLOSED_BY_REMOTE; @@ -602,7 +603,7 @@ static ResultCode ReceiveIPCRequest(SharedPtr 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(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, - SharedPtr object) { + thread->wakeup_callback = [& memory = this->memory](ThreadWakeupReason reason, + SharedPtr thread, + SharedPtr 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(object); - result = ReceiveIPCRequest(server_session, thread); + result = ReceiveIPCRequest(memory, server_session, thread); } thread->SetWaitSynchronizationResult(result); From 9573ee46bda2dddc11a0da1a91dd231b05111ba0 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Fri, 1 Feb 2019 12:43:55 -0500 Subject: [PATCH 6/8] Memory: replace Core::CPU --- src/core/core.cpp | 1 + src/core/memory.cpp | 10 ++++++++-- src/core/memory.h | 5 +++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index f5c640fe5..df0ff93bd 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -189,6 +189,7 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) { } kernel->GetThreadManager().SetCPU(*cpu_core); + memory->SetCPU(*cpu_core); if (Settings::values.enable_dsp_lle) { dsp_core = std::make_unique(*memory, diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 7080b30dc..c1e9c6b9a 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -65,15 +65,21 @@ public: PageTable* current_page_table = nullptr; RasterizerCacheMarker cache_marker; std::vector page_table_list; + + ARM_Interface* cpu = nullptr; }; MemorySystem::MemorySystem() : impl(std::make_unique()) {} 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(); } } diff --git a/src/core/memory.h b/src/core/memory.h index f154affc2..4a72f184e 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -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. * From 64f6e5e597f621f09bef271479d9004b49335fde Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Fri, 1 Feb 2019 14:50:25 -0500 Subject: [PATCH 7/8] ARM: pass MemorySystem separately in the constructor and make System optional So that unit test can test CPU without constructing the entire system. Also remove hacks in the System class --- src/core/arm/dynarmic/arm_dynarmic.cpp | 13 +++++----- src/core/arm/dynarmic/arm_dynarmic.h | 4 ++- src/core/arm/dyncom/arm_dyncom.cpp | 13 +++++++--- src/core/arm/dyncom/arm_dyncom.h | 9 +++++-- .../arm/dyncom/arm_dyncom_interpreter.cpp | 7 +++--- src/core/arm/skyeye_common/armstate.cpp | 25 +++++++++++-------- src/core/arm/skyeye_common/armstate.h | 10 ++++++-- src/core/core.cpp | 6 ++--- src/core/core.h | 2 -- src/tests/core/arm/arm_test_common.cpp | 24 ++++++------------ src/tests/core/arm/arm_test_common.h | 8 +++++- .../core/arm/dyncom/arm_dyncom_vfp_tests.cpp | 2 +- src/tests/core/hle/kernel/hle_ipc.cpp | 14 +++++------ src/tests/core/memory/memory.cpp | 8 +++--- 14 files changed, 80 insertions(+), 65 deletions(-) diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 62c63f9ac..f494b5228 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -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(*this)) { - interpreter_state = std::make_shared(system, initial_mode); +ARM_Dynarmic::ARM_Dynarmic(Core::System* system, Memory::MemorySystem& memory, + PrivilegeMode initial_mode) + : system(*system), memory(memory), cb(std::make_unique(*this)) { + interpreter_state = std::make_shared(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()) { diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index 0a73c05ac..537784e08 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -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 cb; std::unique_ptr MakeJit(); diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index 4ee22dfdd..d54b0cb95 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp @@ -68,14 +68,17 @@ private: u32 fpexc; }; -ARM_DynCom::ARM_DynCom(Core::System& system, PrivilegeMode initial_mode) : system(system) { - state = std::make_unique(system, initial_mode); +ARM_DynCom::ARM_DynCom(Core::System* system, Memory::MemorySystem& memory, + PrivilegeMode initial_mode) + : system(system) { + state = std::make_unique(system, memory, initial_mode); } ARM_DynCom::~ARM_DynCom() {} void ARM_DynCom::Run() { - ExecuteInstructions(std::max(system.CoreTiming().GetDowncount(), 0)); + DEBUG_ASSERT(system != nullptr); + ExecuteInstructions(std::max(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(); } diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index 83366e09d..16c332d3b 100644 --- a/src/core/arm/dyncom/arm_dyncom.h +++ b/src/core/arm/dyncom/arm_dyncom.h @@ -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 state; }; diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 0a50d31b6..9de8dddab 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -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(); } diff --git a/src/core/arm/skyeye_common/armstate.cpp b/src/core/arm/skyeye_common/armstate.cpp index 27a7540cc..3bd4d28f1 100644 --- a/src/core/arm/skyeye_common/armstate.cpp +++ b/src/core/arm/skyeye_common/armstate.cpp @@ -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(); diff --git a/src/core/arm/skyeye_common/armstate.h b/src/core/arm/skyeye_common/armstate.h index 9327dc88c..eedc68c69 100644 --- a/src/core/arm/skyeye_common/armstate.h +++ b/src/core/arm/skyeye_common/armstate.h @@ -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 Reg{}; // The current register file std::array Reg_usr{}; diff --git a/src/core/core.cpp b/src/core/core.cpp index df0ff93bd..9473b5c0c 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -179,13 +179,13 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) { if (Settings::values.use_cpu_jit) { #ifdef ARCHITECTURE_x86_64 - cpu_core = std::make_unique(*this, USER32MODE); + cpu_core = std::make_unique(this, *memory, USER32MODE); #else - cpu_core = std::make_unique(*this, USER32MODE); + cpu_core = std::make_unique(this, *memory, USER32MODE); LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); #endif } else { - cpu_core = std::make_unique(*this, USER32MODE); + cpu_core = std::make_unique(this, *memory, USER32MODE); } kernel->GetThreadManager().SetCPU(*cpu_core); diff --git a/src/core/core.h b/src/core/core.h index b8552fe3b..2e0c9ce7f 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -270,8 +270,6 @@ private: std::unique_ptr archive_manager; -public: // HACK: this is temporary exposed for tests, - // due to WIP kernel refactor causing desync state in memory std::unique_ptr memory; std::unique_ptr kernel; std::unique_ptr timing; diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp index e1ef67a52..3c8ac9878 100644 --- a/src/tests/core/arm/arm_test_common.cpp +++ b/src/tests/core/arm/arm_test_common.cpp @@ -15,15 +15,9 @@ static Memory::PageTable* page_table = nullptr; TestEnvironment::TestEnvironment(bool mutable_memory_) : mutable_memory(mutable_memory_), test_memory(std::make_shared(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::System::GetInstance().memory = std::make_unique(); - Memory::MemorySystem& memory = *Core::System::GetInstance().memory; - Core::System::GetInstance().kernel = std::make_unique( - memory, *Core::System::GetInstance().timing, [] {}, 0); - kernel = Core::System::GetInstance().kernel.get(); + timing = std::make_unique(); + memory = std::make_unique(); + kernel = std::make_unique(*memory, *timing, [] {}, 0); kernel->SetCurrentProcess(kernel->CreateProcess(kernel->CreateCodeSet("", 0))); page_table = &kernel->GetCurrentProcess()->vm_manager.page_table; @@ -31,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) { diff --git a/src/tests/core/arm/arm_test_common.h b/src/tests/core/arm/arm_test_common.h index b52d26e3c..604880d21 100644 --- a/src/tests/core/arm/arm_test_common.h +++ b/src/tests/core/arm/arm_test_common.h @@ -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 test_memory; std::vector write_records; - Kernel::KernelSystem* kernel; + std::unique_ptr timing; + std::unique_ptr memory; + std::unique_ptr kernel; }; } // namespace ArmTests diff --git a/src/tests/core/arm/dyncom/arm_dyncom_vfp_tests.cpp b/src/tests/core/arm/dyncom/arm_dyncom_vfp_tests.cpp index 6eb1a3b7f..5fadaf85e 100644 --- a/src/tests/core/arm/dyncom/arm_dyncom_vfp_tests.cpp +++ b/src/tests/core/arm/dyncom/arm_dyncom_vfp_tests.cpp @@ -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 test_cases{{ #include "vfp_vadd_f32.inc" diff --git a/src/tests/core/hle/kernel/hle_ipc.cpp b/src/tests/core/hle/kernel/hle_ipc.cpp index 3df0a4468..02ba3589b 100644 --- a/src/tests/core/hle/kernel/hle_ipc.cpp +++ b/src/tests/core/hle/kernel/hle_ipc.cpp @@ -21,10 +21,9 @@ static SharedPtr MakeObject(Kernel::KernelSystem& kernel) { } TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel]") { - // HACK: see comments of member timing - Core::System::GetInstance().timing = std::make_unique(); - auto memory = std::make_unique(); - Kernel::KernelSystem kernel(*memory, *Core::System::GetInstance().timing, [] {}, 0); + Core::Timing timing; + Memory::MemorySystem memory; + Kernel::KernelSystem kernel(memory, timing, [] {}, 0); auto session = std::get>(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(); - auto memory = std::make_unique(); - Kernel::KernelSystem kernel(*memory, *Core::System::GetInstance().timing, [] {}, 0); + Core::Timing timing; + Memory::MemorySystem memory; + Kernel::KernelSystem kernel(memory, timing, [] {}, 0); auto session = std::get>(kernel.CreateSessionPair()); HLERequestContext context(std::move(session)); diff --git a/src/tests/core/memory/memory.cpp b/src/tests/core/memory/memory.cpp index 9ccfe4587..4a6d54bf7 100644 --- a/src/tests/core/memory/memory.cpp +++ b/src/tests/core/memory/memory.cpp @@ -11,11 +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::System::GetInstance().memory = std::make_unique(); - Kernel::KernelSystem kernel(*Core::System::GetInstance().memory, - *Core::System::GetInstance().timing, [] {}, 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); From 4d10a2d652fea69662994afc51a6147c46978838 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Thu, 14 Feb 2019 14:08:45 -0500 Subject: [PATCH 8/8] tests/audio_core: remove hack for system objects --- src/tests/audio_core/decoder_tests.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/tests/audio_core/decoder_tests.cpp b/src/tests/audio_core/decoder_tests.cpp index d8f31127d..0e45b5b7d 100644 --- a/src/tests/audio_core/decoder_tests.cpp +++ b/src/tests/audio_core/decoder_tests.cpp @@ -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::System::GetInstance().memory = std::make_unique(); - 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(*Core::System::GetInstance().memory); + std::make_unique(memory); #elif HAVE_FFMPEG - std::make_unique(*Core::System::GetInstance().memory); + std::make_unique(memory); #endif AudioCore::HLE::BinaryRequest request; @@ -40,7 +36,7 @@ TEST_CASE("DSP HLE Audio Decoder", "[audio_core]") { std::optional 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;