diff options
author | Nathan Ringo <nathan@remexre.com> | 2024-08-26 15:25:55 -0500 |
---|---|---|
committer | Nathan Ringo <nathan@remexre.com> | 2024-08-26 15:25:55 -0500 |
commit | 76f0764cebe313a75b9b170fa23fa940d9e5738a (patch) | |
tree | b56641c41748594582aa56f9a539f04152cfc108 /kernel/src/drivers/riscv_timer.rs | |
parent | f1897c47a8f03955b76d521d1843a25123bd65a2 (diff) |
The start of interrupt and timer support, with some DeviceTree parsing.
Diffstat (limited to 'kernel/src/drivers/riscv_timer.rs')
-rw-r--r-- | kernel/src/drivers/riscv_timer.rs | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/kernel/src/drivers/riscv_timer.rs b/kernel/src/drivers/riscv_timer.rs new file mode 100644 index 0000000..a702f7b --- /dev/null +++ b/kernel/src/drivers/riscv_timer.rs @@ -0,0 +1,43 @@ +use core::{arch::asm, ops::Add, time::Duration}; + +/// The number of `Instant` "ticks" in a second. Initialized by the early-boot DeviceTree parser. +pub static mut TIMEBASE_FREQUENCY: u32 = 0; + +/// A moment in time. +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct Instant(u64); + +impl Instant { + /// Returns the current time as an `Instant`. + pub fn now() -> Instant { + let out; + // SAFETY: We require the Sstc extension, enable it before jumping to Rust, and never + // disable it. + unsafe { + asm!("rdtime {out}", out = out(reg) out, options(nomem, nostack)); + } + Instant(out) + } +} + +impl Add<Duration> for Instant { + type Output = Instant; + + #[allow(clippy::suspicious_arithmetic_impl)] + fn add(self, duration: Duration) -> Instant { + // SAFETY: TIMEBASE_FREQUENCY is never concurrently written to. + let ticks_per_second = unsafe { TIMEBASE_FREQUENCY }; + let ticks = duration.as_nanos().wrapping_mul(ticks_per_second as u128) / 1_000_000_000; + Instant(self.0.wrapping_add(ticks as u64)) + } +} + +/// Sets the timer interrupt to fire at the given instant. Note that this sets a global value, +/// rather than interacting with the scheduler in any way. +pub fn set_timer(instant: Instant) { + // SAFETY: We require the Sstc extension, enable it before jumping to Rust, and never + // disable it. + unsafe { + asm!("csrw stimecmp, {instant}", instant = in(reg) instant.0, options(nomem, nostack)); + } +} |