diff --git a/src/interrupts.rs b/src/interrupts.rs index 565a2c7..2caf624 100644 --- a/src/interrupts.rs +++ b/src/interrupts.rs @@ -4,6 +4,7 @@ use lazy_static::lazy_static; use crate::gdt; use pic8259::ChainedPics; use spin; +use crate::print; lazy_static! { static ref IDT: InterruptDescriptorTable = { @@ -11,8 +12,10 @@ lazy_static! { idt.breakpoint.set_handler_fn(breakpoint_handler); unsafe { idt.double_fault.set_handler_fn(double_fault_handler) - .set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX); // new + .set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX); } + idt[InterruptIndex::Timer.as_usize()] + .set_handler_fn(timer_interrupt_handler); idt }; @@ -45,3 +48,30 @@ pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8; pub static PICS: spin::Mutex = spin::Mutex::new(unsafe {ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) }); + +#[derive(Debug, Clone, Copy)] +#[repr(u8)] +pub enum InterruptIndex { + Timer = PIC_1_OFFSET, +} + +impl InterruptIndex { + fn as_u8(self) -> u8 { + self as u8 + } + + fn as_usize(self) -> usize { + usize::from(self.as_u8()) + } +} + +extern "x86-interrupt" fn timer_interrupt_handler( + _stack_frame: InterruptStackFrame) +{ + print!("."); + + unsafe { + PICS.lock() + .notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 29a1583..57ed7af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,7 +48,7 @@ pub fn test_panic_handler(info: &PanicInfo) -> ! { serial_println!("[failed]\n"); serial_println!("Error: {}\n", info); exit_qemu(QemuExitCode::Failed); - loop {} + hlt_loop(); } /// Entry point for `cargo test` @@ -57,7 +57,7 @@ pub fn test_panic_handler(info: &PanicInfo) -> ! { pub extern "C" fn _start() -> ! { init(); test_main(); - loop {} + hlt_loop(); } #[cfg(test)] @@ -80,4 +80,10 @@ pub fn exit_qemu(exit_code: QemuExitCode) { let mut port = Port::new(0xf4); port.write(exit_code as u32); } +} + +pub fn hlt_loop() -> ! { + loop { + x86_64::instructions::hlt(); + } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 25a985b..0e3538e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,19 +10,13 @@ use donald::println; #[no_mangle] pub extern "C" fn _start() -> ! { println!("Hello World{}", "!"); - println!("It did not crash!"); donald::init(); - fn stack_overflow() { - stack_overflow(); - } - - stack_overflow(); - #[cfg(test)] test_main(); - loop {} + println!("It did not crash!"); + donald::hlt_loop(); } /// This function is called on panic. @@ -30,7 +24,7 @@ pub extern "C" fn _start() -> ! { #[panic_handler] fn panic(info: &PanicInfo) -> ! { println!("{}", info); - loop {} + donald::hlt_loop(); } #[cfg(test)] diff --git a/src/serial.rs b/src/serial.rs index 5c575ac..c0bf5cd 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -14,7 +14,14 @@ lazy_static! { #[doc(hidden)] pub fn _print(args: ::core::fmt::Arguments) { use core::fmt::Write; - SERIAL1.lock().write_fmt(args).expect("Printing to serial failed"); + use x86_64::instructions::interrupts; + + interrupts::without_interrupts(|| { + SERIAL1 + .lock() + .write_fmt(args) + .expect("Printing to serial failed"); + }); } /// Prints to the host through the serial interface. diff --git a/src/vga_buffer.rs b/src/vga_buffer.rs index 256129a..ebca327 100644 --- a/src/vga_buffer.rs +++ b/src/vga_buffer.rs @@ -140,7 +140,11 @@ macro_rules! println { #[doc(hidden)] pub fn _print(args: fmt::Arguments) { use core::fmt::Write; - WRITER.lock().write_fmt(args).unwrap(); + use x86_64::instructions::interrupts; + + interrupts::without_interrupts(|| { + WRITER.lock().write_fmt(args).unwrap(); + }); } #[test_case] @@ -157,10 +161,16 @@ fn test_println_many() { #[test_case] fn test_println_output() { + use core::fmt::Write; + use x86_64::instructions::interrupts; + let s = "Some test string that fits on a single line"; - println!("{}", s); - for (i, c) in s.chars().enumerate() { - let screen_char = WRITER.lock().buffer.chars[BUFFER_HEIGHT - 2][i].read(); - assert_eq!(char::from(screen_char.ascii_character), c); - } + interrupts::without_interrupts(|| { + let mut writer = WRITER.lock(); + writeln!(writer, "\n{}", s).expect("writeln failed"); + for (i, c) in s.chars().enumerate() { + let screen_char = writer.buffer.chars[BUFFER_HEIGHT - 2][i].read(); + assert_eq!(char::from(screen_char.ascii_character), c); + } + }); } \ No newline at end of file