Add working exception recovery
This commit is contained in:
		
							parent
							
								
									b7d2fdf0b2
								
							
						
					
					
						commit
						a9d25b74e9
					
				| 
						 | 
				
			
			@ -43,6 +43,7 @@
 | 
			
		|||
// nested exceptions, for example, to allow a higher priority interrupt
 | 
			
		||||
// to interrupt the handling of a lower priority source, then software needs
 | 
			
		||||
// to explicitly re-enable interrupts
 | 
			
		||||
use crate::{arch::endless_sleep, println};
 | 
			
		||||
use cortex_a::{barrier, regs};
 | 
			
		||||
use register::cpu::RegisterReadWrite;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -77,12 +78,10 @@ pub struct ExceptionContext {
 | 
			
		|||
/// The default exception, invoked for every exception type unless the handler
 | 
			
		||||
/// is overwritten.
 | 
			
		||||
#[no_mangle]
 | 
			
		||||
unsafe extern "C" fn default_exception_handler() {
 | 
			
		||||
    // println!("Unexpected exception. Halting CPU.");
 | 
			
		||||
unsafe extern "C" fn default_exception_handler() -> ! {
 | 
			
		||||
    println!("Unexpected exception. Halting CPU.");
 | 
			
		||||
 | 
			
		||||
    loop {
 | 
			
		||||
        cortex_a::asm::wfe()
 | 
			
		||||
    }
 | 
			
		||||
    endless_sleep()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// To implement an exception handler, overwrite it by defining the respective
 | 
			
		||||
| 
						 | 
				
			
			@ -107,15 +106,15 @@ unsafe extern "C" fn default_exception_handler() {
 | 
			
		|||
 | 
			
		||||
#[no_mangle]
 | 
			
		||||
unsafe extern "C" fn current_elx_synchronous(e: &mut ExceptionContext) {
 | 
			
		||||
    // println!("[!] A synchronous exception happened.");
 | 
			
		||||
    // println!("      ELR_EL1: {:#010X}", e.elr_el1);
 | 
			
		||||
    // println!(
 | 
			
		||||
    //     "      Incrementing ELR_EL1 by 4 now to continue with the first \
 | 
			
		||||
    //      instruction after the exception!"
 | 
			
		||||
    // );
 | 
			
		||||
    println!("[!] A synchronous exception happened.");
 | 
			
		||||
    println!("      ELR_EL1: {:#010X}", e.elr_el1);
 | 
			
		||||
    println!(
 | 
			
		||||
        "      Incrementing ELR_EL1 by 4 now to continue with the first \
 | 
			
		||||
         instruction after the exception!"
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    e.elr_el1 += 4;
 | 
			
		||||
 | 
			
		||||
    // println!("      ELR_EL1 modified: {:#010X}", e.elr_el1);
 | 
			
		||||
    // println!("      Returning from exception...\n");
 | 
			
		||||
    println!("      ELR_EL1 modified: {:#010X}", e.elr_el1);
 | 
			
		||||
    println!("      Returning from exception...\n");
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										45
									
								
								src/main.rs
								
								
								
								
							
							
						
						
									
										45
									
								
								src/main.rs
								
								
								
								
							| 
						 | 
				
			
			@ -80,24 +80,35 @@ fn kmain() -> ! {
 | 
			
		|||
 | 
			
		||||
    println!("\n[0] UART is live!");
 | 
			
		||||
 | 
			
		||||
    println!("Hello, world!");
 | 
			
		||||
 | 
			
		||||
    extern "C" {
 | 
			
		||||
        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 {
 | 
			
		||||
        let exception_vectors_start: u64 = &__exception_vectors_start as *const _ as u64;
 | 
			
		||||
 | 
			
		||||
        arch::traps::set_vbar_el1_checked(exception_vectors_start);
 | 
			
		||||
        println!("Exception traps set up");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unsafe {
 | 
			
		||||
        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.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());
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        //==============================================
 | 
			
		||||
        // 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(160, 60, "GREEN", Color::green());
 | 
			
		||||
        display.draw_text(170, 70, "BLUE", Color::blue());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // unsafe {
 | 
			
		||||
    //     mmu::init();
 | 
			
		||||
    // }
 | 
			
		||||
    // Cause an exception by accessing a virtual address for which no
 | 
			
		||||
    // 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");
 | 
			
		||||
    // qemu_aarch64_exit()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue