Skip to content

Commit c9bfc08

Browse files
committed
implement functions for accessing CR8
CR8 aka the task priority register can be used to mask external interrupts. If a non-zero value is written to the lower 4 bit of CR8, all interrupts with an interrupt lower or equal to that number are masked off. If CR8 contains 0, all external interrupts are enabled. I've decided to implement this with an enum representing the 15 possible priority classes and used Option to represent the special 0 value. I've decided to make writing to CR8 safe because by itself, I don't think CR8 can be used to cause UB. This is similar to our methods for manipulating the IF flag.
1 parent 284bdca commit c9bfc08

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

src/registers/control.rs

+113
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,73 @@ bitflags! {
159159
}
160160
}
161161

162+
/// Contains the task priority.
163+
#[derive(Debug)]
164+
pub struct Cr8;
165+
166+
/// A priority class for an interrupt. Loading CR8 with a priority class blocks
167+
/// all interrupts of that class or lower. Note that 0 is not a priority class,
168+
/// if CR8 contains 0, all interrupts are enabled regardless of their priority
169+
/// class.
170+
#[derive(Debug)]
171+
pub enum PriorityClass {
172+
// 0 is not a valid priority class, 1 is the first valid class
173+
/// Priority class 1
174+
PriorityClass1 = 1,
175+
/// Priority class 2
176+
PriorityClass2,
177+
/// Priority class 3
178+
PriorityClass3,
179+
/// Priority class 4
180+
PriorityClass4,
181+
/// Priority class 5
182+
PriorityClass5,
183+
/// Priority class 6
184+
PriorityClass6,
185+
/// Priority class 7
186+
PriorityClass7,
187+
/// Priority class 8
188+
PriorityClass8,
189+
/// Priority class 9
190+
PriorityClass9,
191+
/// Priority class 10
192+
PriorityClass10,
193+
/// Priority class 11
194+
PriorityClass11,
195+
/// Priority class 12
196+
PriorityClass12,
197+
/// Priority class 13
198+
PriorityClass13,
199+
/// Priority class 14
200+
PriorityClass14,
201+
/// Priority class 15
202+
PriorityClass15,
203+
}
204+
205+
impl PriorityClass {
206+
/// Convert a number into a priority class
207+
pub const fn new(priority_class: u8) -> Option<Self> {
208+
Some(match priority_class {
209+
1 => Self::PriorityClass1,
210+
2 => Self::PriorityClass2,
211+
3 => Self::PriorityClass3,
212+
4 => Self::PriorityClass4,
213+
5 => Self::PriorityClass5,
214+
6 => Self::PriorityClass6,
215+
7 => Self::PriorityClass7,
216+
8 => Self::PriorityClass8,
217+
9 => Self::PriorityClass9,
218+
10 => Self::PriorityClass10,
219+
11 => Self::PriorityClass11,
220+
12 => Self::PriorityClass12,
221+
13 => Self::PriorityClass13,
222+
14 => Self::PriorityClass14,
223+
15 => Self::PriorityClass15,
224+
_ => return None,
225+
})
226+
}
227+
}
228+
162229
#[cfg(all(feature = "instructions", target_arch = "x86_64"))]
163230
mod x86_64 {
164231
use super::*;
@@ -496,4 +563,50 @@ mod x86_64 {
496563
}
497564
}
498565
}
566+
567+
impl Cr8 {
568+
/// Read the current priority class in CR8.
569+
#[inline]
570+
pub fn read() -> Option<PriorityClass> {
571+
PriorityClass::new(Self::read_raw() as u8)
572+
}
573+
574+
/// Read the current raw CR8 value.
575+
#[inline]
576+
pub fn read_raw() -> u64 {
577+
let value: u64;
578+
579+
unsafe {
580+
asm!("mov {}, cr8", out(reg) value, options(nomem, nostack, preserves_flags));
581+
}
582+
583+
value
584+
}
585+
586+
/// Write the priority class to CR8.
587+
#[inline]
588+
pub fn write(priority_class: Option<PriorityClass>) {
589+
let value = priority_class.map_or(0, |pc| pc as u64);
590+
Self::write_raw(value);
591+
}
592+
593+
/// Write to CR8.
594+
#[inline]
595+
pub fn write_raw(value: u64) {
596+
unsafe {
597+
asm!("mov cr8, {}", in(reg) value, options(nomem, nostack, preserves_flags));
598+
}
599+
}
600+
601+
/// Updates the priority class in CR8.
602+
#[inline]
603+
pub fn update<F>(f: F)
604+
where
605+
F: FnOnce(&mut Option<PriorityClass>),
606+
{
607+
let mut priority_class = Self::read();
608+
f(&mut priority_class);
609+
Self::write(priority_class);
610+
}
611+
}
499612
}

0 commit comments

Comments
 (0)