libdragon
Files | Data Structures | Macros | Enumerations | Functions | Variables

Handle hardware-generated exceptions. More...

Files

file  exception.c
 Exception Handler.
 
file  exception.h
 Exception Handler.
 

Data Structures

struct  syscall_handler_entry_t
 Syscall exception handler entry. More...
 
struct  reg_block_t
 Structure representing a register block. More...
 
struct  exception_t
 Structure representing an exception. More...
 

Macros

#define MAX_SYSCALL_HANDLERS   4
 Maximum number of syscall handlers that can be registered.
 

Enumerations

enum  { EXCEPTION_TYPE_UNKNOWN = 0 , EXCEPTION_TYPE_RESET , EXCEPTION_TYPE_CRITICAL , EXCEPTION_TYPE_SYSCALL }
 Exception types. More...
 
enum  exception_code_t {
  EXCEPTION_CODE_INTERRUPT = 0 , EXCEPTION_CODE_TLB_MODIFICATION = 1 , EXCEPTION_CODE_TLB_LOAD_I_MISS = 2 , EXCEPTION_CODE_TLB_STORE_MISS = 3 ,
  EXCEPTION_CODE_LOAD_I_ADDRESS_ERROR = 4 , EXCEPTION_CODE_STORE_ADDRESS_ERROR = 5 , EXCEPTION_CODE_I_BUS_ERROR = 6 , EXCEPTION_CODE_D_BUS_ERROR = 7 ,
  EXCEPTION_CODE_SYS_CALL = 8 , EXCEPTION_CODE_BREAKPOINT = 9 , EXCEPTION_CODE_RESERVED_INSTRUCTION = 10 , EXCEPTION_CODE_COPROCESSOR_UNUSABLE = 11 ,
  EXCEPTION_CODE_ARITHMETIC_OVERFLOW = 12 , EXCEPTION_CODE_TRAP = 13 , EXCEPTION_CODE_FLOATING_POINT = 15 , EXCEPTION_CODE_WATCH = 23
}
 Exception codes.
 

Functions

exception_handler_t register_exception_handler (exception_handler_t cb)
 Register an exception handler to handle exceptions. More...
 
void __exception_dump_header (FILE *out, exception_t *ex)
 Dump a brief recap of the exception. More...
 
void __exception_dump_gpr (exception_t *ex, void(*cb)(void *arg, const char *regname, char *value), void *arg)
 Helper to dump the GPRs of an exception. More...
 
void __exception_dump_fpr (exception_t *ex, void(*cb)(void *arg, const char *regname, char *hexvalue, char *singlevalue, char *doublevalue), void *arg)
 Helper to dump the FPRs of an exception. More...
 
void exception_default_handler (exception_t *ex)
 Default exception handler. More...
 
void __onCriticalException (reg_block_t *regs)
 Respond to a critical exception.
 
void register_syscall_handler (syscall_handler_t handler, uint32_t first_code, uint32_t last_code)
 Register a handler that will be called when a syscall exception. More...
 
void __onSyscallException (reg_block_t *regs)
 Respond to a syscall exception. More...
 

Variables

volatile reg_block_t __baseRegAddr
 Base register offset as defined by the interrupt controller.
 

Detailed Description

Handle hardware-generated exceptions.

The exception handler traps exceptions generated by hardware. This could be an invalid instruction or invalid memory access exception or it could be a reset exception. In both cases, a handler registered with register_exception_handler will be passed information regarding the exception type and relevant registers.


Data Structure Documentation

◆ syscall_handler_entry_t

struct syscall_handler_entry_t

Syscall exception handler entry.

Data Fields
syscall_handler_t handler Exception handler.
uint32_t first_code Syscall code range start.
uint32_t last_code Syscall code range end.

◆ reg_block_t

struct reg_block_t

Structure representing a register block.

DO NOT modify the order unless editing inthandler.S

