Skip to content

Commit

Permalink
feat(syscall): 实现syscall restart
Browse files Browse the repository at this point in the history
能够在系统调用返回ERESTARTSYS时,信号处理结束后,自动重启系统调用.

TODO: 实现wait等需要restart_block的系统调用的重启

Signed-off-by: longjin <[email protected]>
  • Loading branch information
fslongjin committed Dec 10, 2024
1 parent 72423f9 commit 6868946
Show file tree
Hide file tree
Showing 25 changed files with 627 additions and 168 deletions.
3 changes: 2 additions & 1 deletion kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ unwinding = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/unwi
"panic",
"personality"
]}
defer = "0.2.1"

# target为x86_64时,使用下面的依赖
[target.'cfg(target_arch = "x86_64")'.dependencies]
Expand Down Expand Up @@ -106,4 +107,4 @@ debug = true # Controls whether the compiler passes `-g`

# The release profile, used for `cargo build --release`
[profile.release]
debug = false
debug = true
2 changes: 1 addition & 1 deletion kernel/crates/system_error/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ edition = "2021"

[dependencies]
num-traits = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false }
num-derive = "0.3"
num-derive = "0.3"
44 changes: 32 additions & 12 deletions kernel/crates/system_error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,31 +277,51 @@ pub enum SystemError {

// === 以下错误码不应该被用户态程序使用 ===
ERESTARTSYS = 512,
ERESTARTNOINTR = 513,
/// restart if no handler
ERESTARTNOHAND = 514,

/// 没有对应的ioctlcmd
ENOIOCTLCMD = 515,
/// restart by calling sys restart syscall
ERESTART_RESTARTBLOCK = 516,

// === TODO: 这几个KVM的错误码不要放在这里 ===

// VMX on 虚拟化开启指令出错
EVMXONFailed = 513,
EVMXONFailed = 1513,
// VMX off 虚拟化关闭指令出错
EVMXOFFFailed = 514,
EVMXOFFFailed = 1514,
// VMX VMWRITE 写入虚拟化VMCS内存出错
EVMWRITEFailed = 515,
EVMREADFailed = 516,
EVMPRTLDFailed = 517,
EVMLAUNCHFailed = 518,
KVM_HVA_ERR_BAD = 519,
/// 没有对应的ioctlcmd
ENOIOCTLCMD = 520,
EVMWRITEFailed = 1515,
EVMREADFailed = 1516,
EVMPRTLDFailed = 1517,
EVMLAUNCHFailed = 1518,
KVM_HVA_ERR_BAD = 1519,

MAXERRNO = 4095,
}

impl SystemError {
/// @brief 把posix错误码转换为系统错误枚举类型。
/// 判断一个值是否是有效的posix错误码。
pub fn is_valid_posix_errno<T>(val: T) -> bool
where
T: PartialOrd + From<i32>,
{
let max_errno = T::from(-(Self::MAXERRNO as i32));
val < T::from(0) && val >= max_errno
}

/// 尝试把posix错误码转换为系统错误枚举类型。
pub fn from_posix_errno(errno: i32) -> Option<SystemError> {
// posix 错误码是小于0的
if errno >= 0 {
if !Self::is_valid_posix_errno(errno) {
return None;
}
return <Self as num_traits::FromPrimitive>::from_i32(-errno);
}

/// @brief 把系统错误枚举类型转换为负数posix错误码。
/// 把系统错误枚举类型转换为负数posix错误码。
pub fn to_posix_errno(&self) -> i32 {
return -<Self as num_traits::ToPrimitive>::to_i32(self).unwrap();
}
Expand Down
8 changes: 4 additions & 4 deletions kernel/src/arch/x86_64/asm/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ ENTRY(ret_from_intr)
// 进入信号处理流程
cli

// 将原本要返回的栈帧的栈指针传入do_signal的第一个参数
// 将原本要返回的栈帧的栈指针传入irqentry_exit的第一个参数
movq %rsp, %rdi
callq do_signal
callq irqentry_exit
cli

__entry_ret_from_intr_before_gs_check_2:
Expand Down Expand Up @@ -375,10 +375,10 @@ ENTRY(syscall_64)
sti
callq *%rdx //调用服务程序

// 将原本要返回的栈帧的栈指针传入do_signal的第一个参数
// 将原本要返回的栈帧的栈指针传入 irqentry_exit 的第一个参数
movq %rsp, %rdi

callq do_signal
callq irqentry_exit

cli

Expand Down
27 changes: 27 additions & 0 deletions kernel/src/arch/x86_64/interrupt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ pub struct TrapFrame {
pub es: ::core::ffi::c_ulong,
pub rax: ::core::ffi::c_ulong,
pub func: ::core::ffi::c_ulong,
/// - 该字段在异常发生时,保存的是错误码
/// - 在系统调用时,由系统调用入口函数将其设置为系统调用号
pub errcode: ::core::ffi::c_ulong,
pub rip: ::core::ffi::c_ulong,
pub cs: ::core::ffi::c_ulong,
Expand Down Expand Up @@ -182,6 +184,31 @@ impl TrapFrame {
pub fn set_pc(&mut self, pc: usize) {
self.rip = pc as u64;
}

/// 获取系统调用号
///
/// # Safety
/// 该函数只能在系统调用上下文中调用,
/// 在其他上下文中,该函数返回值未定义
pub unsafe fn syscall_nr(&self) -> Option<usize> {
if self.errcode == u64::MAX {
return None;
}
Some(self.errcode as usize)
}

/// 获取系统调用错误码
///
/// # Safety
/// 该函数只能在系统调用上下文中调用,
/// 在其他上下文中,该函数返回值未定义
///
/// # Returns
/// 返回一个 `Option<SystemError>`,表示系统调用的错误码。
pub unsafe fn syscall_error(&self) -> Option<SystemError> {
let val = self.rax as i32;
SystemError::from_posix_errno(val)
}
}

impl ProbeArgs for TrapFrame {
Expand Down
Loading

0 comments on commit 6868946

Please sign in to comment.