summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorNico Weber <thakis@chromium.org>2021-10-02 15:50:23 -0400
committerLinus Groh <mail@linusgroh.de>2021-10-02 21:23:28 +0100
commitbc213ad7a293f132ba27b52b30b4951c0613ebc8 (patch)
tree8476be49a6ad264f134d3b0493cbbb3c6780cc12 /Kernel
parent496d2e3c294704618fc5e88a031a229bcd09a650 (diff)
downloadserenity-bc213ad7a293f132ba27b52b30b4951c0613ebc8.zip
Kernel: Add a Timer class for aarch64
For now, this can only query microseconds since boot. Use this to print a timestamp every second. This busy-loops until a second has passed. This might be a good first use of interrupts soon. qemu used to not implement this timer at some point, but it seems to work fine even in qemu now (qemu v 5.2.0).
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Prekernel/Arch/aarch64/Timer.cpp51
-rw-r--r--Kernel/Prekernel/Arch/aarch64/Timer.h27
-rw-r--r--Kernel/Prekernel/Arch/aarch64/init.cpp13
-rw-r--r--Kernel/Prekernel/CMakeLists.txt1
4 files changed, 91 insertions, 1 deletions
diff --git a/Kernel/Prekernel/Arch/aarch64/Timer.cpp b/Kernel/Prekernel/Arch/aarch64/Timer.cpp
new file mode 100644
index 0000000000..4d1f8812ca
--- /dev/null
+++ b/Kernel/Prekernel/Arch/aarch64/Timer.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021, Nico Weber <thakis@chromium.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <Kernel/Prekernel/Arch/aarch64/MMIO.h>
+#include <Kernel/Prekernel/Arch/aarch64/Timer.h>
+
+namespace Prekernel {
+
+// "12.1 System Timer Registers" / "10.2 System Timer Registers"
+struct TimerRegisters {
+ u32 control_and_status;
+ u32 counter_low;
+ u32 counter_high;
+ u32 compare[4];
+};
+
+// Bits of the `control_and_status` register.
+// See "CS register" in Broadcom doc for details.
+enum FlagBits {
+ SystemTimerMatch0 = 1 << 0,
+ SystemTimerMatch1 = 1 << 1,
+ SystemTimerMatch2 = 1 << 2,
+ SystemTimerMatch3 = 1 << 3,
+};
+
+Timer::Timer()
+ : m_registers(MMIO::the().peripheral<TimerRegisters>(0x3000))
+{
+}
+
+Timer& Timer::the()
+{
+ static Timer instance;
+ return instance;
+}
+
+u64 Timer::microseconds_since_boot()
+{
+ u32 high = m_registers->counter_high;
+ u32 low = m_registers->counter_low;
+ if (high != m_registers->counter_high) {
+ high = m_registers->counter_high;
+ low = m_registers->counter_low;
+ }
+ return (static_cast<u64>(high) << 32) | low;
+}
+
+}
diff --git a/Kernel/Prekernel/Arch/aarch64/Timer.h b/Kernel/Prekernel/Arch/aarch64/Timer.h
new file mode 100644
index 0000000000..278df3d493
--- /dev/null
+++ b/Kernel/Prekernel/Arch/aarch64/Timer.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021, Nico Weber <thakis@chromium.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Types.h>
+
+namespace Prekernel {
+
+struct TimerRegisters;
+
+class Timer {
+public:
+ static Timer& the();
+
+ u64 microseconds_since_boot();
+
+private:
+ Timer();
+
+ TimerRegisters volatile* m_registers;
+};
+
+}
diff --git a/Kernel/Prekernel/Arch/aarch64/init.cpp b/Kernel/Prekernel/Arch/aarch64/init.cpp
index f0833bf64e..85662770c5 100644
--- a/Kernel/Prekernel/Arch/aarch64/init.cpp
+++ b/Kernel/Prekernel/Arch/aarch64/init.cpp
@@ -6,6 +6,7 @@
#include <AK/Types.h>
#include <Kernel/Prekernel/Arch/aarch64/Mailbox.h>
+#include <Kernel/Prekernel/Arch/aarch64/Timer.h>
#include <Kernel/Prekernel/Arch/aarch64/UART.h>
extern "C" [[noreturn]] void halt();
@@ -24,7 +25,17 @@ extern "C" [[noreturn]] void init()
uart.print_num(firmware_version);
uart.print_str("\r\n");
- halt();
+ auto& timer = Prekernel::Timer::the();
+ u64 start_musec = 0;
+ for (;;) {
+ u64 now_musec;
+ while ((now_musec = timer.microseconds_since_boot()) - start_musec < 1'000'000)
+ ;
+ start_musec = now_musec;
+ uart.print_str("Timer: ");
+ uart.print_num(now_musec);
+ uart.print_str("\r\n");
+ }
}
// FIXME: Share this with the Intel Prekernel.
diff --git a/Kernel/Prekernel/CMakeLists.txt b/Kernel/Prekernel/CMakeLists.txt
index 66167e6a14..d4f015aaa9 100644
--- a/Kernel/Prekernel/CMakeLists.txt
+++ b/Kernel/Prekernel/CMakeLists.txt
@@ -9,6 +9,7 @@ if ("${SERENITY_ARCH}" STREQUAL "aarch64")
Arch/aarch64/Mailbox.cpp
Arch/aarch64/MainIdRegister.cpp
Arch/aarch64/MMIO.cpp
+ Arch/aarch64/Timer.cpp
Arch/aarch64/UART.cpp
Arch/aarch64/boot.S
Arch/aarch64/init.cpp