Skip to content

Commit 350fec3

Browse files
committed
Use riscv_pac::CoreInterrupt in sie register
1 parent ac78932 commit 350fec3

File tree

5 files changed

+123
-13
lines changed

5 files changed

+123
-13
lines changed

riscv/CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
### Added
1111

1212
- New convenience `try_new` and `new` associated functions for `Mtvec` and `Stvec`.
13-
- New methods and functions for enabling core interrupts in the `mie` register using
14-
the `riscv_pac::CoreInterrupt` trait.
13+
- New methods and functions for enabling core interrupts in the `mie` and `sie` registers
14+
using the `riscv_pac::CoreInterrupt` trait.
15+
- New `riscv::interrupt::{disable_interrupt, enable_interrupt}` functions.
1516

1617
### Changed
1718

riscv/src/interrupt/machine.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
interrupt::Trap,
3-
register::{mcause, mepc, mstatus},
3+
register::{mcause, mepc, mie, mstatus},
44
};
55
use riscv_pac::{
66
result::{Error, Result},
@@ -96,18 +96,42 @@ unsafe impl ExceptionNumber for Exception {
9696
}
9797
}
9898

99-
/// Disables all interrupts in the current hart (machine mode).
99+
/// Disables interrupts for a specific core interrupt source in the current hart (machine mode).
100+
#[inline]
101+
pub fn disable_interrupt<I: CoreInterruptNumber>(interrupt: I) {
102+
// SAFETY: it is safe to disable an interrupt source
103+
mie::disable_interrupt(interrupt);
104+
}
105+
106+
/// Enables interrupts for a specific core interrupt source in the current hart (machine mode).
107+
///
108+
/// # Note
109+
///
110+
/// Interrupts will only be triggered if interrupts are globally enabled in the hart.
111+
/// To do this, you must call [`enable`] after enabling the interrupt.
112+
///
113+
/// # Safety
114+
///
115+
/// Enabling interrupts might break critical sections or other synchronization mechanisms.
116+
/// Ensure that this is called in a safe context where interrupts can be enabled.
117+
#[inline]
118+
pub unsafe fn enable_interrupt<I: CoreInterruptNumber>(interrupt: I) {
119+
mie::enable_interrupt(interrupt);
120+
}
121+
122+
/// Disables interrupts globally in the current hart (machine mode).
100123
#[inline]
101124
pub fn disable() {
102125
// SAFETY: It is safe to disable interrupts
103126
unsafe { mstatus::clear_mie() }
104127
}
105128

106-
/// Enables all the interrupts in the current hart (machine mode).
129+
/// Enables interrupts globally in the current hart (machine mode).
107130
///
108131
/// # Safety
109132
///
110-
/// Do not call this function inside a critical section.
133+
/// Enabling interrupts might break critical sections or other synchronization mechanisms.
134+
/// Ensure that this is called in a safe context where interrupts can be enabled.
111135
#[inline]
112136
pub unsafe fn enable() {
113137
mstatus::set_mie()

riscv/src/interrupt/supervisor.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
interrupt::Trap,
3-
register::{scause, sepc, sstatus},
3+
register::{scause, sepc, sie, sstatus},
44
};
55
use riscv_pac::{
66
result::{Error, Result},
@@ -88,18 +88,42 @@ unsafe impl ExceptionNumber for Exception {
8888
}
8989
}
9090

91-
/// Disables all interrupts in the current hart (supervisor mode).
91+
/// Disables interrupts for a specific core interrupt source in the current hart (supervisor mode).
92+
#[inline]
93+
pub fn disable_interrupt<I: CoreInterruptNumber>(interrupt: I) {
94+
// SAFETY: it is safe to disable an interrupt source
95+
sie::disable_interrupt(interrupt);
96+
}
97+
98+
/// Enables interrupts for a specific core interrupt source in the current hart (supervisor mode).
99+
///
100+
/// # Note
101+
///
102+
/// Interrupts will only be triggered if interrupts are globally enabled in the hart.
103+
/// To do this, you must call [`enable`] after enabling the interrupt.
104+
///
105+
/// # Safety
106+
///
107+
/// Enabling interrupts might break critical sections or other synchronization mechanisms.
108+
/// Ensure that this is called in a safe context where interrupts can be enabled.
109+
#[inline]
110+
pub unsafe fn enable_interrupt<I: CoreInterruptNumber>(interrupt: I) {
111+
sie::enable_interrupt(interrupt);
112+
}
113+
114+
/// Disables interrupts globally in the current hart (supervisor mode).
92115
#[inline]
93116
pub fn disable() {
94117
// SAFETY: It is safe to disable interrupts
95118
unsafe { sstatus::clear_sie() }
96119
}
97120

