xref: /DragonOS/kernel/src/arch/x86_64/init/pvh/mod.rs (revision 59a6bcf6aee15a11a16431bdf875905c5ecf9157)
1*59a6bcf6SLoGin //! x86/HVM启动
2*59a6bcf6SLoGin //!
3*59a6bcf6SLoGin //! 初始化代码可参考:https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/platform/pvh/enlighten.c#45
4*59a6bcf6SLoGin use alloc::string::{String, ToString};
5*59a6bcf6SLoGin use core::{ffi::CStr, hint::spin_loop};
6*59a6bcf6SLoGin use param::{E820Type, HvmMemmapTableEntry, HvmStartInfo};
7*59a6bcf6SLoGin use system_error::SystemError;
8*59a6bcf6SLoGin 
9*59a6bcf6SLoGin use crate::{
10*59a6bcf6SLoGin     arch::MMArch,
11*59a6bcf6SLoGin     driver::{
12*59a6bcf6SLoGin         serial::serial8250::send_to_default_serial8250_port, video::fbdev::base::BootTimeScreenInfo,
13*59a6bcf6SLoGin     },
14*59a6bcf6SLoGin     init::{
15*59a6bcf6SLoGin         boot::{register_boot_callbacks, BootCallbacks, BootloaderAcpiArg},
16*59a6bcf6SLoGin         boot_params,
17*59a6bcf6SLoGin     },
18*59a6bcf6SLoGin     libs::lazy_init::Lazy,
19*59a6bcf6SLoGin     mm::{memblock::mem_block_manager, MemoryManagementArch, PhysAddr},
20*59a6bcf6SLoGin };
21*59a6bcf6SLoGin 
22*59a6bcf6SLoGin mod param;
23*59a6bcf6SLoGin 
24*59a6bcf6SLoGin static START_INFO: Lazy<HvmStartInfo> = Lazy::new();
25*59a6bcf6SLoGin 
26*59a6bcf6SLoGin struct PvhBootCallback;
27*59a6bcf6SLoGin 
28*59a6bcf6SLoGin impl BootCallbacks for PvhBootCallback {
init_bootloader_name(&self) -> Result<Option<String>, SystemError>29*59a6bcf6SLoGin     fn init_bootloader_name(&self) -> Result<Option<String>, SystemError> {
30*59a6bcf6SLoGin         return Ok(Some("x86 PVH".to_string()));
31*59a6bcf6SLoGin     }
32*59a6bcf6SLoGin 
init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError>33*59a6bcf6SLoGin     fn init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError> {
34*59a6bcf6SLoGin         let rsdp_paddr = PhysAddr::new(START_INFO.get().rsdp_paddr as usize);
35*59a6bcf6SLoGin         if rsdp_paddr.data() != 0 {
36*59a6bcf6SLoGin             Ok(BootloaderAcpiArg::Rsdp(rsdp_paddr))
37*59a6bcf6SLoGin         } else {
38*59a6bcf6SLoGin             Ok(BootloaderAcpiArg::NotProvided)
39*59a6bcf6SLoGin         }
40*59a6bcf6SLoGin     }
41*59a6bcf6SLoGin 
init_kernel_cmdline(&self) -> Result<(), SystemError>42*59a6bcf6SLoGin     fn init_kernel_cmdline(&self) -> Result<(), SystemError> {
43*59a6bcf6SLoGin         let cmdline_c_str: &CStr = unsafe {
44*59a6bcf6SLoGin             CStr::from_ptr(
45*59a6bcf6SLoGin                 MMArch::phys_2_virt(PhysAddr::new(START_INFO.get().cmdline_paddr as usize))
46*59a6bcf6SLoGin                     .unwrap()
47*59a6bcf6SLoGin                     .data() as *const i8,
48*59a6bcf6SLoGin             )
49*59a6bcf6SLoGin         };
50*59a6bcf6SLoGin         let cmdline = cmdline_c_str.to_str().unwrap();
51*59a6bcf6SLoGin         boot_params()
52*59a6bcf6SLoGin             .write_irqsave()
53*59a6bcf6SLoGin             .boot_cmdline_append(cmdline.as_bytes());
54*59a6bcf6SLoGin         log::info!("pvh boot cmdline: {:?}", cmdline_c_str);
55*59a6bcf6SLoGin         Ok(())
56*59a6bcf6SLoGin     }
57*59a6bcf6SLoGin 
early_init_framebuffer_info( &self, _scinfo: &mut BootTimeScreenInfo, ) -> Result<(), SystemError>58*59a6bcf6SLoGin     fn early_init_framebuffer_info(
59*59a6bcf6SLoGin         &self,
60*59a6bcf6SLoGin         _scinfo: &mut BootTimeScreenInfo,
61*59a6bcf6SLoGin     ) -> Result<(), SystemError> {
62*59a6bcf6SLoGin         return Err(SystemError::ENODEV);
63*59a6bcf6SLoGin     }
64*59a6bcf6SLoGin 
early_init_memory_blocks(&self) -> Result<(), SystemError>65*59a6bcf6SLoGin     fn early_init_memory_blocks(&self) -> Result<(), SystemError> {
66*59a6bcf6SLoGin         let start_info = START_INFO.get();
67*59a6bcf6SLoGin         let mut total_mem_size = 0usize;
68*59a6bcf6SLoGin         let mut usable_mem_size = 0usize;
69*59a6bcf6SLoGin         send_to_default_serial8250_port("init_memory_area by pvh boot\n\0".as_bytes());
70*59a6bcf6SLoGin 
71*59a6bcf6SLoGin         if (start_info.version > 0) && start_info.memmap_entries > 0 {
72*59a6bcf6SLoGin             let mut ep = unsafe {
73*59a6bcf6SLoGin                 MMArch::phys_2_virt(PhysAddr::new(start_info.memmap_paddr as usize)).unwrap()
74*59a6bcf6SLoGin             }
75*59a6bcf6SLoGin             .data() as *const HvmMemmapTableEntry;
76*59a6bcf6SLoGin 
77*59a6bcf6SLoGin             for _ in 0..start_info.memmap_entries {
78*59a6bcf6SLoGin                 let entry = unsafe { *ep };
79*59a6bcf6SLoGin                 let start = PhysAddr::new(entry.addr as usize);
80*59a6bcf6SLoGin                 let size = entry.size as usize;
81*59a6bcf6SLoGin                 let typ = E820Type::from(entry.type_);
82*59a6bcf6SLoGin 
83*59a6bcf6SLoGin                 total_mem_size += size;
84*59a6bcf6SLoGin                 match typ {
85*59a6bcf6SLoGin                     param::E820Type::Ram => {
86*59a6bcf6SLoGin                         usable_mem_size += size;
87*59a6bcf6SLoGin                         mem_block_manager()
88*59a6bcf6SLoGin                             .add_block(start, size)
89*59a6bcf6SLoGin                             .unwrap_or_else(|e| {
90*59a6bcf6SLoGin                                 log::warn!(
91*59a6bcf6SLoGin                                     "Failed to add memory block: base={:?}, size={:#x}, error={:?}",
92*59a6bcf6SLoGin                                     start,
93*59a6bcf6SLoGin                                     size,
94*59a6bcf6SLoGin                                     e
95*59a6bcf6SLoGin                                 );
96*59a6bcf6SLoGin                             });
97*59a6bcf6SLoGin                     }
98*59a6bcf6SLoGin                     _ => {
99*59a6bcf6SLoGin                         mem_block_manager()
100*59a6bcf6SLoGin                             .reserve_block(start, size)
101*59a6bcf6SLoGin                             .unwrap_or_else(|e| {
102*59a6bcf6SLoGin                                 log::warn!(
103*59a6bcf6SLoGin                                     "Failed to reserve memory block: base={:?}, size={:#x}, error={:?}",
104*59a6bcf6SLoGin                                     start,
105*59a6bcf6SLoGin                                     size,
106*59a6bcf6SLoGin                                     e
107*59a6bcf6SLoGin                                 );
108*59a6bcf6SLoGin                             });
109*59a6bcf6SLoGin                     }
110*59a6bcf6SLoGin                 }
111*59a6bcf6SLoGin                 ep = unsafe { ep.add(1) };
112*59a6bcf6SLoGin             }
113*59a6bcf6SLoGin         }
114*59a6bcf6SLoGin         send_to_default_serial8250_port("init_memory_area_from pvh boot end\n\0".as_bytes());
115*59a6bcf6SLoGin         log::info!(
116*59a6bcf6SLoGin             "Total memory size: {:#x}, Usable memory size: {:#x}",
117*59a6bcf6SLoGin             total_mem_size,
118*59a6bcf6SLoGin             usable_mem_size
119*59a6bcf6SLoGin         );
120*59a6bcf6SLoGin         Ok(())
121*59a6bcf6SLoGin     }
122*59a6bcf6SLoGin }
123*59a6bcf6SLoGin 
124*59a6bcf6SLoGin #[inline(never)]
early_linux32_pvh_init(params_ptr: usize) -> Result<(), SystemError>125*59a6bcf6SLoGin pub(super) fn early_linux32_pvh_init(params_ptr: usize) -> Result<(), SystemError> {
126*59a6bcf6SLoGin     let start_info = unsafe { *(params_ptr as *const HvmStartInfo) };
127*59a6bcf6SLoGin     if start_info.magic != HvmStartInfo::XEN_HVM_START_MAGIC_VALUE {
128*59a6bcf6SLoGin         send_to_default_serial8250_port(
129*59a6bcf6SLoGin             "early_linux32_pvh_init failed: Magic number not matched.\n\0".as_bytes(),
130*59a6bcf6SLoGin         );
131*59a6bcf6SLoGin 
132*59a6bcf6SLoGin         loop {
133*59a6bcf6SLoGin             spin_loop();
134*59a6bcf6SLoGin         }
135*59a6bcf6SLoGin     }
136*59a6bcf6SLoGin 
137*59a6bcf6SLoGin     START_INFO.init(start_info);
138*59a6bcf6SLoGin 
139*59a6bcf6SLoGin     register_boot_callbacks(&PvhBootCallback);
140*59a6bcf6SLoGin     send_to_default_serial8250_port("early_linux32_pvh_init done.\n\0".as_bytes());
141*59a6bcf6SLoGin     Ok(())
142*59a6bcf6SLoGin }
143