Add first approximation of exception handlers

This commit is contained in:
Berkus Decker 2019-02-23 22:58:40 +02:00
parent 4858ae0159
commit c4cb106f79
3 changed files with 213 additions and 22 deletions

View File

@ -3,6 +3,7 @@
mod boot;
mod memory;
pub mod mmu;
pub mod traps;
pub use self::memory::{PhysicalAddress, VirtualAddress};
pub use mmu::*;

View File

@ -1,39 +1,41 @@
// Interrupt handling
// The base address is given by VBAR_ELn and each entry has a defined offset from this
// base address. Each table has 16 entries, with each entry being 128 bytes (32 instructions)
// in size. The table effectively consists of 4 sets of 4 entries.
VBAR_EL1, VBAR_EL2, VBAR_EL3
// Minimal implementation to help catch MMU traps
// Reads ESR_ELx to understand why trap was taken.
CurrentEL with SP0: +0x0
// VBAR_EL1, VBAR_EL2, VBAR_EL3
Synchronous
IRQ/vIRQ
FIQ
SError/vSError
// CurrentEL with SP0: +0x0
CurrentEL with SPx: +0x200
// Synchronous
// IRQ/vIRQ
// FIQ
// SError/vSError
Synchronous
IRQ/vIRQ
FIQ
SError/vSError
// CurrentEL with SPx: +0x200
Lower EL using AArch64: +0x400
// Synchronous
// IRQ/vIRQ
// FIQ
// SError/vSError
Synchronous
IRQ/vIRQ
FIQ
SError/vSError
// Lower EL using AArch64: +0x400
Lower EL using AArch32: +0x600
// Synchronous
// IRQ/vIRQ
// FIQ
// SError/vSError
Synchronous
IRQ/vIRQ
FIQ
SError/vSError
// Lower EL using AArch32: +0x600
// Synchronous
// IRQ/vIRQ
// FIQ
// SError/vSError
// When the processor takes an exception to AArch64 execution state,
// all of the PSTATE interrupt masks is set automatically. This means
@ -41,4 +43,79 @@ Lower EL using AArch32: +0x600
// 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 cortex_a::{barrier, regs};
use register::cpu::RegisterReadWrite;
global_asm!(include_str!("vectors.S"));
pub unsafe fn set_vbar_el1_checked(vec_base_addr: u64) -> bool {
if vec_base_addr.trailing_zeros() < 11 {
false
} else {
regs::VBAR_EL1.set(vec_base_addr);
// Force VBAR update to complete before next instruction.
barrier::isb(barrier::SY);
true
}
}
#[repr(C)]
pub struct GPR {
x: [u64; 31],
}
#[repr(C)]
pub struct ExceptionContext {
// General Purpose Registers
gpr: GPR,
spsr_el1: u64,
elr_el1: u64,
}
/// 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.");
loop {
cortex_a::asm::wfe()
}
}
// To implement an exception handler, overwrite it by defining the respective
// function below.
// Don't forget the #[no_mangle] attribute.
//
// unsafe extern "C" fn current_el0_synchronous(e: &mut ExceptionContext);
// unsafe extern "C" fn current_el0_irq(e: &mut ExceptionContext);
// unsafe extern "C" fn current_el0_serror(e: &mut ExceptionContext);
// unsafe extern "C" fn current_elx_synchronous(e: &mut ExceptionContext);
// unsafe extern "C" fn current_elx_irq(e: &mut ExceptionContext);
// unsafe extern "C" fn current_elx_serror(e: &mut ExceptionContext);
// unsafe extern "C" fn lower_aarch64_synchronous(e: &mut ExceptionContext);
// unsafe extern "C" fn lower_aarch64_irq(e: &mut ExceptionContext);
// unsafe extern "C" fn lower_aarch64_serror(e: &mut ExceptionContext);
// unsafe extern "C" fn lower_aarch32_synchronous(e: &mut ExceptionContext);
// unsafe extern "C" fn lower_aarch32_irq(e: &mut ExceptionContext);
// unsafe extern "C" fn lower_aarch32_serror(e: &mut ExceptionContext);
#[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!"
// );
e.elr_el1 += 4;
// println!(" ELR_EL1 modified: {:#010X}", e.elr_el1);
// println!(" Returning from exception...\n");
}

