diff options
author | Nico Weber <thakis@chromium.org> | 2021-10-02 15:50:23 -0400 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-10-02 21:23:28 +0100 |
commit | bc213ad7a293f132ba27b52b30b4951c0613ebc8 (patch) | |
tree | 8476be49a6ad264f134d3b0493cbbb3c6780cc12 /Kernel | |
parent | 496d2e3c294704618fc5e88a031a229bcd09a650 (diff) | |
download | serenity-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.cpp | 51 | ||||
-rw-r--r-- | Kernel/Prekernel/Arch/aarch64/Timer.h | 27 | ||||
-rw-r--r-- | Kernel/Prekernel/Arch/aarch64/init.cpp | 13 | ||||
-rw-r--r-- | Kernel/Prekernel/CMakeLists.txt | 1 |
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 |