aboutsummaryrefslogtreecommitdiff
path: root/src/lib/riscv.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/riscv.zig')
-rw-r--r--src/lib/riscv.zig112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/lib/riscv.zig b/src/lib/riscv.zig
new file mode 100644
index 0000000..8c5a4ee
--- /dev/null
+++ b/src/lib/riscv.zig
@@ -0,0 +1,112 @@
+// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+const std = @import("std");
+const interrupts = @import("interrupts.zig");
+const paging = @import("paging.zig");
+
+pub const Privilege = enum(u1) {
+ user = 0,
+ supervisor = 1,
+};
+
+pub const ExtensionState = enum(u2) {
+ off = 0,
+ initial = 1,
+ clean = 2,
+ dirty = 3,
+};
+
+pub const Xlen = enum(u2) {
+ rv32 = 1,
+ rv64 = 2,
+ rv128 = 3,
+};
+
+pub const Sstatus = packed struct(usize) {
+ user_interrupt_enable: u1,
+ supervisor_interrupt_enable: u1,
+ reserved0: u2,
+ user_prior_interrupt_enable: u1,
+ supervisor_prior_interrupt_enable: u1,
+ reserved1: u2,
+ previous_privilege: Privilege,
+ reserved2: u4,
+ floating_point_state: ExtensionState,
+ user_extension_state: ExtensionState,
+ reserved3: u1,
+ supervisor_user_memory_access: u1,
+ make_executable_readable: u1,
+ reserved4: u12,
+ user_xlen: Xlen,
+ reserved5: u29,
+ need_state_saving: u1, // Read-only.
+};
+
+pub const SbiRet = struct {
+ err: isize,
+ val: isize,
+};
+
+pub fn ecall(ext_id: usize, fn_id: usize, a0: usize, a1: usize, a2: usize) SbiRet {
+ var ret = SbiRet{ .err = 0, .val = 0 };
+
+ asm volatile (
+ \\ ecall
+ \\ sw a0, 0(%[err])
+ \\ sw a1, 0(%[val])
+ :
+ : [err] "r" (&ret.err),
+ [val] "r" (&ret.val),
+ [eid] "{a7}" (ext_id),
+ [fid] "{a6}" (fn_id),
+ [a0] "{a0}" (a0),
+ [a1] "{a1}" (a1),
+ [a2] "{a2}" (a2),
+ );
+
+ return ret;
+}
+
+pub fn stackPointer() usize {
+ return asm volatile (""
+ : [value] "={sp}" (-> usize),
+ );
+}
+
+pub const satp = Csr(paging.Satp, "satp");
+pub const sstatus = Csr(Sstatus, "sstatus");
+pub const sie = Csr(interrupts.Enable, "sie");
+pub const sip = Csr(interrupts.Enable, "sip");
+pub const sscratch = Csr(usize, "sscratch");
+pub const sepc = Csr(usize, "sepc");
+pub const stval = Csr(usize, "stval");
+pub const time = Csr(usize, "time");
+
+pub fn Csr(comptime T: type, csr: []const u8) type {
+ if (csr.len > 8) @compileError("CSR name length exceeds 8 characters");
+
+ return struct {
+ pub inline fn read() T {
+ comptime var buf = [_]u8{0} ** 23;
+
+ const bits = asm volatile (std.fmt.bufPrint(buf[0..], "csrr %[bits], {s}", .{csr}) catch unreachable
+ : [bits] "=r" (-> usize),
+ );
+
+ return @bitCast(bits);
+ }
+
+ pub inline fn write(value: T) void {
+ const bits: usize = @bitCast(value);
+
+ comptime var buf = [_]u8{0} ** 23;
+
+ asm volatile (std.fmt.bufPrint(buf[0..], "csrw {s}, %[bits]", .{csr}) catch unreachable
+ :
+ : [bits] "r" (bits),
+ );
+ }
+ };
+}