diff --git a/Makefile b/Makefile index e8ca5629..8ed10e51 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ # except according to those terms. arch ?= x86_64 -target ?= $(arch)-unknown-linux-gnu +target ?= $(arch)-blog_os kernel := build/kernel-$(arch).bin iso := build/os-$(arch).iso @@ -49,7 +49,7 @@ $(kernel): cargo $(rust_os) $(assembly_object_files) $(linker_script) @ld -n --gc-sections -T $(linker_script) -o $(kernel) $(assembly_object_files) $(rust_os) cargo: - @cargo build --target $(target) + @xargo build --target $(target) # compile assembly files build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm diff --git a/src/interrupts/mod.rs b/src/interrupts/mod.rs index 76d407f8..d3d441d2 100644 --- a/src/interrupts/mod.rs +++ b/src/interrupts/mod.rs @@ -1,16 +1,50 @@ mod idt; +macro_rules! save_scratch_registers { + () => { + asm!("push rax + push rcx + push rdx + push rsi + push rdi + push r8 + push r9 + push r10 + push r11 + " :::: "intel", "volatile"); + } +} + +macro_rules! restore_scratch_registers { + () => { + asm!("pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + pop rdx + pop rcx + pop rax + " :::: "intel", "volatile"); + } +} + macro_rules! handler { ($name: ident) => {{ #[naked] extern "C" fn wrapper() -> ! { unsafe { + save_scratch_registers!(); asm!("mov rdi, rsp - sub rsp, 8 // align the stack pointer + add rdi, 9*8 // calculate exception stack frame pointer call $0" :: "i"($name as extern "C" fn( - *const ExceptionStackFrame) -> !) + *const ExceptionStackFrame)) : "rdi" : "intel"); + + restore_scratch_registers!(); + asm!("iretq" :::: "intel", "volatile"); ::core::intrinsics::unreachable(); } } @@ -23,13 +57,19 @@ macro_rules! handler_with_error_code { #[naked] extern "C" fn wrapper() -> ! { unsafe { - asm!("pop rsi // pop error code into rsi + save_scratch_registers!(); + asm!("mov rsi, [rsp + 9*8] // load error code into rsi mov rdi, rsp + add rdi, 10*8 // calculate exception stack frame pointer sub rsp, 8 // align the stack pointer - call $0" - :: "i"($name as extern "C" fn( - *const ExceptionStackFrame, u64) -> !) + call $0 + add rsp, 8 // undo stack pointer alignment + " :: "i"($name as extern "C" fn( + *const ExceptionStackFrame, u64)) : "rdi","rsi" : "intel"); + restore_scratch_registers!(); + asm!("add rsp, 8 // pop error code + iretq" :::: "intel", "volatile"); ::core::intrinsics::unreachable(); } } @@ -42,6 +82,7 @@ lazy_static! { let mut idt = idt::Idt::new(); idt.set_handler(0, handler!(divide_by_zero_handler)); + idt.set_handler(3, handler!(breakpoint_handler)); idt.set_handler(6, handler!(invalid_opcode_handler)); idt.set_handler(14, handler_with_error_code!(page_fault_handler)); @@ -65,14 +106,22 @@ struct ExceptionStackFrame { use vga_buffer::print_error; -extern "C" fn divide_by_zero_handler(stack_frame: *const ExceptionStackFrame) -> ! { +extern "C" fn divide_by_zero_handler(stack_frame: *const ExceptionStackFrame) { unsafe { print_error(format_args!("EXCEPTION: DIVIDE BY ZERO\n{:#?}", *stack_frame)); } loop {} } -extern "C" fn invalid_opcode_handler(stack_frame: *const ExceptionStackFrame) -> ! { +extern "C" fn breakpoint_handler(stack_frame: *const ExceptionStackFrame) { + unsafe { + print_error(format_args!("EXCEPTION: BREAKPOINT at {:#x}\n{:#?}", + (*stack_frame).instruction_pointer, + *stack_frame)); + } +} + +extern "C" fn invalid_opcode_handler(stack_frame: *const ExceptionStackFrame) { unsafe { print_error(format_args!("EXCEPTION: INVALID OPCODE at {:#x}\n{:#?}", (*stack_frame).instruction_pointer, @@ -91,7 +140,7 @@ bitflags! { } } -extern "C" fn page_fault_handler(stack_frame: *const ExceptionStackFrame, error_code: u64) -> ! { +extern "C" fn page_fault_handler(stack_frame: *const ExceptionStackFrame, error_code: u64) { use x86::controlregs; unsafe { print_error(format_args!("EXCEPTION: PAGE FAULT while accessing {:#x}\nerror code: \ diff --git a/src/lib.rs b/src/lib.rs index a58f091e..213dcb39 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ extern crate spin; extern crate multiboot2; #[macro_use] extern crate bitflags; +#[macro_use] extern crate x86; #[macro_use] extern crate once; @@ -54,9 +55,8 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) { // initialize our IDT interrupts::init(); - // provoke a page fault - unsafe { *(0xdeadbeaf as *mut u64) = 42 }; - + // trigger a breakpoint exception + unsafe { int!(3) }; println!("It did not crash!"); loop {} diff --git a/x86_64-blog_os.json b/x86_64-blog_os.json new file mode 100644 index 00000000..bf9725b2 --- /dev/null +++ b/x86_64-blog_os.json @@ -0,0 +1,10 @@ +{ + "llvm-target": "x86_64-unknown-linux-gnu", + "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", + "target-endian": "little", + "target-pointer-width": "64", + "arch": "x86_64", + "os": "none", + "features": "-mmx,-sse,+soft-float", + "disable-redzone": true +}