diff --git a/framework/aster-frame/src/arch/x86/cpu.rs b/framework/aster-frame/src/arch/x86/cpu.rs index 736333095..24c6ba04e 100644 --- a/framework/aster-frame/src/arch/x86/cpu.rs +++ b/framework/aster-frame/src/arch/x86/cpu.rs @@ -471,29 +471,6 @@ impl UserContextApi for UserContext { self.user_context.error_code } - fn syscall_num(&self) -> usize { - self.rax() - } - - fn syscall_ret(&self) -> usize { - self.rax() - } - - fn set_syscall_ret(&mut self, ret: usize) { - self.set_rax(ret); - } - - fn syscall_args(&self) -> [usize; 6] { - [ - self.rdi(), - self.rsi(), - self.rdx(), - self.r10(), - self.r8(), - self.r9(), - ] - } - fn set_instruction_pointer(&mut self, ip: usize) { self.set_rip(ip); } diff --git a/framework/aster-frame/src/user.rs b/framework/aster-frame/src/user.rs index 49fc78edb..0d996b1c7 100644 --- a/framework/aster-frame/src/user.rs +++ b/framework/aster-frame/src/user.rs @@ -65,18 +65,6 @@ pub trait UserContextApi { /// Get the trap error code of this interrupt. fn trap_error_code(&self) -> usize; - /// Get number of syscall - fn syscall_num(&self) -> usize; - - /// Get return value of syscall - fn syscall_ret(&self) -> usize; - - /// Set return value of syscall - fn set_syscall_ret(&mut self, ret: usize); - - /// Get syscall args - fn syscall_args(&self) -> [usize; 6]; - /// Set instruction pointer fn set_instruction_pointer(&mut self, ip: usize); diff --git a/kernel/aster-nix/src/arch/mod.rs b/kernel/aster-nix/src/arch/mod.rs new file mode 100644 index 000000000..695b5e60c --- /dev/null +++ b/kernel/aster-nix/src/arch/mod.rs @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 + +#[cfg(target_arch = "x86_64")] +mod x86; +#[cfg(target_arch = "x86_64")] +pub use x86::*; diff --git a/kernel/aster-nix/src/arch/x86/cpu.rs b/kernel/aster-nix/src/arch/x86/cpu.rs new file mode 100644 index 000000000..b58a0304d --- /dev/null +++ b/kernel/aster-nix/src/arch/x86/cpu.rs @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MPL-2.0 + +use aster_frame::cpu::UserContext; + +use crate::cpu::LinuxAbi; + +impl LinuxAbi for UserContext { + fn syscall_num(&self) -> usize { + self.rax() + } + + fn syscall_ret(&self) -> usize { + self.rax() + } + + fn set_syscall_ret(&mut self, ret: usize) { + self.set_rax(ret); + } + + fn syscall_args(&self) -> [usize; 6] { + [ + self.rdi(), + self.rsi(), + self.rdx(), + self.r10(), + self.r8(), + self.r9(), + ] + } + + fn set_tls_pointer(&mut self, tls: usize) { + self.set_fsbase(tls); + } + + fn tls_pointer(&self) -> usize { + self.fsbase() + } +} diff --git a/kernel/aster-nix/src/arch/x86/mod.rs b/kernel/aster-nix/src/arch/x86/mod.rs new file mode 100644 index 000000000..e2a78f3c5 --- /dev/null +++ b/kernel/aster-nix/src/arch/x86/mod.rs @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 + +pub mod cpu; +pub mod signal; diff --git a/kernel/aster-nix/src/arch/x86/signal.rs b/kernel/aster-nix/src/arch/x86/signal.rs new file mode 100644 index 000000000..b3544b3a2 --- /dev/null +++ b/kernel/aster-nix/src/arch/x86/signal.rs @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MPL-2.0 + +use aster_frame::cpu::UserContext; + +use crate::process::signal::{sig_num::SigNum, SignalContext}; + +impl SignalContext for UserContext { + fn set_arguments(&mut self, sig_num: SigNum, siginfo_addr: usize, ucontext_addr: usize) { + self.set_rdi(sig_num.as_u8() as usize); + self.set_rsi(siginfo_addr); + self.set_rdx(ucontext_addr); + } +} diff --git a/kernel/aster-nix/src/cpu.rs b/kernel/aster-nix/src/cpu.rs new file mode 100644 index 000000000..24d8d0c14 --- /dev/null +++ b/kernel/aster-nix/src/cpu.rs @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MPL-2.0 + +pub trait LinuxAbi { + /// Get number of syscall + fn syscall_num(&self) -> usize; + + /// Get return value of syscall + fn syscall_ret(&self) -> usize; + + /// Set return value of syscall + fn set_syscall_ret(&mut self, ret: usize); + + /// Get syscall args + fn syscall_args(&self) -> [usize; 6]; + + /// Set thread-local storage pointer + fn set_tls_pointer(&mut self, tls: usize); + + /// Get thread-local storage pointer + fn tls_pointer(&self) -> usize; +} diff --git a/kernel/aster-nix/src/lib.rs b/kernel/aster-nix/src/lib.rs index 29347069b..fba8c8a99 100644 --- a/kernel/aster-nix/src/lib.rs +++ b/kernel/aster-nix/src/lib.rs @@ -49,7 +49,9 @@ extern crate ktest; #[macro_use] extern crate getset; +pub mod arch; pub mod console; +pub mod cpu; pub mod device; pub mod driver; pub mod error; diff --git a/kernel/aster-nix/src/process/clone.rs b/kernel/aster-nix/src/process/clone.rs index 2ed1cdc8e..3f6d6f564 100644 --- a/kernel/aster-nix/src/process/clone.rs +++ b/kernel/aster-nix/src/process/clone.rs @@ -2,7 +2,11 @@ use core::sync::atomic::Ordering; -use aster_frame::{cpu::UserContext, user::UserSpace, vm::VmIo}; +use aster_frame::{ + cpu::UserContext, + user::{UserContextApi, UserSpace}, + vm::VmIo, +}; use aster_rights::Full; use super::{ @@ -14,6 +18,7 @@ use super::{ Credentials, Process, ProcessBuilder, }; use crate::{ + cpu::LinuxAbi, current_thread, fs::{file_table::FileTable, fs_resolver::FsResolver, utils::FileCreationMask}, prelude::*, @@ -370,18 +375,17 @@ fn clone_cpu_context( ) -> UserContext { let mut child_context = parent_context; // The return value of child thread is zero - child_context.set_rax(0); + child_context.set_syscall_ret(0); if clone_flags.contains(CloneFlags::CLONE_VM) { // if parent and child shares the same address space, a new stack must be specified. debug_assert!(new_sp != 0); } if new_sp != 0 { - child_context.set_rsp(new_sp as usize); + child_context.set_stack_pointer(new_sp as usize); } if clone_flags.contains(CloneFlags::CLONE_SETTLS) { - // x86_64 specific: TLS is the fsbase register - child_context.set_fsbase(tls as usize); + child_context.set_tls_pointer(tls as usize); } child_context diff --git a/kernel/aster-nix/src/process/posix_thread/posix_thread_ext.rs b/kernel/aster-nix/src/process/posix_thread/posix_thread_ext.rs index f44ec0c1c..045673831 100644 --- a/kernel/aster-nix/src/process/posix_thread/posix_thread_ext.rs +++ b/kernel/aster-nix/src/process/posix_thread/posix_thread_ext.rs @@ -1,6 +1,9 @@ // SPDX-License-Identifier: MPL-2.0 -use aster_frame::{cpu::UserContext, user::UserSpace}; +use aster_frame::{ + cpu::UserContext, + user::{UserContextApi, UserSpace}, +}; use super::{builder::PosixThreadBuilder, name::ThreadName, PosixThread}; use crate::{ @@ -45,8 +48,8 @@ impl PosixThreadExt for Thread { let vm_space = process_vm.root_vmar().vm_space().clone(); let mut cpu_ctx = UserContext::default(); - cpu_ctx.set_rip(elf_load_info.entry_point() as _); - cpu_ctx.set_rsp(elf_load_info.user_stack_top() as _); + cpu_ctx.set_instruction_pointer(elf_load_info.entry_point() as _); + cpu_ctx.set_stack_pointer(elf_load_info.user_stack_top() as _); let user_space = Arc::new(UserSpace::new(vm_space, cpu_ctx)); let thread_name = Some(ThreadName::new_from_executable_path(executable_path)?); let thread_builder = PosixThreadBuilder::new(tid, user_space, credentials) diff --git a/kernel/aster-nix/src/process/signal/mod.rs b/kernel/aster-nix/src/process/signal/mod.rs index b29e878da..aac52ef14 100644 --- a/kernel/aster-nix/src/process/signal/mod.rs +++ b/kernel/aster-nix/src/process/signal/mod.rs @@ -16,7 +16,7 @@ pub mod signals; use core::{mem, sync::atomic::Ordering}; use align_ext::AlignExt; -use aster_frame::{cpu::UserContext, task::Task}; +use aster_frame::{cpu::UserContext, task::Task, user::UserContextApi}; use c_types::{siginfo_t, ucontext_t}; pub use events::{SigEvents, SigEventsFilter}; pub use pauser::Pauser; @@ -34,6 +34,11 @@ use crate::{ util::{write_bytes_to_user, write_val_to_user}, }; +pub trait SignalContext { + /// Set signal handler arguments + fn set_arguments(&mut self, sig_num: SigNum, siginfo_addr: usize, ucontext_addr: usize); +} + // TODO: This interface of this method is error prone. // The method takes an argument for the current thread to optimize its efficiency. /// Handle pending signal for current process. @@ -145,7 +150,7 @@ pub fn handle_user_signal( sp as u64 } else { // just use user stack - context.rsp() as u64 + context.stack_pointer() as u64 }; // To avoid corrupting signal stack, we minus 128 first. @@ -194,17 +199,15 @@ pub fn handle_user_signal( write_bytes_to_user(stack_pointer as Vaddr, TRAMPOLINE)?; stack_pointer = write_u64_to_user_stack(stack_pointer, trampoline_rip)?; } + // 4. Set correct register values - context.set_rip(handler_addr as _); - context.set_rsp(stack_pointer as usize); + context.set_instruction_pointer(handler_addr as _); + context.set_stack_pointer(stack_pointer as usize); // parameters of signal handler - context.set_rdi(sig_num.as_u8() as usize); // signal number if flags.contains(SigActionFlags::SA_SIGINFO) { - context.set_rsi(siginfo_addr as usize); // siginfo_t* siginfo - context.set_rdx(ucontext_addr as usize); // void* ctx + context.set_arguments(sig_num, siginfo_addr as usize, ucontext_addr as usize); } else { - context.set_rsi(0); - context.set_rdx(0); + context.set_arguments(sig_num, 0, 0); } Ok(()) diff --git a/kernel/aster-nix/src/syscall/arch_prctl.rs b/kernel/aster-nix/src/syscall/arch_prctl.rs index 97c9be52c..98c4763fd 100644 --- a/kernel/aster-nix/src/syscall/arch_prctl.rs +++ b/kernel/aster-nix/src/syscall/arch_prctl.rs @@ -3,7 +3,7 @@ use aster_frame::cpu::UserContext; use super::SyscallReturn; -use crate::prelude::*; +use crate::{cpu::LinuxAbi, prelude::*}; #[allow(non_camel_case_types)] #[repr(u64)] @@ -28,10 +28,10 @@ pub fn sys_arch_prctl(code: u64, addr: u64, context: &mut UserContext) -> Result pub fn do_arch_prctl(code: ArchPrctlCode, addr: u64, context: &mut UserContext) -> Result { match code { ArchPrctlCode::ARCH_SET_FS => { - context.set_fsbase(addr as usize); + context.set_tls_pointer(addr as usize); Ok(0) } - ArchPrctlCode::ARCH_GET_FS => Ok(context.fsbase() as u64), + ArchPrctlCode::ARCH_GET_FS => Ok(context.tls_pointer() as u64), ArchPrctlCode::ARCH_GET_GS | ArchPrctlCode::ARCH_SET_GS => { return_errno_with_message!(Errno::EINVAL, "GS cannot be accessed from the user space") } diff --git a/kernel/aster-nix/src/syscall/execve.rs b/kernel/aster-nix/src/syscall/execve.rs index 7d2e5885b..892542e8a 100644 --- a/kernel/aster-nix/src/syscall/execve.rs +++ b/kernel/aster-nix/src/syscall/execve.rs @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MPL-2.0 -use aster_frame::cpu::UserContext; +use aster_frame::{cpu::UserContext, user::UserContextApi}; use aster_rights::WriteOp; use super::{constants::*, SyscallReturn}; use crate::{ + cpu::LinuxAbi, fs::{ file_table::FileDesc, fs_resolver::{FsPath, AT_FDCWD}, @@ -127,13 +128,13 @@ fn do_execve( // set cpu context to default let default_content = UserContext::default(); *context.general_regs_mut() = *default_content.general_regs(); - context.set_fsbase(default_content.fsbase()); + context.set_tls_pointer(default_content.tls_pointer()); *context.fp_regs_mut() = *default_content.fp_regs(); // set new entry point - context.set_rip(elf_load_info.entry_point() as _); + context.set_instruction_pointer(elf_load_info.entry_point() as _); debug!("entry_point: 0x{:x}", elf_load_info.entry_point()); // set new user stack top - context.set_rsp(elf_load_info.user_stack_top() as _); + context.set_stack_pointer(elf_load_info.user_stack_top() as _); debug!("user stack top: 0x{:x}", elf_load_info.user_stack_top()); Ok(()) } diff --git a/kernel/aster-nix/src/syscall/mod.rs b/kernel/aster-nix/src/syscall/mod.rs index 5f3ac0e1f..29e84d878 100644 --- a/kernel/aster-nix/src/syscall/mod.rs +++ b/kernel/aster-nix/src/syscall/mod.rs @@ -5,7 +5,7 @@ use aster_frame::cpu::UserContext; pub use clock_gettime::ClockID; -use crate::prelude::*; +use crate::{cpu::LinuxAbi, prelude::*}; mod accept; mod access; @@ -204,14 +204,8 @@ pub enum SyscallReturn { impl SyscallArgument { fn new_from_context(context: &UserContext) -> Self { - let syscall_number = context.rax() as u64; - let mut args = [0u64; 6]; - args[0] = context.rdi() as u64; - args[1] = context.rsi() as u64; - args[2] = context.rdx() as u64; - args[3] = context.r10() as u64; - args[4] = context.r8() as u64; - args[5] = context.r9() as u64; + let syscall_number = context.syscall_num() as u64; + let args = context.syscall_args().map(|x| x as u64); Self { syscall_number, args, @@ -227,13 +221,13 @@ pub fn handle_syscall(context: &mut UserContext) { match syscall_return { Ok(return_value) => { if let SyscallReturn::Return(return_value) = return_value { - context.set_rax(return_value as usize); + context.set_syscall_ret(return_value as usize); } } Err(err) => { debug!("syscall return error: {:?}", err); let errno = err.error() as i32; - context.set_rax((-errno) as usize) + context.set_syscall_ret((-errno) as usize) } } } diff --git a/kernel/aster-nix/src/syscall/rt_sigreturn.rs b/kernel/aster-nix/src/syscall/rt_sigreturn.rs index 75711dbae..c9e6746a6 100644 --- a/kernel/aster-nix/src/syscall/rt_sigreturn.rs +++ b/kernel/aster-nix/src/syscall/rt_sigreturn.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -use aster_frame::cpu::UserContext; +use aster_frame::{cpu::UserContext, user::UserContextApi}; use super::SyscallReturn; use crate::{ @@ -20,13 +20,13 @@ pub fn sys_rt_sigreturn(context: &mut UserContext) -> Result { // FIXME: This assertion is not always true, if RESTORER flag is not presented. // In this case, we will put restorer code on user stack, then the assertion will fail. // However, for most glibc applications, the restorer codes is provided by glibc and RESTORER flag is set. - debug_assert!(sig_context_addr == context.rsp() as Vaddr); + debug_assert!(sig_context_addr == context.stack_pointer() as Vaddr); let ucontext = read_val_from_user::(sig_context_addr)?; // If the sig stack is active and used by current handler, decrease handler counter. if let Some(sig_stack) = posix_thread.sig_stack().lock().as_mut() { - let rsp = context.rsp(); + let rsp = context.stack_pointer(); if rsp >= sig_stack.base() && rsp <= sig_stack.base() + sig_stack.size() { sig_stack.decrease_handler_counter(); } diff --git a/kernel/aster-nix/src/thread/task.rs b/kernel/aster-nix/src/thread/task.rs index 0e97ec74a..a2b5afb22 100644 --- a/kernel/aster-nix/src/thread/task.rs +++ b/kernel/aster-nix/src/thread/task.rs @@ -8,7 +8,7 @@ use aster_frame::{ use super::Thread; use crate::{ - prelude::*, process::signal::handle_pending_signal, syscall::handle_syscall, + cpu::LinuxAbi, prelude::*, process::signal::handle_pending_signal, syscall::handle_syscall, thread::exception::handle_exception, };