interlude
This commit is contained in:
parent
83d1ce9b98
commit
f1570c06b1
|
|
@ -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.
|
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.
|
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
|
* Getting the Framebuffer
|
||||||
|
|
|
||||||
1
kernel/.dir-locals.el
Normal file
1
kernel/.dir-locals.el
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
((nil . ((eglot-workspace-configuration . (:rust-analyzer (:cargo (:extraEnv ((CARGO_UNSTABLE_JSON_TARGET_SPEC . "true")))))))))
|
||||||
|
|
@ -3,4 +3,14 @@ name = "kernel"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "kernel"
|
||||||
|
path = "src/main.rs"
|
||||||
|
test = false
|
||||||
|
bench = false
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
test = false
|
||||||
|
bench = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
|
||||||
15
kernel/src/lib.rs
Normal file
15
kernel/src/lib.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
pub mod x86_64;
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
pub unsafe fn volatile_copy<T: Sized>(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,10 +3,10 @@
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
kernel::x86_64::halt_loop()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
fn _start() -> ! {
|
fn _start() -> ! {
|
||||||
loop {}
|
kernel::x86_64::halt_loop()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
kernel/src/x86_64.rs
Normal file
14
kernel/src/x86_64.rs
Normal file
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue