diff --git a/Makefile b/Makefile index e8b564b..04981c4 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/kernel/src/arch/aarch64/boot/mod.rs b/kernel/src/arch/aarch64/boot/mod.rs index d6b6fd0..d071a8d 100644 --- a/kernel/src/arch/aarch64/boot/mod.rs +++ b/kernel/src/arch/aarch64/boot/mod.rs @@ -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}; diff --git a/kernel/src/arch/aarch64/exception.rs b/kernel/src/arch/aarch64/exception.rs new file mode 100644 index 0000000..bff2c65 --- /dev/null +++ b/kernel/src/arch/aarch64/exception.rs @@ -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")); diff --git a/kernel/src/arch/aarch64/mod.rs b/kernel/src/arch/aarch64/mod.rs index 4583f57..cc26aef 100644 --- a/kernel/src/arch/aarch64/mod.rs +++ b/kernel/src/arch/aarch64/mod.rs @@ -3,6 +3,7 @@ pub mod boot; pub mod timer; pub mod asm; +pub mod exception; cfg_if! { if #[cfg(feature = "mach_qemu")] { diff --git a/kernel/src/arch/aarch64/vectors.S b/kernel/src/arch/aarch64/vectors.S new file mode 100644 index 0000000..958a621 --- /dev/null +++ b/kernel/src/arch/aarch64/vectors.S @@ -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 . diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 1141829..213709b 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -6,6 +6,7 @@ const_mut_refs, const_raw_ptr_deref, const_fn_fn_ptr_basics, + const_panic, panic_info_message )] #![no_std]