Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GDT: Add load_unchecked, from_raw_slice, and as_raw_slice. #210

Merged
merged 6 commits into from
Dec 28, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 54 additions & 2 deletions src/structures/gdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,40 @@ impl GlobalDescriptorTable {
}
}

/// Forms a GDT from a slice of `u64`.
///
/// # Safety
///
/// * The user must make sure that the entries are well formed
/// * The provided slice **must not be larger than 8 items** (only up to the first 8 will be observed.)
#[inline]
#[cfg(feature = "const_fn")]
pub const unsafe fn from_raw_slice(slice: &[u64]) -> GlobalDescriptorTable {
assert!(
slice.len() <= 8,
"initializing a GDT from a slice requires it to be **at most** 8 elements."
);
let next_free = slice.len();

let mut table = [0; 8];
let mut idx = 0;

while idx != next_free {
table[idx] = slice[idx];
idx += 1;
}

GlobalDescriptorTable { table, next_free }
}

/// Get a reference to the internal table.
mental32 marked this conversation as resolved.
Show resolved Hide resolved
///
/// The resulting slice may contain system descriptors, which span two `u64`s.
#[inline]
pub fn as_raw_slice(&self) -> &[u64] {
&self.table[..self.next_free]
}

const_fn! {
/// Adds the given segment descriptor to the GDT, returning the segment selector.
///
Expand Down Expand Up @@ -144,9 +178,27 @@ impl GlobalDescriptorTable {
#[cfg(feature = "instructions")]
#[inline]
pub fn load(&'static self) {
use crate::instructions::tables::lgdt;
// SAFETY: static lifetime ensures no modification after loading.
unsafe { lgdt(&self.pointer()) };
unsafe { self.load_unsafe() };
}

/// Loads the GDT in the CPU using the `lgdt` instruction. This does **not** alter any of the
/// segment registers; you **must** (re)load them yourself using [the appropriate
/// functions](crate::instructions::segmentation):
/// [load_ss](crate::instructions::segmentation::load_ss),
/// [set_cs](crate::instructions::segmentation::set_cs).
///
/// # Safety
///
/// Unlike `load` this function will not impose a static lifetime constraint
/// this means its up to the user to ensure that there will be no modifications
/// after loading and that the GDT will live for as long as it's loaded.
///
#[cfg(feature = "instructions")]
#[inline]
pub unsafe fn load_unsafe(&self) {
use crate::instructions::tables::lgdt;
lgdt(&self.pointer());
}

const_fn! {
Expand Down