DragonOS/kernel/src/init/initial_kthread.rs
LoGin f75cb0f8ed
refactor(process): 调整arch_switch_to_user函数,把riscv和x86_64的共用逻辑抽取出来。 (#773)
* 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程序,直到某个运行成功
2024-04-27 15:35:24 +08:00

113 lines
3.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 这个文件内放置初始内核线程的代码。
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(())
}