Add working exception recovery

This commit is contained in:
Berkus Decker 2019-02-24 00:21:15 +02:00
parent b7d2fdf0b2
commit a9d25b74e9
2 changed files with 43 additions and 27 deletions

View File

@ -43,6 +43,7 @@
// nested exceptions, for example, to allow a higher priority interrupt // nested exceptions, for example, to allow a higher priority interrupt
// to interrupt the handling of a lower priority source, then software needs // to interrupt the handling of a lower priority source, then software needs
// to explicitly re-enable interrupts // to explicitly re-enable interrupts
use crate::{arch::endless_sleep, println};
use cortex_a::{barrier, regs}; use cortex_a::{barrier, regs};
use register::cpu::RegisterReadWrite; use register::cpu::RegisterReadWrite;
@ -77,12 +78,10 @@ pub struct ExceptionContext {
/// The default exception, invoked for every exception type unless the handler /// The default exception, invoked for every exception type unless the handler
/// is overwritten. /// is overwritten.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn default_exception_handler() { unsafe extern "C" fn default_exception_handler() -> ! {
// println!("Unexpected exception. Halting CPU."); println!("Unexpected exception. Halting CPU.");
loop { endless_sleep()
cortex_a::asm::wfe()
}
} }
// To implement an exception handler, overwrite it by defining the respective // To implement an exception handler, overwrite it by defining the respective
@ -107,15 +106,15 @@ unsafe extern "C" fn default_exception_handler() {
#[no_mangle] #[no_mangle]
unsafe extern "C" fn current_elx_synchronous(e: &mut ExceptionContext) { unsafe extern "C" fn current_elx_synchronous(e: &mut ExceptionContext) {
// println!("[!] A synchronous exception happened."); println!("[!] A synchronous exception happened.");
// println!(" ELR_EL1: {:#010X}", e.elr_el1); println!(" ELR_EL1: {:#010X}", e.elr_el1);
// println!( println!(
// " Incrementing ELR_EL1 by 4 now to continue with the first \ " Incrementing ELR_EL1 by 4 now to continue with the first \
// instruction after the exception!" instruction after the exception!"
// ); );
e.elr_el1 += 4; e.elr_el1 += 4;
// println!(" ELR_EL1 modified: {:#010X}", e.elr_el1); println!(" ELR_EL1 modified: {:#010X}", e.elr_el1);
// println!(" Returning from exception...\n"); println!(" Returning from exception...\n");
} }

View File

@ -80,24 +80,35 @@ fn kmain() -> ! {
println!("\n[0] UART is live!"); println!("\n[0] UART is live!");
println!("Hello, world!");
extern "C" { extern "C" {
static __exception_vectors_start: u64; static __exception_vectors_start: u64;
} }
//==============================================
// Since formatted output doesn't work, lets do some other preparatory steps:
// 1. Initialize MMU
// 2. Set up exception handlers
// Obviously, things should keep working after that...
//==============================================
unsafe { unsafe {
let exception_vectors_start: u64 = &__exception_vectors_start as *const _ as u64; let exception_vectors_start: u64 = &__exception_vectors_start as *const _ as u64;
arch::traps::set_vbar_el1_checked(exception_vectors_start); arch::traps::set_vbar_el1_checked(exception_vectors_start);
println!("Exception traps set up");
} }
unsafe { unsafe {
mmu::init(); mmu::init();
} }
println!("MMU initialised");
if let Some(mut display) = VC::init_fb(Size2d { x: 800, y: 600 }) {
println!("Display created");
display.clear(Color::black()); // Takes A LOONG time, check caching opts?
println!("Display cleared");
if let Some(mut display) = VC::init_fb(Size2d { x: 800, y: 600 } /*, &mut uart*/) {
display.clear(Color::black());
display.rect(10, 10, 250, 250, Color::rgb(32, 96, 64)); display.rect(10, 10, 250, 250, Color::rgb(32, 96, 64));
display.draw_text(50, 50, "Hello there!", Color::rgb(128, 192, 255)); display.draw_text(50, 50, "Hello there!", Color::rgb(128, 192, 255));
@ -112,21 +123,27 @@ fn kmain() -> ! {
// display.draw_text(50, 150, s.unwrap(), Color::white()); // display.draw_text(50, 150, s.unwrap(), Color::white());
// } // }
//==============================================
// Since formatted output doesn't work, lets do some other preparatory steps:
// 1. Initialize MMU
// 2. Set up exception handlers
// Obviously, things should keep working after that...
//==============================================
display.draw_text(150, 50, "RED", Color::red()); display.draw_text(150, 50, "RED", Color::red());
display.draw_text(160, 60, "GREEN", Color::green()); display.draw_text(160, 60, "GREEN", Color::green());
display.draw_text(170, 70, "BLUE", Color::blue()); display.draw_text(170, 70, "BLUE", Color::blue());
} }
// unsafe { // Cause an exception by accessing a virtual address for which no
// mmu::init(); // address translations have been set up.
// } //
// This line of code accesses the address 3 GiB, but page tables are
// only set up for the range [0..1] GiB.
let big_addr: u64 = 3 * 1024 * 1024 * 1024;
unsafe { core::ptr::read_volatile(big_addr as *mut u64) };
println!("[i] Whoa! We recovered from an exception.");
//------------------------------------------------------------
// Start a command prompt
//------------------------------------------------------------
CONSOLE.lock(|c| {
c.command_prompt();
});
// writeln!(uart, "Bye, going to sleep now"); // writeln!(uart, "Bye, going to sleep now");
// qemu_aarch64_exit() // qemu_aarch64_exit()