x86_64/instructions/mod.rs
1#![cfg(all(feature = "instructions", target_arch = "x86_64"))]
2
3//! Special x86_64 instructions.
4
5pub mod interrupts;
6pub mod port;
7pub mod random;
8pub mod segmentation;
9pub mod smap;
10pub mod tables;
11pub mod tlb;
12
13use core::arch::asm;
14
15/// Halts the CPU until the next interrupt arrives.
16#[inline]
17pub fn hlt() {
18 unsafe {
19 asm!("hlt", options(nomem, nostack, preserves_flags));
20 }
21}
22
23/// Executes the `nop` instructions, which performs no operation (i.e. does nothing).
24///
25/// This operation is useful to work around the LLVM bug that endless loops are illegally
26/// optimized away (see [the issue](https://github.com/rust-lang/rust/issues/28728)). By invoking this
27/// instruction (which is marked as volatile), the compiler should no longer optimize the
28/// endless loop away.
29#[inline]
30pub fn nop() {
31 unsafe {
32 asm!("nop", options(nomem, nostack, preserves_flags));
33 }
34}
35
36/// Emits a '[magic breakpoint](https://wiki.osdev.org/Bochs#Magic_Breakpoint)'
37/// instruction for the [Bochs](http://bochs.sourceforge.net/) CPU
38/// emulator.
39///
40/// Make sure to set `magic_break: enabled=1` in your `.bochsrc` file.
41#[inline]
42pub fn bochs_breakpoint() {
43 unsafe {
44 asm!("xchg bx, bx", options(nomem, nostack, preserves_flags));
45 }
46}
47
48/// Gets the current instruction pointer. Note that this is only approximate as it requires a few
49/// instructions to execute.
50#[inline(always)]
51pub fn read_rip() -> crate::VirtAddr {
52 let rip: u64;
53 unsafe {
54 asm!("lea {}, [rip]", out(reg) rip, options(nostack, nomem, preserves_flags));
55 }
56 crate::VirtAddr::new(rip)
57}