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