summaryrefslogtreecommitdiff
path: root/Kernel/Time/TimeManagement.cpp
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2020-10-25 09:13:47 -0600
committerAndreas Kling <kling@serenityos.org>2020-10-25 21:18:35 +0100
commitfe615e601a95033c160b464728d8a0c195739f72 (patch)
treed9a60984028a82984ba7cb372ee2d76638826e75 /Kernel/Time/TimeManagement.cpp
parent9d347352a1a6c47867bc8340a13d69c8272952d9 (diff)
downloadserenity-fe615e601a95033c160b464728d8a0c195739f72.zip
Kernel: Set up and calibrate APIC timer, and enable timer on all CPUs
This enables the APIC timer on all CPUs, which means Scheduler::timer_tick is now called on all CPUs independently. We still don't do anything on the APs as it instantly crashes due to a number of other problems.
Diffstat (limited to 'Kernel/Time/TimeManagement.cpp')
-rw-r--r--Kernel/Time/TimeManagement.cpp49
1 files changed, 37 insertions, 12 deletions
diff --git a/Kernel/Time/TimeManagement.cpp b/Kernel/Time/TimeManagement.cpp
index ab0ed2bd8c..c04f096073 100644
--- a/Kernel/Time/TimeManagement.cpp
+++ b/Kernel/Time/TimeManagement.cpp
@@ -28,7 +28,9 @@
#include <AK/Time.h>
#include <Kernel/ACPI/Parser.h>
#include <Kernel/CommandLine.h>
+#include <Kernel/Interrupts/APIC.h>
#include <Kernel/Scheduler.h>
+#include <Kernel/Time/APICTimer.h>
#include <Kernel/Time/HPET.h>
#include <Kernel/Time/HPETComparator.h>
#include <Kernel/Time/HardwareTimer.h>
@@ -48,7 +50,7 @@ TimeManagement& TimeManagement::the()
return *s_the;
}
-bool TimeManagement::is_system_timer(const HardwareTimer& timer) const
+bool TimeManagement::is_system_timer(const HardwareTimerBase& timer) const
{
return &timer == m_system_timer.ptr();
}
@@ -69,11 +71,36 @@ timespec TimeManagement::epoch_time() const
return ts;
}
-void TimeManagement::initialize()
+void TimeManagement::initialize(u32 cpu)
{
- ASSERT(!s_the.is_initialized());
- s_the.ensure_instance();
+ if (cpu == 0) {
+ ASSERT(!s_the.is_initialized());
+ s_the.ensure_instance();
+
+ // Initialize the APIC timers after the other timers as the
+ // initialization needs to briefly enable interrupts, which then
+ // would trigger a deadlock trying to get the s_the instance while
+ // creating it.
+ if (auto* apic_timer = APIC::the().initialize_timers(*s_the->m_system_timer)) {
+ klog() << "Time: Using APIC timer as system timer";
+ s_the->set_system_timer(*apic_timer);
+ }
+ } else {
+ ASSERT(s_the.is_initialized());
+ if (auto* apic_timer = APIC::the().get_timer()) {
+ klog() << "Time: Enable APIC timer on CPU #" << cpu;
+ apic_timer->enable_local_timer();
+ }
+ }
}
+
+void TimeManagement::set_system_timer(HardwareTimerBase& timer)
+{
+ auto original_callback = m_system_timer->set_callback(nullptr);
+ timer.set_callback(move(original_callback));
+ m_system_timer = timer;
+}
+
time_t TimeManagement::seconds_since_boot() const
{
return m_seconds_since_boot;
@@ -112,11 +139,9 @@ TimeManagement::TimeManagement()
if (!probe_and_set_non_legacy_hardware_timers())
if (!probe_and_set_legacy_hardware_timers())
ASSERT_NOT_REACHED();
- return;
+ } else if (!probe_and_set_legacy_hardware_timers()) {
+ ASSERT_NOT_REACHED();
}
- if (probe_and_set_legacy_hardware_timers())
- return;
- ASSERT_NOT_REACHED();
}
timeval TimeManagement::now_as_timeval()
@@ -127,11 +152,11 @@ timeval TimeManagement::now_as_timeval()
return tv;
}
-Vector<HardwareTimer*> TimeManagement::scan_and_initialize_periodic_timers()
+Vector<HardwareTimerBase*> TimeManagement::scan_and_initialize_periodic_timers()
{
bool should_enable = is_hpet_periodic_mode_allowed();
dbg() << "Time: Scanning for periodic timers";
- Vector<HardwareTimer*> timers;
+ Vector<HardwareTimerBase*> timers;
for (auto& hardware_timer : m_hardware_timers) {
if (hardware_timer.is_periodic_capable()) {
timers.append(&hardware_timer);
@@ -142,10 +167,10 @@ Vector<HardwareTimer*> TimeManagement::scan_and_initialize_periodic_timers()
return timers;
}
-Vector<HardwareTimer*> TimeManagement::scan_for_non_periodic_timers()
+Vector<HardwareTimerBase*> TimeManagement::scan_for_non_periodic_timers()
{
dbg() << "Time: Scanning for non-periodic timers";
- Vector<HardwareTimer*> timers;
+ Vector<HardwareTimerBase*> timers;
for (auto& hardware_timer : m_hardware_timers) {
if (!hardware_timer.is_periodic_capable())
timers.append(&hardware_timer);