mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-29 04:13:24 +00:00
Extract x86-specific exception handling in aster-nix
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
a997d9f0b0
commit
4d36dd541f
@ -12,6 +12,8 @@ use core::{
|
||||
use bitflags::bitflags;
|
||||
use cfg_if::cfg_if;
|
||||
use log::debug;
|
||||
use num_derive::FromPrimitive;
|
||||
use num_traits::FromPrimitive;
|
||||
use x86::bits64::segmentation::wrfsbase;
|
||||
use x86_64::registers::rflags::RFlags;
|
||||
|
||||
@ -109,41 +111,37 @@ impl UserContextApiInternal for UserContext {
|
||||
// set ID flag which means cpu support CPUID instruction
|
||||
self.user_context.general.rflags |= (RFlags::INTERRUPT_FLAG | RFlags::ID).bits() as usize;
|
||||
|
||||
let return_reason: ReturnReason;
|
||||
const SYSCALL_TRAPNUM: u16 = 0x100;
|
||||
|
||||
// return when it is syscall or cpu exception type is Fault or Trap.
|
||||
loop {
|
||||
let return_reason = loop {
|
||||
scheduler::might_preempt();
|
||||
self.user_context.run();
|
||||
match CpuException::to_cpu_exception(self.user_context.trap_num as u16) {
|
||||
Some(exception) => {
|
||||
#[cfg(feature = "cvm_guest")]
|
||||
if *exception == VIRTUALIZATION_EXCEPTION {
|
||||
if exception == CpuException::VIRTUALIZATION_EXCEPTION {
|
||||
handle_virtualization_exception(self);
|
||||
continue;
|
||||
}
|
||||
if exception.typ == CpuExceptionType::FaultOrTrap
|
||||
|| exception.typ == CpuExceptionType::Fault
|
||||
|| exception.typ == CpuExceptionType::Trap
|
||||
{
|
||||
return_reason = ReturnReason::UserException;
|
||||
break;
|
||||
match exception.typ() {
|
||||
CpuExceptionType::FaultOrTrap
|
||||
| CpuExceptionType::Trap
|
||||
| CpuExceptionType::Fault => break ReturnReason::UserException,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if self.user_context.trap_num as u16 == SYSCALL_TRAPNUM {
|
||||
return_reason = ReturnReason::UserSyscall;
|
||||
break;
|
||||
break ReturnReason::UserSyscall;
|
||||
}
|
||||
}
|
||||
};
|
||||
call_irq_callback_functions(&self.as_trap_frame(), self.as_trap_frame().trap_num);
|
||||
if has_kernel_event() {
|
||||
return_reason = ReturnReason::KernelEvent;
|
||||
break;
|
||||
break ReturnReason::KernelEvent;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
crate::arch::irq::enable_local();
|
||||
if return_reason == ReturnReason::UserException {
|
||||
@ -212,39 +210,26 @@ pub enum CpuExceptionType {
|
||||
Reserved,
|
||||
}
|
||||
|
||||
/// CPU exception.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct CpuException {
|
||||
/// The ID of the CPU exception.
|
||||
pub number: u16,
|
||||
/// The type of the CPU exception.
|
||||
pub typ: CpuExceptionType,
|
||||
}
|
||||
|
||||
/// Copy from: https://veykril.github.io/tlborm/decl-macros/building-blocks/counting.html#slice-length
|
||||
macro_rules! replace_expr {
|
||||
($_t:tt $sub:expr) => {
|
||||
$sub
|
||||
};
|
||||
}
|
||||
|
||||
/// Copy from: https://veykril.github.io/tlborm/decl-macros/building-blocks/counting.html#slice-length
|
||||
macro_rules! count_tts {
|
||||
($($tts:tt)*) => {<[()]>::len(&[$(replace_expr!($tts ())),*])};
|
||||
}
|
||||
|
||||
macro_rules! define_cpu_exception {
|
||||
( $([ $name: ident = $exception_num:tt, $exception_type:tt]),* ) => {
|
||||
const EXCEPTION_LIST : [CpuException;count_tts!($($name)*)] = [
|
||||
$($name,)*
|
||||
];
|
||||
$(
|
||||
#[doc = concat!("The ", stringify!($name), " exception")]
|
||||
pub const $name : CpuException = CpuException{
|
||||
number: $exception_num,
|
||||
typ: CpuExceptionType::$exception_type,
|
||||
};
|
||||
)*
|
||||
( $([ $name: ident = $exception_id:tt, $exception_type:tt]),* ) => {
|
||||
/// CPU exception.
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, FromPrimitive)]
|
||||
pub enum CpuException {
|
||||
$(
|
||||
#[doc = concat!("The ", stringify!($name), " exception")]
|
||||
$name = $exception_id,
|
||||
)*
|
||||
}
|
||||
|
||||
impl CpuException {
|
||||
/// The type of the CPU exception.
|
||||
pub fn typ(&self) -> CpuExceptionType {
|
||||
match self {
|
||||
$( CpuException::$name => CpuExceptionType::$exception_type, )*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,19 +299,19 @@ bitflags! {
|
||||
impl CpuException {
|
||||
/// Checks if the given `trap_num` is a valid CPU exception.
|
||||
pub fn is_cpu_exception(trap_num: u16) -> bool {
|
||||
trap_num < EXCEPTION_LIST.len() as u16
|
||||
Self::to_cpu_exception(trap_num).is_some()
|
||||
}
|
||||
|
||||
/// Maps a `trap_num` to its corresponding CPU exception.
|
||||
pub fn to_cpu_exception(trap_num: u16) -> Option<&'static CpuException> {
|
||||
EXCEPTION_LIST.get(trap_num as usize)
|
||||
pub fn to_cpu_exception(trap_num: u16) -> Option<CpuException> {
|
||||
FromPrimitive::from_u16(trap_num)
|
||||
}
|
||||
}
|
||||
|
||||
impl CpuExceptionInfo {
|
||||
/// Get corresponding CPU exception
|
||||
pub fn cpu_exception(&self) -> CpuException {
|
||||
EXCEPTION_LIST[self.id]
|
||||
CpuException::to_cpu_exception(self.id as u16).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ use log::debug;
|
||||
|
||||
use super::ex_table::ExTable;
|
||||
use crate::{
|
||||
cpu::{CpuException, CpuExceptionInfo, PageFaultErrorCode, PAGE_FAULT},
|
||||
cpu::{CpuException, CpuExceptionInfo, PageFaultErrorCode},
|
||||
cpu_local_cell,
|
||||
mm::{
|
||||
kspace::{KERNEL_PAGE_TABLE, LINEAR_MAPPING_BASE_VADDR, LINEAR_MAPPING_VADDR_RANGE},
|
||||
@ -40,7 +40,7 @@ use crate::{
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "cvm_guest")] {
|
||||
use tdx_guest::{tdcall, tdx_is_enabled, handle_virtual_exception};
|
||||
use crate::arch::{cpu::VIRTUALIZATION_EXCEPTION, tdx_guest::TrapFrameWrapper};
|
||||
use crate::arch::tdx_guest::TrapFrameWrapper;
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,13 +223,13 @@ extern "sysv64" fn trap_handler(f: &mut TrapFrame) {
|
||||
if CpuException::is_cpu_exception(f.trap_num as u16) {
|
||||
match CpuException::to_cpu_exception(f.trap_num as u16).unwrap() {
|
||||
#[cfg(feature = "cvm_guest")]
|
||||
&VIRTUALIZATION_EXCEPTION => {
|
||||
CpuException::VIRTUALIZATION_EXCEPTION => {
|
||||
let ve_info = tdcall::get_veinfo().expect("#VE handler: fail to get VE info\n");
|
||||
let mut trapframe_wrapper = TrapFrameWrapper(&mut *f);
|
||||
handle_virtual_exception(&mut trapframe_wrapper, &ve_info);
|
||||
*f = *trapframe_wrapper.0;
|
||||
}
|
||||
&PAGE_FAULT => {
|
||||
CpuException::PAGE_FAULT => {
|
||||
let page_fault_addr = x86_64::registers::control::Cr2::read_raw();
|
||||
// The actual user space implementation should be responsible
|
||||
// for providing mechanism to treat the 0 virtual address.
|
||||
|
Reference in New Issue
Block a user