1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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,
supervisor,
};
pub const ExtensionState = enum(u2) {
off,
initial,
clean,
dirty,
};
pub const Xlen = enum(u2) {
rv32 = 1,
rv64,
rv128,
};
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),
);
}
};
}
|