mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
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程序,直到某个运行成功
This commit is contained in:
parent
173c4567cf
commit
f75cb0f8ed
@ -19,7 +19,7 @@ use crate::{
|
||||
smp::cpu::ProcessorId,
|
||||
};
|
||||
|
||||
use self::init::riscv_mm_init;
|
||||
use self::init::{riscv_mm_init, INITIAL_PGTABLE_VALUE};
|
||||
|
||||
pub mod bump;
|
||||
pub(super) mod init;
|
||||
@ -185,7 +185,7 @@ impl MemoryManagementArch for RiscV64MMArch {
|
||||
}
|
||||
|
||||
fn initial_page_table() -> PhysAddr {
|
||||
todo!()
|
||||
unsafe { INITIAL_PGTABLE_VALUE }
|
||||
}
|
||||
|
||||
fn setup_new_usermapper() -> Result<UserMapper, SystemError> {
|
||||
|
@ -1,8 +1,6 @@
|
||||
use core::hint::spin_loop;
|
||||
|
||||
use crate::{
|
||||
arch::CurrentIrqArch, exception::InterruptArch, kBUG, kdebug, process::ProcessManager,
|
||||
};
|
||||
use crate::{arch::CurrentIrqArch, exception::InterruptArch, kBUG, process::ProcessManager};
|
||||
|
||||
impl ProcessManager {
|
||||
/// 每个核的idle进程
|
||||
|
@ -19,7 +19,7 @@ use crate::{
|
||||
CurrentIrqArch,
|
||||
},
|
||||
exception::InterruptArch,
|
||||
kdebug, kerror,
|
||||
kerror,
|
||||
libs::spinlock::SpinLockGuard,
|
||||
mm::VirtAddr,
|
||||
process::{
|
||||
@ -53,7 +53,7 @@ static BSP_IDLE_STACK_SPACE: InitProcUnion = InitProcUnion {
|
||||
idle_stack: [0; 32768],
|
||||
};
|
||||
|
||||
pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<String>) -> ! {
|
||||
pub unsafe fn arch_switch_to_user(trap_frame: TrapFrame) -> ! {
|
||||
// 以下代码不能发生中断
|
||||
CurrentIrqArch::interrupt_disable();
|
||||
|
||||
@ -69,28 +69,12 @@ pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<Str
|
||||
arch_guard.ra = new_pc.data();
|
||||
drop(arch_guard);
|
||||
|
||||
// 删除kthread的标志
|
||||
current_pcb.flags().remove(ProcessFlags::KTHREAD);
|
||||
current_pcb.worker_private().take();
|
||||
drop(current_pcb);
|
||||
|
||||
*current_pcb.sched_info().sched_policy.write_irqsave() = crate::sched::SchedPolicy::CFS;
|
||||
|
||||
let mut trap_frame = TrapFrame::new();
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
Syscall::do_execve(path, argv, envp, &mut trap_frame).unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"arch_switch_to_user(): pid: {pid:?}, Failed to execve: , error: {e:?}",
|
||||
pid = current_pcb.pid(),
|
||||
e = e
|
||||
);
|
||||
});
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
// 重要!在这里之后,一定要保证上面的引用计数变量、动态申请的变量、锁的守卫都被drop了,否则可能导致内存安全问题!
|
||||
|
||||
drop(current_pcb);
|
||||
|
||||
*(trap_frame_vaddr.data() as *mut TrapFrame) = trap_frame;
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
@ -1,11 +1,10 @@
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use riscv::register::sstatus::{Sstatus, FS, SPP};
|
||||
use riscv::register::sstatus::{FS, SPP};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
arch::{interrupt::TrapFrame, CurrentIrqArch},
|
||||
exception::InterruptArch,
|
||||
kdebug,
|
||||
mm::ucontext::AddressSpace,
|
||||
process::{
|
||||
exec::{load_binary_file, ExecParam, ExecParamFlags},
|
||||
@ -64,8 +63,7 @@ impl Syscall {
|
||||
let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC)?;
|
||||
|
||||
// 加载可执行文件
|
||||
let load_result = load_binary_file(&mut param)
|
||||
.unwrap_or_else(|e| panic!("Failed to load binary file: {:?}, path: {:?}", e, path));
|
||||
let load_result = load_binary_file(&mut param)?;
|
||||
// kdebug!("load binary file done");
|
||||
// kdebug!("argv: {:?}, envp: {:?}", argv, envp);
|
||||
param.init_info_mut().args = argv;
|
||||
|
@ -2,7 +2,7 @@
|
||||
pub mod nr;
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{exception::InterruptArch, kdebug, process::ProcessManager, syscall::Syscall};
|
||||
use crate::{exception::InterruptArch, process::ProcessManager, syscall::Syscall};
|
||||
|
||||
use super::{interrupt::TrapFrame, CurrentIrqArch};
|
||||
|
||||
|
@ -5,11 +5,7 @@ use core::{
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
};
|
||||
|
||||
use alloc::{
|
||||
string::String,
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use alloc::sync::{Arc, Weak};
|
||||
|
||||
use kdepends::memoffset::offset_of;
|
||||
use system_error::SystemError;
|
||||
@ -511,7 +507,7 @@ unsafe extern "sysv64" fn switch_back() -> ! {
|
||||
asm!("ret", options(noreturn));
|
||||
}
|
||||
|
||||
pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<String>) -> ! {
|
||||
pub unsafe fn arch_switch_to_user(trap_frame: TrapFrame) -> ! {
|
||||
// 以下代码不能发生中断
|
||||
CurrentIrqArch::interrupt_disable();
|
||||
|
||||
@ -520,7 +516,6 @@ pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<Str
|
||||
current_pcb.kernel_stack().stack_max_address().data() - core::mem::size_of::<TrapFrame>(),
|
||||
);
|
||||
// kdebug!("trap_frame_vaddr: {:?}", trap_frame_vaddr);
|
||||
let new_rip = VirtAddr::new(ret_from_intr as usize);
|
||||
|
||||
assert!(
|
||||
(x86::current::registers::rsp() as usize) < trap_frame_vaddr.data(),
|
||||
@ -531,6 +526,7 @@ pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<Str
|
||||
trap_frame_vaddr.data()
|
||||
);
|
||||
|
||||
let new_rip = VirtAddr::new(ret_from_intr as usize);
|
||||
let mut arch_guard = current_pcb.arch_info_irqsave();
|
||||
arch_guard.rsp = trap_frame_vaddr.data();
|
||||
|
||||
@ -548,28 +544,11 @@ pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<Str
|
||||
|
||||
drop(arch_guard);
|
||||
|
||||
// 删除kthread的标志
|
||||
current_pcb.flags().remove(ProcessFlags::KTHREAD);
|
||||
current_pcb.worker_private().take();
|
||||
|
||||
*current_pcb.sched_info().sched_policy.write_irqsave() = crate::sched::SchedPolicy::CFS;
|
||||
|
||||
let mut trap_frame = TrapFrame::new();
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
Syscall::do_execve(path, argv, envp, &mut trap_frame).unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"arch_switch_to_user(): pid: {pid:?}, Failed to execve: , error: {e:?}",
|
||||
pid = current_pcb.pid(),
|
||||
e = e
|
||||
);
|
||||
});
|
||||
drop(current_pcb);
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
// 重要!在这里之后,一定要保证上面的引用计数变量、动态申请的变量、锁的守卫都被drop了,否则可能导致内存安全问题!
|
||||
|
||||
drop(current_pcb);
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
ready_to_switch_to_user(trap_frame, trap_frame_vaddr.data(), new_rip.data());
|
||||
}
|
||||
|
@ -66,8 +66,7 @@ impl Syscall {
|
||||
let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC)?;
|
||||
|
||||
// 加载可执行文件
|
||||
let load_result = load_binary_file(&mut param)
|
||||
.unwrap_or_else(|e| panic!("Failed to load binary file: {:?}, path: {:?}", e, path));
|
||||
let load_result = load_binary_file(&mut param)?;
|
||||
// kdebug!("load binary file done");
|
||||
// kdebug!("argv: {:?}, envp: {:?}", argv, envp);
|
||||
param.init_info_mut().args = argv;
|
||||
|
@ -11,7 +11,6 @@ use crate::{
|
||||
process::ProcessManager,
|
||||
syscall::{Syscall, SYS_SCHED},
|
||||
};
|
||||
use alloc::string::String;
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::{
|
||||
@ -133,19 +132,6 @@ pub fn arch_syscall_init() -> Result<(), SystemError> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 执行第一个用户进程的函数(只应该被调用一次)
|
||||
///
|
||||
/// 当进程管理重构完成后,这个函数应该被删除。调整为别的函数。
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rs_exec_init_process(frame: &mut TrapFrame) -> usize {
|
||||
let path = String::from("/bin/shell.elf");
|
||||
let argv = vec![String::from("/bin/shell.elf")];
|
||||
let envp = vec![String::from("PATH=/bin")];
|
||||
let r = Syscall::do_execve(path, argv, envp, frame);
|
||||
// kdebug!("rs_exec_init_process: r: {:?}\n", r);
|
||||
return r.map(|_| 0).unwrap_or_else(|e| e.to_posix_errno() as usize);
|
||||
}
|
||||
|
||||
/// syscall指令初始化函数
|
||||
pub(super) unsafe fn init_syscall_64() {
|
||||
let mut efer = x86::msr::rdmsr(x86::msr::IA32_EFER);
|
||||
|
@ -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(())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user