Skip to content

Commit 42346c2

Browse files
committed
fixup: riscv: apply review suggestions
1 parent 16251d8 commit 42346c2

File tree

1 file changed

+100
-23
lines changed

1 file changed

+100
-23
lines changed

riscv/src/register/mvien.rs

Lines changed: 100 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
//! mvien register
22
3+
use crate::bits::{bf_extract, bf_insert};
4+
use riscv_pac::InterruptNumber;
5+
36
#[cfg(target_arch = "riscv32")]
47
const MASK: usize = 0xffff_e222;
58
#[cfg(not(target_arch = "riscv32"))]
@@ -13,53 +16,127 @@ read_write_csr! {
1316

1417
read_write_csr_field! {
1518
Mvien,
16-
/// Alias of `mip.SSIP`
17-
ssip: 1,
19+
/// Alias of `mie.SSIE`
20+
ssoft: 1,
1821
}
1922

2023
read_write_csr_field! {
2124
Mvien,
22-
/// Alias of `mip.STIP`
23-
stip: 5,
25+
/// Alias of `mie.STIE`
26+
stimer: 5,
2427
}
2528

2629
read_write_csr_field! {
2730
Mvien,
28-
/// Alias of `mip.SEIP`
29-
seip: 9,
31+
/// Alias of `mie.SEIE`
32+
sext: 9,
3033
}
3134

32-
#[cfg(target_arch = "riscv32")]
33-
read_write_csr_field! {
34-
Mvien,
35-
/// Represents the enable status of a virtual major interrupt.
36-
interrupt: 13..=31,
37-
}
35+
impl Mvien {
36+
/// Represents the minimum interrupt of the unlabelled virtual interrupt range.
37+
pub const MIN_INTERRUPT: usize = 13;
38+
/// Represents the maximum interrupt of the unlabelled virtual interrupt range.
39+
#[cfg(target_arch = "riscv32")]
40+
pub const MAX_INTERRUPT: usize = 31;
41+
/// Represents the maximum interrupt of the unlabelled virtual interrupt range.
42+
#[cfg(not(target_arch = "riscv32"))]
43+
pub const MAX_INTERRUPT: usize = 63;
3844

39-
#[cfg(not(target_arch = "riscv32"))]
40-
read_write_csr_field! {
41-
Mvien,
42-
/// Represents the enable status of a virtual major interrupt.
43-
interrupt: 13..=63,
45+
/// Gets whether the interrupt number is a valid virtual interrupt.
46+
#[inline]
47+
pub const fn is_valid_interrupt(int: usize) -> bool {
48+
matches!(int, 1 | 5 | 9 | Self::MIN_INTERRUPT..=Self::MAX_INTERRUPT)
49+
}
50+
51+
/// Check if a specific core interrupt source is enabled.
52+
#[inline]
53+
pub fn is_enabled<I: InterruptNumber>(&self, interrupt: I) -> bool {
54+
let n = interrupt.number();
55+
Self::is_valid_interrupt(n) && bf_extract(self.bits, n, 1) != 0
56+
}
57+
58+
/// Enable a specific core interrupt source.
59+
#[inline]
60+
pub fn enable<I: InterruptNumber>(&mut self, interrupt: I) {
61+
let n = interrupt.number();
62+
63+
if Self::is_valid_interrupt(n) {
64+
self.bits = bf_insert(self.bits, n, 1, 1);
65+
}
66+
}
67+
68+
/// Disable a specific core interrupt source.
69+
#[inline]
70+
pub fn disable<I: InterruptNumber>(&mut self, interrupt: I) {
71+
let n = interrupt.number();
72+
73+
if Self::is_valid_interrupt(n) {
74+
self.bits = bf_insert(self.bits, n, 1, 0);
75+
}
76+
}
4477
}
4578

4679
set!(0x308);
4780
clear!(0x308);
4881

82+
set_clear_csr!(
83+
/// Supervisor Software Interrupt Enable
84+
, set_ssoft, clear_ssoft, 1 << 1);
85+
set_clear_csr!(
86+
/// Supervisor Timer Interrupt Enable
87+
, set_stimer, clear_stimer, 1 << 5);
88+
set_clear_csr!(
89+
/// Supervisor External Interrupt Enable
90+
, set_sext, clear_sext, 1 << 9);
91+
4992
#[cfg(test)]
5093
mod tests {
5194
use super::*;
95+
use riscv_pac::result::{Error, Result};
96+
97+
/// Represents a custom set of virtual interrupts.
98+
///
99+
/// NOTE: a real implementation may want to enumerate the valid virtual interrupt variants.
100+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
101+
pub struct VirtualInterrupt(usize);
102+
103+
/// SAFETY: `Interrupt` represents the standard RISC-V interrupts
104+
unsafe impl InterruptNumber for VirtualInterrupt {
105+
const MAX_INTERRUPT_NUMBER: usize = Mvien::MAX_INTERRUPT;
106+
107+
#[inline]
108+
fn number(self) -> usize {
109+
self.0
110+
}
111+
112+
#[inline]
113+
fn from_number(value: usize) -> Result<Self> {
114+
if Mvien::is_valid_interrupt(value) {
115+
Ok(Self(value))
116+
} else {
117+
Err(Error::InvalidVariant(value))
118+
}
119+
}
120+
}
52121

53122
#[test]
54123
fn test_mvien() {
55124
let mut m = Mvien::from_bits(0);
56125

57-
test_csr_field!(m, ssip);
58-
test_csr_field!(m, stip);
59-
test_csr_field!(m, seip);
126+
test_csr_field!(m, ssoft);
127+
test_csr_field!(m, stimer);
128+
test_csr_field!(m, sext);
129+
130+
(0..=VirtualInterrupt::MAX_INTERRUPT_NUMBER)
131+
.filter_map(|n| VirtualInterrupt::from_number(n).ok())
132+
.for_each(|int| {
133+
assert!(!m.is_enabled(int));
134+
135+
m.enable(int);
136+
assert!(m.is_enabled(int));
60137

61-
(13..64).for_each(|idx| {
62-
test_csr_field!(m, interrupt, idx);
63-
});
138+
m.disable(int);
139+
assert!(!m.is_enabled(int));
140+
});
64141
}
65142
}

0 commit comments

Comments
 (0)