diff --git a/Cargo.toml b/Cargo.toml index 6526084..4e8cef2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,15 +3,19 @@ name = "kernel" version = "0.1.0" [lib] +name = "kernel" path = "kernel/lib.rs" crate-type = ["staticlib"] -[target.'cfg(target_arch = "x86_64")'.dependencies] -arch = { path = "arch/x86_64" } - [dependencies] bitflags = "*" +[dev-dependencies] +arch_test = { path = "arch/test" } + +[target.'cfg(target_arch = "x86_64")'.dependencies] +arch_x86_64 = { path = "arch/x86_64" } + [profile.dev] panic = "abort" diff --git a/Makefile b/Makefile index e25521b..284722f 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ qemu: build/harddrive.bin FORCE: build/libkernel.a: FORCE - cargo rustc -- -C lto -o $@ + cargo rustc -- --crate-type staticlib -o $@ #--target $(ARCH)-unknown-none.json build/kernel.bin: build/libkernel.a diff --git a/arch/test/Cargo.toml b/arch/test/Cargo.toml new file mode 100644 index 0000000..1900c7d --- /dev/null +++ b/arch/test/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "arch_test" +version = "0.1.0" diff --git a/arch/test/src/interrupt.rs b/arch/test/src/interrupt.rs new file mode 100644 index 0000000..b167232 --- /dev/null +++ b/arch/test/src/interrupt.rs @@ -0,0 +1,24 @@ +//! Interrupt instructions + +static mut INTERRUPTS_ENABLED: bool = false; + +/// Clear interrupts +#[inline(always)] +pub unsafe fn clear_interrupts() { + println!("CLEAR INTERRUPTS"); + INTERRUPTS_ENABLED = false; +} + +/// Set interrupts +#[inline(always)] +pub unsafe fn set_interrupts() { + println!("SET INTERRUPTS"); + INTERRUPTS_ENABLED = true; +} + +/// Halt instruction +#[inline(always)] +pub unsafe fn halt() { + assert!(INTERRUPTS_ENABLED); + ::std::thread::yield_now(); +} diff --git a/arch/test/src/lib.rs b/arch/test/src/lib.rs new file mode 100644 index 0000000..f9d3660 --- /dev/null +++ b/arch/test/src/lib.rs @@ -0,0 +1,40 @@ +//! Architecture support for testing + +pub use std::io; + +/// Print to console +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ({ + use $crate::io::Write; + let _ = write!($crate::io::stdout(), $($arg)*); + }); +} + +/// Print with new line to console +#[macro_export] +macro_rules! println { + ($fmt:expr) => (print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); +} + +/// Create an interrupt function that can safely run rust code +#[macro_export] +macro_rules! interrupt { + ($name:ident, $func:block) => { + pub unsafe extern fn $name () { + unsafe fn inner() { + $func + } + + // Call inner rust function + inner(); + } + }; +} + +/// Interrupt instructions +pub mod interrupt; + +/// Initialization and main function +pub mod main; diff --git a/arch/test/src/main.rs b/arch/test/src/main.rs new file mode 100644 index 0000000..3f93ffb --- /dev/null +++ b/arch/test/src/main.rs @@ -0,0 +1,11 @@ +/// This function is where the kernel sets up IRQ handlers +/// It is increcibly unsafe, and should be minimal in nature + +extern { + fn kmain() -> !; +} + +#[no_mangle] +pub unsafe extern fn kstart() -> ! { + kmain(); +} diff --git a/arch/x86_64/Cargo.toml b/arch/x86_64/Cargo.toml index 1992ebe..aa3d43b 100644 --- a/arch/x86_64/Cargo.toml +++ b/arch/x86_64/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "arch" +name = "arch_x86_64" version = "0.1.0" [dependencies] diff --git a/kernel/lib.rs b/kernel/lib.rs index d9353c7..5927692 100644 --- a/kernel/lib.rs +++ b/kernel/lib.rs @@ -72,13 +72,23 @@ extern crate bitflags; use arch::interrupt::{set_interrupts, halt}; -/// Architecture specific items +/// Architecture specific items (test) +#[cfg(test)] #[macro_use] -extern crate arch; +extern crate arch_test as arch; + +/// Architecture specific items (x86_64) +#[cfg(all(not(test), target_arch = "x86_64"))] +#[macro_use] +extern crate arch_x86_64 as arch; /// Intrinsics for panic handling pub mod panic; +/// Tests +#[cfg(test)] +pub mod tests; + #[no_mangle] pub extern fn kmain() { println!("TEST"); diff --git a/kernel/tests/mod.rs b/kernel/tests/mod.rs new file mode 100644 index 0000000..42896c0 --- /dev/null +++ b/kernel/tests/mod.rs @@ -0,0 +1,9 @@ +use arch::interrupt::{set_interrupts, halt}; + +#[test] +fn halt_with_interrupts() { + unsafe { + set_interrupts(); + halt(); + } +}