pub use error_code::*;
use crate::{
hal::{cpu::Cpu, smp::CPUS},
mem::VirtualAddress,
};
mod error_code;
#[derive(Debug, Clone, Default)]
#[repr(C)]
pub struct TrapFrame {
pub r15: usize,
pub r14: usize,
pub r13: usize,
pub r12: usize,
pub rbp: usize,
pub rbx: usize,
pub r11: usize,
pub r10: usize,
pub r9: usize,
pub r8: usize,
pub rsi: usize,
pub rdi: usize,
pub rdx: usize,
pub rcx: usize,
pub rax: usize,
pub int_num: usize,
pub error_code: usize,
pub rip: usize,
pub cs: usize,
pub rflags: usize,
pub rsp: usize,
pub ss: usize,
}
impl TrapFrame {
pub(crate) fn init(
&mut self,
kernel_stack: &[u8],
entry: usize,
stack: usize,
user_mode: bool,
) {
let kernel_stack_end = kernel_stack.as_ptr() as usize + kernel_stack.len();
log::info!("Kernel stack end: {:x}", kernel_stack_end);
self.rip = entry;
self.rsp = if user_mode { stack } else { kernel_stack_end };
self.rflags = 0x200;
CPUS.with_cpu_info(Cpu::current(), |cpu_info| {
self.cs = if user_mode {
cpu_info.user_code_selector()
} else {
cpu_info.kernel_code_selector()
};
self.ss = if user_mode {
cpu_info.user_data_selector()
} else {
cpu_info.kernel_data_selector()
};
});
}
#[allow(dead_code)]
pub(crate) fn set_stack(&mut self, stack: VirtualAddress) {
self.rsp = stack;
}
pub fn syscall_index(&self) -> usize {
self.rax
}
pub fn syscall_arguments(&self) -> [usize; 6] {
[self.rdi, self.rsi, self.rdx, self.r10, self.r8, self.r9]
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CpuException {
DivisionError,
Debug,
NonMaskableInterrupt,
BreakPoint,
Overflow,
BoundRangeExceeded,
InvalidOpcode,
DeviceNotAvailable,
DoubleFault,
CoprocessorSegmentOverrun,
InvalidTss(SelectorErrorCode),
SegmentNotPresent(SelectorErrorCode),
StackSegmentFault(SelectorErrorCode),
GeneralProtectionFault(Option<SelectorErrorCode>),
PageFault(PageFaultErrorCode, VirtualAddress),
X87FloatingPointException,
AlignmentCheck,
MachineCheck,
SIMDFloatingPointException,
VirtualizationException,
ControlProtectionException,
HypervisorInjectionException,
VMMCommunicationException,
SecurityException,
Reserved,
}
impl CpuException {
pub(crate) fn new(trap_num: usize, error_code: usize) -> Option<Self> {
let exception = match trap_num {
0 => Self::DivisionError,
1 => Self::Debug,
2 => Self::NonMaskableInterrupt,
3 => Self::BreakPoint,
4 => Self::Overflow,
5 => Self::BoundRangeExceeded,
6 => Self::InvalidOpcode,
7 => Self::DeviceNotAvailable,
8 => {
debug_assert_eq!(error_code, 0);
Self::DoubleFault
}
9 => Self::CoprocessorSegmentOverrun,
10 => Self::InvalidTss(SelectorErrorCode::new_truncate(error_code as u64)),
11 => Self::SegmentNotPresent(SelectorErrorCode::new_truncate(error_code as u64)),
12 => Self::StackSegmentFault(SelectorErrorCode::new_truncate(error_code as u64)),
13 => {
let error_code = if error_code == 0 {
None
} else {
Some(SelectorErrorCode::new_truncate(error_code as u64))
};
Self::GeneralProtectionFault(error_code)
}
14 => {
let page_fault_addr = x86_64::registers::control::Cr2::read_raw() as usize;
Self::PageFault(
PageFaultErrorCode::from_bits(error_code as u64).unwrap(),
page_fault_addr,
)
}
16 => Self::X87FloatingPointException,
17 => Self::AlignmentCheck,
18 => Self::MachineCheck,
19 => Self::SIMDFloatingPointException,
20 => Self::VirtualizationException,
21 => Self::ControlProtectionException,
28 => Self::HypervisorInjectionException,
29 => Self::VMMCommunicationException,
30 => Self::SecurityException,
15 | 22..=27 | 31 => Self::Reserved,
_ => return None,
};
Some(exception)
}
}