Skip to content

Commit 4345dce

Browse files
committed
feat(port_riscv): add InterruptControllerToPort to provide access to the correct instance of xEIE for the selected privilege level
1 parent 13b72c8 commit 4345dce

File tree

6 files changed

+48
-8
lines changed

6 files changed

+48
-8
lines changed

src/r3_port_riscv/src/lib.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ The remaining interrupt numbers (≥ [`INTERRUPT_PLATFORM_START`]) are controlle
4646

4747
<span class="center">![interrupts]</span>
4848

49-
Usually, there are more than one interrupt source connected to the external interrupt pin of a hart through an interrupt controller. An interrupt controller driver is responsible for determining the source of an external interrupt and dispatching the appropriate handler. At configuration time, it attaches an interrupt handler to [`INTERRUPT_EXTERNAL`]. The interrupt handler, when called, queries the currently pending interrupt (let's assume the interrupt number is `n`). It can set `mie.MEIE` to allow nested interrupts (assuming the underlying hardware supports that). Then it fetches the corresponding interrupt handler by indexing [`INTERRUPT_HANDLERS`] by `n + INTERRUPT_PLATFORM_START` and calls that.
49+
Usually, there are more than one interrupt source connected to the external interrupt pin of a hart through an interrupt controller. An interrupt controller driver is responsible for determining the source of an external interrupt and dispatching the appropriate handler. At configuration time, it attaches an interrupt handler to [`INTERRUPT_EXTERNAL`]. The interrupt handler, when called, queries the currently pending interrupt (let's assume the interrupt number is `n`). It may call [`InterruptControllerToPort::enable_external_interrupts`][] to allow nested interrupts (assuming the underlying hardware supports that). Then it fetches the corresponding interrupt handler by indexing [`INTERRUPT_HANDLERS`] by `n + INTERRUPT_PLATFORM_START` and calls that.
5050

5151
The [`PortInterrupts`] implementation generated by `use_port!` delegates method calls to an interrupt controller driver through [`InterruptController`] for these interrupt numbers.
5252

src/r3_port_riscv/src/lib.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,20 @@ pub trait InterruptController {
251251
Err(QueryInterruptLineError::BadParam)
252252
}
253253
}
254+
255+
/// An API intended to be used by an interrupt controller driver. Implemented by
256+
/// [`use_port!`][].
257+
///
258+
/// # Safety
259+
///
260+
/// These methods are only intended to be called by the [`INTERRUPT_EXTERNAL`]
261+
/// interrupt handler of the interrupt controller driver attached to `Self`.
262+
pub trait InterruptControllerToPort {
263+
/// Enable external interrupts by setting `mie.MEIE` or its counterpart
264+
/// for [`ThreadingOptions::PRIVILEGE_LEVEL`].
265+
unsafe fn enable_external_interrupts();
266+
267+
/// Disable external interrupts by clearing `mie.MEIE` or its counterpart
268+
/// for [`ThreadingOptions::PRIVILEGE_LEVEL`].
269+
unsafe fn disable_external_interrupts();
270+
}

src/r3_port_riscv/src/plic/cfg.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ use super::plic_regs;
55

66
/// Implement [`InterruptController`] and [`Plic`] on the given kernel trait
77
/// type using the Platform-Level Interrupt Controller (PLIC) on the target.
8-
/// **Requires [`PlicOptions`].**
8+
/// **Requires [`PlicOptions`] and [`InterruptControllerToPort`].**
99
///
1010
/// [`InterruptController`]: crate::InterruptController
11+
/// [`InterruptControllerToPort`]: crate::InterruptControllerToPort
1112
///
1213
/// This macro adds `const fn configure_plic(b: &mut CfgBuilder<Self>)` to the
1314
/// system type. **It should be called by your application's configuration

src/r3_port_riscv/src/plic/imp.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ use r3_core::kernel::{
66
use r3_kernel::{KernelTraits, System};
77
use tock_registers::interfaces::{Readable, Writeable};
88

9-
use crate::{Plic, INTERRUPT_EXTERNAL, INTERRUPT_PLATFORM_START};
9+
use crate::{InterruptControllerToPort, Plic, INTERRUPT_EXTERNAL, INTERRUPT_PLATFORM_START};
1010

1111
/// The configuration function.
12-
pub const fn configure<C, Traits: Plic + KernelTraits>(b: &mut Cfg<C>)
12+
pub const fn configure<C, Traits: Plic + KernelTraits + InterruptControllerToPort>(b: &mut Cfg<C>)
1313
where
1414
C: ~const traits::CfgInterruptLine<System = System<Traits>>,
1515
{
@@ -36,11 +36,11 @@ pub fn init<Traits: Plic>() {
3636
}
3737

3838
#[inline]
39-
fn interrupt_handler<Traits: Plic + KernelTraits>(_: usize) {
39+
fn interrupt_handler<Traits: Plic + KernelTraits + InterruptControllerToPort>(_: usize) {
4040
if let Some((token, num)) = claim_interrupt::<Traits>() {
4141
if let Some(handler) = Traits::INTERRUPT_HANDLERS.get(num) {
4242
if Traits::USE_NESTING {
43-
unsafe { riscv::register::mie::set_mext() };
43+
unsafe { Traits::enable_external_interrupts() };
4444
}
4545

4646
// Safety: The interrupt controller driver is responsible for
@@ -49,7 +49,7 @@ fn interrupt_handler<Traits: Plic + KernelTraits>(_: usize) {
4949
unsafe { handler() };
5050

5151
if Traits::USE_NESTING {
52-
unsafe { riscv::register::mie::clear_mext() };
52+
unsafe { Traits::disable_external_interrupts() };
5353
}
5454
}
5555

src/r3_port_riscv/src/threading/cfg.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,13 @@ pub const PRIVILEGE_LEVEL_SUPERVISOR: u8 = 0b01;
4848
pub const PRIVILEGE_LEVEL_USER: u8 = 0b00;
4949

5050
/// Define a kernel trait type implementing [`PortThreading`],
51-
/// [`PortInterrupts`], and [`EntryPoint`].
51+
/// [`PortInterrupts`], [`InterruptControllerToPort`], and [`EntryPoint`].
5252
/// **Requires [`ThreadingOptions`], [`Timer`], and [`InterruptController`].**
5353
///
5454
/// [`PortThreading`]: r3_kernel::PortThreading
5555
/// [`PortInterrupts`]: r3_kernel::PortInterrupts
5656
/// [`EntryPoint`]: crate::EntryPoint
57+
/// [`InterruptControllerToPort`]: crate::InterruptControllerToPort
5758
/// [`InterruptController`]: crate::InterruptController
5859
/// [`Timer`]: crate::Timer
5960
#[macro_export]
@@ -76,6 +77,7 @@ macro_rules! use_port {
7677
use $crate::{
7778
threading::imp::{State, TaskState, PortInstance, CsrSet, NumTy},
7879
ThreadingOptions, EntryPoint, InterruptController,
80+
InterruptControllerToPort,
7981
};
8082

8183
pub(super) static PORT_STATE: State = State::new();
@@ -105,6 +107,16 @@ macro_rules! use_port {
105107
const TRAP_HANDLER: unsafe extern "C" fn() -> ! = State::exception_handler::<Self>;
106108
}
107109

110+
impl InterruptControllerToPort for $Traits {
111+
unsafe fn enable_external_interrupts() {
112+
unsafe { PORT_STATE.enable_external_interrupts::<Self>() }
113+
}
114+
115+
unsafe fn disable_external_interrupts() {
116+
unsafe { PORT_STATE.disable_external_interrupts::<Self>() }
117+
}
118+
}
119+
108120
// Assume `$Traits: KernelTraits`
109121
unsafe impl PortThreading for $Traits {
110122
type PortTaskState = TaskState;

src/r3_port_riscv/src/threading/imp.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,16 @@ impl State {
10481048
}
10491049
}
10501050

1051+
#[inline]
1052+
pub unsafe fn enable_external_interrupts<Traits: PortInstance>(&self) {
1053+
Traits::Csr::xie().set(Traits::Csr::XIE_XEIE);
1054+
}
1055+
1056+
#[inline]
1057+
pub unsafe fn disable_external_interrupts<Traits: PortInstance>(&self) {
1058+
Traits::Csr::xie().clear(Traits::Csr::XIE_XEIE);
1059+
}
1060+
10511061
/// Implements [`crate::EntryPoint::exception_handler`].
10521062
#[naked]
10531063
pub unsafe extern "C" fn exception_handler<Traits: PortInstance>() -> ! {

0 commit comments

Comments
 (0)