#[inline] pub fn hlt() { unsafe { core::arch::asm!("hlt", options(nomem, nostack, preserves_flags)); } } #[inline] pub unsafe fn lidt(idt: &super::idt::IdtRegister) { unsafe { core::arch::asm!( "lidt [{}]", in(reg) idt, options(readonly, nostack, preserves_flags) ); } } #[inline] pub fn int3() { unsafe { core::arch::asm!("int3", options(nomem, nostack, preserves_flags)); } } macro_rules! read_segment { ($segment:literal) => { { let value: u16; unsafe { core::arch::asm!( concat!("mov {0:x}, ", $segment), out(reg) value, options(nomem, nostack, preserves_flags) ); } value } } } #[inline] pub unsafe fn get_cs() -> u16 { read_segment!("cs") } pub mod msr { use core::arch::asm; pub const MSR_STAR: u32 = 0xC000_0081; pub const MSR_LSTAR: u32 = 0xC000_0082; pub const MSR_CSTAR: u32 = 0xC000_0083; pub const MSR_SFMASK: u32 = 0xC000_0084; pub const MSR_FS_BASE: u32 = 0xC000_0100; pub const MSR_GS_BASE: u32 = 0xC000_0101; pub const MSR_KERNEL_GS_BASE: u32 = 0xC000_0102; /// Reads the value of the specified Model-Specific Register (MSR). /// # Safety /// This operation is inherently unsafe. #[inline] pub unsafe fn read_msr(msr: u32) -> u64 { unsafe { let eax: u32; let edx: u32; asm!( "rdmsr", in("ecx") msr, out("eax") eax, out("edx") edx, options(nomem, nostack, preserves_flags) ); ((edx as u64) << 32) | (eax as u64) } } /// Writes the value to the specified Model-Specific Register (MSR). /// # Safety /// This operation is inherently unsafe. #[inline] pub unsafe fn write_msr(msr: u32, value: u64) { unsafe { let eax = value as u32; let edx = (value >> 32) as u32; asm!( "wrmsr", in("ecx") msr, in("eax") eax, in("edx") edx, options(nomem, nostack, preserves_flags) ); } } } #[inline] pub fn rdtsc() -> u64 { let low: u32; let high: u32; unsafe { core::arch::asm!( "rdtsc", out("eax") low, out("edx") high, options(nomem, nostack, preserves_flags) ); } ((high as u64) << 32) | (low as u64) }