hal_x86_64/cpu/intrinsics.rs
1use super::DtablePtr;
2use core::arch::asm;
3pub use core::arch::x86_64::{
4 _rdrand16_step as rdrand16_step, _rdrand32_step as rdrand32_step,
5 _rdrand64_step as rdrand64_step, _rdtsc as rdtsc,
6};
7
8/// Perform one x86 `hlt` instruction.
9///
10/// # Safety
11///
12/// Intrinsics are inherently unsafe — this is just a less ugly way of writing
13/// inline assembly.
14///
15/// Also...this halts the CPU.
16#[inline(always)]
17pub unsafe fn hlt() {
18 asm!("hlt")
19}
20
21/// Perform one x86 `cli` instruction.
22///
23/// `cli` disables CPU interrupts.
24///
25/// # Safety
26///
27/// Intrinsics are inherently unsafe — this is just a less ugly way of writing
28/// inline assembly. Also, this does not guarantee that interrupts will be
29/// re-enabled, ever.
30///
31/// Prefer the higher-level [`interrupt::Control::enter_critical`] API when
32/// possible.
33///
34/// [`interrupt::Control::enter_critical`]: crate::interrupt::Idt#method.enter_critical
35#[inline(always)]
36pub unsafe fn cli() {
37 asm!("cli", options(nomem, nostack))
38}
39
40/// Perform one x86 `sti` instruction.
41///
42/// `sti` enables CPU interrupts.
43///
44/// # Safety
45///
46/// Intrinsics are inherently unsafe — this is just a less ugly way of writing
47/// inline assembly.
48///
49/// Prefer the higher-level [`interrupt::Control::enter_critical`] API when
50/// possible.
51///
52/// [`interrupt::Control::enter_critical`]: crate::interrupt::Idt#method.enter_critical
53#[inline(always)]
54pub unsafe fn sti() {
55 asm!("sti", options(nomem, nostack))
56}
57
58/// Perform one x86 `lidt` (*L*oad *I*interrupt *D*escriptor *T*able)
59/// instruction.
60///
61/// `lidt` loads an [interrupt descriptor table (IDT)][IDT] from a [`DtablePtr`].
62///
63/// # Safety
64///
65/// - Intrinsics are inherently unsafe — this is just a less ugly way of writing
66/// inline assembly.
67/// - The provided [`DtablePtr`] must point to a valid [IDT].
68/// - The pointed [IDT] must not be deallocated or overwritten while it is active.
69///
70/// Prefer the higher-level [`interrupt::Idt::load`] API when
71/// possible.
72///
73/// [IDT]: crate::interrupt::Idt
74/// [`interrupt::Idt::load`]: crate::interrupt::Idt::load
75#[inline(always)]
76pub(crate) unsafe fn lidt(ptr: DtablePtr) {
77 asm!("lidt [{0}]", in(reg) &ptr, options(readonly, nostack, preserves_flags))
78}
79
80/// Perform one x86 `lidt` (*L*oad *G*lobal *D*escriptor *T*able)
81/// instruction.
82///
83/// `lgdt` loads a [global descriptor table (GDT)][GDT] from a [`DtablePtr`].
84///
85/// # Safety
86///
87/// - Intrinsics are inherently unsafe — this is just a less ugly way of writing
88/// inline assembly.
89/// - The provided [`DtablePtr`] must point to a valid [GDT].
90/// - The pointed [GDT] must not be deallocated or overwritten while it is active.
91///
92/// Prefer the higher-level [`segment::Gdt::load`] API when possible.
93///
94/// [GDT]: crate::segment::Gdt
95/// [`segment::Gdt::load`]: crate::segment::Gdt::load
96#[inline(always)]
97pub(crate) unsafe fn lgdt(ptr: DtablePtr) {
98 asm!("lgdt [{0}]", in(reg) &ptr, options(readonly, nostack, preserves_flags))
99}
100
101/// Perform one x86 `ltr` (*L*oad *T*ask *R*egister) instruction.
102///
103/// `ltr` loads a [task state segment (TSS)][TSS] selector into the current task
104/// register.
105///
106/// # Safety
107///
108/// - Intrinsics are inherently unsafe — this is just a less ugly way of writing
109/// inline assembly.
110/// - The provided [segment selector] must select a task state segment in the
111/// [GDT].
112/// - The pointed [TSS] must not be deallocated or overwritten while it is active.
113///
114/// Prefer the higher-level [`task::StateSegment::load_tss`] API when possible.
115///
116/// [TSS]: crate::task::StateSegment
117/// [segment selector]: crate::segment::Selector
118/// [GDT]: crate::segment::Gdt
119/// [`task::StateSegment::load_tss`]: crate::task::StateSegment::load_tss
120#[inline(always)]
121pub unsafe fn ltr(sel: crate::segment::Selector) {
122 asm!("ltr {0:x}", in(reg) sel.bits(), options(nomem, nostack, preserves_flags))
123}