|
@@ -1,16 +1,19 @@
|
|
|
//! 这个文件内放置初始内核线程的代码。
|
|
|
|
|
|
-use alloc::string::String;
|
|
|
+use core::sync::atomic::{compiler_fence, Ordering};
|
|
|
+
|
|
|
+use alloc::string::{String, ToString};
|
|
|
use system_error::SystemError;
|
|
|
|
|
|
use crate::{
|
|
|
- arch::process::arch_switch_to_user,
|
|
|
+ arch::{interrupt::TrapFrame, process::arch_switch_to_user},
|
|
|
driver::{net::e1000e::e1000e::e1000e_init, virtio::virtio::virtio_probe},
|
|
|
filesystem::vfs::core::mount_root_fs,
|
|
|
kdebug, kerror,
|
|
|
net::net_core::net_init,
|
|
|
- process::{kthread::KernelThreadMechanism, stdio::stdio_init},
|
|
|
+ process::{kthread::KernelThreadMechanism, stdio::stdio_init, ProcessFlags, ProcessManager},
|
|
|
smp::smp_init,
|
|
|
+ syscall::Syscall,
|
|
|
};
|
|
|
|
|
|
use super::initcall::do_initcalls;
|
|
@@ -21,8 +24,6 @@ pub fn initial_kernel_thread() -> i32 {
|
|
|
});
|
|
|
|
|
|
switch_to_user();
|
|
|
-
|
|
|
- unreachable!();
|
|
|
}
|
|
|
|
|
|
fn kernel_init() -> Result<(), SystemError> {
|
|
@@ -60,11 +61,52 @@ fn kenrel_init_freeable() -> Result<(), SystemError> {
|
|
|
}
|
|
|
|
|
|
/// 切换到用户态
|
|
|
-fn switch_to_user() {
|
|
|
- const INIT_PROGRAM: &str = "/bin/dragonreach";
|
|
|
- let path = String::from(INIT_PROGRAM);
|
|
|
+#[inline(never)]
|
|
|
+fn switch_to_user() -> ! {
|
|
|
+ let current_pcb = ProcessManager::current_pcb();
|
|
|
+
|
|
|
+ // 删除kthread的标志
|
|
|
+ current_pcb.flags().remove(ProcessFlags::KTHREAD);
|
|
|
+ current_pcb.worker_private().take();
|
|
|
+
|
|
|
+ *current_pcb.sched_info().sched_policy.write_irqsave() = crate::sched::SchedPolicy::CFS;
|
|
|
+ drop(current_pcb);
|
|
|
+
|
|
|
+ let mut trap_frame = TrapFrame::new();
|
|
|
+ // 逐个尝试运行init进程
|
|
|
+
|
|
|
+ if try_to_run_init_process("/bin/dragonreach", &mut trap_frame).is_err()
|
|
|
+ && try_to_run_init_process("/bin/init", &mut trap_frame).is_err()
|
|
|
+ && try_to_run_init_process("/bin/sh", &mut trap_frame).is_err()
|
|
|
+ {
|
|
|
+ panic!("Failed to run init process: No working init found.");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 需要确保执行到这里之后,上面所有的资源都已经释放(比如arc之类的)
|
|
|
+
|
|
|
+ unsafe { arch_switch_to_user(trap_frame) };
|
|
|
+}
|
|
|
+
|
|
|
+fn try_to_run_init_process(path: &str, trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
|
|
|
+ if let Err(e) = run_init_process(path.to_string(), trap_frame) {
|
|
|
+ if e != SystemError::ENOENT {
|
|
|
+ kerror!(
|
|
|
+ "Failed to run init process: {path} exists but couldn't execute it (error {:?})",
|
|
|
+ e
|
|
|
+ );
|
|
|
+ }
|
|
|
+ return Err(e);
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok(())
|
|
|
+}
|
|
|
+
|
|
|
+fn run_init_process(path: String, trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
|
|
|
let argv = vec![path.clone()];
|
|
|
let envp = vec![String::from("PATH=/")];
|
|
|
|
|
|
- unsafe { arch_switch_to_user(path, argv, envp) };
|
|
|
+ compiler_fence(Ordering::SeqCst);
|
|
|
+ Syscall::do_execve(path, argv, envp, trap_frame)?;
|
|
|
+
|
|
|
+ Ok(())
|
|
|
}
|