diff options
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 52 |
1 files changed, 51 insertions, 1 deletions
@@ -24,6 +24,7 @@ pub mod dtables; pub mod io; pub mod irq; pub mod msr; +pub mod random; pub mod segmentation; pub mod task; pub mod time; @@ -33,6 +34,7 @@ pub mod xapic; #[cfg(feature = "performance-counter")] pub mod perfcnt; +/// A short-cut to the architecture (bits32 or bits64) this crate was compiled for. pub mod current { #[cfg(target_arch = "x86")] pub use crate::bits32::*; @@ -40,6 +42,7 @@ pub mod current { pub use crate::bits64::*; } +/// Support for the CPUID instructions. pub mod cpuid { pub use raw_cpuid::*; } @@ -54,7 +57,9 @@ mod std { #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(u8)] /// x86 Protection levels -/// Note: This should not contain values larger than 2 bits, otherwise +/// +/// # Note +/// This should not contain values larger than 2 bits, otherwise /// segment descriptor code needs to be adjusted accordingly. pub enum Ring { Ring0 = 0b00, @@ -63,7 +68,52 @@ pub enum Ring { Ring3 = 0b11, } + +/// Stops instruction execution and places the processor in a HALT state. +/// +/// An enabled interrupt (including NMI and SMI), a debug exception, the BINIT# +/// signal, the INIT# signal, or the RESET# signal will resume execution. If an +/// interrupt (including NMI) is used to resume execution after a HLT instruction, +/// the saved instruction pointer (CS:EIP) points to the instruction following +/// the HLT instruction. +/// +/// # Unsafe +/// Will cause a general protection fault if used outside of ring 0. #[inline(always)] pub unsafe fn halt() { asm!("hlt" :::: "volatile"); } + +/// Read Processor ID +/// +/// Reads the value of the IA32_TSC_AUX MSR (address C0000103H) +/// into the destination register. +/// +/// # Unsafe +/// May fail with #UD if rdpid is not supported (check CPUID). +#[inline(always)] +pub unsafe fn rdpid() -> u64 { + let mut pid: u64; + asm!("rdpid $0" : "=r"(pid)); + return pid; +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_rdpid() { + let rdpid_support = cpuid::CpuId::new() + .get_extended_feature_info() + .map_or(false, |finfo| finfo.has_rdpid()); + unsafe { + if rdpid_support { + let pid1 = rdpid(); + let pid2 = rdpid(); + // Let's hope we didn't migrate + assert!(pid1 == pid2, "RDPID not consistent values?"); + } + } + } +}
\ No newline at end of file |