From 0539f8673e3db2cb7f6bfcd5dd9ba7884187693a Mon Sep 17 00:00:00 2001 From: WangRunji Date: Thu, 26 Apr 2018 01:00:32 +0800 Subject: [PATCH] Rewrite interrupt handlers using Redox style. Prepare for saving context. --- src/arch/x86_64/driver/apic/ioapic.rs | 2 +- src/arch/x86_64/driver/keyboard/mod.rs | 2 +- src/arch/x86_64/driver/serial.rs | 3 +- src/arch/x86_64/gdt.rs | 7 +- src/arch/x86_64/idt.rs | 32 -- src/arch/x86_64/idt/idt.rs | 104 +++++++ src/arch/x86_64/idt/mod.rs | 33 +++ src/arch/x86_64/interrupt/consts.rs | 31 ++ src/arch/x86_64/interrupt/handler.rs | 85 ++++++ src/arch/x86_64/interrupt/irq.rs | 101 ------- src/arch/x86_64/interrupt/mod.rs | 3 +- src/arch/x86_64/interrupt/template.rs | 394 +++++++++++++++++++++++++ src/consts.rs | 14 - src/io/mod.rs | 10 +- src/lib.rs | 1 + 15 files changed, 659 insertions(+), 163 deletions(-) delete mode 100644 src/arch/x86_64/idt.rs create mode 100644 src/arch/x86_64/idt/idt.rs create mode 100644 src/arch/x86_64/idt/mod.rs create mode 100644 src/arch/x86_64/interrupt/consts.rs create mode 100644 src/arch/x86_64/interrupt/handler.rs delete mode 100644 src/arch/x86_64/interrupt/irq.rs create mode 100644 src/arch/x86_64/interrupt/template.rs diff --git a/src/arch/x86_64/driver/apic/ioapic.rs b/src/arch/x86_64/driver/apic/ioapic.rs index c123dba..91f9797 100644 --- a/src/arch/x86_64/driver/apic/ioapic.rs +++ b/src/arch/x86_64/driver/apic/ioapic.rs @@ -6,7 +6,7 @@ use syscall::io::{Io, Mmio}; use bit_field::BitField; -use consts::irq::T_IRQ0; +use arch::interrupt::consts::T_IRQ0; use spin::Mutex; pub fn init(ioapic_id: u8) diff --git a/src/arch/x86_64/driver/keyboard/mod.rs b/src/arch/x86_64/driver/keyboard/mod.rs index d922bea..396d5d0 100644 --- a/src/arch/x86_64/driver/keyboard/mod.rs +++ b/src/arch/x86_64/driver/keyboard/mod.rs @@ -1,7 +1,7 @@ pub fn init() { assert_has_not_been_called!("keyboard::init must be called only once"); - use consts::irq::*; + use arch::interrupt::consts::*; use arch::interrupt::enable_irq; enable_irq(IRQ_KBD); } diff --git a/src/arch/x86_64/driver/serial.rs b/src/arch/x86_64/driver/serial.rs index 9895099..2e98289 100644 --- a/src/arch/x86_64/driver/serial.rs +++ b/src/arch/x86_64/driver/serial.rs @@ -12,8 +12,7 @@ pub fn init() { COM1.lock().init(); COM2.lock().init(); - use consts::irq::*; - use arch::interrupt::enable_irq; + use arch::interrupt::{enable_irq, consts::{IRQ_COM1, IRQ_COM2}}; enable_irq(IRQ_COM1); enable_irq(IRQ_COM2); } diff --git a/src/arch/x86_64/gdt.rs b/src/arch/x86_64/gdt.rs index 2db9cca..5d2f8b1 100644 --- a/src/arch/x86_64/gdt.rs +++ b/src/arch/x86_64/gdt.rs @@ -13,12 +13,7 @@ pub fn init() { use x86_64::instructions::segmentation::set_cs; use x86_64::instructions::tables::load_tss; - struct DoubleFaultStack { - space: [u8; 4096] - } - let double_fault_stack_top = Box::into_raw(Box::new( - DoubleFaultStack{space: [0; 4096]} - )) as usize + 4096; + let double_fault_stack_top = Box::into_raw(Box::new([0u8; 4096])) as usize + 4096; let mut tss = Box::new({ let mut tss = TaskStateSegment::new(); diff --git a/src/arch/x86_64/idt.rs b/src/arch/x86_64/idt.rs deleted file mode 100644 index f08428a..0000000 --- a/src/arch/x86_64/idt.rs +++ /dev/null @@ -1,32 +0,0 @@ -use x86_64::structures::idt::Idt; -use spin::Once; -use alloc::boxed::Box; - -/// Alloc IDT at kernel heap, then init and load it. -pub fn init() { - let idt = Box::new({ - use arch::interrupt::irq::*; - use consts::irq::*; - use arch::gdt::DOUBLE_FAULT_IST_INDEX; - - let mut idt = Idt::new(); - idt.breakpoint.set_handler_fn(breakpoint_handler); - idt.double_fault.set_handler_fn(double_fault_handler); - idt.general_protection_fault.set_handler_fn(general_protection_fault_handler); - idt[(T_IRQ0 + IRQ_COM1) as usize].set_handler_fn(com1_handler); - idt[(T_IRQ0 + IRQ_COM2) as usize].set_handler_fn(com2_handler); - idt[(T_IRQ0 + IRQ_KBD) as usize].set_handler_fn(keyboard_handler); - idt[(T_IRQ0 + IRQ_TIMER) as usize].set_handler_fn(timer_handler); - idt[T_SWITCH_TOU as usize].set_handler_fn(to_user_handler); - idt[T_SWITCH_TOK as usize].set_handler_fn(to_kernel_handler); - idt[T_SYSCALL as usize].set_handler_fn(syscall_handler); - unsafe { - idt.page_fault.set_handler_fn(page_fault_handler) - .set_stack_index(DOUBLE_FAULT_IST_INDEX as u16); - } - idt - }); - let idt = unsafe{ &*Box::into_raw(idt) }; - - idt.load(); -} \ No newline at end of file diff --git a/src/arch/x86_64/idt/idt.rs b/src/arch/x86_64/idt/idt.rs new file mode 100644 index 0000000..d8af161 --- /dev/null +++ b/src/arch/x86_64/idt/idt.rs @@ -0,0 +1,104 @@ +// Following copied from crate `x86_64` + +use core::ops::{Index, IndexMut}; + +pub struct Idt { + entries: [IdtEntry; 256], +} + +impl Idt { + pub const fn new() -> Idt { + Idt {entries: [IdtEntry::new(); 256]} + } + pub fn load(&'static self) { + use x86_64::instructions::tables::{DescriptorTablePointer, lidt}; + use core::mem::size_of; + + let ptr = DescriptorTablePointer { + base: self as *const _ as u64, + limit: (size_of::() - 1) as u16, + }; + + unsafe { lidt(&ptr) }; + } +} + +impl Index for Idt { + type Output = IdtEntry; + fn index(&self, index: u8) -> &Self::Output { + &self.entries[index as usize] + } +} + +impl IndexMut for Idt { + fn index_mut(&mut self, index: u8) -> &mut Self::Output { + &mut self.entries[index as usize] + } +} + +// Following copied from Redox + +bitflags! { + pub struct IdtFlags: u8 { + const PRESENT = 1 << 7; + const RING_0 = 0 << 5; + const RING_1 = 1 << 5; + const RING_2 = 2 << 5; + const RING_3 = 3 << 5; + const SS = 1 << 4; + const INTERRUPT = 0xE; + const TRAP = 0xF; + } +} + +#[derive(Copy, Clone, Debug)] +#[repr(packed)] +pub struct IdtEntry { + offsetl: u16, + selector: u16, + zero: u8, + attribute: u8, + offsetm: u16, + offseth: u32, + zero2: u32 +} + +impl IdtEntry { + pub const fn new() -> IdtEntry { + IdtEntry { + offsetl: 0, + selector: 0, + zero: 0, + attribute: 0, + offsetm: 0, + offseth: 0, + zero2: 0 + } + } + + pub fn set_flags(&mut self, flags: IdtFlags) { + self.attribute = flags.bits; + } + + pub fn set_offset(&mut self, selector: u16, base: usize) { + self.selector = selector; + self.offsetl = base as u16; + self.offsetm = (base >> 16) as u16; + self.offseth = (base >> 32) as u32; + } + + // A function to set the offset more easily + pub fn set_handler_fn(&mut self, func: unsafe extern fn()) -> &mut Self { + self.set_flags(IdtFlags::PRESENT | IdtFlags::RING_0 | IdtFlags::INTERRUPT); + self.set_offset(8, func as usize); + self + } + + pub unsafe fn set_stack_index(&mut self, index: u16) -> &mut Self { + // The hardware IST index starts at 1, but our software IST index + // starts at 0. Therefore we need to add 1 here. + self.offsetl &= !0b111; + self.offsetl += index + 1; + self + } +} \ No newline at end of file diff --git a/src/arch/x86_64/idt/mod.rs b/src/arch/x86_64/idt/mod.rs new file mode 100644 index 0000000..cf751c8 --- /dev/null +++ b/src/arch/x86_64/idt/mod.rs @@ -0,0 +1,33 @@ +use self::idt::Idt; +use spin::Once; +use alloc::boxed::Box; + +mod idt; + +/// Alloc IDT at kernel heap, then init and load it. +pub fn init() { + let idt = Box::new({ + use arch::interrupt::{handler::*, consts::*}; + use arch::gdt::DOUBLE_FAULT_IST_INDEX; + + let mut idt = Idt::new(); + idt[T_BRKPT].set_handler_fn(breakpoint); + idt[T_DBLFLT].set_handler_fn(double_fault); + idt[T_GPFLT].set_handler_fn(general_protection_fault); + idt[T_IRQ0 + IRQ_COM1].set_handler_fn(com1); + idt[T_IRQ0 + IRQ_COM2].set_handler_fn(com2); + idt[T_IRQ0 + IRQ_KBD].set_handler_fn(keyboard); + idt[T_IRQ0 + IRQ_TIMER].set_handler_fn(timer); + idt[T_SWITCH_TOU].set_handler_fn(to_user); + idt[T_SWITCH_TOK].set_handler_fn(to_kernel); + idt[T_SYSCALL].set_handler_fn(syscall); + unsafe { + idt[T_PGFLT].set_handler_fn(page_fault) + .set_stack_index(DOUBLE_FAULT_IST_INDEX as u16); + } + idt + }); + let idt = unsafe{ &*Box::into_raw(idt) }; + + idt.load(); +} \ No newline at end of file diff --git a/src/arch/x86_64/interrupt/consts.rs b/src/arch/x86_64/interrupt/consts.rs new file mode 100644 index 0000000..ba9cc0b --- /dev/null +++ b/src/arch/x86_64/interrupt/consts.rs @@ -0,0 +1,31 @@ +pub const T_DIVIDE : u8 = 0 ; // divide error +pub const T_DEBUG : u8 = 1 ; // debug exception +pub const T_NMI : u8 = 2 ; // non-maskable interrupt +pub const T_BRKPT : u8 = 3 ; // breakpoint +pub const T_OFLOW : u8 = 4 ; // overflow +pub const T_BOUND : u8 = 5 ; // bounds check +pub const T_ILLOP : u8 = 6 ; // illegal opcode +pub const T_DEVICE : u8 = 7 ; // device not available +pub const T_DBLFLT : u8 = 8 ; // double fault +pub const T_COPROC : u8 = 9 ; // reserved (not used since 486) +pub const T_TSS : u8 = 10; // invalid task switch segment +pub const T_SEGNP : u8 = 11; // segment not present +pub const T_STACK : u8 = 12; // stack exception +pub const T_GPFLT : u8 = 13; // general protection fault +pub const T_PGFLT : u8 = 14; // page fault +pub const T_RES : u8 = 15; // reserved +pub const T_FPERR : u8 = 16; // floating point error +pub const T_ALIGN : u8 = 17; // aligment check +pub const T_MCHK : u8 = 18; // machine check +pub const T_SIMDERR : u8 = 19; // SIMD floating point error +pub const T_IRQ0 : u8 = 32; // IRQ 0 corresponds to int T_IRQ +pub const IRQ_TIMER : u8 = 0; +pub const IRQ_KBD : u8 = 1; +pub const IRQ_COM2 : u8 = 3; +pub const IRQ_COM1 : u8 = 4; +pub const IRQ_IDE : u8 = 14; +pub const IRQ_ERROR : u8 = 19; +pub const IRQ_SPURIOUS : u8 = 31; +pub const T_SYSCALL : u8 = 0x80; // SYSCALL, ONLY FOR THIS PROJ +pub const T_SWITCH_TOU : u8 = 120; // user/kernel switch +pub const T_SWITCH_TOK : u8 = 121; // user/kernel switch \ No newline at end of file diff --git a/src/arch/x86_64/interrupt/handler.rs b/src/arch/x86_64/interrupt/handler.rs new file mode 100644 index 0000000..c1d8cf0 --- /dev/null +++ b/src/arch/x86_64/interrupt/handler.rs @@ -0,0 +1,85 @@ +#[macro_use] +#[path = "./template.rs"] +mod template; +use self::template::*; + +interrupt_stack!(breakpoint, stack, { + println!("\nEXCEPTION: Breakpoint"); + stack.dump(); +}); + +interrupt_error_p!(double_fault, stack, { + println!("\nEXCEPTION: Double Fault"); + stack.dump(); + loop {} +}); + +interrupt_stack_p!(page_fault, stack, { + use x86_64::registers::control_regs::cr2; + println!("\nEXCEPTION: Page Fault\nAddress: {:#x}", cr2()); + stack.dump(); + loop {} +}); + +interrupt_error_p!(general_protection_fault, stack, { + println!("\nEXCEPTION: General Protection Fault"); + stack.dump(); + loop {} +}); + +#[cfg(feature = "use_apic")] +use arch::driver::apic::ack; +#[cfg(not(feature = "use_apic"))] +use arch::driver::pic::ack; + +use super::consts::*; + +interrupt!(keyboard, { + use arch::driver::keyboard; + println!("\nInterupt: Keyboard"); + let c = keyboard::get(); + println!("Key = '{}' {}", c as u8 as char, c); + ack(IRQ_KBD); + +}); + +interrupt!(com1, { + use arch::driver::serial::COM1; + println!("\nInterupt: COM1"); + COM1.lock().receive(); + ack(IRQ_COM1); +}); + +interrupt!(com2, { + use arch::driver::serial::COM2; + println!("\nInterupt: COM2"); + COM2.lock().receive(); + ack(IRQ_COM2); +}); + +use spin::Mutex; +static TICK: Mutex = Mutex::new(0); + +interrupt!(timer, { + let mut tick = TICK.lock(); + *tick += 1; + let tick = *tick; + if tick % 100 == 0 { + println!("\nInterupt: Timer\ntick = {}", tick); + } + ack(IRQ_TIMER); +}); + +interrupt_stack_p!(to_user, stack, { + println!("\nInterupt: To User"); + stack.iret.cs = 16; +}); + +interrupt_stack_p!(to_kernel, stack, { + println!("\nInterupt: To Kernel"); + stack.iret.cs = 8; +}); + +interrupt_stack_p!(syscall, stack, { + println!("\nInterupt: Syscall"); +}); \ No newline at end of file diff --git a/src/arch/x86_64/interrupt/irq.rs b/src/arch/x86_64/interrupt/irq.rs deleted file mode 100644 index b875805..0000000 --- a/src/arch/x86_64/interrupt/irq.rs +++ /dev/null @@ -1,101 +0,0 @@ -use x86_64::structures::idt::*; - -pub extern "x86-interrupt" fn breakpoint_handler( - stack_frame: &mut ExceptionStackFrame) -{ - println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); -} - -pub extern "x86-interrupt" fn double_fault_handler( - stack_frame: &mut ExceptionStackFrame, _error_code: u64) -{ - println!("\nEXCEPTION: DOUBLE FAULT\n{:#?}\nErrorCode: {:#x}", stack_frame, _error_code); - loop {} -} - -pub extern "x86-interrupt" fn page_fault_handler( - stack_frame: &mut ExceptionStackFrame, error_code: PageFaultErrorCode) -{ - use x86_64::registers::control_regs::cr2; - println!("\nEXCEPTION: PAGE FAULT\n{:#?}\nErrorCode: {:#?}\nAddress: {:#x}", - stack_frame, error_code, cr2()); - loop {} -} - -pub extern "x86-interrupt" fn general_protection_fault_handler( - stack_frame: &mut ExceptionStackFrame, error_code: u64) -{ - println!("\nEXCEPTION: General Protection Fault\n{:#?}\nErrorCode: {:#x}", stack_frame, error_code); -} - -#[cfg(feature = "use_apic")] -use arch::driver::apic::ack; -#[cfg(not(feature = "use_apic"))] -use arch::driver::pic::ack; - -use consts::irq::*; - -pub extern "x86-interrupt" fn keyboard_handler( - stack_frame: &mut ExceptionStackFrame) -{ - use arch::driver::keyboard; - println!("\nInterupt: Keyboard"); - let c = keyboard::get(); - println!("Key = '{}' {}", c as u8 as char, c); - ack(IRQ_KBD); -} - -pub extern "x86-interrupt" fn com1_handler( - stack_frame: &mut ExceptionStackFrame) -{ - use arch::driver::serial::COM1; - println!("\nInterupt: COM1"); - COM1.lock().receive(); - ack(IRQ_COM1); -} - -pub extern "x86-interrupt" fn com2_handler( - stack_frame: &mut ExceptionStackFrame) -{ - use arch::driver::serial::COM2; - println!("\nInterupt: COM2"); - COM2.lock().receive(); - ack(IRQ_COM2); -} - -use spin::Mutex; -static TICK: Mutex = Mutex::new(0); - -pub extern "x86-interrupt" fn timer_handler( - stack_frame: &mut ExceptionStackFrame) -{ - let mut tick = TICK.lock(); - *tick += 1; - let tick = *tick; - if tick % 100 == 0 { - println!("\nInterupt: Timer\ntick = {}", tick); - } - ack(IRQ_TIMER); -} - -pub extern "x86-interrupt" fn to_user_handler( - stack_frame: &mut ExceptionStackFrame) -{ - println!("\nInterupt: To User"); - stack_frame.code_segment = 16; - stack_frame.stack_segment = 32; -} - -pub extern "x86-interrupt" fn to_kernel_handler( - stack_frame: &mut ExceptionStackFrame) -{ - println!("\nInterupt: To Kernel"); - stack_frame.code_segment = 8; - stack_frame.stack_segment = 24; -} - -pub extern "x86-interrupt" fn syscall_handler( - stack_frame: &mut ExceptionStackFrame) -{ - println!("\nInterupt: Syscall"); -} \ No newline at end of file diff --git a/src/arch/x86_64/interrupt/mod.rs b/src/arch/x86_64/interrupt/mod.rs index 9c6931a..7bc24c0 100644 --- a/src/arch/x86_64/interrupt/mod.rs +++ b/src/arch/x86_64/interrupt/mod.rs @@ -1,7 +1,8 @@ use x86_64; use arch::driver::{apic::IOAPIC, pic}; -pub mod irq; +pub mod handler; +pub mod consts; #[inline(always)] pub unsafe fn enable() { diff --git a/src/arch/x86_64/interrupt/template.rs b/src/arch/x86_64/interrupt/template.rs new file mode 100644 index 0000000..f323e7b --- /dev/null +++ b/src/arch/x86_64/interrupt/template.rs @@ -0,0 +1,394 @@ +//! Copy from Redox + +#[allow(dead_code)] +#[repr(packed)] +pub struct ScratchRegisters { + 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, +} + +impl ScratchRegisters { + pub fn dump(&self) { + println!("RAX: {:>016X}", { self.rax }); + println!("RCX: {:>016X}", { self.rcx }); + println!("RDX: {:>016X}", { self.rdx }); + println!("RDI: {:>016X}", { self.rdi }); + println!("RSI: {:>016X}", { self.rsi }); + println!("R8: {:>016X}", { self.r8 }); + println!("R9: {:>016X}", { self.r9 }); + println!("R10: {:>016X}", { self.r10 }); + println!("R11: {:>016X}", { self.r11 }); + } +} + +macro_rules! scratch_push { + () => (asm!( + "push rax + push rcx + push rdx + push rdi + push rsi + push r8 + push r9 + push r10 + push r11" + : : : : "intel", "volatile" + )); +} + +macro_rules! scratch_pop { + () => (asm!( + "pop r11 + pop r10 + pop r9 + pop r8 + pop rsi + pop rdi + pop rdx + pop rcx + pop rax" + : : : : "intel", "volatile" + )); +} + +#[allow(dead_code)] +#[repr(packed)] +pub struct PreservedRegisters { + pub r15: usize, + pub r14: usize, + pub r13: usize, + pub r12: usize, + pub rbp: usize, + pub rbx: usize, +} + +impl PreservedRegisters { + pub fn dump(&self) { + println!("RBX: {:>016X}", { self.rbx }); + println!("RBP: {:>016X}", { self.rbp }); + println!("R12: {:>016X}", { self.r12 }); + println!("R13: {:>016X}", { self.r13 }); + println!("R14: {:>016X}", { self.r14 }); + println!("R15: {:>016X}", { self.r15 }); + } +} + +macro_rules! preserved_push { + () => (asm!( + "push rbx + push rbp + push r12 + push r13 + push r14 + push r15" + : : : : "intel", "volatile" + )); +} + +macro_rules! preserved_pop { + () => (asm!( + "pop r15 + pop r14 + pop r13 + pop r12 + pop rbp + pop rbx" + : : : : "intel", "volatile" + )); +} + +macro_rules! fs_push { + () => (asm!( + "push fs + mov rax, 0x18 + mov fs, ax" + : : : : "intel", "volatile" + )); +} + +macro_rules! fs_pop { + () => (asm!( + "pop fs" + : : : : "intel", "volatile" + )); +} + +#[allow(dead_code)] +#[repr(packed)] +pub struct IretRegisters { + pub rip: usize, + pub cs: usize, + pub rflags: usize, +} + +impl IretRegisters { + pub fn dump(&self) { + println!("RFLAG: {:>016X}", { self.rflags }); + println!("CS: {:>016X}", { self.cs }); + println!("RIP: {:>016X}", { self.rip }); + } +} + +macro_rules! iret { + () => (asm!( + "iretq" + : : : : "intel", "volatile" + )); +} + +/// Create an interrupt function that can safely run rust code +#[macro_export] +macro_rules! interrupt { + ($name:ident, $func:block) => { + #[naked] + pub unsafe extern fn $name () { + #[inline(never)] + unsafe fn inner() { + $func + } + + // Push scratch registers + scratch_push!(); + fs_push!(); + + // Map kernel +// $crate::arch::x86_64::pti::map(); + + // Call inner rust function + inner(); + + // Unmap kernel +// $crate::arch::x86_64::pti::unmap(); + + // Pop scratch registers and return + fs_pop!(); + scratch_pop!(); + iret!(); + } + }; +} + +#[allow(dead_code)] +#[repr(packed)] +pub struct InterruptStack { + pub fs: usize, + pub scratch: ScratchRegisters, + pub iret: IretRegisters, +} + +impl InterruptStack { + pub fn dump(&self) { + self.iret.dump(); + self.scratch.dump(); + println!("FS: {:>016X}", { self.fs }); + } +} + +#[macro_export] +macro_rules! interrupt_stack { + ($name:ident, $stack: ident, $func:block) => { + #[naked] + pub unsafe extern fn $name () { + #[inline(never)] + unsafe fn inner($stack: &mut InterruptStack) { + $func + } + + // Push scratch registers + scratch_push!(); + fs_push!(); + + // Get reference to stack variables + let rsp: usize; + asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); + + // Map kernel +// $crate::arch::x86_64::pti::map(); + + // Call inner rust function + inner(&mut *(rsp as *mut InterruptStack)); + + // Unmap kernel +// $crate::arch::x86_64::pti::unmap(); + + // Pop scratch registers and return + fs_pop!(); + scratch_pop!(); + iret!(); + } + }; +} + +#[allow(dead_code)] +#[repr(packed)] +pub struct InterruptErrorStack { + pub fs: usize, + pub scratch: ScratchRegisters, + pub code: usize, + pub iret: IretRegisters, +} + +impl InterruptErrorStack { + pub fn dump(&self) { + self.iret.dump(); + println!("CODE: {:>016X}", { self.code }); + self.scratch.dump(); + println!("FS: {:>016X}", { self.fs }); + } +} + +#[macro_export] +macro_rules! interrupt_error { + ($name:ident, $stack:ident, $func:block) => { + #[naked] + pub unsafe extern fn $name () { + #[inline(never)] + unsafe fn inner($stack: &InterruptErrorStack) { + $func + } + + // Push scratch registers + scratch_push!(); + fs_push!(); + + // Get reference to stack variables + let rsp: usize; + asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); + + // Map kernel +// $crate::arch::x86_64::pti::map(); + + // Call inner rust function + inner(&*(rsp as *const InterruptErrorStack)); + + // Unmap kernel +// $crate::arch::x86_64::pti::unmap(); + + // Pop scratch registers, error code, and return + fs_pop!(); + scratch_pop!(); + asm!("add rsp, 8" : : : : "intel", "volatile"); + iret!(); + } + }; +} + +#[allow(dead_code)] +#[repr(packed)] +pub struct InterruptStackP { + pub fs: usize, + pub preserved: PreservedRegisters, + pub scratch: ScratchRegisters, + pub iret: IretRegisters, +} + +impl InterruptStackP { + pub fn dump(&self) { + self.iret.dump(); + self.scratch.dump(); + self.preserved.dump(); + println!("FS: {:>016X}", { self.fs }); + } +} + +#[macro_export] +macro_rules! interrupt_stack_p { + ($name:ident, $stack: ident, $func:block) => { + #[naked] + pub unsafe extern fn $name () { + #[inline(never)] + unsafe fn inner($stack: &mut InterruptStackP) { + $func + } + + // Push scratch registers + scratch_push!(); + preserved_push!(); + fs_push!(); + + // Get reference to stack variables + let rsp: usize; + asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); + + // Map kernel +// $crate::arch::x86_64::pti::map(); + + // Call inner rust function + inner(&mut *(rsp as *mut InterruptStackP)); + + // Unmap kernel +// $crate::arch::x86_64::pti::unmap(); + + // Pop scratch registers and return + fs_pop!(); + preserved_pop!(); + scratch_pop!(); + iret!(); + } + }; +} + +#[allow(dead_code)] +#[repr(packed)] +pub struct InterruptErrorStackP { + pub fs: usize, + pub preserved: PreservedRegisters, + pub scratch: ScratchRegisters, + pub code: usize, + pub iret: IretRegisters, +} + +impl InterruptErrorStackP { + pub fn dump(&self) { + self.iret.dump(); + println!("CODE: {:>016X}", { self.code }); + self.scratch.dump(); + self.preserved.dump(); + println!("FS: {:>016X}", { self.fs }); + } +} + +#[macro_export] +macro_rules! interrupt_error_p { + ($name:ident, $stack:ident, $func:block) => { + #[naked] + pub unsafe extern fn $name () { + #[inline(never)] + unsafe fn inner($stack: &InterruptErrorStackP) { + $func + } + + // Push scratch registers + scratch_push!(); + preserved_push!(); + fs_push!(); + + // Get reference to stack variables + let rsp: usize; + asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); + + // Map kernel +// $crate::arch::x86_64::pti::map(); + + // Call inner rust function + inner(&*(rsp as *const InterruptErrorStackP)); + + // Unmap kernel +// $crate::arch::x86_64::pti::unmap(); + + // Pop scratch registers, error code, and return + fs_pop!(); + preserved_pop!(); + scratch_pop!(); + asm!("add rsp, 8" : : : : "intel", "volatile"); + iret!(); + } + }; +} diff --git a/src/consts.rs b/src/consts.rs index 19f5cb3..6281cd4 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -94,17 +94,3 @@ pub const MAX_CPU_NUM: usize = 8; /// Offset for usage in other temporary pages pub const USER_TMP_MISC_OFFSET: usize = USER_TMP_TLS_OFFSET + PML4_SIZE; pub const USER_TMP_MISC_PML4: usize = (USER_TMP_MISC_OFFSET & PML4_MASK)/PML4_SIZE; - -pub mod irq { - pub const T_IRQ0 : u8 = 32; // IRQ 0 corresponds to int T_IRQ - pub const IRQ_TIMER : u8 = 0; - pub const IRQ_KBD : u8 = 1; - pub const IRQ_COM2 : u8 = 3; - pub const IRQ_COM1 : u8 = 4; - pub const IRQ_IDE : u8 = 14; - pub const IRQ_ERROR : u8 = 19; - pub const IRQ_SPURIOUS : u8 = 31; - pub const T_SYSCALL : u8 = 0x80; // SYSCALL, ONLY FOR THIS PROJ - pub const T_SWITCH_TOU : u8 = 120; // user/kernel switch - pub const T_SWITCH_TOK : u8 = 121; // user/kernel switch -} diff --git a/src/io/mod.rs b/src/io/mod.rs index b4a037e..b1b19af 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -30,11 +30,11 @@ use arch::driver::vga::Color; fn print_in_color(args: fmt::Arguments, color: Color) { use core::fmt::Write; use arch::driver::vga::*; - { - let mut writer = vga_writer::VGA_WRITER.lock(); - writer.set_color(color); - writer.write_fmt(args).unwrap(); - } +// { +// let mut writer = vga_writer::VGA_WRITER.lock(); +// writer.set_color(color); +// writer.write_fmt(args).unwrap(); +// } COM1.lock().write_fmt(args).unwrap(); } diff --git a/src/lib.rs b/src/lib.rs index fc4f920..c8801c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ #![feature(abi_x86_interrupt)] #![feature(iterator_step_by)] #![feature(unboxed_closures)] +#![feature(naked_functions)] #![feature(asm)] #![no_std]