kern: use single interrupt manager object

This commit is contained in:
Michael Scire 2020-12-01 07:35:43 -08:00 committed by SciresM
parent a4e09fc6c4
commit 5cb237d030
5 changed files with 39 additions and 40 deletions

View file

@ -47,23 +47,23 @@ namespace ams::kern::arch::arm64 {
constexpr KGlobalInterruptEntry() : handler(nullptr), manually_cleared(false), needs_clear(false) { /* ... */ } constexpr KGlobalInterruptEntry() : handler(nullptr), manually_cleared(false), needs_clear(false) { /* ... */ }
}; };
private: private:
static KSpinLock s_lock; KCoreLocalInterruptEntry core_local_interrupts[cpu::NumCores][KInterruptController::NumLocalInterrupts]{};
static std::array<KGlobalInterruptEntry, KInterruptController::NumGlobalInterrupts> s_global_interrupts; KInterruptController interrupt_controller{};
static KInterruptController::GlobalState s_global_state; KInterruptController::LocalState local_states[cpu::NumCores]{};
static bool s_global_state_saved; bool local_state_saved[cpu::NumCores]{};
mutable KSpinLock global_interrupt_lock{};
KGlobalInterruptEntry global_interrupts[KInterruptController::NumGlobalInterrupts]{};
KInterruptController::GlobalState global_state{};
bool global_state_saved{};
private: private:
KCoreLocalInterruptEntry core_local_interrupts[KInterruptController::NumLocalInterrupts]; ALWAYS_INLINE KSpinLock &GetGlobalInterruptLock() const { return this->global_interrupt_lock; }
KInterruptController interrupt_controller; ALWAYS_INLINE KGlobalInterruptEntry &GetGlobalInterruptEntry(s32 irq) { return this->global_interrupts[KInterruptController::GetGlobalInterruptIndex(irq)]; }
KInterruptController::LocalState local_state; ALWAYS_INLINE KCoreLocalInterruptEntry &GetLocalInterruptEntry(s32 irq) { return this->core_local_interrupts[GetCurrentCoreId()][KInterruptController::GetLocalInterruptIndex(irq)]; }
bool local_state_saved;
private:
static ALWAYS_INLINE KSpinLock &GetLock() { return s_lock; }
static ALWAYS_INLINE KGlobalInterruptEntry &GetGlobalInterruptEntry(s32 irq) { return s_global_interrupts[KInterruptController::GetGlobalInterruptIndex(irq)]; }
ALWAYS_INLINE KCoreLocalInterruptEntry &GetLocalInterruptEntry(s32 irq) { return this->core_local_interrupts[KInterruptController::GetLocalInterruptIndex(irq)]; }
bool OnHandleInterrupt(); bool OnHandleInterrupt();
public: public:
constexpr KInterruptManager() : core_local_interrupts(), interrupt_controller(), local_state(), local_state_saved(false) { /* ... */ } constexpr KInterruptManager() = default;
NOINLINE void Initialize(s32 core_id); NOINLINE void Initialize(s32 core_id);
NOINLINE void Finalize(s32 core_id); NOINLINE void Finalize(s32 core_id);

View file

