Testing groundwork

This commit is contained in:
Ryan Kennedy 2020-03-12 23:41:00 -05:00
parent 079579af06
commit be6acf47da
6 changed files with 98 additions and 8 deletions

View file

@ -4,6 +4,7 @@ version = "0.1.0"
authors = ["Ryan Kennedy <rkennedy9064@gmail.com>"] authors = ["Ryan Kennedy <rkennedy9064@gmail.com>"]
edition = "2018" edition = "2018"
description = "Support for vga specific functions, data structures, and registers." description = "Support for vga specific functions, data structures, and registers."
documentation = "https://docs.rs/vga"
keywords = [ keywords = [
"vga", "vga",
"no_std", "no_std",

View file

@ -14,5 +14,5 @@ mod registers;
pub mod vga; pub mod vga;
mod writers; mod writers;
pub use self::vga::VGA; pub use self::vga::{VideoMode, VGA};
pub use self::writers::{Graphics640x480x16, Text40x25, Text40x50, Text80x25}; pub use self::writers::{Graphics640x480x16, Text40x25, Text40x50, Text80x25};

View file

@ -5,9 +5,11 @@ authors = ["Ryan Kennedy <rkennedy9064@gmail.com>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
bootloader = "0.8.9" bootloader = { version = "0.8.9", features = ["map_physical_memory"] }
conquer-once = { version = "0.2.0", default-features = false } conquer-once = { version = "0.2.0", default-features = false }
spinning_top = { version = "0.1.0", features = ["nightly"] } spinning_top = { version = "0.1.0", features = ["nightly"] }
pic8259_simple = "0.1.1"
vga = { path = "../" }
uart_16550 = "0.2.4" uart_16550 = "0.2.4"
x86_64 = "0.9.6" x86_64 = "0.9.6"

68
testing/src/interrupts.rs Normal file
View file

@ -0,0 +1,68 @@
use crate::gdt;
use crate::{hlt_loop, serial_print, serial_println};
use conquer_once::spin::Lazy;
use core::convert::Into;
use pic8259_simple::ChainedPics;
use spinning_top::Spinlock;
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
pub const PIC_1_OFFSET: u8 = 32;
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum InterruptIndex {
Timer = PIC_1_OFFSET,
Keyboard,
}
impl Into<u8> for InterruptIndex {
fn into(self) -> u8 {
self as u8
}
}
impl Into<usize> for InterruptIndex {
fn into(self) -> usize {
self as usize
}
}
pub static PICS: Spinlock<ChainedPics> =
Spinlock::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
let mut idt = InterruptDescriptorTable::new();
idt.page_fault.set_handler_fn(page_fault_handler);
unsafe {
idt.double_fault
.set_handler_fn(double_fault_handler)
.set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX);
}
idt
});
pub fn init_idt() {
IDT.load();
}
extern "x86-interrupt" fn double_fault_handler(
stack_frame: &mut InterruptStackFrame,
_error_code: u64,
) -> ! {
panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
}
extern "x86-interrupt" fn page_fault_handler(
stack_frame: &mut InterruptStackFrame,
error_code: PageFaultErrorCode,
) {
use x86_64::registers::control::Cr2;
serial_print!("EXCEPTION: PAGE FAULT");
serial_println!("Accessed Address: {:?}", Cr2::read());
serial_println!("Error Code: {:?}", error_code);
serial_println!("{:#?}", stack_frame);
hlt_loop();
}

View file

@ -1,4 +1,5 @@
#![cfg_attr(test, no_main)] #![cfg_attr(test, no_main)]
#![feature(abi_x86_interrupt)]
#![feature(custom_test_frameworks)] #![feature(custom_test_frameworks)]
#![test_runner(crate::test_runner)] #![test_runner(crate::test_runner)]
#![reexport_test_harness_main = "test_main"] #![reexport_test_harness_main = "test_main"]
@ -6,9 +7,9 @@
use core::panic::PanicInfo; use core::panic::PanicInfo;
#[macro_use]
pub mod serial;
pub mod gdt; pub mod gdt;
pub mod interrupts;
pub mod serial;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
@ -26,6 +27,12 @@ pub fn exit_qemu(exit_code: QemuExitCode) {
} }
} }
pub fn hlt_loop() -> ! {
loop {
x86_64::instructions::hlt();
}
}
pub fn test_runner(tests: &[&dyn Fn()]) { pub fn test_runner(tests: &[&dyn Fn()]) {
serial_println!("Running {} tests", tests.len()); serial_println!("Running {} tests", tests.len());
for test in tests { for test in tests {

View file

@ -5,23 +5,35 @@
#![test_runner(testing::test_runner)] #![test_runner(testing::test_runner)]
use core::panic::PanicInfo; use core::panic::PanicInfo;
use testing::{serial_print, serial_println}; use testing::{gdt, interrupts, serial_print, serial_println};
use vga::{VideoMode, VGA};
#[no_mangle] // don't mangle the name of this function #[no_mangle] // don't mangle the name of this function
pub extern "C" fn _start() -> ! { pub extern "C" fn _start() -> ! {
init();
test_main(); test_main();
loop {} loop {}
} }
fn init() {
gdt::init();
interrupts::init_idt();
unsafe { interrupts::PICS.lock().initialize() };
x86_64::instructions::interrupts::enable();
}
#[panic_handler] #[panic_handler]
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
testing::test_panic_handler(info) testing::test_panic_handler(info)
} }
#[test_case] #[test_case]
fn basic_boot() { fn set_mode_80x25() {
serial_print!("basic_boot... "); serial_print!("mode 80x25... ");
assert_eq!(0, 0);
let mut vga = VGA.lock();
vga.set_video_mode(VideoMode::Mode80x25);
serial_println!("[ok]"); serial_println!("[ok]");
} }