feat: elx_sp_el0 exception handling

This commit is contained in:
Mark Poliakov 2021-09-29 18:56:52 +03:00
parent 2d31cfd3ca
commit 683861b401
6 changed files with 179 additions and 3 deletions

View File

@ -25,7 +25,7 @@ $(error TODO)
else
ifeq ($(MACH),qemu)
QEMU_OPTS+=-kernel $(O)/kernel.bin \
-M virt,virtualization=on \
-M virt,virtualization=off \
-cpu cortex-a72 \
-m 512 \
-serial chardev:serial0
@ -45,8 +45,8 @@ endif
clean:
cargo clean
qemu:
qemu: all
qemu-system-$(ARCH) $(QEMU_OPTS)
gdb:
gdb: all
$(GDB) -x etc/gdbrc $(O)/kernel

View File

@ -1,5 +1,6 @@
//! aarch64 common boot logic
use crate::arch::aarch64::asm::CPACR_EL1;
use cortex_a::registers::VBAR_EL1;
use tock_registers::interfaces::Writeable;
#[no_mangle]
@ -7,6 +8,15 @@ fn __aa64_bsp_main() {
// Disable FP instruction trapping
CPACR_EL1.write(CPACR_EL1::FPEN::TrapNone);
extern "C" {
static aa64_el1_vectors: u8;
}
unsafe {
VBAR_EL1.set(&aa64_el1_vectors as *const _ as u64);
}
debugln!("Test");
use crate::arch::machine;
use crate::dev::{serial::SerialDevice, timer::TimestampSource, Device};

View File

@ -0,0 +1,87 @@
//! AArch64 exception handling
/// Trapped SIMD/FP functionality
pub const EC_FP_TRAP: u64 = 0b000111;
/// Data Abort at current EL
pub const EC_DATA_ABORT_ELX: u64 = 0b100101;
#[derive(Debug)]
#[repr(C)]
struct ExceptionFrame {
x0: u64,
x1: u64,
x2: u64,
x3: u64,
x4: u64,
x5: u64,
x6: u64,
x7: u64,
x8: u64,
x9: u64,
x10: u64,
x11: u64,
x12: u64,
x13: u64,
x14: u64,
x15: u64,
x16: u64,
x17: u64,
x18: u64,
x29: u64,
x30: u64,
elr: u64,
esr: u64,
far: u64,
}
#[inline(always)]
const fn data_abort_access_type(iss: u64) -> &'static str {
if iss & (1 << 6) != 0 {
"WRITE"
} else {
"READ"
}
}
#[inline(always)]
const fn data_abort_access_size(iss: u64) -> &'static str {
match (iss >> 22) & 0x3 {
0 => "BYTE",
1 => "HALFWORD",
2 => "WORD",
3 => "DOUBLEWORD",
_ => unreachable!(),
}
}
#[no_mangle]
extern "C" fn __aa64_exc_handler(exc: &mut ExceptionFrame) {
let err_code = exc.esr >> 26;
let iss = exc.esr & 0x1FFFFFF;
debugln!("Unhandled exception at ELR={:#018x}", exc.elr);
match err_code {
EC_DATA_ABORT_ELX => {
debugln!("Data Abort:");
debug!(" Illegal {}", data_abort_access_type(iss),);
if iss & (1 << 24) != 0 {
debug!(" of a {}", data_abort_access_size(iss));
}
if iss & (1 << 10) == 0 {
debug!(" at {:#018x}", exc.far);
} else {
debug!(" at UNKNOWN");
}
debugln!("");
}
_ => {}
}
debugln!("{:#018x?}", exc);
panic!("Unhandled exception");
}
global_asm!(include_str!("vectors.S"));

View File

@ -3,6 +3,7 @@
pub mod boot;
pub mod timer;
pub mod asm;
pub mod exception;
cfg_if! {
if #[cfg(feature = "mach_qemu")] {

View File

@ -0,0 +1,77 @@
.section .text
.global aa64_el1_vectors
.p2align 8
aa64_el1_vectors:
.el1_sp_el0_sync:
b .
.p2align 7
.el1_sp_el0_irq:
b .
.p2align 7
.el1_sp_el0_fiq:
b .
.p2align 7
.el1_sp_el0_serror:
b .
.p2align 7
.el1_sp_el1_sync:
sub sp, sp, #192
stp x0, x1, [sp, #0]
stp x2, x3, [sp, #16]
stp x4, x5, [sp, #32]
stp x6, x7, [sp, #48]
stp x8, x9, [sp, #64]
stp x10, x11, [sp, #80]
stp x12, x13, [sp, #96]
stp x14, x15, [sp, #112]
stp x16, x17, [sp, #128]
stp x18, x29, [sp, #144]
mrs x0, elr_el1
stp x30, x0, [sp, #160]
mrs x0, esr_el1
mrs x1, far_el1
stp x0, x1, [sp, #176]
mov x0, sp
bl __aa64_exc_handler
b .
.p2align 7
.el1_sp_el1_irq:
b .
.p2align 7
.el1_sp_el1_fiq:
b .
.p2align 7
.el1_sp_el1_serror:
b .
.p2align 7
.el0_aa64_sync:
b .
.p2align 7
.el0_aa64_irq:
b .
.p2align 7
.el0_aa64_fiq:
b .
.p2align 7
.el0_aa64_serror:
b .
.p2align 7
.el0_aa32_sync:
b .
.p2align 7
.el0_aa32_irq:
b .
.p2align 7
.el0_aa32_fiq:
b .
.p2align 7
.el0_aa32_serror:
b .

View File

@ -6,6 +6,7 @@
const_mut_refs,
const_raw_ptr_deref,
const_fn_fn_ptr_basics,
const_panic,
panic_info_message
)]
#![no_std]