1 //! 这个文件内放置初始内核线程的代码。 2 3 use core::sync::atomic::{compiler_fence, Ordering}; 4 5 use alloc::{ffi::CString, string::ToString}; 6 use log::{debug, error}; 7 use system_error::SystemError; 8 9 use crate::{ 10 arch::{interrupt::TrapFrame, process::arch_switch_to_user}, 11 driver::{net::e1000e::e1000e::e1000e_init, virtio::virtio::virtio_probe}, 12 filesystem::vfs::core::mount_root_fs, 13 net::net_core::net_init, 14 process::{ 15 exec::ProcInitInfo, kthread::KernelThreadMechanism, stdio::stdio_init, ProcessFlags, 16 ProcessManager, 17 }, 18 smp::smp_init, 19 syscall::Syscall, 20 }; 21 22 use super::{cmdline::kenrel_cmdline_param_manager, initcall::do_initcalls}; 23 24 const INIT_PROC_TRYLIST: [&str; 3] = ["/bin/dragonreach", "/bin/init", "/bin/sh"]; 25 26 pub fn initial_kernel_thread() -> i32 { 27 kernel_init().unwrap_or_else(|err| { 28 log::error!("Failed to initialize kernel: {:?}", err); 29 panic!() 30 }); 31 32 switch_to_user(); 33 } 34 35 fn kernel_init() -> Result<(), SystemError> { 36 KernelThreadMechanism::init_stage2(); 37 kenrel_init_freeable()?; 38 #[cfg(target_arch = "x86_64")] 39 crate::driver::disk::ahci::ahci_init() 40 .inspect_err(|e| log::error!("ahci_init failed: {:?}", e)) 41 .ok(); 42 virtio_probe(); 43 mount_root_fs().expect("Failed to mount root fs"); 44 e1000e_init(); 45 net_init().unwrap_or_else(|err| { 46 error!("Failed to initialize network: {:?}", err); 47 }); 48 49 debug!("initial kernel thread done."); 50 51 return Ok(()); 52 } 53 54 #[inline(never)] 55 fn kenrel_init_freeable() -> Result<(), SystemError> { 56 do_initcalls().unwrap_or_else(|err| { 57 panic!("Failed to initialize subsystems: {:?}", err); 58 }); 59 stdio_init().expect("Failed to initialize stdio"); 60 smp_init(); 61 62 return Ok(()); 63 } 64 65 /// 切换到用户态 66 #[inline(never)] 67 fn switch_to_user() -> ! { 68 let current_pcb = ProcessManager::current_pcb(); 69 70 // 删除kthread的标志 71 current_pcb.flags().remove(ProcessFlags::KTHREAD); 72 current_pcb.worker_private().take(); 73 74 *current_pcb.sched_info().sched_policy.write_irqsave() = crate::sched::SchedPolicy::CFS; 75 drop(current_pcb); 76 77 let mut proc_init_info = ProcInitInfo::new(""); 78 proc_init_info.envs.push(CString::new("PATH=/").unwrap()); 79 proc_init_info.args = kenrel_cmdline_param_manager().init_proc_args(); 80 proc_init_info.envs = kenrel_cmdline_param_manager().init_proc_envs(); 81 82 let mut trap_frame = TrapFrame::new(); 83 84 if let Some(path) = kenrel_cmdline_param_manager().init_proc_path() { 85 log::info!("Boot with specified init process: {:?}", path); 86 87 try_to_run_init_process( 88 path.as_c_str().to_str().unwrap(), 89 &mut proc_init_info, 90 &mut trap_frame, 91 ) 92 .unwrap_or_else(|e| { 93 panic!( 94 "Failed to run specified init process: {:?}, err: {:?}", 95 path, e 96 ) 97 }); 98 } else { 99 let mut ok = false; 100 for path in INIT_PROC_TRYLIST.iter() { 101 if try_to_run_init_process(path, &mut proc_init_info, &mut trap_frame).is_ok() { 102 ok = true; 103 break; 104 } 105 } 106 if !ok { 107 panic!("Failed to run init process: No working init found."); 108 } 109 } 110 drop(proc_init_info); 111 // 需要确保执行到这里之后,上面所有的资源都已经释放(比如arc之类的) 112 compiler_fence(Ordering::SeqCst); 113 114 unsafe { arch_switch_to_user(trap_frame) }; 115 } 116 117 fn try_to_run_init_process( 118 path: &str, 119 proc_init_info: &mut ProcInitInfo, 120 trap_frame: &mut TrapFrame, 121 ) -> Result<(), SystemError> { 122 proc_init_info.proc_name = CString::new(path).unwrap(); 123 proc_init_info.args.insert(0, CString::new(path).unwrap()); 124 if let Err(e) = run_init_process(proc_init_info, trap_frame) { 125 if e != SystemError::ENOENT { 126 error!( 127 "Failed to run init process: {path} exists but couldn't execute it (error {:?})", 128 e 129 ); 130 } 131 132 proc_init_info.args.remove(0); 133 return Err(e); 134 } 135 Ok(()) 136 } 137 138 fn run_init_process( 139 proc_init_info: &ProcInitInfo, 140 trap_frame: &mut TrapFrame, 141 ) -> Result<(), SystemError> { 142 compiler_fence(Ordering::SeqCst); 143 let path = proc_init_info.proc_name.to_str().unwrap(); 144 145 Syscall::do_execve( 146 path.to_string(), 147 proc_init_info.args.clone(), 148 proc_init_info.envs.clone(), 149 trap_frame, 150 )?; 151 Ok(()) 152 } 153