| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- use super::{KResult, Signal, SignalMask, SAVED_DATA_SIZE};
- use crate::{
- io::BufferFill as _,
- kernel::{
- constants::{EFAULT, EINVAL, ENOSYS},
- user::UserBuffer,
- },
- SIGNAL_NOW,
- };
- use alloc::collections::btree_map::BTreeMap;
- use core::num::NonZero;
- use eonix_hal::{fpu::FpuState, traits::trap::RawTrapContext, trap::TrapContext};
- use eonix_mm::address::{Addr as _, AddrOps as _, VAddr};
- use posix_types::signal::{SigAction, TryFromSigAction};
- #[derive(Debug, Clone, Copy)]
- pub enum SignalAction {
- Default,
- Ignore,
- SimpleHandler {
- handler: VAddr,
- restorer: Option<VAddr>,
- mask: SignalMask,
- },
- }
- #[derive(Debug)]
- pub struct SignalActionList {
- actions: BTreeMap<Signal, SignalAction>,
- }
- impl SignalActionList {
- pub const fn new() -> Self {
- Self {
- actions: BTreeMap::new(),
- }
- }
- pub fn set(&mut self, signal: Signal, action: SignalAction) {
- debug_assert!(
- !matches!(signal, SIGNAL_NOW!()),
- "SIGSTOP and SIGKILL should not be set for a handler."
- );
- match action {
- SignalAction::Default => self.actions.remove(&signal),
- _ => self.actions.insert(signal, action),
- };
- }
- pub fn get(&self, signal: Signal) -> SignalAction {
- match self.actions.get(&signal) {
- None => SignalAction::Default,
- Some(action) => action.clone(),
- }
- }
- pub fn remove_non_ignore(&mut self) {
- // Remove all custom handlers except for the ignore action.
- // Default handlers should never appear in the list so we don't consider that.
- self.actions
- .retain(|_, action| matches!(action, SignalAction::Ignore));
- }
- }
- impl SignalAction {
- /// # Might Sleep
- pub(super) fn handle(
- self,
- signal: Signal,
- old_mask: SignalMask,
- trap_ctx: &mut TrapContext,
- fpu_state: &mut FpuState,
- ) -> KResult<()> {
- let SignalAction::SimpleHandler {
- handler, restorer, ..
- } = self
- else {
- unreachable!("Default and Ignore actions should not be handled here");
- };
- let Some(restorer) = restorer else {
- // We don't accept signal handlers with no signal restorers for now.
- return Err(ENOSYS)?;
- };
- let current_sp = VAddr::from(trap_ctx.get_stack_pointer());
- // Save current interrupt context to 128 bytes above current user stack
- // (in order to keep away from x86 red zone) and align to 16 bytes.
- let saved_data_addr = (current_sp - 128 - SAVED_DATA_SIZE).floor_to(16);
- let mut saved_data_buffer =
- UserBuffer::new(saved_data_addr.addr() as *mut u8, SAVED_DATA_SIZE)?;
- saved_data_buffer.copy(trap_ctx)?.ok_or(EFAULT)?;
- saved_data_buffer.copy(fpu_state)?.ok_or(EFAULT)?;
- saved_data_buffer.copy(&old_mask)?.ok_or(EFAULT)?;
- // We need to push the arguments to the handler and then save the return address.
- let new_sp = saved_data_addr - 16 - 4;
- let restorer_address = restorer.addr() as u32;
- let mut stack = UserBuffer::new(new_sp.addr() as *mut u8, 4 + 4)?;
- stack.copy(&restorer_address)?.ok_or(EFAULT)?; // Restorer address
- stack.copy(&u32::from(signal))?.ok_or(EFAULT)?; // The argument to the handler
- trap_ctx.set_program_counter(handler.addr());
- trap_ctx.set_stack_pointer(new_sp.addr());
- Ok(())
- }
- }
- impl Clone for SignalActionList {
- fn clone(&self) -> Self {
- Self {
- actions: self.actions.clone(),
- }
- }
- }
- impl Default for SignalAction {
- fn default() -> Self {
- Self::Default
- }
- }
- impl TryFromSigAction for SignalAction {
- type Error = u32;
- fn default() -> Self {
- Self::Default
- }
- fn ignore() -> Self {
- Self::Ignore
- }
- fn new() -> Self {
- Self::SimpleHandler {
- handler: VAddr::NULL,
- restorer: None,
- mask: SignalMask::empty(),
- }
- }
- fn set_siginfo(self) -> Result<Self, Self::Error> {
- Err(EINVAL)
- }
- fn handler(mut self, handler_addr: usize) -> Result<Self, Self::Error> {
- if let Self::SimpleHandler { handler, .. } = &mut self {
- *handler = VAddr::from(handler_addr);
- Ok(self)
- } else {
- unreachable!()
- }
- }
- fn restorer(mut self, restorer_addr: usize) -> Result<Self, Self::Error> {
- if let Self::SimpleHandler { restorer, .. } = &mut self {
- *restorer = NonZero::new(restorer_addr).map(|x| VAddr::from(x.get()));
- Ok(self)
- } else {
- unreachable!()
- }
- }
- fn mask(mut self, mask_value: u64) -> Result<Self, Self::Error> {
- if let Self::SimpleHandler { mask, .. } = &mut self {
- *mask = SignalMask::from(mask_value);
- Ok(self)
- } else {
- unreachable!()
- }
- }
- }
- impl From<SignalAction> for SigAction {
- fn from(action: SignalAction) -> SigAction {
- match action {
- SignalAction::Default => SigAction::default(),
- SignalAction::Ignore => SigAction::ignore(),
- SignalAction::SimpleHandler {
- handler,
- restorer,
- mask,
- } => {
- let action = SigAction::new()
- .handler(handler.addr())
- .mask(u64::from(mask));
- if let Some(restorer) = restorer {
- action.restorer(restorer.addr())
- } else {
- action
- }
- }
- }
- }
- }
|