libarch/riscv64/
system.rs1use bitrs::{bitfield_repr, layout};
6use regio::riscv64::{Csr, encoding};
7use zerocopy::{IntoBytes, TryFromBytes};
8
9pub const SSTATUS: Csr<encoding::sstatus, SupervisorStatus> = Csr::new();
11
12#[bitfield_repr(u8)]
13#[derive(Clone, Copy)]
14pub enum Xlen {
15 Xlen32 = 1,
16 Xlen64 = 2,
17 Xlen128 = 3,
18}
19
20#[bitfield_repr(u8)]
21#[derive(Clone, Copy)]
22pub enum ExtensionStatus {
23 Off = 0, Initial = 1, Clean = 2, Dirty = 3, }
28
29layout!({
30 pub struct SupervisorStatus(u64);
32 {
33 let sd @ 63; let __ @ 62..34;
35 let uxl @ 33..32: Xlen; let __ @ 31..20;
37 let mxr @ 19; let sum @ 18; let xs @ 16..15: ExtensionStatus; let fs @ 14..13: ExtensionStatus; let __ @ 12..11;
42 let vs @ 10..9: ExtensionStatus; let spp @ 8; let __ @ 7;
45 let ube @ 6; let spie @ 5; let __ @ 4..2;
48 let sie @ 1; let __ @ 0;
50 }
51});
52
53pub const STVEC: Csr<encoding::stvec, SupervisorTrapVector> = Csr::new();
55
56#[bitfield_repr(u8)]
57#[derive(Clone, Copy)]
58pub enum TrapVectorMode {
59 Direct = 0,
60 Vectored = 1,
61}
62
63layout!({
64 pub struct SupervisorTrapVector(u64);
66 {
67 #[unshifted]
68 let base @ 63..2;
69 let mode @ 1..0: TrapVectorMode;
70 }
71});
72
73pub const SCAUSE: Csr<encoding::scause, SupervisorCause> = Csr::new();
75
76#[bitfield_repr(u64)]
78#[derive(Clone, Copy)]
79pub enum InterruptCode {
80 SoftwareInterrupt = 1,
81 TimerInterrupt = 5,
82 ExternalInterrupt = 9,
83}
84
85#[bitfield_repr(u64)]
87#[derive(Clone, Copy)]
88pub enum ExceptionCode {
89 InstructionAddressMisaligned = 0,
90 InstructionAccessFault = 1,
91 IllegalInstruction = 2,
92 Breakpoint = 3,
93 LoadAddressMisaligned = 4,
94 LoadAccessFault = 5,
95 StoreAddressMisaligned = 6,
96 StoreAccessFault = 7,
97 EcallUmode = 8,
98 EcallSmode = 9,
99 InstructionPageFault = 12,
100 LoadPageFault = 13,
101 StorePageFault = 15,
102}
103
104layout!({
105 pub struct SupervisorCause(u64);
107 {
108 let interrupt @ 63;
109 let code @ 62..0;
110 }
111});
112
113impl SupervisorCause {
114 #[inline]
115 pub fn exception_code(self) -> Option<ExceptionCode> {
116 if self.interrupt() {
117 return None;
118 }
119 ExceptionCode::try_read_from_bytes(self.code().as_bytes()).ok()
120 }
121
122 #[inline]
123 pub fn interrupt_code(self) -> Option<InterruptCode> {
124 if !self.interrupt() {
125 return None;
126 }
127 InterruptCode::try_read_from_bytes(self.code().as_bytes()).ok()
128 }
129}
130
131pub const STVAL: Csr<encoding::stval, u64> = Csr::new();
133
134pub const VTYPE: Csr<encoding::vtype, VectorType> = Csr::new();
136
137layout!({
138 pub struct VectorType(u64);
144 {
145 let vill @ 63; let __ @ 62..8;
147 let vma @ 7; let vta @ 6; let vsew @ 5..3; let vlmul @ 2..0; }
152});
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157
158 #[test]
159 fn vtype() {
160 let vtype = VectorType::from((1 << 7) | (1 << 6) | (0b010 << 3) | 0b111);
162 assert!(!vtype.vill());
163 assert!(vtype.vma());
164 assert!(vtype.vta());
165 assert_eq!(vtype.vsew(), 0b010);
166 assert_eq!(vtype.vlmul(), 0b111);
167 }
168
169 #[test]
170 fn scause() {
171 let mut scause = SupervisorCause::new();
172 scause.set_interrupt(false).set_code(ExceptionCode::LoadPageFault as u64);
173 assert_eq!(scause.exception_code(), Some(ExceptionCode::LoadPageFault));
174 assert_eq!(scause.interrupt_code(), None);
175
176 scause.set_interrupt(true).set_code(InterruptCode::TimerInterrupt as u64);
177 assert_eq!(scause.exception_code(), None);
178 assert_eq!(scause.interrupt_code(), Some(InterruptCode::TimerInterrupt));
179 }
180}