mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-14 15:56:47 +00:00
Extract OS-specific part from UserContextApi
This commit is contained in:
parent
657d6719c7
commit
a5707b4ddc
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
6
kernel/aster-nix/src/arch/mod.rs
Normal file
6
kernel/aster-nix/src/arch/mod.rs
Normal file
@ -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::*;
|
38
kernel/aster-nix/src/arch/x86/cpu.rs
Normal file
38
kernel/aster-nix/src/arch/x86/cpu.rs
Normal file
@ -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()
|
||||
}
|
||||
}
|
4
kernel/aster-nix/src/arch/x86/mod.rs
Normal file
4
kernel/aster-nix/src/arch/x86/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
pub mod cpu;
|
||||
pub mod signal;
|
13
kernel/aster-nix/src/arch/x86/signal.rs
Normal file
13
kernel/aster-nix/src/arch/x86/signal.rs
Normal file
@ -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);
|
||||
}
|
||||
}
|
21
kernel/aster-nix/src/cpu.rs
Normal file
21
kernel/aster-nix/src/cpu.rs
Normal file
@ -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;
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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(())
|
||||
|
@ -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<u64> {
|
||||
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")
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<SyscallReturn> {
|
||||
// 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::<ucontext_t>(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();
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user