aboutsummaryrefslogtreecommitdiff
path: root/src/lib/sbi/time.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/sbi/time.zig')
-rw-r--r--src/lib/sbi/time.zig39
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);
+}