1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
use core::fmt;
pub mod ctx;
pub use self::ctx::Context;
/// An interrupt controller for a platform.
pub trait Control {
type Registers: fmt::Debug + fmt::Display;
/// Disable all interrupts.
///
/// # Safety
///
/// This may cause a fault if called when interrupts are already disabled
/// (depending on the platform). It does not guarantee that interrupts will
/// ever be unmasked.
unsafe fn disable(&mut self);
/// Enable all interrupts.
///
/// # Safety
///
/// This may cause a fault if called when interrupts are already enabled
/// (depending on the platform).
unsafe fn enable(&mut self);
/// Returns `true` if interrupts are enabled.
fn is_enabled(&self) -> bool;
fn register_handlers<H>(&mut self) -> Result<(), RegistrationError>
where
H: Handlers<Self::Registers>;
/// Enter a critical section, returning a guard.
fn enter_critical(&mut self) -> CriticalGuard<'_, Self> {
unsafe {
self.disable();
}
CriticalGuard { ctrl: self }
}
}
pub trait Handlers<R: fmt::Debug + fmt::Display> {
fn page_fault<C>(cx: C)
where
C: ctx::Context<Registers = R> + ctx::PageFault;
fn code_fault<C>(cx: C)
where
C: ctx::Context<Registers = R> + ctx::CodeFault;
fn double_fault<C>(cx: C)
where
C: ctx::Context<Registers = R>;
fn timer_tick();
/// Called when a PS/2 keyboard interrupt is fired. The handler is provided
/// with the scancode read from the PS/2 keyboard controller.
fn ps2_keyboard(scancode: u8);
fn test_interrupt<C>(_cx: C)
where
C: ctx::Context<Registers = R>,
{
// nop
}
}
/// Errors that may occur while registering an interrupt handler.
#[derive(Clone, Eq, PartialEq)]
pub struct RegistrationError {
kind: RegistrationErrorKind,
}
#[derive(Debug)]
pub struct CriticalGuard<'a, C: Control + ?Sized> {
ctrl: &'a mut C,
}
#[derive(Debug, Clone, Eq, PartialEq)]
enum RegistrationErrorKind {
Nonexistant,
AlreadyRegistered,
Other(&'static str),
}
// === impl CriticalGuard ===
impl<'a, C: Control + ?Sized> Drop for CriticalGuard<'a, C> {
fn drop(&mut self) {
unsafe {
self.ctrl.enable();
}
}
}
// === impl RegistrationError ===
impl RegistrationError {
/// Returns a new error indicating that the registered interrupt vector does
/// not exist.
pub fn nonexistant() -> Self {
Self {
kind: RegistrationErrorKind::Nonexistant,
}
}
/// Returns a new error indicating that the registered interrupt vector has
/// already been registered and cannot be registered again.
pub fn already_registered() -> Self {
Self {
kind: RegistrationErrorKind::AlreadyRegistered,
}
}
/// Returns a new platform-specific error with the provided message.
pub fn other(message: &'static str) -> Self {
Self {
kind: RegistrationErrorKind::Other(message),
}
}
pub fn is_nonexistant(&self) -> bool {
matches!(self.kind, RegistrationErrorKind::Nonexistant)
}
pub fn is_already_registered(&self) -> bool {
matches!(self.kind, RegistrationErrorKind::AlreadyRegistered)
}
}
impl fmt::Debug for RegistrationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { kind } = self;
f.debug_struct("RegistrationError")
.field("kind", kind)
.finish()
}
}