x86/
controlregs.rs

1//! Functions to read and write control registers.
2//! See Intel Vol. 3a Section 2.5, especially Figure 2-7.
3
4use bitflags::*;
5
6use crate::arch::{_xgetbv, _xsetbv};
7use core::arch::asm;
8
9bitflags! {
10    pub struct Cr0: usize {
11        const CR0_ENABLE_PAGING = 1 << 31;
12        const CR0_CACHE_DISABLE = 1 << 30;
13        const CR0_NOT_WRITE_THROUGH = 1 << 29;
14        const CR0_ALIGNMENT_MASK = 1 << 18;
15        const CR0_WRITE_PROTECT = 1 << 16;
16        const CR0_NUMERIC_ERROR = 1 << 5;
17        const CR0_EXTENSION_TYPE = 1 << 4;
18        const CR0_TASK_SWITCHED = 1 << 3;
19        const CR0_EMULATE_COPROCESSOR = 1 << 2;
20        const CR0_MONITOR_COPROCESSOR = 1 << 1;
21        const CR0_PROTECTED_MODE = 1 << 0;
22    }
23}
24
25bitflags! {
26    pub struct Cr4: usize {
27        /// Enables use of Protection Keys (MPK).
28        const CR4_ENABLE_PROTECTION_KEY = 1 << 22;
29        /// Enable Supervisor Mode Access Prevention.
30        const CR4_ENABLE_SMAP = 1 << 21;
31        /// Enable Supervisor Mode Execution Protection.
32        const CR4_ENABLE_SMEP = 1 << 20;
33        /// Enable XSAVE and Processor Extended States.
34        const CR4_ENABLE_OS_XSAVE = 1 << 18;
35        /// Enables process-context identifiers (PCIDs).
36        const CR4_ENABLE_PCID = 1 << 17;
37        /// Enables the instructions RDFSBASE, RDGSBASE, WRFSBASE, and WRGSBASE.
38        const CR4_ENABLE_FSGSBASE = 1 << 16;
39        /// Enables Safer Mode Extensions (Trusted Execution Technology (TXT)).
40        const CR4_ENABLE_SMX = 1 << 14;
41        /// Enables Virtual Machine Extensions.
42        const CR4_ENABLE_VMX = 1 << 13;
43        /// Enables 5-Level Paging.
44        const CR4_ENABLE_LA57 = 1 << 12;
45        /// Enable User-Mode Instruction Prevention (the SGDT, SIDT, SLDT, SMSW and STR instructions
46        /// cannot be executed if CPL > 0).
47        const CR4_ENABLE_UMIP = 1 << 11;
48        /// Enables unmasked SSE exceptions.
49        const CR4_UNMASKED_SSE = 1 << 10;
50        /// Enables Streaming SIMD Extensions (SSE) instructions and fast FPU
51        /// save & restore FXSAVE and FXRSTOR instructions.
52        const CR4_ENABLE_SSE = 1 << 9;
53        /// Enable Performance-Monitoring Counters
54        const CR4_ENABLE_PPMC = 1 << 8;
55        /// Enable shared (PDE or PTE) address translation between address spaces.
56        const CR4_ENABLE_GLOBAL_PAGES = 1 << 7;
57        /// Enable machine check interrupts.
58        const CR4_ENABLE_MACHINE_CHECK = 1 << 6;
59        /// Enable: Physical Address Extension (allows to address physical
60        /// memory larger than 4 GiB).
61        const CR4_ENABLE_PAE = 1 << 5;
62        /// Enable Page Size Extensions (allows for pages larger than the traditional 4 KiB size)
63        /// Note: If Physical Address Extension (PAE) is used, the size of large pages is reduced
64        /// from 4 MiB down to 2 MiB, and PSE is always enabled, regardless of the PSE bit in CR4.
65        const CR4_ENABLE_PSE = 1 << 4;
66        /// If set, enables debug register based breaks on I/O space access.
67        const CR4_DEBUGGING_EXTENSIONS = 1 << 3;
68        /// If set, disables ability to take time-stamps.
69        const CR4_TIME_STAMP_DISABLE = 1 << 2;
70        /// If set, enables support for the virtual interrupt flag (VIF) in protected mode.
71        const CR4_VIRTUAL_INTERRUPTS = 1 << 1;
72        /// If set, enables support for the virtual interrupt flag (VIF) in virtual-8086 mode.
73        const CR4_ENABLE_VME = 1 << 0;
74    }
75}
76
77bitflags! {
78    pub struct Xcr0: u64 {
79        const XCR0_PKRU_STATE = 1 << 9;
80        const XCR0_HI16_ZMM_STATE = 1 << 7;
81        const XCR0_ZMM_HI256_STATE = 1 << 6;
82        const XCR0_OPMASK_STATE = 1 << 5;
83        const XCR0_BNDCSR_STATE = 1 << 4;
84        const XCR0_BNDREG_STATE = 1 << 3;
85        const XCR0_AVX_STATE = 1 << 2;
86        const XCR0_SSE_STATE = 1 << 1;
87        const XCR0_FPU_MMX_STATE = 1 << 0;
88    }
89}
90
91/// Read cr0
92///
93/// # Safety
94/// Needs CPL 0.
95pub unsafe fn cr0() -> Cr0 {
96    let ret: usize;
97    asm!("mov %cr0, {0}", out(reg) ret, options(att_syntax));
98    Cr0::from_bits_truncate(ret)
99}
100
101/// Write cr0.
102///
103/// # Safety
104/// Needs CPL 0.
105pub unsafe fn cr0_write(val: Cr0) {
106    asm!("mov {0}, %cr0", in(reg) val.bits, options(att_syntax));
107}
108
109/// Contains page-fault linear address.
110///
111/// # Safety
112/// Needs CPL 0.
113pub unsafe fn cr2() -> usize {
114    let ret: usize;
115    asm!("mov %cr2, {0}", out(reg) ret, options(att_syntax));
116    ret
117}
118
119/// Write cr2, for instance to reset cr2
120///
121/// # Safety
122/// Needs CPL 0.
123pub unsafe fn cr2_write(val: u64) {
124    asm!("mov {0}, %cr2", in(reg) val as usize, options(att_syntax));
125}
126
127/// Contains page-table root pointer.
128///
129/// # Safety
130/// Needs CPL 0.
131pub unsafe fn cr3() -> u64 {
132    let ret: usize;
133    asm!("mov %cr3, {0}", out(reg) ret, options(att_syntax));
134    ret as u64
135}
136
137/// Switch page-table PML4 pointer.
138///
139/// # Safety
140/// Needs CPL 0.
141pub unsafe fn cr3_write(val: u64) {
142    asm!("mov {0}, %cr3", in(reg) val as usize, options(att_syntax));
143}
144
145/// Contains various flags to control operations in protected mode.
146///
147/// # Safety
148/// Needs CPL 0.
149pub unsafe fn cr4() -> Cr4 {
150    let ret: usize;
151    asm!("mov %cr4, {0}", out(reg) ret, options(att_syntax));
152    Cr4::from_bits_truncate(ret)
153}
154
155/// Write cr4.
156///
157/// # Example
158///
159/// ```no_run
160/// use x86::controlregs::*;
161/// unsafe {
162///   let cr4 = cr4();
163///   let cr4 = cr4 | Cr4::CR4_ENABLE_PSE;
164///   cr4_write(cr4);
165/// }
166/// ```
167///
168/// # Safety
169/// Needs CPL 0.
170pub unsafe fn cr4_write(val: Cr4) {
171    asm!("mov {0}, %cr4", in(reg) val.bits, options(att_syntax));
172}
173
174/// Read Extended Control Register XCR0.
175/// Only supported if CR4_ENABLE_OS_XSAVE is set.
176///
177/// # Safety
178/// Needs CPL 0.
179pub unsafe fn xcr0() -> Xcr0 {
180    Xcr0::from_bits_truncate(_xgetbv(0))
181}
182
183/// Write to Extended Control Register XCR0.
184/// Only supported if CR4_ENABLE_OS_XSAVE is set.
185///
186/// # Safety
187/// Needs CPL 0.
188pub unsafe fn xcr0_write(val: Xcr0) {
189    _xsetbv(0, val.bits);
190}