113
src/arch/aarch64/vectors.S Normal file
View File

@ -0,0 +1,113 @@
//
// MIT License
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
.macro SAVE_CONTEXT_CALL_HANDLER_AND_RESTORE handler
.balign 0x80
sub sp, sp, #16 * 17
stp x0, x1, [sp, #16 * 0]
stp x2, x3, [sp, #16 * 1]
stp x4, x5, [sp, #16 * 2]
stp x6, x7, [sp, #16 * 3]
stp x8, x9, [sp, #16 * 4]
stp x10, x11, [sp, #16 * 5]
stp x12, x13, [sp, #16 * 6]
stp x14, x15, [sp, #16 * 7]
stp x16, x17, [sp, #16 * 8]
stp x18, x19, [sp, #16 * 9]
stp x20, x21, [sp, #16 * 10]
stp x22, x23, [sp, #16 * 11]
stp x24, x25, [sp, #16 * 12]
stp x26, x27, [sp, #16 * 13]
stp x28, x29, [sp, #16 * 14]
mrs x1, SPSR_EL1
mrs x2, ELR_EL1
stp x30, x1, [sp, #16 * 15]
str x2, [sp, #16 * 16]
mov x0, sp
bl \handler
b __restore_context
.endm
.macro FIQ_DUMMY
.balign 0x80
1: wfe
b 1b
.endm
// The vector definitions
.section .vectors, "ax"
.global __exception_vectors_start
__exception_vectors_start:
SAVE_CONTEXT_CALL_HANDLER_AND_RESTORE current_el0_synchronous // 0x000
SAVE_CONTEXT_CALL_HANDLER_AND_RESTORE current_el0_irq // 0x080
FIQ_DUMMY // 0x100
SAVE_CONTEXT_CALL_HANDLER_AND_RESTORE current_el0_serror // 0x180
SAVE_CONTEXT_CALL_HANDLER_AND_RESTORE current_elx_synchronous // 0x200
SAVE_CONTEXT_CALL_HANDLER_AND_RESTORE current_elx_irq // 0x280
FIQ_DUMMY // 0x300
SAVE_CONTEXT_CALL_HANDLER_AND_RESTORE current_elx_serror // 0x380
SAVE_CONTEXT_CALL_HANDLER_AND_RESTORE lower_aarch64_synchronous // 0x400
SAVE_CONTEXT_CALL_HANDLER_AND_RESTORE lower_aarch64_irq // 0x480
FIQ_DUMMY // 0x500
SAVE_CONTEXT_CALL_HANDLER_AND_RESTORE lower_aarch64_serror // 0x580
SAVE_CONTEXT_CALL_HANDLER_AND_RESTORE lower_aarch32_synchronous // 0x600
SAVE_CONTEXT_CALL_HANDLER_AND_RESTORE lower_aarch32_irq // 0x680
FIQ_DUMMY // 0x700
SAVE_CONTEXT_CALL_HANDLER_AND_RESTORE lower_aarch32_serror // 0x780
.global __restore_context
__restore_context:
ldr x19, [sp, #16 * 16]
ldp x30, x20, [sp, #16 * 15]
msr ELR_EL1, x19
msr SPSR_EL1, x20
ldp x0, x1, [sp, #16 * 0]
ldp x2, x3, [sp, #16 * 1]
ldp x4, x5, [sp, #16 * 2]
ldp x6, x7, [sp, #16 * 3]
ldp x8, x9, [sp, #16 * 4]
ldp x10, x11, [sp, #16 * 5]
ldp x12, x13, [sp, #16 * 6]
ldp x14, x15, [sp, #16 * 7]
ldp x16, x17, [sp, #16 * 8]
ldp x18, x19, [sp, #16 * 9]
ldp x20, x21, [sp, #16 * 10]
ldp x22, x23, [sp, #16 * 11]
ldp x24, x25, [sp, #16 * 12]
ldp x26, x27, [sp, #16 * 13]
ldp x28, x29, [sp, #16 * 14]
add sp, sp, #16 * 17
eret