250 lines
6.5 KiB
C
250 lines
6.5 KiB
C
/*
|
|
* Copyright (c) 2006-2023, RT-Thread Development Team
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Change Logs:
|
|
* Date Author Notes
|
|
* 2023-02-08 RT-Thread the first version
|
|
*/
|
|
#include "rtthread.h"
|
|
|
|
static void data_abort(unsigned long far, unsigned long iss)
|
|
{
|
|
rt_kprintf("fault addr = 0x%016lx\n", far);
|
|
if (iss & 0x40)
|
|
{
|
|
rt_kprintf("abort caused by write instruction\n");
|
|
}
|
|
else
|
|
{
|
|
rt_kprintf("abort caused by read instruction\n");
|
|
}
|
|
switch (iss & 0x3f)
|
|
{
|
|
case 0b000000:
|
|
rt_kprintf("Address size fault, zeroth level of translation or translation table base register\n");
|
|
break;
|
|
|
|
case 0b000001:
|
|
rt_kprintf("Address size fault, first level\n");
|
|
break;
|
|
|
|
case 0b000010:
|
|
rt_kprintf("Address size fault, second level\n");
|
|
break;
|
|
|
|
case 0b000011:
|
|
rt_kprintf("Address size fault, third level\n");
|
|
break;
|
|
|
|
case 0b000100:
|
|
rt_kprintf("Translation fault, zeroth level\n");
|
|
break;
|
|
|
|
case 0b000101:
|
|
rt_kprintf("Translation fault, first level\n");
|
|
break;
|
|
|
|
case 0b000110:
|
|
rt_kprintf("Translation fault, second level\n");
|
|
break;
|
|
|
|
case 0b000111:
|
|
rt_kprintf("Translation fault, third level\n");
|
|
break;
|
|
|
|
case 0b001000:
|
|
rt_kprintf("Access flag fault, zeroth level\n");
|
|
break;
|
|
|
|
case 0b001001:
|
|
rt_kprintf("Access flag fault, first level\n");
|
|
break;
|
|
|
|
case 0b001010:
|
|
rt_kprintf("Access flag fault, second level\n");
|
|
break;
|
|
|
|
case 0b001011:
|
|
rt_kprintf("Access flag fault, third level\n");
|
|
break;
|
|
|
|
case 0b001100:
|
|
rt_kprintf("Permission fault, zeroth level\n");
|
|
break;
|
|
|
|
case 0b001101:
|
|
rt_kprintf("Permission fault, first level\n");
|
|
break;
|
|
|
|
case 0b001110:
|
|
rt_kprintf("Permission fault, second level\n");
|
|
break;
|
|
|
|
case 0b001111:
|
|
rt_kprintf("Permission fault, third level\n");
|
|
break;
|
|
|
|
case 0b010000:
|
|
rt_kprintf("Synchronous external abort, not on translation table walk\n");
|
|
break;
|
|
|
|
case 0b011000:
|
|
rt_kprintf("Synchronous parity or ECC error on memory access, not on translation table walk\n");
|
|
break;
|
|
|
|
case 0b010100:
|
|
rt_kprintf("Synchronous external abort on translation table walk, zeroth level\n");
|
|
break;
|
|
|
|
case 0b010101:
|
|
rt_kprintf("Synchronous external abort on translation table walk, first level\n");
|
|
break;
|
|
|
|
case 0b010110:
|
|
rt_kprintf("Synchronous external abort on translation table walk, second level\n");
|
|
break;
|
|
|
|
case 0b010111:
|
|
rt_kprintf("Synchronous external abort on translation table walk, third level\n");
|
|
break;
|
|
|
|
case 0b011100:
|
|
rt_kprintf("Synchronous parity or ECC error on memory access on translation table walk, zeroth level\n");
|
|
break;
|
|
|
|
case 0b011101:
|
|
rt_kprintf("Synchronous parity or ECC error on memory access on translation table walk, first level\n");
|
|
break;
|
|
|
|
case 0b011110:
|
|
rt_kprintf("Synchronous parity or ECC error on memory access on translation table walk, second level\n");
|
|
break;
|
|
|
|
case 0b011111:
|
|
rt_kprintf("Synchronous parity or ECC error on memory access on translation table walk, third level\n");
|
|
break;
|
|
|
|
case 0b100001:
|
|
rt_kprintf("Alignment fault\n");
|
|
break;
|
|
|
|
case 0b110000:
|
|
rt_kprintf("TLB conflict abort\n");
|
|
break;
|
|
|
|
case 0b110100:
|
|
rt_kprintf("IMPLEMENTATION DEFINED fault (Lockdown fault)\n");
|
|
break;
|
|
|
|
case 0b110101:
|
|
rt_kprintf("IMPLEMENTATION DEFINED fault (Unsupported Exclusive access fault)\n");
|
|
break;
|
|
|
|
case 0b111101:
|
|
rt_kprintf("Section Domain Fault, used only for faults reported in the PAR_EL1\n");
|
|
break;
|
|
|
|
case 0b111110:
|
|
rt_kprintf("Page Domain Fault, used only for faults reported in the PAR_EL1\n");
|
|
break;
|
|
|
|
default:
|
|
rt_kprintf("unknow abort\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void print_exception(unsigned long esr, unsigned long epc)
|
|
{
|
|
rt_uint8_t ec;
|
|
rt_uint32_t iss;
|
|
unsigned long fault_addr;
|
|
rt_kprintf("\nexception info:\n");
|
|
ec = (unsigned char)((esr >> 26) & 0x3fU);
|
|
iss = (unsigned int)(esr & 0x00ffffffU);
|
|
rt_kprintf("esr.EC :0x%02x\n", ec);
|
|
rt_kprintf("esr.IL :0x%02x\n", (unsigned char)((esr >> 25) & 0x01U));
|
|
rt_kprintf("esr.ISS:0x%08x\n", iss);
|
|
rt_kprintf("epc :0x%016p\n", (void *)epc);
|
|
switch (ec)
|
|
{
|
|
case 0x00:
|
|
rt_kprintf("Exceptions with an unknow reason\n");
|
|
break;
|
|
|
|
case 0x01:
|
|
rt_kprintf("Exceptions from an WFI or WFE instruction\n");
|
|
break;
|
|
|
|
case 0x03:
|
|
rt_kprintf("Exceptions from an MCR or MRC access to CP15 from AArch32\n");
|
|
break;
|
|
|
|
case 0x04:
|
|
rt_kprintf("Exceptions from an MCRR or MRRC access to CP15 from AArch32\n");
|
|
break;
|
|
|
|
case 0x05:
|
|
rt_kprintf("Exceptions from an MCR or MRC access to CP14 from AArch32\n");
|
|
break;
|
|
|
|
case 0x06:
|
|
rt_kprintf("Exceptions from an LDC or STC access to CP14 from AArch32\n");
|
|
break;
|
|
|
|
case 0x07:
|
|
rt_kprintf("Exceptions from Access to Advanced SIMD or floating-point registers\n");
|
|
break;
|
|
|
|
case 0x08:
|
|
rt_kprintf("Exceptions from an MRC (or VMRS) access to CP10 from AArch32\n");
|
|
break;
|
|
|
|
case 0x0c:
|
|
rt_kprintf("Exceptions from an MCRR or MRRC access to CP14 from AArch32\n");
|
|
break;
|
|
|
|
case 0x0e:
|
|
rt_kprintf("Exceptions that occur because ther value of PSTATE.IL is 1\n");
|
|
break;
|
|
|
|
case 0x11:
|
|
rt_kprintf("SVC call from AArch32 state\n");
|
|
break;
|
|
|
|
case 0x15:
|
|
rt_kprintf("SVC call from AArch64 state\n");
|
|
break;
|
|
|
|
case 0x20:
|
|
rt_kprintf("Instruction abort from lower exception level\n");
|
|
break;
|
|
|
|
case 0x21:
|
|
rt_kprintf("Instruction abort from current exception level\n");
|
|
break;
|
|
|
|
case 0x22:
|
|
rt_kprintf("PC alignment fault\n");
|
|
break;
|
|
|
|
case 0x24:
|
|
rt_kprintf("Data abort from a lower Exception level\n");
|
|
__asm__ volatile("mrs %0, far_el1":"=r"(fault_addr));
|
|
data_abort(fault_addr, iss);
|
|
break;
|
|
|
|
case 0x25:
|
|
rt_kprintf("Data abort\n");
|
|
__asm__ volatile("mrs %0, far_el1":"=r"(fault_addr));
|
|
data_abort(fault_addr, iss);
|
|
break;
|
|
|
|
default:
|
|
rt_kprintf("Other error\n");
|
|
break;
|
|
}
|
|
}
|