From 09074798cd31a29370f234f4e4c8d798b8c52612 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 5 Nov 2021 23:38:43 -0700 Subject: [PATCH] KScheduler big brain strat for mdscr_el1 cfg change --- .../include/mesosphere/kern_k_scheduler.hpp | 3 +-- .../libmesosphere/source/kern_k_scheduler.cpp | 16 ++++++---------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_scheduler.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_scheduler.hpp index 6570eb33a..b26e1053b 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_scheduler.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_scheduler.hpp @@ -62,8 +62,7 @@ namespace ams::kern { KThread *m_idle_thread; util::Atomic m_current_thread; public: - constexpr KScheduler() : m_state(), m_is_active(false), m_core_id(0), m_last_context_switch_time(0), m_idle_thread(nullptr), m_current_thread(nullptr) - { + constexpr KScheduler() : m_state(), m_is_active(false), m_core_id(0), m_last_context_switch_time(0), m_idle_thread(nullptr), m_current_thread(nullptr) { m_state.needs_scheduling = true; m_state.interrupt_task_runnable = false; m_state.should_count_idle = false; diff --git a/libraries/libmesosphere/source/kern_k_scheduler.cpp b/libraries/libmesosphere/source/kern_k_scheduler.cpp index a19f2ddad..e8e228b1c 100644 --- a/libraries/libmesosphere/source/kern_k_scheduler.cpp +++ b/libraries/libmesosphere/source/kern_k_scheduler.cpp @@ -249,22 +249,18 @@ namespace ams::kern { #if defined(MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP) /* Ensure the single-step bit in mdscr reflects the correct single-step state for the new thread. */ + /* NOTE: Per ARM docs, changing the single-step bit requires a "context synchronization event" to */ + /* be sure that our new configuration takes. However, there are three types of synchronization event: */ + /* Taking an exception, returning from an exception, and ISB. The single-step bit change only matters */ + /* in EL0...which implies a return-from-exception has occurred since we set the bit. Thus, forcing */ + /* an ISB is unnecessary, and we can modify the register safely and be confident it will affect the next */ + /* userland instruction executed. */ cpu::MonitorDebugSystemControlRegisterAccessor().SetSoftwareStep(next_thread->IsSingleStep()).Store(); #endif /* Switch the current process, if we're switching processes. */ if (KProcess *next_process = next_thread->GetOwnerProcess(); next_process != cur_process) { KProcess::Switch(cur_process, next_process); - } else { - /* The single-step bit set up above requires an instruction synchronization barrier, to ensure */ - /* the state change takes before we actually perform a return which might break-to-step. */ - /* KProcess::Switch performs an isb incidentally, and so when we're changing process we */ - /* can piggy-back off of that isb to avoid unnecessarily emptying the pipeline twice. */ - /* However, this means that when we're switching to thread in a different process, */ - /* we must ensure that we still isb. In practice, gcc will deduplicate into a single isb. */ - #if defined(MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP) - cpu::InstructionMemoryBarrier(); - #endif } /* Set the new thread. */