Data Fields
uint64_t gpr[32] General purpose registers 1-32.
uint64_t hi HI.
uint64_t lo LO.
uint32_t sr SR.
uint32_t cr CR (NOTE: can't modify this from an exception handler)
uint32_t epc represents EPC - COP0 register $14

The coprocessor 0 (system control coprocessor - COP0) register $14 is the return from exception program counter. For asynchronous exceptions it points to the place to continue execution whereas for synchronous (caused by code) exceptions, point to the instruction causing the fault condition, which needs correction in the exception handler. This member is for reading/writing its value.

uint32_t fc31 FC31.
uint64_t fpr[32] Floating point registers 1-32.

◆ exception_t

struct exception_t

Structure representing an exception.

Data Fields
int32_t type Exception type.
See also
EXCEPTION_TYPE_RESET, EXCEPTION_TYPE_CRITICAL
exception_code_t code Underlying exception code.
const char * info String information of exception.
reg_block_t * regs Registers at point of exception.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

Exception types.

Enumerator
EXCEPTION_TYPE_UNKNOWN 

Unknown exception.

EXCEPTION_TYPE_RESET 

Reset exception.

EXCEPTION_TYPE_CRITICAL 

Critical exception.

EXCEPTION_TYPE_SYSCALL 

Syscall exception.

Function Documentation

◆ register_exception_handler()

exception_handler_t register_exception_handler ( exception_handler_t  cb)

Register an exception handler to handle exceptions.

The registered handle is responsible for clearing any bits that may cause a re-trigger of the same exception and updating the EPC. An important example is the cause bits (12-17) of FCR31 from cop1. To prevent re-triggering the exception they should be cleared by the handler.

To manipulate the registers, update the values in the exception_t struct. They will be restored to appropriate locations when returning from the handler. Setting them directly will not work as expected as they will get overwritten with the values pointed by the struct.

There is only one exception to this, cr (cause register) which is also modified by the int handler before the saved values are restored thus it is only possible to update it through C0_WRITE_CR macro if it is needed. This shouldn't be necessary though as they are already handled by the library.

k0 ($26), k1 ($27) are not saved/restored and will not be available in the handler. Theoretically we can exclude s0-s7 ($16-$23), and gp ($28) to gain some performance as they are already saved by GCC when necessary. The same is true for sp ($29) and ra ($31) but current interrupt handler manipulates them via allocating a new stack and doing a jal. Similarly floating point registers f21-f31 are callee-saved. In the future we may consider removing them from the save state for interrupts (but not for exceptions)

Parameters
[in]cbCallback function to call when exceptions happen

◆ __exception_dump_header()

void __exception_dump_header ( FILE *  out,
exception_t ex 
)

Dump a brief recap of the exception.

Parameters
[in]outFile to write to
[in]exException to dump

◆ __exception_dump_gpr()

void __exception_dump_gpr ( exception_t ex,
void(*)(void *arg, const char *regname, char *value)  cb,
void *  arg 
)

Helper to dump the GPRs of an exception.

Parameters
exException
cbCallback that will be called for each register
argArgument to pass to the callback

◆ __exception_dump_fpr()

void __exception_dump_fpr ( exception_t ex,
void(*)(void *arg, const char *regname, char *hexvalue, char *singlevalue, char *doublevalue)  cb,
void *  arg 
)

Helper to dump the FPRs of an exception.

Parameters
exException
cbCallback that will be called for each register
argArgument to pass to the callback

◆ exception_default_handler()

void exception_default_handler ( exception_t ex)

Default exception handler.

This handler is installed by default for all exceptions. It initializes the console and dump the exception state to the screen, including the value of all GPR/FPR registers. It then calls abort() to abort execution.

◆ register_syscall_handler()

void register_syscall_handler ( syscall_handler_t  handler,
uint32_t  first_code,
uint32_t  last_code 
)

Register a handler that will be called when a syscall exception.

This function allows to register a handler to be invoked in response to a syscall exception, generated by the SYSCALL opcode. The opcode allows to specify a 20-bit code which, in a more traditional operating system architecture, corresponds to the "service" to be called.

When the registered handler returns, the execution will resume from the instruction following the syscall one.

To allow for different usages of the code field, this function accepts a range of codes to associated with the handler. This allows a single handler to be invoked for multiple different codes, to specialize services.

Note
Syscall codes in the range 0x00000 - 0x0FFFF are reserved to libdragon itself. Use a code outside that range to avoid conflicts with future versions of libdragon.
Parameters
handlerHandler to invoke when a syscall exception is triggered
first_codeFirst syscall code to associate with this handler (begin of range)
last_codeLast syscall code to associate with this handler (end of range)

◆ __onSyscallException()

void __onSyscallException ( reg_block_t regs)

Respond to a syscall exception.

Calls the handlers registered by register_syscall_handler.