Skip to content

Commit 77eaadf

Browse files
mental32phil-opp
andauthored
GDT: Add load_unchecked, from_raw_slice, and as_raw_slice. (#210)
* Add unsafe `load_unchecked`, `from_raw_parts`, and `into_raw_parts`. * cargo fmt * Apply suggested changes. * Apply suggested changes. * cfg `from_raw_parts` to "nightly" * Apply suggestions from code review Co-authored-by: Philipp Oppermann <[email protected]> Co-authored-by: Philipp Oppermann <[email protected]>
1 parent 76add2c commit 77eaadf

File tree

1 file changed

+54
-2
lines changed

1 file changed

+54
-2
lines changed

src/structures/gdt.rs

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,40 @@ impl GlobalDescriptorTable {
105105
}
106106
}
107107

108+
/// Forms a GDT from a slice of `u64`.
109+
///
110+
/// # Safety
111+
///
112+
/// * The user must make sure that the entries are well formed
113+
/// * The provided slice **must not be larger than 8 items** (only up to the first 8 will be observed.)
114+
#[inline]
115+
#[cfg(feature = "const_fn")]
116+
pub const unsafe fn from_raw_slice(slice: &[u64]) -> GlobalDescriptorTable {
117+
assert!(
118+
slice.len() <= 8,
119+
"initializing a GDT from a slice requires it to be **at most** 8 elements."
120+
);
121+
let next_free = slice.len();
122+
123+
let mut table = [0; 8];
124+
let mut idx = 0;
125+
126+
while idx != next_free {
127+
table[idx] = slice[idx];
128+
idx += 1;
129+
}
130+
131+
GlobalDescriptorTable { table, next_free }
132+
}
133+
134+
/// Get a reference to the internal table.
135+
///
136+
/// The resulting slice may contain system descriptors, which span two `u64`s.
137+
#[inline]
138+
pub fn as_raw_slice(&self) -> &[u64] {
139+
&self.table[..self.next_free]
140+
}
141+
108142
const_fn! {
109143
/// Adds the given segment descriptor to the GDT, returning the segment selector.
110144
///
@@ -144,9 +178,27 @@ impl GlobalDescriptorTable {
144178
#[cfg(feature = "instructions")]
145179
#[inline]
146180
pub fn load(&'static self) {
147-
use crate::instructions::tables::lgdt;
148181
// SAFETY: static lifetime ensures no modification after loading.
149-
unsafe { lgdt(&self.pointer()) };
182+
unsafe { self.load_unsafe() };
183+
}
184+
185+
/// Loads the GDT in the CPU using the `lgdt` instruction. This does **not** alter any of the
186+
/// segment registers; you **must** (re)load them yourself using [the appropriate
187+
/// functions](crate::instructions::segmentation):
188+
/// [load_ss](crate::instructions::segmentation::load_ss),
189+
/// [set_cs](crate::instructions::segmentation::set_cs).
190+
///
191+
/// # Safety
192+
///
193+
/// Unlike `load` this function will not impose a static lifetime constraint
194+
/// this means its up to the user to ensure that there will be no modifications
195+
/// after loading and that the GDT will live for as long as it's loaded.
196+
///
197+
#[cfg(feature = "instructions")]
198+
#[inline]
199+
pub unsafe fn load_unsafe(&self) {
200+
use crate::instructions::tables::lgdt;
201+
lgdt(&self.pointer());
150202
}
151203

152204
const_fn! {

0 commit comments

Comments
 (0)