diff --git a/Cargo.lock b/Cargo.lock index 5e2f52815..6f513372a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,7 +13,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -23,10 +23,11 @@ dependencies = [ "array-init 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "bootloader_precompiled 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pic8259_simple 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "volatile 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "x86_64 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "x86_64 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -37,13 +38,18 @@ dependencies = [ "os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cpuio" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "lazy_static" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -56,6 +62,14 @@ name = "os_bootinfo" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "pic8259_simple" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cpuio 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "spin" version = "0.4.9" @@ -66,8 +80,8 @@ name = "uart_16550" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "x86_64 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "x86_64 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -82,7 +96,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "version_check" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -92,11 +106,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "x86_64" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ux 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -105,15 +119,17 @@ dependencies = [ [metadata] "checksum array-init 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c3cc8456d0ae81a8c76f59e384683a601548c38949a4bfcb65dd31ded5c75ff3" "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" -"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum bootloader_precompiled 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "245362094f3e7e5c801e71646a672c1fa895c033ca47473278e3d99af6300be6" +"checksum cpuio 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22b8e308ccfc5acf3b82f79c0eac444cf6114cb2ac67a230ca6c177210068daa" "checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "66481dbeb5e773e7bd85b63cd6042c30786f834338288c5ec4f3742673db360a" +"checksum pic8259_simple 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc64b2fd10828da8521b6cdabe0679385d7d2a3a6d4c336b819d1fa31ba35c72" "checksum spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "37b5646825922b96b5d7d676b5bb3458a54498e96ed7b0ce09dc43a07038fea4" "checksum uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "269f953d8de3226f7c065c589c7b4a3e83d10a419c7c3b5e2e0f197e6acc966e" "checksum usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f70329e2cbe45d6c97a5112daad40c34cd9a4e18edb5a2a18fefeb584d8d25e5" "checksum ux 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53d8df5dd8d07fedccd202de1887d94481fadaea3db70479f459e8163a1fab41" -"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum volatile 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "54d4343a2df2d65144a874f95950754ee7b7e8594f6027aae8c7d0f4858a3fe8" -"checksum x86_64 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "466c2002e38edde7ebbaae6656793d4f71596634971c7e8cbf7afa4827968445" +"checksum x86_64 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "a7e95a2813e20d24546c2b29ecc6df55cfde30c983df69eeece0b179ca9d68ac" diff --git a/Cargo.toml b/Cargo.toml index 76e47e7b3..d99803cd2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ spin = "0.4.6" volatile = "0.2.3" uart_16550 = "0.1.0" x86_64 = "0.2.8" +pic8259_simple = "0.1.1" [dependencies.lazy_static] version = "1.0" diff --git a/blog/content/second-edition/posts/08-hardware-interrupts/index.md b/blog/content/second-edition/posts/08-hardware-interrupts/index.md index 690079086..08d4f1a7a 100644 --- a/blog/content/second-edition/posts/08-hardware-interrupts/index.md +++ b/blog/content/second-edition/posts/08-hardware-interrupts/index.md @@ -102,7 +102,7 @@ pub mod interrupts; // in src/interrupts.rs -use pic8259::ChainedPics; +use pic8259_simple::ChainedPics; use spin; pub const PIC_1_OFFSET: u8 = 32; @@ -165,7 +165,7 @@ pub extern "C" fn _start() -> ! { The `interrupts::enable` function of the `x86_64` crate executes the special `sti` instruction (“set interrupts”) to enable external interrupts. When we try `bootimage run` now, we see that a double fault occurs: -TODO screenshot +![QEMU printing `EXCEPTION: DOUBLE FAULT` because of hardware timer](qemu-hardware-timer-double-fault.png) The reason for this double fault is that the hardware timer (the [Intel 8253] to be exact) is enabled by default, so we start receiving timer interrupts as soon as we enable interrupts. Since we didn't define a handler function for it yet, our double fault handler is invoked. @@ -208,7 +208,7 @@ We introduce a `TIMER_INTERRUPT_ID` constant to keep things organized. Our `time In our timer interrupt handler, we print a dot to the screen. As the timer interrupt happens periodically, we would expect to see a dot appearing on each timer tick. However, when we run it we see that only a single dot is printed: -TODO screenshot +![QEMU printing only a single dot for hardware timer](qemu-single-dot-printed.png) ### End of Interrupt @@ -233,7 +233,7 @@ We need to be careful to use the correct interrupt vector number, otherwise we c When we now execute `bootimage run` we see dots periodically appearing on the screen: -TODO screenshot gif +![QEMU printing consequtive dots showing the hardware timer](qemu-hardware-timer-dots.gif) ### Configuring The Timer diff --git a/blog/content/second-edition/posts/08-hardware-interrupts/qemu-hardware-timer-dots.gif b/blog/content/second-edition/posts/08-hardware-interrupts/qemu-hardware-timer-dots.gif new file mode 100644 index 000000000..8ea34202a Binary files /dev/null and b/blog/content/second-edition/posts/08-hardware-interrupts/qemu-hardware-timer-dots.gif differ diff --git a/blog/content/second-edition/posts/08-hardware-interrupts/qemu-hardware-timer-double-fault.png b/blog/content/second-edition/posts/08-hardware-interrupts/qemu-hardware-timer-double-fault.png new file mode 100644 index 000000000..7d02b13ad Binary files /dev/null and b/blog/content/second-edition/posts/08-hardware-interrupts/qemu-hardware-timer-double-fault.png differ diff --git a/blog/content/second-edition/posts/08-hardware-interrupts/qemu-single-dot-printed.png b/blog/content/second-edition/posts/08-hardware-interrupts/qemu-single-dot-printed.png new file mode 100644 index 000000000..cfdc06cc9 Binary files /dev/null and b/blog/content/second-edition/posts/08-hardware-interrupts/qemu-single-dot-printed.png differ diff --git a/src/interrupts.rs b/src/interrupts.rs new file mode 100644 index 000000000..810219df9 --- /dev/null +++ b/src/interrupts.rs @@ -0,0 +1,10 @@ +use pic8259_simple::ChainedPics; +use spin; + +pub const PIC_1_OFFSET: u8 = 32; +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) }); + +pub const TIMER_INTERRUPT_ID: u8 = PIC_1_OFFSET; diff --git a/src/lib.rs b/src/lib.rs index 86ef1bc1b..351a79ca0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ extern crate spin; extern crate volatile; #[macro_use] extern crate lazy_static; +extern crate pic8259_simple; extern crate uart_16550; extern crate x86_64; @@ -14,6 +15,7 @@ extern crate array_init; extern crate std; pub mod gdt; +pub mod interrupts; pub mod serial; pub mod vga_buffer; diff --git a/src/main.rs b/src/main.rs index bb7e1a924..f2b5756e5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ extern crate x86_64; extern crate lazy_static; use core::panic::PanicInfo; +use blog_os::interrupts::{self, PICS}; /// This function is the entry point, since the linker looks for a function /// named `_start` by default. @@ -20,13 +21,8 @@ pub extern "C" fn _start() -> ! { blog_os::gdt::init(); init_idt(); - - fn stack_overflow() { - stack_overflow(); // for each recursion, the return address is pushed - } - - // trigger a stack overflow - stack_overflow(); + unsafe { PICS.lock().initialize() }; + x86_64::instructions::interrupts::enable(); println!("It did not crash!"); loop {} @@ -52,6 +48,9 @@ lazy_static! { .set_stack_index(blog_os::gdt::DOUBLE_FAULT_IST_INDEX); } + let timer_interrupt_id = usize::from(interrupts::TIMER_INTERRUPT_ID); + idt[timer_interrupt_id].set_handler_fn(timer_interrupt_handler); + idt }; } @@ -71,3 +70,11 @@ extern "x86-interrupt" fn double_fault_handler( println!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); loop {} } + +extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: &mut ExceptionStackFrame) { + print!("."); + unsafe { + PICS.lock() + .notify_end_of_interrupt(interrupts::TIMER_INTERRUPT_ID) + } +}