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}