Skip to content

Commit 2d2da93

Browse files
committed
fix(interrupt): add missing "task context" check to set_priority*, don't try to get CPU Lock again in init
1 parent 4079fb6 commit 2d2da93

File tree

2 files changed

+31
-8
lines changed

2 files changed

+31
-8
lines changed

src/constance/src/kernel.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,9 +298,7 @@ pub unsafe trait Port: KernelCfg1 {
298298

299299
/// Set the priority of the specified interrupt line.
300300
///
301-
/// Precondition: CPU Lock active
302-
///
303-
/// Postcondition: CPU Lock active
301+
/// Precondition: CPU Lock active. Task context or boot phase.
304302
unsafe fn set_interrupt_line_priority(
305303
_line: InterruptNum,
306304
_priority: InterruptPriority,
@@ -383,7 +381,7 @@ impl<System: Kernel> PortToKernel for System {
383381
// safety*. Thus the use of unmanaged priority values has been already
384382
// authorized.
385383
unsafe {
386-
System::INTERRUPT_ATTR.init();
384+
System::INTERRUPT_ATTR.init(lock.borrow_mut());
387385
}
388386

389387
forget(lock);

src/constance/src/kernel/interrupt.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,29 @@ impl<System: Kernel> InterruptLine<System> {
107107
self,
108108
value: InterruptPriority,
109109
) -> Result<(), SetInterruptLinePriorityError> {
110-
let _lock = utils::lock_cpu::<System>()?;
110+
let mut lock = utils::lock_cpu::<System>()?;
111+
112+
if System::is_interrupt_context() {
113+
return Err(SetInterruptLinePriorityError::BadContext);
114+
}
111115

116+
// Safety: (1) Some of the preconditions of `set_priority_unchecked`,
117+
// which are upheld by the caller.
118+
// (2) A task context.
119+
unsafe { self.set_priority_unchecked_inner(value, lock.borrow_mut()) }
120+
}
121+
122+
/// Like `set_priority_unchecked` but assumes a task context or a boot
123+
/// phase.
124+
///
125+
/// # Safety
126+
///
127+
/// In addition to `set_priority_unchecked`,
128+
unsafe fn set_priority_unchecked_inner(
129+
self,
130+
value: InterruptPriority,
131+
_lock: utils::CpuLockGuardBorrowMut<System>,
132+
) -> Result<(), SetInterruptLinePriorityError> {
112133
// Safety: (1) We are the kernel, so it's okay to call `Port`'s methods.
113134
// (2) CPU Lock active
114135
unsafe { System::set_interrupt_line_priority(self.0, value) }
@@ -199,17 +220,21 @@ impl<System: Kernel> InterruptAttr<System> {
199220
///
200221
/// This method may call `InterruptLine::set_priority_unchecked`. The caller
201222
/// is responsible for ensuring *unmanaged safety*.
202-
pub(super) unsafe fn init(&self) {
223+
///
224+
/// Can be called only during a boot phase.
225+
pub(super) unsafe fn init(&self, mut lock: utils::CpuLockGuardBorrowMut<System>) {
203226
for line_init in self.line_inits {
204227
if line_init
205228
.flags
206229
.contains(InterruptLineInitFlags::SET_PRIORITY)
207230
{
208-
// Safety: The caller is responsible for making sure this is safe
231+
// Safety: (1) The caller is responsible for ensuring unmanaged
232+
// safety.
233+
// (2) Boot phase
209234
unsafe {
210235
line_init
211236
.line
212-
.set_priority_unchecked(line_init.priority)
237+
.set_priority_unchecked_inner(line_init.priority, lock.borrow_mut())
213238
.unwrap()
214239
};
215240
}

0 commit comments

Comments
 (0)