mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
kern: use single interrupt manager object
This commit is contained in:
parent
a4e09fc6c4
commit
5cb237d030
5 changed files with 39 additions and 40 deletions
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue