x86/registers/
controlregs.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2025.
4
5// This is inspired and adapted for Tock from the [x86](https://github.com/gz/rust-x86) crate.
6
7use kernel::utilities::registers::register_bitfields;
8use tock_registers::LocalRegisterCopy;
9
10#[cfg(target_arch = "x86")]
11use core::arch::asm;
12
13register_bitfields![u32,
14    pub CR0[
15        CR0_PROTECTED_MODE OFFSET(0) NUMBITS(1),
16        CR0_MONITOR_COPROCESSOR OFFSET(1) NUMBITS(1),
17        CR0_EMULATE_COPROCESSOR OFFSET(2) NUMBITS(1),
18        CR0_TASK_SWITCHED OFFSET(3) NUMBITS(1),
19        CR0_EXTENSION_TYPE OFFSET(4) NUMBITS(1),
20        CR0_NUMERIC_ERROR OFFSET(5) NUMBITS(11),
21        CR0_WRITE_PROTECT OFFSET(16) NUMBITS(2),
22        CR0_ALIGNMENT_MASK OFFSET(18) NUMBITS(11),
23        CR0_NOT_WRITE_THROUGH OFFSET(29) NUMBITS(1),
24        CR0_CACHE_DISABLE OFFSET(30) NUMBITS(1),
25        CR0_ENABLE_PAGING OFFSET(31) NUMBITS(1),
26    ],
27    pub CR4[
28        CR4_ENABLE_VME OFFSET(0) NUMBITS(1),
29        CR4_VIRTUAL_INTERRUPTS OFFSET(1) NUMBITS(1),
30        CR4_TIME_STAMP_DISABLE OFFSET(2) NUMBITS(1),
31        CR4_DEBUGGING_EXTENSIONS OFFSET(3) NUMBITS(1),
32        CR4_ENABLE_PSE OFFSET(4) NUMBITS(1),
33        CR4_ENABLE_PAE OFFSET(5) NUMBITS(1),
34        CR4_ENABLE_MACHINE_CHECK OFFSET(6) NUMBITS(1),
35        CR4_ENABLE_GLOBAL_PAGE OFFSET(7) NUMBITS(1),
36        CR4_ENABLE_PPMC OFFSET(8) NUMBITS(1),
37        CR4_ENABLE_SSE OFFSET(9) NUMBITS(1),
38        CR4_UNMASKED_SSE OFFSET(10) NUMBITS(1),
39        CR4_ENABLE_UMIP OFFSET(11) NUMBITS(1),
40        CR4_ENABLE_LA57 OFFSET(12) NUMBITS(1),
41        CR4_ENABLE_VMX OFFSET(13) NUMBITS(1),
42        CR4_ENABLE_SMX OFFSET(14) NUMBITS(2),
43        CR4_ENABLE_FSGSBASE OFFSET(16) NUMBITS(1),
44        CR4_ENABLE_PCID OFFSET(17) NUMBITS(1),
45        CR4_ENABLE_OS_XSAV OFFSET(18) NUMBITS(2),
46        CR4_ENABLE_SMEP OFFSET(20) NUMBITS(1),
47        CR4_ENABLE_SMAP OFFSET(21) NUMBITS(1),
48        CR4_ENABLE_PROTECTION_KEY OFFSET(22) NUMBITS(1),
49    ],
50];
51
52pub type Cr0 = LocalRegisterCopy<u32, CR0::Register>;
53pub type Cr4 = LocalRegisterCopy<u32, CR4::Register>;
54
55/// Read cr0
56///
57/// # Safety
58/// Needs CPL 0.
59#[cfg(target_arch = "x86")]
60pub unsafe fn cr0() -> Cr0 {
61    let ret: u32;
62    unsafe {
63        asm!("mov %cr0, {0}", out(reg) ret, options(att_syntax));
64    }
65    LocalRegisterCopy::new(ret)
66}
67
68/// Write cr0.
69///
70/// # Safety
71/// Needs CPL 0.
72#[cfg(target_arch = "x86")]
73pub unsafe fn cr0_write(val: Cr0) {
74    unsafe {
75        asm!("mov {0}, %cr0", in(reg) val.get(), options(att_syntax));
76    }
77}
78
79/// Contains various flags to control operations in protected mode.
80///
81/// # Safety
82/// Needs CPL 0.
83#[cfg(target_arch = "x86")]
84pub unsafe fn cr4() -> Cr4 {
85    let ret: u32;
86    unsafe {
87        asm!("mov %cr4, {0}", out(reg) ret, options(att_syntax));
88    }
89    LocalRegisterCopy::new(ret)
90}
91
92/// Write cr4.
93///
94/// # Example
95///
96/// ```no_run
97/// use x86::registers::controlregs::*;
98/// unsafe {
99///   let cr4 = cr4();
100///   let cr4 = cr4 | Cr4::CR4_ENABLE_PSE;
101///   cr4_write(cr4);
102/// }
103/// ```
104///
105/// # Safety
106/// Needs CPL 0.
107#[cfg(target_arch = "x86")]
108pub unsafe fn cr4_write(val: Cr4) {
109    unsafe {
110        asm!("mov {0}, %cr4", in(reg) val.get(), options(att_syntax));
111    }
112}
113
114/// Contains page-table root pointer.
115///
116/// # Safety
117/// Needs CPL 0.
118#[cfg(target_arch = "x86")]
119pub unsafe fn cr3() -> u64 {
120    let ret: usize;
121    unsafe {
122        asm!("mov %cr3, {0}", out(reg) ret, options(att_syntax));
123    }
124    ret as u64
125}
126
127/// Switch page-table PML4 pointer.
128///
129/// # Safety
130/// Needs CPL 0.
131#[cfg(target_arch = "x86")]
132pub unsafe fn cr3_write(val: u64) {
133    unsafe {
134        asm!("mov {0}, %cr3", in(reg) val as usize, options(att_syntax));
135    }
136}
137
138// For CI only
139
140#[cfg(not(any(doc, target_arch = "x86")))]
141pub unsafe fn cr0() -> Cr0 {
142    unimplemented!()
143}
144
145#[cfg(not(any(doc, target_arch = "x86")))]
146pub unsafe fn cr0_write(_val: Cr0) {
147    unimplemented!()
148}
149
150#[cfg(not(any(doc, target_arch = "x86")))]
151pub unsafe fn cr4() -> Cr4 {
152    unimplemented!()
153}
154
155#[cfg(not(any(doc, target_arch = "x86")))]
156pub unsafe fn cr4_write(_val: Cr4) {
157    unimplemented!()
158}
159
160#[cfg(not(any(doc, target_arch = "x86")))]
161pub unsafe fn cr3() -> u64 {
162    unimplemented!()
163}
164
165#[cfg(not(any(doc, target_arch = "x86")))]
166pub unsafe fn cr3_write(_val: u64) {
167    unimplemented!()
168}