mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
* refactor(process): Extract common logic for riscv and x86_64 in arch_switch_to_user to run_init_process 调整arch_switch_to_user函数,把riscv和x86_64的共用逻辑抽取出来。写成run_init_process函数,并且能够尝试运行多个不同的init程序,直到某个运行成功
113 lines
3.2 KiB
Rust
113 lines
3.2 KiB
Rust
//! 这个文件内放置初始内核线程的代码。
|
||
|
||
use core::sync::atomic::{compiler_fence, Ordering};
|
||
|
||
use alloc::string::{String, ToString};
|
||
use system_error::SystemError;
|
||
|
||
use crate::{
|
||
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, ProcessFlags, ProcessManager},
|
||
smp::smp_init,
|
||
syscall::Syscall,
|
||
};
|
||
|
||
use super::initcall::do_initcalls;
|
||
|
||
pub fn initial_kernel_thread() -> i32 {
|
||
kernel_init().unwrap_or_else(|err| {
|
||
panic!("Failed to initialize kernel: {:?}", err);
|
||
});
|
||
|
||
switch_to_user();
|
||
}
|
||
|
||
fn kernel_init() -> Result<(), SystemError> {
|
||
KernelThreadMechanism::init_stage2();
|
||
kenrel_init_freeable()?;
|
||
|
||
// 由于目前加锁,速度过慢,所以先不开启双缓冲
|
||
// scm_enable_double_buffer().expect("Failed to enable double buffer");
|
||
|
||
#[cfg(target_arch = "x86_64")]
|
||
crate::driver::disk::ahci::ahci_init().expect("Failed to initialize AHCI");
|
||
|
||
virtio_probe();
|
||
mount_root_fs().expect("Failed to mount root fs");
|
||
|
||
e1000e_init();
|
||
net_init().unwrap_or_else(|err| {
|
||
kerror!("Failed to initialize network: {:?}", err);
|
||
});
|
||
|
||
kdebug!("initial kernel thread done.");
|
||
|
||
return Ok(());
|
||
}
|
||
|
||
#[inline(never)]
|
||
fn kenrel_init_freeable() -> Result<(), SystemError> {
|
||
do_initcalls().unwrap_or_else(|err| {
|
||
panic!("Failed to initialize subsystems: {:?}", err);
|
||
});
|
||
stdio_init().expect("Failed to initialize stdio");
|
||
smp_init();
|
||
|
||
return Ok(());
|
||
}
|
||
|
||
/// 切换到用户态
|
||
#[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=/")];
|
||
|
||
compiler_fence(Ordering::SeqCst);
|
||
Syscall::do_execve(path, argv, envp, trap_frame)?;
|
||
|
||
Ok(())
|
||
}
|