@ -29,7 +29,6 @@ namespace ams::kern {
KCurrentContext current; KCurrentContext current;
KScheduler scheduler; KScheduler scheduler;
KInterruptTaskManager interrupt_task_manager; KInterruptTaskManager interrupt_task_manager;
KInterruptManager interrupt_manager;
KHardwareTimer hardware_timer; KHardwareTimer hardware_timer;
/* Everything after this point is for debugging. */ /* Everything after this point is for debugging. */
/* Retail kernel doesn't even consistently update these fields. */ /* Retail kernel doesn't even consistently update these fields. */

View file

@ -37,8 +37,6 @@ namespace ams::kern {
class KSynchronization; class KSynchronization;
class KUnsafeMemory; class KUnsafeMemory;
#if defined(ATMOSPHERE_ARCH_ARM64) #if defined(ATMOSPHERE_ARCH_ARM64)
namespace arch::arm64 { namespace arch::arm64 {
@ -75,6 +73,7 @@ namespace ams::kern {
static KSynchronization s_synchronization; static KSynchronization s_synchronization;
static KUnsafeMemory s_unsafe_memory; static KUnsafeMemory s_unsafe_memory;
static KWorkerTaskManager s_worker_task_managers[KWorkerTaskManager::WorkerType_Count]; static KWorkerTaskManager s_worker_task_managers[KWorkerTaskManager::WorkerType_Count];
static KInterruptManager s_interrupt_manager;
private: private:
static ALWAYS_INLINE KCoreLocalContext &GetCoreLocalContext() { static ALWAYS_INLINE KCoreLocalContext &GetCoreLocalContext() {
return reinterpret_cast<KCoreLocalRegion *>(cpu::GetCoreLocalRegionAddress())->current.context; return reinterpret_cast<KCoreLocalRegion *>(cpu::GetCoreLocalRegionAddress())->current.context;
@ -111,7 +110,7 @@ namespace ams::kern {
} }
static ALWAYS_INLINE KInterruptManager &GetInterruptManager() { static ALWAYS_INLINE KInterruptManager &GetInterruptManager() {
return GetCoreLocalContext().interrupt_manager; return s_interrupt_manager;
} }
static ALWAYS_INLINE KHardwareTimer &GetHardwareTimer() { static ALWAYS_INLINE KHardwareTimer &GetHardwareTimer() {

View file

@ -17,12 +17,6 @@
namespace ams::kern::arch::arm64 { namespace ams::kern::arch::arm64 {
/* Instantiate static members in specific translation unit. */
KSpinLock KInterruptManager::s_lock;
std::array<KInterruptManager::KGlobalInterruptEntry, KInterruptController::NumGlobalInterrupts> KInterruptManager::s_global_interrupts;
KInterruptController::GlobalState KInterruptManager::s_global_state;
bool KInterruptManager::s_global_state_saved;
void KInterruptManager::Initialize(s32 core_id) { void KInterruptManager::Initialize(s32 core_id) {
this->interrupt_controller.Initialize(core_id); this->interrupt_controller.Initialize(core_id);
} }
@ -32,23 +26,26 @@ namespace ams::kern::arch::arm64 {
} }
void KInterruptManager::Save(s32 core_id) { void KInterruptManager::Save(s32 core_id) {
/* Verify core id. */
MESOSPHERE_ASSERT(core_id == GetCurrentCoreId());
/* Ensure all cores get to this point before continuing. */ /* Ensure all cores get to this point before continuing. */
cpu::SynchronizeAllCores(); cpu::SynchronizeAllCores();
/* If on core 0, save the global interrupts. */ /* If on core 0, save the global interrupts. */
if (core_id == 0) { if (core_id == 0) {
MESOSPHERE_ABORT_UNLESS(!s_global_state_saved); MESOSPHERE_ABORT_UNLESS(!this->global_state_saved);
this->interrupt_controller.SaveGlobal(std::addressof(s_global_state)); this->interrupt_controller.SaveGlobal(std::addressof(this->global_state));
s_global_state_saved = true; this->global_state_saved = true;
} }
/* Ensure all cores get to this point before continuing. */ /* Ensure all cores get to this point before continuing. */
cpu::SynchronizeAllCores(); cpu::SynchronizeAllCores();
/* Save all local interrupts. */ /* Save all local interrupts. */
MESOSPHERE_ABORT_UNLESS(!this->local_state_saved); MESOSPHERE_ABORT_UNLESS(!this->local_state_saved[core_id]);
this->interrupt_controller.SaveCoreLocal(std::addressof(this->local_state)); this->interrupt_controller.SaveCoreLocal(std::addressof(this->local_states[core_id]));
this->local_state_saved = true; this->local_state_saved[core_id] = true;
/* Ensure all cores get to this point before continuing. */ /* Ensure all cores get to this point before continuing. */
cpu::SynchronizeAllCores(); cpu::SynchronizeAllCores();
@ -68,6 +65,9 @@ namespace ams::kern::arch::arm64 {
} }
void KInterruptManager::Restore(s32 core_id) { void KInterruptManager::Restore(s32 core_id) {
/* Verify core id. */
MESOSPHERE_ASSERT(core_id == GetCurrentCoreId());
/* Ensure all cores get to this point before continuing. */ /* Ensure all cores get to this point before continuing. */
cpu::SynchronizeAllCores(); cpu::SynchronizeAllCores();
@ -88,18 +88,18 @@ namespace ams::kern::arch::arm64 {
cpu::SynchronizeAllCores(); cpu::SynchronizeAllCores();
/* Restore all local interrupts. */ /* Restore all local interrupts. */
MESOSPHERE_ASSERT(this->local_state_saved); MESOSPHERE_ASSERT(this->local_state_saved[core_id]);
this->interrupt_controller.RestoreCoreLocal(std::addressof(this->local_state)); this->interrupt_controller.RestoreCoreLocal(std::addressof(this->local_states[core_id]));
this->local_state_saved = false; this->local_state_saved[core_id] = false;
/* Ensure all cores get to this point before continuing. */ /* Ensure all cores get to this point before continuing. */
cpu::SynchronizeAllCores(); cpu::SynchronizeAllCores();
/* If on core 0, restore the global interrupts. */ /* If on core 0, restore the global interrupts. */
if (core_id == 0) { if (core_id == 0) {
MESOSPHERE_ASSERT(s_global_state_saved); MESOSPHERE_ASSERT(this->global_state_saved);
this->interrupt_controller.RestoreGlobal(std::addressof(s_global_state)); this->interrupt_controller.RestoreGlobal(std::addressof(this->global_state));
s_global_state_saved = false; this->global_state_saved = false;
} }
/* Ensure all cores get to this point before continuing. */ /* Ensure all cores get to this point before continuing. */
@ -136,7 +136,7 @@ namespace ams::kern::arch::arm64 {
MESOSPHERE_LOG("Core%d: Unhandled local interrupt %d\n", GetCurrentCoreId(), irq); MESOSPHERE_LOG("Core%d: Unhandled local interrupt %d\n", GetCurrentCoreId(), irq);
} }
} else if (KInterruptController::IsGlobal(irq)) { } else if (KInterruptController::IsGlobal(irq)) {
KScopedSpinLock lk(GetLock()); KScopedSpinLock lk(this->GetGlobalInterruptLock());
/* Get global interrupt entry. */ /* Get global interrupt entry. */
auto &entry = GetGlobalInterruptEntry(irq); auto &entry = GetGlobalInterruptEntry(irq);
@ -213,7 +213,7 @@ namespace ams::kern::arch::arm64 {
KScopedInterruptDisable di; KScopedInterruptDisable di;
if (KInterruptController::IsGlobal(irq)) { if (KInterruptController::IsGlobal(irq)) {
KScopedSpinLock lk(GetLock()); KScopedSpinLock lk(this->GetGlobalInterruptLock());
return this->BindGlobal(handler, irq, core_id, priority, manual_clear, level); return this->BindGlobal(handler, irq, core_id, priority, manual_clear, level);
} else { } else {
MESOSPHERE_ASSERT(core_id == GetCurrentCoreId()); MESOSPHERE_ASSERT(core_id == GetCurrentCoreId());
@ -227,7 +227,7 @@ namespace ams::kern::arch::arm64 {
KScopedInterruptDisable di; KScopedInterruptDisable di;
if (KInterruptController::IsGlobal(irq)) { if (KInterruptController::IsGlobal(irq)) {
KScopedSpinLock lk(GetLock()); KScopedSpinLock lk(this->GetGlobalInterruptLock());
return this->UnbindGlobal(irq); return this->UnbindGlobal(irq);
} else { } else {
MESOSPHERE_ASSERT(core_id == GetCurrentCoreId()); MESOSPHERE_ASSERT(core_id == GetCurrentCoreId());
@ -239,7 +239,7 @@ namespace ams::kern::arch::arm64 {
R_UNLESS(KInterruptController::IsGlobal(irq), svc::ResultOutOfRange()); R_UNLESS(KInterruptController::IsGlobal(irq), svc::ResultOutOfRange());
KScopedInterruptDisable di; KScopedInterruptDisable di;
KScopedSpinLock lk(GetLock()); KScopedSpinLock lk(this->GetGlobalInterruptLock());
return this->ClearGlobal(irq); return this->ClearGlobal(irq);
} }
@ -249,7 +249,7 @@ namespace ams::kern::arch::arm64 {
KScopedInterruptDisable di; KScopedInterruptDisable di;
if (KInterruptController::IsGlobal(irq)) { if (KInterruptController::IsGlobal(irq)) {
KScopedSpinLock lk(GetLock()); KScopedSpinLock lk(this->GetGlobalInterruptLock());
return this->ClearGlobal(irq); return this->ClearGlobal(irq);
} else { } else {
MESOSPHERE_ASSERT(core_id == GetCurrentCoreId()); MESOSPHERE_ASSERT(core_id == GetCurrentCoreId());

View file

@ -29,6 +29,7 @@ namespace ams::kern {
constinit KSynchronization Kernel::s_synchronization; constinit KSynchronization Kernel::s_synchronization;
constinit KUnsafeMemory Kernel::s_unsafe_memory; constinit KUnsafeMemory Kernel::s_unsafe_memory;
constinit KWorkerTaskManager Kernel::s_worker_task_managers[KWorkerTaskManager::WorkerType_Count]; constinit KWorkerTaskManager Kernel::s_worker_task_managers[KWorkerTaskManager::WorkerType_Count];
constinit KInterruptManager Kernel::s_interrupt_manager;
namespace { namespace {