mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
kern: update KHardwareTimer, move out of KCoreLocalRegion
This commit is contained in:
parent
5cb237d030
commit
bee629b8ad
5 changed files with 27 additions and 47 deletions
|
@ -19,15 +19,11 @@
|
||||||
|
|
||||||
namespace ams::kern::arch::arm64 {
|
namespace ams::kern::arch::arm64 {
|
||||||
|
|
||||||
namespace impl {
|
class KHardwareTimer : public KInterruptTask, public KHardwareTimerBase {
|
||||||
|
private:
|
||||||
class KHardwareTimerInterruptTask;
|
s64 maximum_time;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class KHardwareTimer : public KHardwareTimerBase {
|
|
||||||
public:
|
public:
|
||||||
constexpr KHardwareTimer() : KHardwareTimerBase() { /* ... */ }
|
constexpr KHardwareTimer() : KInterruptTask(), KHardwareTimerBase(), maximum_time(std::numeric_limits<s64>::max()) { /* ... */ }
|
||||||
public:
|
public:
|
||||||
/* Public API. */
|
/* Public API. */
|
||||||
NOINLINE void Initialize(s32 core_id);
|
NOINLINE void Initialize(s32 core_id);
|
||||||
|
@ -42,13 +38,12 @@ namespace ams::kern::arch::arm64 {
|
||||||
KScopedSpinLock lk(this->GetLock());
|
KScopedSpinLock lk(this->GetLock());
|
||||||
|
|
||||||
if (this->RegisterAbsoluteTaskImpl(task, task_time)) {
|
if (this->RegisterAbsoluteTaskImpl(task, task_time)) {
|
||||||
SetCompareValue(task_time);
|
if (task_time <= this->maximum_time) {
|
||||||
EnableInterrupt();
|
SetCompareValue(task_time);
|
||||||
|
EnableInterrupt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
friend class impl::KHardwareTimerInterruptTask;
|
|
||||||
NOINLINE void DoInterruptTask();
|
|
||||||
private:
|
private:
|
||||||
/* Hardware register accessors. */
|
/* Hardware register accessors. */
|
||||||
static ALWAYS_INLINE void InitializeGlobalTimer() {
|
static ALWAYS_INLINE void InitializeGlobalTimer() {
|
||||||
|
@ -88,7 +83,13 @@ namespace ams::kern::arch::arm64 {
|
||||||
static ALWAYS_INLINE void SetCompareValue(s64 value) {
|
static ALWAYS_INLINE void SetCompareValue(s64 value) {
|
||||||
cpu::CounterTimerPhysicalTimerCompareValueRegisterAccessor(0).SetCompareValue(static_cast<u64>(value)).Store();
|
cpu::CounterTimerPhysicalTimerCompareValueRegisterAccessor(0).SetCompareValue(static_cast<u64>(value)).Store();
|
||||||
}
|
}
|
||||||
|
public:
|
||||||
|
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override {
|
||||||
|
MESOSPHERE_UNUSED(interrupt_id);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DoTask() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ namespace ams::kern {
|
||||||
KCurrentContext current;
|
KCurrentContext current;
|
||||||
KScheduler scheduler;
|
KScheduler scheduler;
|
||||||
KInterruptTaskManager interrupt_task_manager;
|
KInterruptTaskManager interrupt_task_manager;
|
||||||
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. */
|
||||||
u64 num_sw_interrupts;
|
u64 num_sw_interrupts;
|
||||||
|
|
|
@ -74,6 +74,7 @@ namespace ams::kern {
|
||||||
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;
|
static KInterruptManager s_interrupt_manager;
|
||||||
|
static KHardwareTimer s_hardware_timers[cpu::NumCores];
|
||||||
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;
|
||||||
|
@ -114,7 +115,11 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE KHardwareTimer &GetHardwareTimer() {
|
static ALWAYS_INLINE KHardwareTimer &GetHardwareTimer() {
|
||||||
return GetCoreLocalContext(GetCurrentCoreId()).hardware_timer;
|
return s_hardware_timers[GetCurrentCoreId()];
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE KHardwareTimer &GetHardwareTimer(s32 core_id) {
|
||||||
|
return s_hardware_timers[core_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE KResourceLimit &GetSystemResourceLimit() {
|
static ALWAYS_INLINE KResourceLimit &GetSystemResourceLimit() {
|
||||||
|
|
|
@ -17,41 +17,15 @@
|
||||||
|
|
||||||
namespace ams::kern::arch::arm64 {
|
namespace ams::kern::arch::arm64 {
|
||||||
|
|
||||||
namespace impl {
|
|
||||||
|
|
||||||
class KHardwareTimerInterruptTask : public KInterruptTask {
|
|
||||||
public:
|
|
||||||
constexpr KHardwareTimerInterruptTask() : KInterruptTask() { /* ... */ }
|
|
||||||
|
|
||||||
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override {
|
|
||||||
MESOSPHERE_UNUSED(interrupt_id);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void DoTask() override {
|
|
||||||
Kernel::GetHardwareTimer().DoInterruptTask();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
/* One global hardware timer interrupt task per core. */
|
|
||||||
impl::KHardwareTimerInterruptTask g_hardware_timer_interrupt_tasks[cpu::NumCores];
|
|
||||||
|
|
||||||
ALWAYS_INLINE auto *GetHardwareTimerInterruptTask(s32 core_id) {
|
|
||||||
return std::addressof(g_hardware_timer_interrupt_tasks[core_id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void KHardwareTimer::Initialize(s32 core_id) {
|
void KHardwareTimer::Initialize(s32 core_id) {
|
||||||
/* Setup the global timer for the core. */
|
/* Setup the global timer for the core. */
|
||||||
InitializeGlobalTimer();
|
InitializeGlobalTimer();
|
||||||
|
|
||||||
|
/* Set maximum time. */
|
||||||
|
this->maximum_time = static_cast<s64>(std::min<u64>(std::numeric_limits<s64>::max(), cpu::CounterTimerPhysicalTimerCompareValueRegisterAccessor().GetCompareValue()));
|
||||||
|
|
||||||
/* Bind the interrupt task for this core. */
|
/* Bind the interrupt task for this core. */
|
||||||
Kernel::GetInterruptManager().BindHandler(GetHardwareTimerInterruptTask(core_id), KInterruptName_NonSecurePhysicalTimer, core_id, KInterruptController::PriorityLevel_Timer, true, true);
|
Kernel::GetInterruptManager().BindHandler(std::addressof(Kernel::GetHardwareTimer(core_id)), KInterruptName_NonSecurePhysicalTimer, core_id, KInterruptController::PriorityLevel_Timer, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KHardwareTimer::Finalize() {
|
void KHardwareTimer::Finalize() {
|
||||||
|
@ -59,7 +33,7 @@ namespace ams::kern::arch::arm64 {
|
||||||
StopTimer();
|
StopTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KHardwareTimer::DoInterruptTask() {
|
void KHardwareTimer::DoTask() {
|
||||||
/* Handle the interrupt. */
|
/* Handle the interrupt. */
|
||||||
{
|
{
|
||||||
KScopedSchedulerLock slk;
|
KScopedSchedulerLock slk;
|
||||||
|
@ -67,7 +41,7 @@ namespace ams::kern::arch::arm64 {
|
||||||
|
|
||||||
/* Disable the timer interrupt while we handle this. */
|
/* Disable the timer interrupt while we handle this. */
|
||||||
DisableInterrupt();
|
DisableInterrupt();
|
||||||
if (const s64 next_time = this->DoInterruptTaskImpl(GetTick()); next_time > 0) {
|
if (const s64 next_time = this->DoInterruptTaskImpl(GetTick()); 0 < next_time && next_time <= this->maximum_time) {
|
||||||
/* We have a next time, so we should set the time to interrupt and turn the interrupt on. */
|
/* We have a next time, so we should set the time to interrupt and turn the interrupt on. */
|
||||||
SetCompareValue(next_time);
|
SetCompareValue(next_time);
|
||||||
EnableInterrupt();
|
EnableInterrupt();
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace ams::kern {
|
||||||
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;
|
constinit KInterruptManager Kernel::s_interrupt_manager;
|
||||||
|
constinit KHardwareTimer Kernel::s_hardware_timers[cpu::NumCores];
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue