Compare commits

...

3 Commits

11 changed files with 132 additions and 12 deletions

37
moon/Cargo.lock generated
View File

@ -8,6 +8,18 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bit_field"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "lock_api"
version = "0.4.9"
@ -23,8 +35,15 @@ name = "moon"
version = "0.1.0"
dependencies = [
"spin",
"x86_64",
]
[[package]]
name = "rustversion"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
[[package]]
name = "scopeguard"
version = "1.1.0"
@ -39,3 +58,21 @@ checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09"
dependencies = [
"lock_api",
]
[[package]]
name = "volatile"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3ca98349dda8a60ae74e04fd90c7fb4d6a4fbe01e6d3be095478aa0b76f6c0c"
[[package]]
name = "x86_64"
version = "0.14.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "100555a863c0092238c2e0e814c1096c1e5cf066a309c696a87e907b5f8c5d69"
dependencies = [
"bit_field",
"bitflags",
"rustversion",
"volatile",
]

View File

@ -17,3 +17,4 @@ strip = "debuginfo"
[dependencies]
spin = "0.9.4"
x86_64 = "0.14.10"

View File

@ -0,0 +1,2 @@
#![cfg(target_arch = "x86_64")]
pub use super::x86_64::interrupts::*;

View File

@ -1,5 +1,6 @@
pub mod cpu;
pub mod io;
pub mod interrupts;
#[cfg(target_arch = "x86_64")]
mod x86_64;

View File

@ -0,0 +1,34 @@
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
use crate::try_println;
use core::arch::asm;
static mut IDT: InterruptDescriptorTable = InterruptDescriptorTable::new();
extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame)
{
try_println!("Breakpoint!\n{:#?}", stack_frame);
}
extern "x86-interrupt" fn page_fault_handler(stack_frame: InterruptStackFrame, faulting_address: PageFaultErrorCode)
{
try_println!("Page fault at {:#?}\n{:#?}", faulting_address, stack_frame);
}
pub fn load()
{
unsafe {
IDT.breakpoint.set_handler_fn(breakpoint_handler);
IDT.page_fault.set_handler_fn(page_fault_handler);
IDT.load();
}
}
pub fn enable()
{
unsafe { asm!("sti"); }
}
pub fn disable()
{
unsafe { asm!("cli"); }
}

View File

@ -1,3 +1,4 @@
#![cfg(target_arch = "x86_64")]
pub mod cpu;
pub mod io;
pub mod interrupts;

View File

@ -4,13 +4,13 @@ use crate::util::get_bootboot;
use crate::arch::cpu;
pub fn halt_other_cores() -> () {
let boot: BOOTBOOT = get_bootboot();
let boot: &BOOTBOOT = get_bootboot();
if cpu::get_processor_id() != boot.bspid as u32 {
cpu::halt();
}
}
pub fn check_magic() -> () {
let boot: BOOTBOOT = get_bootboot();
let boot: &BOOTBOOT = get_bootboot();
assert_eq!(boot.magic, BOOTBOOT_MAGIC[..4]);
}

View File

@ -1,19 +1,48 @@
use crate::arch::io::SERIAL;
use core::fmt;
/// Locks the serial port and writes formatted output.
#[macro_export]
macro_rules! print {
($($arg:tt)*) => ($crate::log::_print(format_args!($($arg)*)));
}
/// Tries to lock the serial port and writes formatted output.
/// Should be used in interrupt handlers, as it does not block but silently fails.
/// (If we are blocked waiting for interrupted code to unlock a lock, that's an instant deadlock unless we are on SMP and another CPU schedules that code)
#[macro_export]
macro_rules! try_print {
($($arg:tt)*) => ($crate::log::_try_print(format_args!($($arg)*)));
}
/// Locks the serial port and writes formatted output with a trailing newline.
#[macro_export]
macro_rules! println {
() => ($crate::print!("\n"));
($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
}
/// Tries to lock the serial port and writes formatted output with a trailing newline.
/// Should be used in interrupt handlers, as it does not block but silently fails.
/// (If we are blocked waiting for interrupted code to unlock a lock, that's an instant deadlock unless we are on SMP and another CPU schedules that code)
#[macro_export]
macro_rules! try_println {
() => ($crate::try_print!("\n"));
($($arg:tt)*) => ($crate::try_print!("{}\n", format_args!($($arg)*)));
}
#[doc(hidden)]
pub fn _print(args: fmt::Arguments) {
use core::fmt::Write;
SERIAL.lock().write_fmt(args).unwrap();
}
#[doc(hidden)]
pub fn _try_print(args: fmt::Arguments) {
use core::fmt::Write;
let serial = SERIAL.try_lock();
if serial.is_some()
{
serial.unwrap().write_fmt(args).unwrap();
}
}

View File

@ -2,6 +2,7 @@
#![no_main]
#![feature(core_intrinsics)]
#![feature(abi_x86_interrupt)]
mod video;
mod bootboot;
@ -12,19 +13,32 @@ mod arch;
mod log;
use arch::cpu;
use arch::interrupts;
use x86_64::instructions::interrupts::int3;
use video::Color;
#[no_mangle]
pub extern "C" fn _start() -> ! {
interrupts::disable();
init::halt_other_cores();
init::check_magic();
interrupts::load();
video::clear(Color::White);
println!("Hello, world!");
interrupts::enable();
int3();
println!("Still here!");
cpu::halt();
}

View File

@ -1,5 +1,5 @@
use crate::bootboot::{BOOTBOOT, BOOTBOOT_INFO};
pub fn get_bootboot() -> BOOTBOOT {
return unsafe { *(BOOTBOOT_INFO as *const BOOTBOOT) }
pub fn get_bootboot() -> &'static BOOTBOOT {
return unsafe { & *(BOOTBOOT_INFO as *const BOOTBOOT) }
}

View File

@ -39,7 +39,7 @@ impl Color {
bswap(self as u32)
}
fn to_layout(self, layout: u32) -> u32 {
fn to_data_layout(self, layout: u32) -> u32 {
match layout {
FB_ARGB => self.to_argb(),
FB_BGRA => self.to_bgra(),
@ -49,24 +49,25 @@ impl Color {
}
pub fn put_pixel(x: u32, y: u32, color: Color) -> () {
let boot: BOOTBOOT = get_bootboot();
let boot: &BOOTBOOT = get_bootboot();
let ptr: u64 = FB + (boot.fb_scanline * y) as u64 + (x * 4) as u64;
unsafe { *(ptr as *mut u32) = color.to_layout(boot.fb_type as u32) };
unsafe { *(ptr as *mut u32) = color.to_data_layout(boot.fb_type as u32) };
}
pub fn draw_rect(x: u32, y: u32, width: u32, height: u32, color: Color) -> () {
let boot: BOOTBOOT = get_bootboot();
let boot: &BOOTBOOT = get_bootboot();
let col: u32 = color.to_data_layout(boot.fb_type as u32);
for i in y..(y + height)
{
let addr: u64 = FB + (boot.fb_scanline * i) as u64 + (x * 4) as u64;
for ptr in (addr..(addr + (width*4) as u64)).step_by(4)
{
unsafe { *(ptr as *mut u32) = color.to_layout(boot.fb_type as u32) };
unsafe { *(ptr as *mut u32) = col };
}
}
}
pub fn clear(color: Color) -> () {
let boot: BOOTBOOT = get_bootboot();
let boot: &BOOTBOOT = get_bootboot();
draw_rect(0, 0, boot.fb_width, boot.fb_height, color)
}