#include <asmoffsets.h>
#include <offsets.h>
+#include <exceptions.h>
.global do_resume
.global vectors
-.macro invalid_exception
+.macro invalid_exception vector
/* Just stick the trap frame on the kernel stack - we're about to panic
* anyway. */
/* Exception Syndrome Register */
mrs x2, esr_el1
+ /* Exception vector */
+ mov x3, \vector
+
/* Base of the register save area. */
- mov x3, sp
+ mov x4, sp
- /* Arguments: x0 = EPC, x1 = SPSR, x2 = ESR, x3 = save area. */
+ /* Arguments: x0 = EPC, x1 = SPSR, x2 = ESR, x3 = vector, x4 = save area. */
b fatal_kernel_fault
.endm
* here before we branch. */
.align 7 /* 0x000 */
el1_sp_el0_sync:
- invalid_exception
+ invalid_exception AARCH64_EVECTOR_EL0_SYNC
.align 7 /* 0x080 */
el1_sp_el0_irq:
- invalid_exception
+ invalid_exception AARCH64_EVECTOR_EL0_IRQ /* TODO: Waait, wenn we do wait for interrupt in kernel, that shouldnt be invalid */
.align 7 /* 0x100 */
el1_sp_el0_fiq:
- invalid_exception
+ invalid_exception AARCH64_EVECTOR_EL0_FIQ
.align 7 /* 0x180 */
el1_sp_el0_serror:
- invalid_exception
+ invalid_exception AARCH64_EVECTOR_EL0_SERROR
/* Offset 0x200 */
/* Exceptions from the kernel itself, at EL1. */
.align 7 /* 0x200 */
el1_sync:
- invalid_exception
+ invalid_exception AARCH64_EVECTOR_EL1_SYNC
.align 7 /* 0x280 */
el1_irq:
- invalid_exception
+ invalid_exception AARCH64_EVECTOR_EL1_IRQ
.align 7 /* 0x300 */
el1_fiq:
- invalid_exception
+ invalid_exception AARCH64_EVECTOR_EL1_FIQ
.align 7 /* 0x380 */
el1_serror:
- invalid_exception
+ invalid_exception AARCH64_EVECTOR_EL1_SERROR
/* Offset 0x400 */
/* Exceptions from user level, EL0, executing AArch64. For any of these four
.align 7 /* 0x500 */
/* We don't implement fast IRQs */
el0_aarch64_fiq:
- invalid_exception
+ invalid_exception AARCH64_EVECTOR_EL0_FIQ
.align 7 /* 0x580 */
/* A delayed abort. We don't handle this. */
el0_aarch64_serror:
- invalid_exception
+ invalid_exception AARCH64_EVECTOR_EL0_SERROR
/* Offset 0x600 */
/* Exceptions from user level, EL0, executing AArch32. This is currently
* unimplemented. */
.align 7 /* 0x600 */
el0_aarch32_sync:
- invalid_exception
+ invalid_exception AARCH32_EVECTOR_EL0_SYNC
.align 7 /* 0x680 */
el0_aarch32_irq:
- invalid_exception
+ invalid_exception AARCH32_EVECTOR_EL0_IRQ
.align 7 /* 0x700 */
el0_aarch32_fiq:
- invalid_exception
+ invalid_exception AARCH32_EVECTOR_EL0_FIQ
.align 7 /* 0x780 */
el0_aarch32_serror:
- invalid_exception
+ invalid_exception AARCH32_EVECTOR_EL0_SERROR
.align 11
/********************************/
/* For unhandled faults, we print a register dump and panic. */
void fatal_kernel_fault(lvaddr_t epc, uint64_t spsr, uint64_t esr,
- arch_registers_state_t* save_area)
+ uint64_t vector, arch_registers_state_t* save_area)
{
size_t i;
enum aarch64_exception_class exception_class = FIELD(26,6,esr);
printk(LOG_PANIC, "Fatal (unexpected) fault at 0x%"PRIx64 " (%#" PRIx64 ")\n\n", epc, epc - (uintptr_t)&kernel_first_byte);
printk(LOG_PANIC, "Register context saved at: %p\n", save_area);
+ printk(LOG_PANIC, "Vector: ");
+ switch(vector) {
+ case AARCH64_EVECTOR_UNDEF:
+ printk(LOG_PANIC, "UNDEF\n");
+ break;
+ case AARCH64_EVECTOR_EL0_SYNC:
+ printk(LOG_PANIC, "EL0_SYNC\n");
+ break;
+ case AARCH64_EVECTOR_EL0_IRQ:
+ printk(LOG_PANIC, "EL0_IRQ\n");
+ break;
+ case AARCH64_EVECTOR_EL0_FIQ:
+ printk(LOG_PANIC, "EL0_FIQ\n");
+ break;
+ case AARCH64_EVECTOR_EL0_SERROR:
+ printk(LOG_PANIC, "EL0_SERROR\n");
+ break;
+ case AARCH64_EVECTOR_EL1_SYNC:
+ printk(LOG_PANIC, "EL1_SYNC\n");
+ break;
+ case AARCH64_EVECTOR_EL1_IRQ:
+ printk(LOG_PANIC, "EL1_IRQ\n");
+ break;
+ case AARCH64_EVECTOR_EL1_FIQ:
+ printk(LOG_PANIC, "EL1_FIQ\n");
+ break;
+ case AARCH64_EVECTOR_EL1_SERROR:
+ printk(LOG_PANIC, "EL1_SERROR\n");
+ break;
+ case AARCH64_EVECTOR_EL2_SYNC:
+ printk(LOG_PANIC, "EL2_SYNC\n");
+ break;
+ case AARCH64_EVECTOR_EL2_IRQ:
+ printk(LOG_PANIC, "EL2_IRQ\n");
+ break;
+ case AARCH64_EVECTOR_EL2_FIQ:
+ printk(LOG_PANIC, "EL2_FIQ\n");
+ break;
+ case AARCH64_EVECTOR_EL2_SERROR:
+ printk(LOG_PANIC, "EL2_SERROR\n");
+ break;
+ case AARCH32_EVECTOR_EL0_SYNC:
+ printk(LOG_PANIC, "AARCH32_EL0_SYNC\n");
+ break;
+ case AARCH32_EVECTOR_EL0_IRQ:
+ printk(LOG_PANIC, "AARCH32_EL0_IRQ\n");
+ break;
+ case AARCH32_EVECTOR_EL0_FIQ:
+ printk(LOG_PANIC, "AARCH32_EL0_FIQ\n");
+ break;
+ case AARCH32_EVECTOR_EL0_SERROR:
+ printk(LOG_PANIC, "AARCH32_EL0_SERROR\n");
+ break;
+ }
for (i = 0; i < 31; i++) {
uint64_t reg = save_area->regs[i];
switch(exception_class) {
case aarch64_ec_unknown:
- panic("Unknown instruction.\n");
+ panic("Unknown reason/instruction.\n");
case aarch64_ec_wfi:
panic("Trapped WFI/WFI.\n");
#ifndef KERNEL_ARMV8_EXCEPTIONS_H
#define KERNEL_ARMV8_EXCEPTIONS_H
-/* XXX - this looks like cruft. */
-#define AARCH64_EVECTOR_RESET 0x00
-#define AARCH64_EVECTOR_UNDEF 0x04
-#define AARCH64_EVECTOR_SWI 0x08
-#define AARCH64_EVECTOR_PABT 0x0c
-#define AARCH64_EVECTOR_DABT 0x10
-#define AARCH64_EVECTOR_IRQ 0x18
-#define AARCH64_EVECTOR_FIQ 0x1c
+#define AARCH64_EVECTOR_UNDEF 0x00
+#define AARCH64_EVECTOR_EL0_SYNC 0x01
+#define AARCH64_EVECTOR_EL0_IRQ 0x02
+#define AARCH64_EVECTOR_EL0_FIQ 0x03
+#define AARCH64_EVECTOR_EL0_SERROR 0x04
+#define AARCH64_EVECTOR_EL1_SYNC 0x05
+#define AARCH64_EVECTOR_EL1_IRQ 0x06
+#define AARCH64_EVECTOR_EL1_FIQ 0x07
+#define AARCH64_EVECTOR_EL1_SERROR 0x08
+#define AARCH64_EVECTOR_EL2_SYNC 0x09
+#define AARCH64_EVECTOR_EL2_IRQ 0x0a
+#define AARCH64_EVECTOR_EL2_FIQ 0x0b
+#define AARCH64_EVECTOR_EL2_SERROR 0x0c
+#define AARCH32_EVECTOR_EL0_SYNC 0x10
+#define AARCH32_EVECTOR_EL0_IRQ 0x11
+#define AARCH32_EVECTOR_EL0_FIQ 0x12
+#define AARCH32_EVECTOR_EL0_SERROR 0x13
+
+#if !defined(__ASSEMBLER__)
enum aarch64_exception_class {
aarch64_ec_unknown = 0x0,
#define JUMP_TABLE_OFFSET 0x100
#define ETABLE_PHYS_BASE 0x800f0000
-#if !defined(__ASSEMBLER__)
/* The exception vector table. */
extern int vectors;
* This function should be called with interrupts disabled.
*/
void fatal_kernel_fault(lvaddr_t epc, uint64_t spsr, uint64_t esr,
- arch_registers_state_t* save_area)
+ uint64_t vector, arch_registers_state_t* save_area)
__attribute__((noreturn));
/**