diff options
Diffstat (limited to 'src/lib/riscv.zig')
-rw-r--r-- | src/lib/riscv.zig | 112 |
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), + ); + } + }; +} |