Browse Source

feat: 完善sys_reboot (#1084)

* fix(process): 修复copy_process的一些bug & 支持默认init进程传参

- 修复`copy_process`函数对标志位处理不正确的bug
- init进程搜索列表中,支持为默认init程序传入参数

Signed-off-by: longjin <[email protected]>

* feat: 完善sys_reboot

- 校验magic number
- 支持多个cmd (具体内容未实现)

Signed-off-by: longjin <[email protected]>

---------

Signed-off-by: longjin <[email protected]>
LoGin 1 month ago
parent
commit
7ae6621cfa

+ 2 - 0
kernel/src/misc/mod.rs

@@ -1,2 +1,4 @@
 pub mod events;
 pub mod ksysfs;
+pub mod reboot;
+pub mod syscall;

+ 154 - 0
kernel/src/misc/reboot.rs

@@ -0,0 +1,154 @@
+use core::hint::spin_loop;
+
+use system_error::SystemError;
+
+use crate::{arch::cpu::cpu_reset, libs::mutex::Mutex, syscall::user_access::check_and_clone_cstr};
+
+static SYSTEM_TRANSITION_MUTEX: Mutex<()> = Mutex::new(());
+
+const LINUX_REBOOT_MAGIC1: u32 = 0xfee1dead;
+const LINUX_REBOOT_MAGIC2: u32 = 672274793;
+const LINUX_REBOOT_MAGIC2A: u32 = 85072278;
+const LINUX_REBOOT_MAGIC2B: u32 = 369367448;
+const LINUX_REBOOT_MAGIC2C: u32 = 537993216;
+
+#[derive(Debug)]
+pub enum RebootCommand {
+    /// 重启系统,使用默认命令和模式
+    Restart,
+    /// 停止操作系统,并将系统控制权交给ROM监视器(如果有)
+    Halt,
+    /// Ctrl-Alt-Del序列导致执行RESTART命令
+    CadOn,
+    /// Ctrl-Alt-Del序列向init任务发送SIGINT信号
+    CadOff,
+    /// 停止操作系统,如果可能的话从系统中移除所有电源
+    PowerOff,
+    /// 使用给定的命令字符串重启系统
+    Restart2,
+    /// 使用软件挂起(如果编译在内)挂起系统
+    SoftwareSuspend,
+    /// 使用预先加载的Linux内核重启系统
+    Kexec,
+}
+
+impl TryFrom<u32> for RebootCommand {
+    type Error = SystemError;
+
+    fn try_from(value: u32) -> Result<Self, Self::Error> {
+        match value {
+            0x01234567 => Ok(RebootCommand::Restart),
+            0xCDEF0123 => Ok(RebootCommand::Halt),
+            0x89ABCDEF => Ok(RebootCommand::CadOn),
+            0x00000000 => Ok(RebootCommand::CadOff),
+            0x4321FEDC => Ok(RebootCommand::PowerOff),
+            0xA1B2C3D4 => Ok(RebootCommand::Restart2),
+            0xD000FCE2 => Ok(RebootCommand::SoftwareSuspend),
+            0x45584543 => Ok(RebootCommand::Kexec),
+            _ => Err(SystemError::EINVAL),
+        }
+    }
+}
+
+impl From<RebootCommand> for u32 {
+    fn from(val: RebootCommand) -> Self {
+        match val {
+            RebootCommand::Restart => 0x01234567,
+            RebootCommand::Halt => 0xCDEF0123,
+            RebootCommand::CadOn => 0x89ABCDEF,
+            RebootCommand::CadOff => 0x00000000,
+            RebootCommand::PowerOff => 0x4321FEDC,
+            RebootCommand::Restart2 => 0xA1B2C3D4,
+            RebootCommand::SoftwareSuspend => 0xD000FCE2,
+            RebootCommand::Kexec => 0x45584543,
+        }
+    }
+}
+
+/// 系统调用reboot的实现
+///
+/// 参考:https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/reboot.c#700
+pub(super) fn do_sys_reboot(
+    magic1: u32,
+    magic2: u32,
+    cmd: u32,
+    arg: usize,
+) -> Result<(), SystemError> {
+    if magic1 != LINUX_REBOOT_MAGIC1
+        || (magic2 != LINUX_REBOOT_MAGIC2
+            && magic2 != LINUX_REBOOT_MAGIC2A
+            && magic2 != LINUX_REBOOT_MAGIC2B
+            && magic2 != LINUX_REBOOT_MAGIC2C)
+    {
+        return Err(SystemError::EINVAL);
+    }
+    let command = RebootCommand::try_from(cmd)?;
+    let _guard = SYSTEM_TRANSITION_MUTEX.lock();
+    log::debug!(
+        "do_sys_reboot: magic1={}, magic2={}, cmd={:?}",
+        magic1,
+        magic2,
+        command
+    );
+    match command {
+        RebootCommand::Restart => kernel_restart(None),
+        RebootCommand::Halt => kernel_halt(),
+        RebootCommand::CadOn => {
+            // todo: 支持Ctrl-Alt-Del序列
+            return Ok(());
+        }
+        RebootCommand::CadOff => {
+            // todo: 支持Ctrl-Alt-Del序列
+            return Ok(());
+        }
+        RebootCommand::PowerOff => kernel_power_off(),
+        RebootCommand::Restart2 => {
+            let s = check_and_clone_cstr(arg as *const u8, Some(256))?;
+            let cmd_str = s.to_str().map_err(|_| SystemError::EINVAL)?;
+            kernel_restart(Some(cmd_str));
+        }
+        RebootCommand::SoftwareSuspend => {
+            log::warn!("do_sys_reboot: SoftwareSuspend not implemented");
+            return Err(SystemError::ENOSYS);
+        }
+        RebootCommand::Kexec => {
+            log::warn!("do_sys_reboot: Kexec not implemented");
+            return Err(SystemError::ENOSYS);
+        }
+    }
+}
+
+/// kernel_restart - 重启系统
+///
+/// ## 参数
+/// - cmd: 指向包含重启命令的缓冲区的指针,或者 None
+///
+/// 关闭所有东西并执行一个干净的重启。
+/// 在中断上下文中调用这是不安全的。
+///
+/// todo: 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/reboot.c#265
+pub fn kernel_restart(cmd: Option<&str>) -> ! {
+    if let Some(cmd) = cmd {
+        log::warn!("Restarting system with command: '{}'", cmd);
+    } else {
+        log::warn!("Restarting system...");
+    }
+    unsafe { cpu_reset() }
+}
+
+/// todo: 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/reboot.c#678
+pub fn kernel_power_off() -> ! {
+    log::warn!("Power down");
+    log::warn!("Currently, the system cannot be powered off, so we halt here.");
+    loop {
+        spin_loop();
+    }
+}
+
+/// todo: 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/reboot.c#293
+pub fn kernel_halt() -> ! {
+    log::warn!("System halted.");
+    loop {
+        spin_loop();
+    }
+}

+ 11 - 0
kernel/src/misc/syscall.rs

@@ -0,0 +1,11 @@
+use system_error::SystemError;
+
+use crate::syscall::Syscall;
+
+use super::reboot::do_sys_reboot;
+
+impl Syscall {
+    pub fn reboot(magic1: u32, magic2: u32, cmd: u32, arg: usize) -> Result<usize, SystemError> {
+        do_sys_reboot(magic1, magic2, cmd, arg).map(|_| 0)
+    }
+}

+ 0 - 1
kernel/src/process/exit.rs

@@ -63,7 +63,6 @@ pub fn kernel_wait4(
 
     // 判断pid类型
     let pidtype: PidType;
-
     if pid == -1 {
         pidtype = PidType::MAX;
     } else if pid < 0 {

+ 8 - 7
kernel/src/syscall/mod.rs

@@ -24,7 +24,7 @@ use num_traits::FromPrimitive;
 use system_error::SystemError;
 
 use crate::{
-    arch::{cpu::cpu_reset, interrupt::TrapFrame, MMArch},
+    arch::{interrupt::TrapFrame, MMArch},
     filesystem::vfs::{
         fcntl::{AtFlags, FcntlCommand},
         file::FileMode,
@@ -232,7 +232,13 @@ impl Syscall {
                 Self::sbrk(increment).map(|vaddr: VirtAddr| vaddr.data())
             }
 
-            SYS_REBOOT => Self::reboot(),
+            SYS_REBOOT => {
+                let magic1 = args[0] as u32;
+                let magic2 = args[1] as u32;
+                let cmd = args[2] as u32;
+                let arg = args[3];
+                Self::reboot(magic1, magic2, cmd, arg)
+            }
 
             SYS_CHDIR => {
                 let r = args[0] as *const u8;
@@ -1253,9 +1259,4 @@ impl Syscall {
         print!("\x1B[38;2;{fr};{fg};{fb};48;2;{br};{bg};{bb}m{s}\x1B[0m");
         return Ok(s.len());
     }
-
-    pub fn reboot() -> Result<usize, SystemError> {
-        log::info!("reboot");
-        unsafe { cpu_reset() };
-    }
 }

+ 1 - 1
user/dadk/config/nova_shell-0.1.0.toml

@@ -24,7 +24,7 @@ source = "git"
 source-path = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/NovaShell.git"
 # git标签或分支
 # 注意: branch和revision只能二选一,且source要设置为"git"
-revision = "feaebefaef"
+revision = "d7d2136c5a"
 # 构建相关信息
 [build]
 # (可选)构建命令