1pub(crate) mod boot;
6pub mod cpu;
7pub mod device;
8pub(crate) mod io;
9pub(crate) mod iommu;
10pub mod irq;
11pub mod kernel;
12pub(crate) mod mm;
13pub mod power;
14pub mod serial;
15pub(crate) mod task;
16mod timer;
17pub mod trap;
18pub mod vm;
19
20#[cfg(feature = "cvm_guest")]
21pub(crate) mod tdx_guest;
22
23#[cfg(feature = "cvm_guest")]
24use crate::mm::frame::unaccepted;
25
26#[cfg(feature = "cvm_guest")]
27pub(crate) fn init_cvm_guest(boot_params: &linux_boot_params::BootParams) {
28 use ::tdx_guest::{
29 SeptVeError, disable_sept_ve, init_tdx, metadata, reduce_unnecessary_ve,
30 tdcall::{InitError, write_td_metadata},
31 tdvmcall::report_fatal_error_simple,
32 };
33
34 match init_tdx() {
35 Ok(td_info) => {
36 reduce_unnecessary_ve().unwrap();
37 match disable_sept_ve(td_info.attributes) {
38 Ok(_) => {}
39 Err(SeptVeError::Misconfiguration) => {
40 crate::early_println!(
41 "[kernel] Error: TD misconfiguration: \
42 The SEPT_VE_DISABLE bit of the TD attributes must be set by VMM \
43 when running in non-debug mode and FLEXIBLE_PENDING_VE is not enabled."
44 );
45 report_fatal_error_simple("TD misconfiguration: SEPT #VE has to be disabled");
46 }
47 Err(e) => {
48 crate::early_println!("[kernel] Error: Unexpected TDX error: {:?}", e);
49 report_fatal_error_simple(
50 "Disabling SEPT #VE failed due to unexpected TDX error",
51 );
52 }
53 }
54 write_td_metadata(metadata::NOTIFY_ENABLES, 1, 1).unwrap();
56
57 crate::early_println!(
58 "[kernel] Intel TDX initialized\n[kernel] td gpaw: {}, td attributes: {:?}",
59 td_info.gpaw,
60 td_info.attributes
61 );
62 unaccepted::init(boot_params);
63 }
64 Err(InitError::TdxGetVpInfoError(td_call_error)) => {
65 crate::early_println!(
66 "[kernel] Intel TDX not initialized, Failed to get TD info. TD call error: {:?}",
67 td_call_error
68 );
69 report_fatal_error_simple("Intel TDX not initialized, Failed to get TD info.");
70 }
71 Err(_) => {}
73 }
74}
75
76pub(crate) unsafe fn late_init_on_bsp() {
87 unsafe { trap::init_on_cpu() };
89
90 let io_mem_builder = unsafe { io::construct_io_mem_allocator_builder() };
93
94 kernel::apic::init(&io_mem_builder).expect("APIC doesn't exist");
95 irq::chip::init(&io_mem_builder);
96 irq::ipi::init();
97
98 kernel::tsc::init_tsc_freq();
99 timer::init_on_bsp();
100
101 unsafe { crate::boot::smp::boot_all_aps() };
103
104 if_tdx_enabled!({
105 unsafe { unaccepted::accept_memory_on_bsp() };
107 });
108
109 if_tdx_enabled!({
110 } else {
111 match iommu::init(&io_mem_builder) {
112 Ok(_) => {}
113 Err(err) => crate::warn!("IOMMU initialization error: {:?}", err),
114 }
115 });
116
117 unsafe { crate::io::init(io_mem_builder) };
122
123 kernel::acpi::init();
124 power::init();
125}
126
127pub(crate) unsafe fn init_on_ap() {
136 timer::init_on_ap();
137}
138
139pub fn tsc_freq() -> u64 {
141 use core::sync::atomic::Ordering;
142
143 kernel::tsc::TSC_FREQ.load(Ordering::Acquire)
144}
145
146pub fn read_tsc() -> u64 {
148 use core::arch::x86_64::_rdtsc;
149
150 unsafe { _rdtsc() }
152}
153
154pub fn read_random() -> Option<u64> {
158 use core::arch::x86_64::_rdrand64_step;
159
160 use cpu::extension::{IsaExtensions, has_extensions};
161
162 if !has_extensions(IsaExtensions::RDRAND) {
163 return None;
164 }
165
166 const RETRY_LIMIT: usize = 10;
170
171 for _ in 0..RETRY_LIMIT {
172 let mut val = 0;
173 let generated = unsafe { _rdrand64_step(&mut val) };
174 if generated == 1 {
175 return Some(val);
176 }
177 }
178 None
179}
180
181pub(crate) fn enable_cpu_features() {
182 use cpu::extension::{IsaExtensions, has_extensions};
183 use x86_64::registers::{
184 control::{Cr0Flags, Cr4Flags},
185 xcontrol::XCr0Flags,
186 };
187
188 cpu::extension::init();
189 vm::init();
190
191 let mut cr0 = x86_64::registers::control::Cr0::read();
192 cr0 |= Cr0Flags::WRITE_PROTECT;
193 cr0 |= Cr0Flags::NUMERIC_ERROR | Cr0Flags::MONITOR_COPROCESSOR;
197 unsafe { x86_64::registers::control::Cr0::write(cr0) };
198
199 let mut cr4 = x86_64::registers::control::Cr4::read();
200 cr4 |= Cr4Flags::OSFXSR | Cr4Flags::OSXMMEXCPT_ENABLE | Cr4Flags::PAGE_GLOBAL;
201 if has_extensions(IsaExtensions::XSAVE) {
202 cr4 |= Cr4Flags::OSXSAVE;
203 }
204 if has_extensions(IsaExtensions::FSGSBASE) {
213 cr4 |= Cr4Flags::FSGSBASE;
214 }
215 unsafe { x86_64::registers::control::Cr4::write(cr4) };
216
217 if has_extensions(IsaExtensions::XSAVE) {
218 let mut xcr0 = x86_64::registers::xcontrol::XCr0::read();
219 xcr0 |= XCr0Flags::SSE;
220 if has_extensions(IsaExtensions::AVX) {
221 xcr0 |= XCr0Flags::AVX;
222 }
223 if has_extensions(IsaExtensions::AVX512F) {
224 xcr0 |= XCr0Flags::OPMASK | XCr0Flags::ZMM_HI256 | XCr0Flags::HI16_ZMM;
225 }
226 unsafe { x86_64::registers::xcontrol::XCr0::write(xcr0) };
227 }
228
229 cpu::context::enable_essential_features();
230
231 mm::enable_essential_features();
232}
233
234#[macro_export]
243macro_rules! if_tdx_enabled {
244 ($if_block:block else $else_block:block) => {{
246 #[cfg(feature = "cvm_guest")]
247 {
248 if ::tdx_guest::tdx_is_enabled() {
249 $if_block
250 } else {
251 $else_block
252 }
253 }
254 #[cfg(not(feature = "cvm_guest"))]
255 {
256 $else_block
257 }
258 }};
259 ($if_block:block) => {{
261 #[cfg(feature = "cvm_guest")]
262 {
263 if ::tdx_guest::tdx_is_enabled() {
264 $if_block
265 }
266 }
267 }};
268}
269
270pub use if_tdx_enabled;