diff --git a/blog/intro.org b/blog/intro.org index bd0dfde..a9c8f2c 100644 --- a/blog/intro.org +++ b/blog/intro.org @@ -345,4 +345,57 @@ If we now run =cargo run=, cargo will build our kernel and automatically start q Unfortunately, since our kernel currently does nothing, this is hard to discern. Therefore, our next goal will be to get some output from our kernel, which we will do by making use of limine’s framebuffer. +* Interlude: Welcome to kernel-land + If you have an aggressive LSP client, or you ran the =cargo clippy= command on our current crate, you may have noticed a warning telling you that an empty loop wastes CPU cycles. + This is true, and is in fact the very reason why we use it! + However, now that we have arrived in kernel-land, we can actually do a little better: the =hlt= instruction which, according to the Intel manual, stops execution of a logical processor until further notice. + Further notice here may be an interrupt, which means we will want to run the =hlt= instruction in a loop. + =hlt= is one of a handful of privileged instructions that when attempted to be executed in user-space will cause a general protection fault and terminate the program. + + We start by creating a =lib.rs= file in the =src= directory, which will contain our kernel library code. + Just line in our =main.rs=, we will need to tell the compiler that we want to opt out of the standard library: + #+begin_src rust +#![no_std] + #+end_src + + Since the =hlt= instruction is specific to the x86 architecture and not available in the =core::arch::x86_64= module of the core library, we will need to write our own wrapper around some inline assembly to execute the instruction. + We create a new =x86_64= module in our new library to house this and future x86-64 specific code: + + #+begin_src rust +#![no_std] + +pbu mod x86_64; + #+end_src + + #+begin_src rust +#![cfg(target_arch = "x86_64")] + +#[inline] +pub fn hlt() { + unsafe { + core::arch::asm!("hlt", options(nomem, nostack, preserves_flags)); + } +} + +pub fn halt_loop() -> ! { + loop { + hlt(); + } +} + #+end_src +For a detailed explanation of the =asm!= macro, see the [[https://doc.rust-lang.org/nightly/reference/inline-assembly.html][Rust reference]]. + +In our =main.rs=, we can now replace the infinite loop with a call to our new =halt_loop= function: + #+begin_src rust +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + kernel::x86_64::halt_loop() +} + +#[unsafe(no_mangle)] +fn _start() -> ! { + kernel::x86_64::halt_loop() +} +#+end_src + * Getting the Framebuffer diff --git a/kernel/.dir-locals.el b/kernel/.dir-locals.el new file mode 100644 index 0000000..8fa8dd0 --- /dev/null +++ b/kernel/.dir-locals.el @@ -0,0 +1 @@ +((nil . ((eglot-workspace-configuration . (:rust-analyzer (:cargo (:extraEnv ((CARGO_UNSTABLE_JSON_TARGET_SPEC . "true"))))))))) diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index c9211be..8b30eaa 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -3,4 +3,14 @@ name = "kernel" version = "0.1.0" edition = "2024" +[[bin]] +name = "kernel" +path = "src/main.rs" +test = false +bench = false + +[lib] +test = false +bench = false + [dependencies] diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs new file mode 100644 index 0000000..7206481 --- /dev/null +++ b/kernel/src/lib.rs @@ -0,0 +1,15 @@ +#![no_std] + +pub mod x86_64; + +/// # Safety +pub unsafe fn volatile_copy(src: *const T, dst: *mut T, count: usize) { + unsafe { + for i in 0..count { + let src_ptr = src.add(i); + let dst_ptr = dst.add(i); + let val = src_ptr.read_volatile(); + dst_ptr.write_volatile(val); + } + } +} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index a9e03f1..734bd41 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -3,10 +3,10 @@ #[panic_handler] fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} + kernel::x86_64::halt_loop() } #[unsafe(no_mangle)] fn _start() -> ! { - loop {} + kernel::x86_64::halt_loop() } diff --git a/kernel/src/x86_64.rs b/kernel/src/x86_64.rs new file mode 100644 index 0000000..319fc18 --- /dev/null +++ b/kernel/src/x86_64.rs @@ -0,0 +1,14 @@ +#![cfg(target_arch = "x86_64")] + +#[inline] +pub fn hlt() { + unsafe { + core::arch::asm!("hlt", options(nomem, nostack, preserves_flags)); + } +} + +pub fn halt_loop() -> ! { + loop { + hlt(); + } +}