hal_x86_64/cpu/intrinsics.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 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
use super::DtablePtr;
use core::arch::asm;
pub use core::arch::x86_64::{
_rdrand16_step as rdrand16_step, _rdrand32_step as rdrand32_step,
_rdrand64_step as rdrand64_step, _rdtsc as rdtsc,
};
/// Perform one x86 `hlt` instruction.
///
/// # Safety
///
/// Intrinsics are inherently unsafe — this is just a less ugly way of writing
/// inline assembly.
///
/// Also...this halts the CPU.
#[inline(always)]
pub unsafe fn hlt() {
asm!("hlt")
}
/// Perform one x86 `cli` instruction.
///
/// `cli` disables CPU interrupts.
///
/// # Safety
///
/// Intrinsics are inherently unsafe — this is just a less ugly way of writing
/// inline assembly. Also, this does not guarantee that interrupts will be
/// re-enabled, ever.
///
/// Prefer the higher-level [`interrupt::Control::enter_critical`] API when
/// possible.
///
/// [`interrupt::Control::enter_critical`]: crate::interrupt::Idt#method.enter_critical
#[inline(always)]
pub unsafe fn cli() {
asm!("cli", options(nomem, nostack))
}
/// Perform one x86 `sti` instruction.
///
/// `sti` enables CPU interrupts.
///
/// # Safety
///
/// Intrinsics are inherently unsafe — this is just a less ugly way of writing
/// inline assembly.
///
/// Prefer the higher-level [`interrupt::Control::enter_critical`] API when
/// possible.
///
/// [`interrupt::Control::enter_critical`]: crate::interrupt::Idt#method.enter_critical
#[inline(always)]
pub unsafe fn sti() {
asm!("sti", options(nomem, nostack))
}
/// Perform one x86 `lidt` (*L*oad *I*interrupt *D*escriptor *T*able)
/// instruction.
///
/// `lidt` loads an [interrupt descriptor table (IDT)][IDT] from a [`DtablePtr`].
///
/// # Safety
///
/// - Intrinsics are inherently unsafe — this is just a less ugly way of writing
/// inline assembly.
/// - The provided [`DtablePtr`] must point to a valid [IDT].
/// - The pointed [IDT] must not be deallocated or overwritten while it is active.
///
/// Prefer the higher-level [`interrupt::Idt::load`] API when
/// possible.
///
/// [IDT]: crate::interrupt::Idt
/// [`interrupt::Idt::load`]: crate::interrupt::Idt::load
#[inline(always)]
pub(crate) unsafe fn lidt(ptr: DtablePtr) {
asm!("lidt [{0}]", in(reg) &ptr, options(readonly, nostack, preserves_flags))
}
/// Perform one x86 `lidt` (*L*oad *G*lobal *D*escriptor *T*able)
/// instruction.
///
/// `lgdt` loads a [global descriptor table (GDT)][GDT] from a [`DtablePtr`].
///
/// # Safety
///
/// - Intrinsics are inherently unsafe — this is just a less ugly way of writing
/// inline assembly.
/// - The provided [`DtablePtr`] must point to a valid [GDT].
/// - The pointed [GDT] must not be deallocated or overwritten while it is active.
///
/// Prefer the higher-level [`segment::Gdt::load`] API when possible.
///
/// [GDT]: crate::segment::Gdt
/// [`segment::Gdt::load`]: crate::segment::Gdt::load
#[inline(always)]
pub(crate) unsafe fn lgdt(ptr: DtablePtr) {
asm!("lgdt [{0}]", in(reg) &ptr, options(readonly, nostack, preserves_flags))
}
/// Perform one x86 `ltr` (*L*oad *T*ask *R*egister) instruction.
///
/// `ltr` loads a [task state segment (TSS)][TSS] selector into the current task
/// register.
///
/// # Safety
///
/// - Intrinsics are inherently unsafe — this is just a less ugly way of writing
/// inline assembly.
/// - The provided [segment selector] must select a task state segment in the
/// [GDT].
/// - The pointed [TSS] must not be deallocated or overwritten while it is active.
///
/// Prefer the higher-level [`task::StateSegment::load_tss`] API when possible.
///
/// [TSS]: crate::task::StateSegment
/// [segment selector]: crate::segment::Selector
/// [GDT]: crate::segment::Gdt
/// [`task::StateSegment::load_tss`]: crate::task::StateSegment::load_tss
#[inline(always)]
pub unsafe fn ltr(sel: crate::segment::Selector) {
asm!("ltr {0:x}", in(reg) sel.bits(), options(nomem, nostack, preserves_flags))
}