hal_x86_64/task.rs
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
use crate::{cpu, segment, VAddr};
use core::mem;
use mycelium_util::fmt;
/// A 64-bit mode task-state segment (TSS).
#[derive(Clone, Copy)]
#[repr(C, packed(4))]
pub struct StateSegment {
_reserved_1: u32,
/// The stack pointers for privilege levels 0-2.
///
/// These addresses must be in canonical form.
pub privilege_stacks: [VAddr; 3],
_reserved_2: u64,
/// The interrupt stack table.
pub interrupt_stacks: [VAddr; 7],
_reserved_3: u64,
_reserved_4: u16,
/// The 16-bit offset from the TSS' base address to the I/O permissions bitmap.
pub iomap_offset: u16,
}
impl StateSegment {
/// Returns a new task-state segment with all fields zeroed.
pub const fn empty() -> Self {
Self {
privilege_stacks: [VAddr::zero(); 3],
interrupt_stacks: [VAddr::zero(); 7],
iomap_offset: mem::size_of::<Self>() as u16,
_reserved_1: 0,
_reserved_2: 0,
_reserved_3: 0,
_reserved_4: 0,
}
}
/// Returns the virtual address of the I/O permission bitmap.
#[inline]
pub fn iomap_addr(&self) -> VAddr {
VAddr::of(self).offset(self.iomap_offset as isize)
}
/// Loads the provided [`selector`](segment::Selector) into the current task
/// register.
///
/// Prefer this higher-level wrapper to the [`ltr` CPU intrinsic][ltr].
///
/// # Safety
///
/// The caller is responsible for ensuring that `selector` selects a valid
/// task state segment, and that the selected TSS will not be deallocated as
/// long as it's active.
///
/// [ltr]: crate::cpu::intrinsics::ltr
pub unsafe fn load_tss(selector: segment::Selector) {
tracing::trace!(?selector, "setting TSS...");
cpu::intrinsics::ltr(selector);
tracing::debug!(?selector, "TSS set");
}
}
impl Default for StateSegment {
fn default() -> Self {
Self::empty()
}
}
impl fmt::Debug for StateSegment {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self {
privilege_stacks,
interrupt_stacks,
iomap_offset,
_reserved_1: _,
_reserved_2: _,
_reserved_3: _,
_reserved_4: _,
} = *self;
f.debug_struct("task::StateSegment")
.field("privilege_stacks", &privilege_stacks)
.field("interrupt_stacks", &interrupt_stacks)
.field("iomap_offset", &fmt::hex(iomap_offset))
.field("iomap_addr", &self.iomap_addr())
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sizeof_tss() {
assert_eq!(mem::size_of::<StateSegment>(), 0x68)
}
}