1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
#[cfg(feature = "monolithic")]
use crate::trap::handle_page_fault;
#[cfg(feature = "monolithic")]
use page_table_entry::MappingFlags;
use x86::{controlregs::cr2, irq::*};
use super::context::TrapFrame;
core::arch::global_asm!(include_str!("trap.S"));
const IRQ_VECTOR_START: u8 = 0x20;
const IRQ_VECTOR_END: u8 = 0xff;
#[no_mangle]
fn x86_trap_handler(tf: &mut TrapFrame) {
match tf.vector as u8 {
PAGE_FAULT_VECTOR => {
if tf.is_user() {
warn!(
"User #PF @ {:#x}, fault_vaddr={:#x}, error_code={:#x}",
tf.rip,
unsafe { cr2() },
tf.error_code,
);
#[cfg(feature = "monolithic")]
{
// 31 15 4 0
// +---+-- --+---+-----+---+-- --+---+----+----+---+---+---+---+---+
// | Reserved | SGX | Reserved | SS | PK | I | R | U | W | P |
// +---+-- --+---+-----+---+-- --+---+----+----+---+---+---+---+---+
let mut map_flags = MappingFlags::USER; // TODO: add this flags through user tf.
if tf.error_code & (1 << 1) != 0 {
map_flags |= MappingFlags::WRITE;
}
if tf.error_code & (1 << 2) != 0 {
map_flags |= MappingFlags::USER;
}
if tf.error_code & (1 << 3) != 0 {
map_flags |= MappingFlags::READ;
}
if tf.error_code & (1 << 4) != 0 {
map_flags |= MappingFlags::EXECUTE;
}
axlog::debug!("error_code: {:?}", tf.error_code);
handle_page_fault(unsafe { cr2() }.into(), map_flags);
}
} else {
panic!(
"Kernel #PF @ {:#x}, fault_vaddr={:#x}, error_code={:#x}:\n{:#x?}",
tf.rip,
unsafe { cr2() },
tf.error_code,
tf,
);
}
}
BREAKPOINT_VECTOR => debug!("#BP @ {:#x} ", tf.rip),
GENERAL_PROTECTION_FAULT_VECTOR => {
panic!(
"#GP @ {:#x}, error_code={:#x}:\n{:#x?}",
tf.rip, tf.error_code, tf
);
}
IRQ_VECTOR_START..=IRQ_VECTOR_END => crate::trap::handle_irq_extern(tf.vector as _, false),
_ => {
panic!(
"Unhandled exception {} (error_code = {:#x}) @ {:#x}:\n{:#x?}",
tf.vector, tf.error_code, tf.rip, tf
);
}
}
#[cfg(feature = "signal")]
if tf.is_user() {
crate::trap::handle_signal();
}
}
#[no_mangle]
#[cfg(feature = "monolithic")]
/// To handle the first time into the user space
///
/// 1. push the given trap frame into the kernel stack
/// 2. go into the user space
///
/// args:
///
/// 1. kernel_sp: the top of the kernel stack
///
/// 2. frame_base: the address of the trap frame which will be pushed into the kernel stack
pub fn first_into_user(kernel_sp: usize, frame_base: usize) {
// Make sure that all csr registers are stored before enable the interrupt
use memory_addr::VirtAddr;
use crate::arch::flush_tlb;
use super::disable_irqs;
disable_irqs();
flush_tlb(None);
let trap_frame_size = core::mem::size_of::<TrapFrame>();
let kernel_base = kernel_sp - trap_frame_size;
crate::set_tss_stack_top(VirtAddr::from(kernel_sp));
unsafe {
*(kernel_base as *mut TrapFrame) = *(frame_base as *const TrapFrame);
core::arch::asm!(
r"
mov gs:[offset __PERCPU_KERNEL_RSP_OFFSET], {kernel_sp}
mov rsp, {kernel_base}
pop rax
pop rcx
pop rdx
pop rbx
pop rbp
pop rsi
pop rdi
pop r8
pop r9
pop r10
pop r11
pop r12
pop r13
pop r14
pop r15
add rsp, 16
swapgs
iretq
",
kernel_sp = in(reg) kernel_sp,
kernel_base = in(reg) kernel_base,
);
};
}