1#![cfg(any(target_arch = "x86", target_arch = "x86_64"))]
2#![no_std]
3#![cfg_attr(test, allow(unused_features))]
4#![cfg_attr(all(test, feature = "vmtest"), feature(custom_test_frameworks))]
5#![cfg_attr(all(test, feature = "vmtest"), test_runner(x86test::runner::runner))]
6#![cfg_attr(feature = "unstable", feature(step_trait))]
7
8use core::arch::asm;
9#[cfg(target_arch = "x86")]
10pub(crate) use core::arch::x86 as arch;
11#[cfg(target_arch = "x86_64")]
12pub(crate) use core::arch::x86_64 as arch;
13
14macro_rules! bit {
15 ($x:expr) => {
16 1 << $x
17 };
18}
19
20pub mod bits16;
21pub mod bits32;
22pub mod bits64;
23
24pub mod apic;
25pub mod controlregs;
26pub mod debugregs;
27pub mod dtables;
28pub mod fence;
29pub mod io;
30pub mod irq;
31pub mod msr;
32pub mod random;
33pub mod segmentation;
34pub mod task;
35pub mod time;
36pub mod tlb;
37pub mod vmx;
38
39#[cfg(feature = "performance-counter")]
40pub mod perfcnt;
41
42pub mod current {
44 #[cfg(target_arch = "x86")]
45 pub use crate::bits32::*;
46 #[cfg(target_arch = "x86_64")]
47 pub use crate::bits64::*;
48}
49
50pub mod cpuid {
52 pub use raw_cpuid::*;
53}
54
55#[cfg(not(test))]
56mod std {
57 pub use core::fmt;
58 pub use core::ops;
59 pub use core::option;
60}
61
62#[cfg(all(test, feature = "vmtest"))]
63extern crate klogger;
64#[cfg(all(test, feature = "vmtest"))]
65extern crate x86test;
66
67#[derive(Copy, Clone, Debug, Eq, PartialEq)]
68#[repr(u8)]
69pub enum Ring {
75 Ring0 = 0b00,
76 Ring1 = 0b01,
77 Ring2 = 0b10,
78 Ring3 = 0b11,
79}
80
81#[inline(always)]
92pub unsafe fn halt() {
93 asm!("hlt", options(att_syntax, nomem, nostack)); }
95
96#[cfg(all(test, feature = "vmtest"))]
97mod x86testing {
98 use super::*;
99 use x86test::*;
100
101 #[x86test(should_halt)]
102 fn should_halt() {
103 unsafe { halt() }
104 }
105
106 #[x86test]
107 fn should_not_halt() {}
108}
109
110#[inline(always)]
121pub unsafe fn rdpid() -> u64 {
122 #[cfg(target_pointer_width = "64")]
123 let mut pid: u64;
124 #[cfg(target_pointer_width = "32")]
125 let mut pid: u32;
126 asm!("rdpid {pid}", pid = out(reg) pid, options(att_syntax));
127 pid.into()
128}
129
130#[cfg(all(test, feature = "utest"))]
131mod test {
132 use super::*;
133
134 #[test]
135 fn test_rdpid() {
136 let rdpid_support = cpuid::CpuId::new()
137 .get_extended_feature_info()
138 .map_or(false, |finfo| finfo.has_rdpid());
139 unsafe {
140 if rdpid_support {
141 let pid1 = rdpid();
142 let pid2 = rdpid();
143 assert!(pid1 == pid2, "RDPID not consistent values?");
145 }
146 }
147 }
148}