xref: /DragonOS/kernel/src/init/initial_kthread.rs (revision 55e6f0b65f91b32638fd56581f711a816eccdcd1)
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