98-
/// Enables all the interrupts in the current hart (supervisor mode).
121+
/// Enables interrupts globally in the current hart (supervisor mode).
99122
///
100123
/// # Safety
101124
///
102-
/// Do not call this function inside a critical section.
125+
/// Enabling interrupts might break critical sections or other synchronization mechanisms.
126+
/// Ensure that this is called in a safe context where interrupts can be enabled.
103127
#[inline]
104128
pub unsafe fn enable() {
105129
sstatus::set_sie()

riscv/src/register/mie.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ set_clear_csr!(
8888

8989
/// Disables a specific core interrupt source.
9090
#[inline]
91-
pub fn clear_interrupt<I: CoreInterruptNumber>(interrupt: I) {
91+
pub fn disable_interrupt<I: CoreInterruptNumber>(interrupt: I) {
9292
// SAFETY: it is safe to disable an interrupt source
9393
unsafe { _clear(1 << interrupt.number()) };
9494
}
@@ -100,7 +100,7 @@ pub fn clear_interrupt<I: CoreInterruptNumber>(interrupt: I) {
100100
/// Enabling interrupts might break critical sections or other synchronization mechanisms.
101101
/// Ensure that this is called in a safe context where interrupts can be enabled.
102102
#[inline]
103-
pub unsafe fn set_interrupt<I: CoreInterruptNumber>(interrupt: I) {
103+
pub unsafe fn enable_interrupt<I: CoreInterruptNumber>(interrupt: I) {
104104
unsafe { _set(1 << interrupt.number()) };
105105
}
106106

riscv/src/register/sie.rs

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
//! sie register
22
3+
use riscv_pac::CoreInterruptNumber;
4+
35
read_write_csr! {
46
/// sie register
57
Sie: 0x104,
6-
mask: 0x222,
8+
mask: usize::MAX,
79
}
810

911
read_write_csr_field! {
@@ -24,6 +26,26 @@ read_write_csr_field! {
2426
sext: 9,
2527
}
2628

29+
impl Sie {
30+
/// Check if a specific core interrupt source is enabled.
31+
#[inline]
32+
pub fn is_enabled<I: CoreInterruptNumber>(&self, interrupt: I) -> bool {
33+
(self.bits & (1 << interrupt.number())) != 0
34+
}
35+
36+
/// Enable a specific core interrupt source.
37+
#[inline]
38+
pub fn enable<I: CoreInterruptNumber>(&mut self, interrupt: I) {
39+
self.bits |= 1 << interrupt.number();
40+
}
41+
42+
/// Disable a specific core interrupt source.
43+
#[inline]
44+
pub fn disable<I: CoreInterruptNumber>(&mut self, interrupt: I) {
45+
self.bits &= !(1 << interrupt.number());
46+
}
47+
}
48+
2749
set!(0x104);
2850
clear!(0x104);
2951

@@ -37,9 +59,28 @@ set_clear_csr!(
3759
/// Supervisor External Interrupt Enable
3860
, set_sext, clear_sext, 1 << 9);
3961

62+
/// Disables a specific core interrupt source.
63+
#[inline]
64+
pub fn disable_interrupt<I: CoreInterruptNumber>(interrupt: I) {
65+
// SAFETY: it is safe to disable an interrupt source
66+
unsafe { _clear(1 << interrupt.number()) };
67+
}
68+
69+
/// Enables a specific core interrupt source.
70+
///
71+
/// # Safety
72+
///
73+
/// Enabling interrupts might break critical sections or other synchronization mechanisms.
74+
/// Ensure that this is called in a safe context where interrupts can be enabled.
75+
#[inline]
76+
pub unsafe fn enable_interrupt<I: CoreInterruptNumber>(interrupt: I) {
77+
unsafe { _set(1 << interrupt.number()) };
78+
}
79+
4080
#[cfg(test)]
4181
mod tests {
4282
use super::*;
83+
use crate::interrupt::supervisor::Interrupt;
4384

4485
#[test]
4586
fn test_sie() {
@@ -49,4 +90,24 @@ mod tests {
4990
test_csr_field!(sie, stimer);
5091
test_csr_field!(sie, sext);
5192
}
93+
94+
#[test]
95+
fn test_sie_interrupt() {
96+
let mut s = Sie::from_bits(0);
97+
98+
s.enable(Interrupt::SupervisorSoft);
99+
assert!(s.is_enabled(Interrupt::SupervisorSoft));
100+
s.disable(Interrupt::SupervisorSoft);
101+
assert!(!s.is_enabled(Interrupt::SupervisorSoft));
102+
103+
s.enable(Interrupt::SupervisorTimer);
104+
assert!(s.is_enabled(Interrupt::SupervisorTimer));
105+
s.disable(Interrupt::SupervisorTimer);
106+
assert!(!s.is_enabled(Interrupt::SupervisorTimer));
107+
108+
s.enable(Interrupt::SupervisorExternal);
109+
assert!(s.is_enabled(Interrupt::SupervisorExternal));
110+
s.disable(Interrupt::SupervisorExternal);
111+
assert!(!s.is_enabled(Interrupt::SupervisorExternal));
112+
}
52113
}

0 commit comments

Comments
 (0)