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,
|
smp::cpu::ProcessorId,
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::init::riscv_mm_init;
|
use self::init::{riscv_mm_init, INITIAL_PGTABLE_VALUE};
|
||||||
|
|
||||||
pub mod bump;
|
pub mod bump;
|
||||||
pub(super) mod init;
|
pub(super) mod init;
|
||||||
@ -185,7 +185,7 @@ impl MemoryManagementArch for RiscV64MMArch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn initial_page_table() -> PhysAddr {
|
fn initial_page_table() -> PhysAddr {
|
||||||
todo!()
|
unsafe { INITIAL_PGTABLE_VALUE }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_new_usermapper() -> Result<UserMapper, SystemError> {
|
fn setup_new_usermapper() -> Result<UserMapper, SystemError> {
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
use core::hint::spin_loop;
|
use core::hint::spin_loop;
|
||||||
|
|
||||||
use crate::{
|
use crate::{arch::CurrentIrqArch, exception::InterruptArch, kBUG, process::ProcessManager};
|
||||||
arch::CurrentIrqArch, exception::InterruptArch, kBUG, kdebug, process::ProcessManager,
|
|
||||||
};
|
|
||||||
|
|
||||||
impl ProcessManager {
|
impl ProcessManager {
|
||||||
/// 每个核的idle进程
|
/// 每个核的idle进程
|
||||||
|
@ -19,7 +19,7 @@ use crate::{
|
|||||||
CurrentIrqArch,
|
CurrentIrqArch,
|
||||||
},
|
},
|
||||||
exception::InterruptArch,
|
exception::InterruptArch,
|
||||||
kdebug, kerror,
|
kerror,
|
||||||
libs::spinlock::SpinLockGuard,
|
libs::spinlock::SpinLockGuard,
|
||||||
mm::VirtAddr,
|
mm::VirtAddr,
|
||||||
process::{
|
process::{
|
||||||
@ -53,7 +53,7 @@ static BSP_IDLE_STACK_SPACE: InitProcUnion = InitProcUnion {
|
|||||||
idle_stack: [0; 32768],
|
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();
|
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();
|
arch_guard.ra = new_pc.data();
|
||||||
drop(arch_guard);
|
drop(arch_guard);
|
||||||
|
|
||||||
// 删除kthread的标志
|
drop(current_pcb);
|
||||||
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
|
|
||||||
);
|
|
||||||
});
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
// 重要!在这里之后,一定要保证上面的引用计数变量、动态申请的变量、锁的守卫都被drop了,否则可能导致内存安全问题!
|
// 重要!在这里之后,一定要保证上面的引用计数变量、动态申请的变量、锁的守卫都被drop了,否则可能导致内存安全问题!
|
||||||
|
|
||||||
drop(current_pcb);
|
|
||||||
|
|
||||||
*(trap_frame_vaddr.data() as *mut TrapFrame) = trap_frame;
|
*(trap_frame_vaddr.data() as *mut TrapFrame) = trap_frame;
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
use alloc::{string::String, vec::Vec};
|
use alloc::{string::String, vec::Vec};
|
||||||
use riscv::register::sstatus::{Sstatus, FS, SPP};
|
use riscv::register::sstatus::{FS, SPP};
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{interrupt::TrapFrame, CurrentIrqArch},
|
arch::{interrupt::TrapFrame, CurrentIrqArch},
|
||||||
exception::InterruptArch,
|
exception::InterruptArch,
|
||||||
kdebug,
|
|
||||||
mm::ucontext::AddressSpace,
|
mm::ucontext::AddressSpace,
|
||||||
process::{
|
process::{
|
||||||
exec::{load_binary_file, ExecParam, ExecParamFlags},
|
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 mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC)?;
|
||||||
|
|
||||||
// 加载可执行文件
|
// 加载可执行文件
|
||||||
let load_result = load_binary_file(&mut param)
|
let load_result = load_binary_file(&mut param)?;
|
||||||
.unwrap_or_else(|e| panic!("Failed to load binary file: {:?}, path: {:?}", e, path));
|
|
||||||
// kdebug!("load binary file done");
|
// kdebug!("load binary file done");
|
||||||
// kdebug!("argv: {:?}, envp: {:?}", argv, envp);
|
// kdebug!("argv: {:?}, envp: {:?}", argv, envp);
|
||||||
param.init_info_mut().args = argv;
|
param.init_info_mut().args = argv;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
pub mod nr;
|
pub mod nr;
|
||||||
use system_error::SystemError;
|
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};
|
use super::{interrupt::TrapFrame, CurrentIrqArch};
|
||||||
|
|
||||||
|
@ -5,11 +5,7 @@ use core::{
|
|||||||
sync::atomic::{compiler_fence, Ordering},
|
sync::atomic::{compiler_fence, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
use alloc::{
|
use alloc::sync::{Arc, Weak};
|
||||||
string::String,
|
|
||||||
sync::{Arc, Weak},
|
|
||||||
vec::Vec,
|
|
||||||
};
|
|
||||||
|
|
||||||
use kdepends::memoffset::offset_of;
|
use kdepends::memoffset::offset_of;
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
@ -511,7 +507,7 @@ unsafe extern "sysv64" fn switch_back() -> ! {
|
|||||||
asm!("ret", options(noreturn));
|
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();
|
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>(),
|
current_pcb.kernel_stack().stack_max_address().data() - core::mem::size_of::<TrapFrame>(),
|
||||||
);
|
);
|
||||||
// kdebug!("trap_frame_vaddr: {:?}", trap_frame_vaddr);
|
// kdebug!("trap_frame_vaddr: {:?}", trap_frame_vaddr);
|
||||||
let new_rip = VirtAddr::new(ret_from_intr as usize);
|
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
(x86::current::registers::rsp() as usize) < trap_frame_vaddr.data(),
|
(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()
|
trap_frame_vaddr.data()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let new_rip = VirtAddr::new(ret_from_intr as usize);
|
||||||
let mut arch_guard = current_pcb.arch_info_irqsave();
|
let mut arch_guard = current_pcb.arch_info_irqsave();
|
||||||
arch_guard.rsp = trap_frame_vaddr.data();
|
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);
|
drop(arch_guard);
|
||||||
|
|
||||||
// 删除kthread的标志
|
drop(current_pcb);
|
||||||
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
|
|
||||||
);
|
|
||||||
});
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
// 重要!在这里之后,一定要保证上面的引用计数变量、动态申请的变量、锁的守卫都被drop了,否则可能导致内存安全问题!
|
// 重要!在这里之后,一定要保证上面的引用计数变量、动态申请的变量、锁的守卫都被drop了,否则可能导致内存安全问题!
|
||||||
|
|
||||||
drop(current_pcb);
|
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
ready_to_switch_to_user(trap_frame, trap_frame_vaddr.data(), new_rip.data());
|
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 mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC)?;
|
||||||
|
|
||||||
// 加载可执行文件
|
// 加载可执行文件
|
||||||
let load_result = load_binary_file(&mut param)
|
let load_result = load_binary_file(&mut param)?;
|
||||||
.unwrap_or_else(|e| panic!("Failed to load binary file: {:?}, path: {:?}", e, path));
|
|
||||||
// kdebug!("load binary file done");
|
// kdebug!("load binary file done");
|
||||||
// kdebug!("argv: {:?}, envp: {:?}", argv, envp);
|
// kdebug!("argv: {:?}, envp: {:?}", argv, envp);
|
||||||
param.init_info_mut().args = argv;
|
param.init_info_mut().args = argv;
|
||||||
|
@ -11,7 +11,6 @@ use crate::{
|
|||||||
process::ProcessManager,
|
process::ProcessManager,
|
||||||
syscall::{Syscall, SYS_SCHED},
|
syscall::{Syscall, SYS_SCHED},
|
||||||
};
|
};
|
||||||
use alloc::string::String;
|
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@ -133,19 +132,6 @@ pub fn arch_syscall_init() -> Result<(), SystemError> {
|
|||||||
return Ok(());
|
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指令初始化函数
|
/// syscall指令初始化函数
|
||||||
pub(super) unsafe fn init_syscall_64() {
|
pub(super) unsafe fn init_syscall_64() {
|
||||||
let mut efer = x86::msr::rdmsr(x86::msr::IA32_EFER);
|
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 system_error::SystemError;
|
||||||
|
|
||||||
use crate::{
|
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},
|
driver::{net::e1000e::e1000e::e1000e_init, virtio::virtio::virtio_probe},
|
||||||
filesystem::vfs::core::mount_root_fs,
|
filesystem::vfs::core::mount_root_fs,
|
||||||
kdebug, kerror,
|
kdebug, kerror,
|
||||||
net::net_core::net_init,
|
net::net_core::net_init,
|
||||||
process::{kthread::KernelThreadMechanism, stdio::stdio_init},
|
process::{kthread::KernelThreadMechanism, stdio::stdio_init, ProcessFlags, ProcessManager},
|
||||||
smp::smp_init,
|
smp::smp_init,
|
||||||
|
syscall::Syscall,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::initcall::do_initcalls;
|
use super::initcall::do_initcalls;
|
||||||
@ -21,8 +24,6 @@ pub fn initial_kernel_thread() -> i32 {
|
|||||||
});
|
});
|
||||||
|
|
||||||
switch_to_user();
|
switch_to_user();
|
||||||
|
|
||||||
unreachable!();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kernel_init() -> Result<(), SystemError> {
|
fn kernel_init() -> Result<(), SystemError> {
|
||||||
@ -60,11 +61,52 @@ fn kenrel_init_freeable() -> Result<(), SystemError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 切换到用户态
|
/// 切换到用户态
|
||||||
fn switch_to_user() {
|
#[inline(never)]
|
||||||
const INIT_PROGRAM: &str = "/bin/dragonreach";
|
fn switch_to_user() -> ! {
|
||||||
let path = String::from(INIT_PROGRAM);
|
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 argv = vec![path.clone()];
|
||||||
let envp = vec![String::from("PATH=/")];
|
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