Extract OS-specific part from UserContextApi

This commit is contained in:
YanWQ-monad 2024-05-20 03:14:13 +08:00 committed by Tate, Hongliang Tian
parent 657d6719c7
commit a5707b4ddc
16 changed files with 128 additions and 74 deletions

View File

@ -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);
}

View File

@ -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);

View 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::*;

View 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()
}
}

View File

@ -0,0 +1,4 @@
// SPDX-License-Identifier: MPL-2.0
pub mod cpu;
pub mod signal;

View 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);
}
}

View 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;
}

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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(())

View File

@ -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")
}

View File

@ -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(())
}

View File

@ -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)
}
}
}

View File

@ -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();
}

View File

@ -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,
};