diff options
Diffstat (limited to 'src/lib/sbi/time.zig')
-rw-r--r-- | src/lib/sbi/time.zig | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/src/lib/sbi/time.zig b/src/lib/sbi/time.zig new file mode 100644 index 0000000..2fad3e8 --- /dev/null +++ b/src/lib/sbi/time.zig @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org> +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +const std = @import("std"); + +const hwinfo = @import("../hwinfo.zig"); +const instructions = @import("../instructions.zig"); +const sbi = @import("../sbi.zig"); + +const ExtId: usize = 0x54494d45; + +const FnId = enum(usize) { + SetTimer = 0, +}; + +pub const Error = error{ + NoCpusHwInfo, +}; + +pub fn setTimer(stime_absolute: u64) !void { + if (!try sbi.probeExt(ExtId)) return sbi.Error.NotSupported; + + const ret = instructions.ecall(ExtId, @intFromEnum(FnId.SetTimer), stime_absolute, 0, 0); + if (ret.err != 0) return sbi.errorFromCode(ret.err); +} + +pub fn interruptInMillis(millis: u64) !void { + const stime = asm volatile ( + \\ csrr %[stime], time + : [stime] "=r" (-> u64), + ); + + var cpus = hwinfo.byKind(.cpus); + const frequency = try cpus.next() orelse return error.NoCpusHwInfo; + const cycles = frequency.value / 1000 * millis; + + try setTimer(stime + cycles); +} |