kern: update KHardwareTimer, move out of KCoreLocalRegion

This commit is contained in:
Michael Scire 2020-12-01 07:47:29 -08:00 committed by SciresM
parent 5cb237d030
commit bee629b8ad
5 changed files with 27 additions and 47 deletions

View file

@ -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;
}; };
} }

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;
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;

View file

@ -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() {

View file

@ -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();

View file

@ -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 {