Extract x86-specific exception handling in aster-nix

This commit is contained in:
YanWQ-monad
2024-07-19 15:42:53 +08:00
committed by Tate, Hongliang Tian
parent a997d9f0b0
commit 4d36dd541f
7 changed files with 86 additions and 142 deletions

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
use ostd::{
cpu::{CpuExceptionInfo, RawGeneralRegs, UserContext, PAGE_FAULT},
cpu::{CpuException, CpuExceptionInfo, RawGeneralRegs, UserContext},
Pod,
};
@ -107,7 +107,7 @@ impl TryFrom<&CpuExceptionInfo> for PageFaultInfo {
type Error = ();
fn try_from(value: &CpuExceptionInfo) -> Result<Self, ()> {
if value.cpu_exception() != PAGE_FAULT {
if value.cpu_exception() != CpuException::PAGE_FAULT {
return Err(());
}

View File

@ -1,8 +1,10 @@
// SPDX-License-Identifier: MPL-2.0
use ostd::cpu::UserContext;
use ostd::cpu::{CpuException, CpuExceptionInfo, UserContext};
use crate::process::signal::{sig_num::SigNum, SignalContext};
use crate::process::signal::{
constants::*, sig_num::SigNum, signals::fault::FaultSignal, SignalContext,
};
impl SignalContext for UserContext {
fn set_arguments(&mut self, sig_num: SigNum, siginfo_addr: usize, ucontext_addr: usize) {
@ -11,3 +13,30 @@ impl SignalContext for UserContext {
self.set_rdx(ucontext_addr);
}
}
impl From<&CpuExceptionInfo> for FaultSignal {
fn from(trap_info: &CpuExceptionInfo) -> Self {
let exception = CpuException::to_cpu_exception(trap_info.id as u16).unwrap();
let (num, code, addr) = match exception {
CpuException::DIVIDE_BY_ZERO => (SIGFPE, FPE_INTDIV, None),
CpuException::X87_FLOATING_POINT_EXCEPTION
| CpuException::SIMD_FLOATING_POINT_EXCEPTION => (SIGFPE, FPE_FLTDIV, None),
CpuException::BOUND_RANGE_EXCEEDED => (SIGSEGV, SEGV_BNDERR, None),
CpuException::ALIGNMENT_CHECK => (SIGBUS, BUS_ADRALN, None),
CpuException::INVALID_OPCODE => (SIGILL, ILL_ILLOPC, None),
CpuException::GENERAL_PROTECTION_FAULT => (SIGBUS, BUS_ADRERR, None),
CpuException::PAGE_FAULT => {
const PF_ERR_FLAG_PRESENT: usize = 1usize << 0;
let code = if trap_info.error_code & PF_ERR_FLAG_PRESENT != 0 {
SEGV_ACCERR
} else {
SEGV_MAPERR
};
let addr = Some(trap_info.page_fault_addr as u64);
(SIGSEGV, code, addr)
}
_ => panic!("Exception cannot be a signal"),
};
FaultSignal::new(num, code, addr)
}
}

View File

@ -11,7 +11,7 @@ use id_alloc::IdAlloc;
use ostd::{
arch::{
timer::{self, TIMER_FREQ},
x86::trap::is_kernel_interrupted,
trap::is_kernel_interrupted,
},
sync::Mutex,
};

View File

@ -1,16 +1,11 @@
// SPDX-License-Identifier: MPL-2.0
use ostd::cpu::{
CpuException, CpuExceptionInfo, ALIGNMENT_CHECK, BOUND_RANGE_EXCEEDED, DIVIDE_BY_ZERO,
GENERAL_PROTECTION_FAULT, INVALID_OPCODE, PAGE_FAULT, SIMD_FLOATING_POINT_EXCEPTION,
X87_FLOATING_POINT_EXCEPTION,
};
use super::Signal;
use crate::{
prelude::*,
process::signal::{c_types::siginfo_t, constants::*, sig_num::SigNum},
process::signal::{c_types::siginfo_t, sig_num::SigNum},
};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct FaultSignal {
num: SigNum,
@ -19,30 +14,7 @@ pub struct FaultSignal {
}
impl FaultSignal {
pub fn new(trap_info: &CpuExceptionInfo) -> FaultSignal {
debug!("Trap id: {}", trap_info.id);
let exception = CpuException::to_cpu_exception(trap_info.id as u16).unwrap();
let (num, code, addr) = match *exception {
DIVIDE_BY_ZERO => (SIGFPE, FPE_INTDIV, None),
X87_FLOATING_POINT_EXCEPTION | SIMD_FLOATING_POINT_EXCEPTION => {
(SIGFPE, FPE_FLTDIV, None)
}
BOUND_RANGE_EXCEEDED => (SIGSEGV, SEGV_BNDERR, None),
ALIGNMENT_CHECK => (SIGBUS, BUS_ADRALN, None),
INVALID_OPCODE => (SIGILL, ILL_ILLOPC, None),
GENERAL_PROTECTION_FAULT => (SIGBUS, BUS_ADRERR, None),
PAGE_FAULT => {
const PF_ERR_FLAG_PRESENT: usize = 1usize << 0;
let code = if trap_info.error_code & PF_ERR_FLAG_PRESENT != 0 {
SEGV_ACCERR
} else {
SEGV_MAPERR
};
let addr = Some(trap_info.page_fault_addr as u64);
(SIGSEGV, code, addr)
}
_ => panic!("Exception cannot be a signal"),
};
pub fn new(num: SigNum, code: i32, addr: Option<u64>) -> FaultSignal {
FaultSignal { num, code, addr }
}
}

View File

@ -73,61 +73,19 @@ pub(crate) fn handle_page_fault_from_vmar(
/// generate a fault signal for current process.
fn generate_fault_signal(trap_info: &CpuExceptionInfo, ctx: &Context) {
let signal = FaultSignal::new(trap_info);
let signal = FaultSignal::from(trap_info);
ctx.posix_thread.enqueue_signal(Box::new(signal));
}
macro_rules! log_trap_common {
($exception_name: ident, $trap_info: ident) => {
trace!(
"[Trap][{}][err = {}]",
stringify!($exception_name),
$trap_info.error_code
)
};
}
fn log_trap_info(trap_info: &CpuExceptionInfo) {
match trap_info.cpu_exception() {
DIVIDE_BY_ZERO => log_trap_common!(DIVIDE_BY_ZERO, trap_info),
DEBUG => log_trap_common!(DEBUG, trap_info),
NON_MASKABLE_INTERRUPT => log_trap_common!(NON_MASKABLE_INTERRUPT, trap_info),
BREAKPOINT => log_trap_common!(BREAKPOINT, trap_info),
OVERFLOW => log_trap_common!(OVERFLOW, trap_info),
BOUND_RANGE_EXCEEDED => log_trap_common!(BOUND_RANGE_EXCEEDED, trap_info),
INVALID_OPCODE => log_trap_common!(INVALID_OPCODE, trap_info),
DEVICE_NOT_AVAILABLE => log_trap_common!(DEVICE_NOT_AVAILABLE, trap_info),
DOUBLE_FAULT => log_trap_common!(DOUBLE_FAULT, trap_info),
COPROCESSOR_SEGMENT_OVERRUN => log_trap_common!(COPROCESSOR_SEGMENT_OVERRUN, trap_info),
INVALID_TSS => log_trap_common!(INVALID_TSS, trap_info),
SEGMENT_NOT_PRESENT => log_trap_common!(SEGMENT_NOT_PRESENT, trap_info),
STACK_SEGMENT_FAULT => log_trap_common!(STACK_SEGMENT_FAULT, trap_info),
GENERAL_PROTECTION_FAULT => log_trap_common!(GENERAL_PROTECTION_FAULT, trap_info),
PAGE_FAULT => {
trace!(
"[Trap][{}][page fault addr = 0x{:x}, err = {}]",
stringify!(PAGE_FAULT),
trap_info.page_fault_addr,
trap_info.error_code
);
}
// 15 reserved
X87_FLOATING_POINT_EXCEPTION => log_trap_common!(X87_FLOATING_POINT_EXCEPTION, trap_info),
ALIGNMENT_CHECK => log_trap_common!(ALIGNMENT_CHECK, trap_info),
MACHINE_CHECK => log_trap_common!(MACHINE_CHECK, trap_info),
SIMD_FLOATING_POINT_EXCEPTION => log_trap_common!(SIMD_FLOATING_POINT_EXCEPTION, trap_info),
VIRTUALIZATION_EXCEPTION => log_trap_common!(VIRTUALIZATION_EXCEPTION, trap_info),
CONTROL_PROTECTION_EXCEPTION => log_trap_common!(CONTROL_PROTECTION_EXCEPTION, trap_info),
HYPERVISOR_INJECTION_EXCEPTION => {
log_trap_common!(HYPERVISOR_INJECTION_EXCEPTION, trap_info)
}
VMM_COMMUNICATION_EXCEPTION => log_trap_common!(VMM_COMMUNICATION_EXCEPTION, trap_info),
SECURITY_EXCEPTION => log_trap_common!(SECURITY_EXCEPTION, trap_info),
_ => {
info!(
"[Trap][Unknown trap type][id = {}, err = {}]",
trap_info.id, trap_info.error_code
);
}
if let Ok(page_fault_info) = PageFaultInfo::try_from(trap_info) {
trace!(
"[Trap][PAGE_FAULT][page fault addr = 0x{:x}, err = {}]",
trap_info.page_fault_addr,
trap_info.error_code
);
} else {
let exception = trap_info.cpu_exception();
trace!("[Trap][{exception:?}][err = {}]", trap_info.error_code)
}
}