x86_64::structures::gdt

Struct GlobalDescriptorTable

Source
pub struct GlobalDescriptorTable<const MAX: usize = 8> { /* private fields */ }
Expand description

A 64-bit mode global descriptor table (GDT).

In 64-bit mode, segmentation is not supported. The GDT is used nonetheless, for example for switching between user and kernel mode or for loading a TSS.

The GDT has a fixed maximum size given by the MAX const generic parameter. Overflowing this limit by adding too many Descriptors via GlobalDescriptorTable::append will panic.

You do not need to add a null segment descriptor yourself - this is already done internally. This means you can add up to MAX - 1 additional Entrys to this table. Note that some Descriptors may take up 2 Entrys.

Data segment registers in ring 0 can be loaded with the null segment selector. When running in ring 3, the ss register must point to a valid data segment which can be obtained through the Descriptor::user_data_segment() function. Code segments must be valid and non-null at all times and can be obtained through the Descriptor::kernel_code_segment() and Descriptor::user_code_segment() in rings 0 and 3 respectively.

For more info, see: x86 Instruction Reference for mov, Intel Manual, AMD Manual

§Example

use x86_64::structures::gdt::{GlobalDescriptorTable, Descriptor};

let mut gdt = GlobalDescriptorTable::new();
gdt.append(Descriptor::kernel_code_segment());
gdt.append(Descriptor::user_code_segment());
gdt.append(Descriptor::user_data_segment());

// Add entry for TSS, call gdt.load() then update segment registers

Implementations§

Source§

impl GlobalDescriptorTable

Source

pub const fn new() -> Self

Creates an empty GDT with the default length of 8.

Source§

impl<const MAX: usize> GlobalDescriptorTable<MAX>

Source

pub const fn empty() -> Self

Creates an empty GDT which can hold MAX number of Entrys.

Source

pub const fn from_raw_entries(slice: &[u64]) -> Self

Forms a GDT from a slice of u64.

This method allows for creation of a GDT with malformed or invalid entries. However, it is safe because loading a GDT with invalid entires doesn’t do anything until those entries are used. For example, CS::set_reg and load_tss are both unsafe for this reason.

Panics if:

  • the provided slice has more than MAX entries
  • the provided slice is empty
  • the first entry is not zero
Source

pub fn entries(&self) -> &[Entry]

Get a reference to the internal Entry table.

The resulting slice may contain system descriptors, which span two Entrys.

Source

pub const fn append(&mut self, entry: Descriptor) -> SegmentSelector

Appends the given segment descriptor to the GDT, returning the segment selector.

Note that depending on the type of the Descriptor this may append either one or two new Entrys to the table.

Panics if the GDT doesn’t have enough free entries.

Source

pub fn load(&'static self)

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: SS::set_reg() and CS::set_reg().

Source

pub unsafe fn load_unsafe(&self)

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: SS::set_reg() and CS::set_reg().

§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.

Trait Implementations§

Source§

impl<const MAX: usize> Clone for GlobalDescriptorTable<MAX>

Source§

fn clone(&self) -> GlobalDescriptorTable<MAX>

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<const MAX: usize> Debug for GlobalDescriptorTable<MAX>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<const MAX: usize = 8> !Freeze for GlobalDescriptorTable<MAX>

§

impl<const MAX: usize> RefUnwindSafe for GlobalDescriptorTable<MAX>

§

impl<const MAX: usize> Send for GlobalDescriptorTable<MAX>

§

impl<const MAX: usize> Sync for GlobalDescriptorTable<MAX>

§

impl<const MAX: usize> Unpin for GlobalDescriptorTable<MAX>

§

impl<const MAX: usize> UnwindSafe for GlobalDescriptorTable<MAX>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.