RISC-V trap API#

group Interrupt and exception handling

Typedefs

typedef enum hal_riscv_trap_interrupt hal_riscv_trap_interrupt_t#

Encoded interrupt cause values from the RISC-V scause CSR.

typedef enum hal_riscv_trap_exception hal_riscv_trap_exception_t#

Encoded exception cause values from the RISC-V scause CSR.

typedef struct hal_trap_frame hal_trap_frame_t#

Opaque trap context structure.

Internal implementation detail - should not be accessed directly.

typedef void (*hal_timer_handler_t)(void)#

Timer interrupt handler callback.

typedef hal_syscall_result_t (*hal_syscall_handler_t)(reg_t syscall_id, reg_t arg0, reg_t arg1, reg_t arg2, reg_t arg3, reg_t arg4, reg_t arg5)#

System call handler callback.

Handles system calls (ecall/svc instructions). Parameters are architecture-dependent register types.

Param syscall_id:

System call number (from a7/r7)

Param arg0-arg5:

System call arguments

Return:

Syscall result with error code and return value

Enums

enum hal_riscv_trap_interrupt#

Encoded interrupt cause values from the RISC-V scause CSR.

Values:

enumerator HAL_RISCV_TRAP_INT_S_SOFTWARE#
enumerator HAL_RISCV_TRAP_INT_S_TIMER#
enumerator HAL_RISCV_TRAP_INT_S_EXTERNAL#
enumerator HAL_RISCV_TRAP_INT_COUNTER_OVERFLOW#
enum hal_riscv_trap_exception#

Encoded exception cause values from the RISC-V scause CSR.

Values:

enumerator HAL_RISCV_TRAP_EXC_INSTR_ADDRESS_MISALIGNED#
enumerator HAL_RISCV_TRAP_EXC_INSTR_ACCESS_FAULT#
enumerator HAL_RISCV_TRAP_EXC_ILLEGAL_INSTR#
enumerator HAL_RISCV_TRAP_EXC_BREAKPOINT#
enumerator HAL_RISCV_TRAP_EXC_LOAD_ADDRESS_MISALIGNED#
enumerator HAL_RISCV_TRAP_EXC_LOAD_ACCESS_FAULT#
enumerator HAL_RISCV_TRAP_EXC_STORE_ADDRESS_MISALIGNED#
enumerator HAL_RISCV_TRAP_EXC_STORE_ADDRESS_FAULT#
enumerator HAL_RISCV_TRAP_EXC_ENV_CALL_U#
enumerator HAL_RISCV_TRAP_EXC_ENV_CALL_S#
enumerator HAL_RISCV_TRAP_EXC_INSTR_PAGE_FAULT#
enumerator HAL_RISCV_TRAP_EXC_LOAD_PAGE_FAULT#
enumerator HAL_RISCV_TRAP_EXC_STORE_PAGE_FAULT#
enumerator HAL_RISCV_TRAP_EXC_SOFTWARE_CHECK#
enumerator HAL_RISCV_TRAP_EXC_HARDWARE_ERROR#

Functions

static inline bool hal_riscv_trap_is_interrupt(reg_t cause)#

Returns true if a trap cause corresponds to an interrupt.

Parameters:

cause – Raw scause value.

Returns:

true if the cause is an interrupt, false if it is an exception.

static inline hal_riscv_trap_interrupt_t hal_riscv_trap_get_interrupt_code(reg_t cause)#

Extracts interrupt code from scause by clearing the interrupt bit.

Parameters:

cause – Raw scause value.

Returns:

Interrupt code.

static inline hal_riscv_trap_exception_t hal_riscv_trap_get_exception_code(reg_t cause)#

Returns exception code from scause.

Parameters:

cause – Raw scause value.

Returns:

Exception code.

size_t hal_trap_frame_size(void)#

Returns the required size of an architecture trap frame.

Use this together with hal_trap_frame_alignment and hal_trap_frame_from_buffer when storing trap frames in user-provided memory.

size_t hal_trap_frame_alignment(void)#

Returns required alignment of an architecture trap frame.

hal_trap_frame_t *hal_trap_frame_from_buffer(void *buffer, size_t buffer_size)#

Constructs a trap frame view from a caller-provided buffer.

The function aligns the returned pointer as needed for the current architecture. If the buffer is too small after alignment adjustment, returns NULL.

Parameters:
  • buffer – Backing memory buffer.

  • buffer_size – Buffer size in bytes.

Returns:

Pointer to trap frame in buffer, or NULL if requirements are not met.

error_t hal_trap_frame_copy_out(hal_trap_frame_t *out_frame)#

Copies the currently active trap frame to out_frame.

This function is only valid while running inside trap handling code.

Parameters:

out_frame – Destination trap frame.

Return values:
  • ERR_NONE – on success

  • ERR_BAD_ARG – if out_frame is NULL

  • ERR_NOT_VALID – if called outside trap context

error_t hal_trap_frame_swap(hal_trap_frame_t *in_out_frame)#

Swaps the current trap frame with in_out_frame.

This function is only valid while running inside trap handling code. It is intended for cooperative/preemptive task context switching.

Parameters:

in_out_frame – On input: frame to restore. On output: previous current frame.

Return values:
  • ERR_NONE – on success

  • ERR_BAD_ARG – if in_out_frame is NULL

  • ERR_NOT_VALID – if called outside trap context

void hal_trap_frame_init_userspace(hal_trap_frame_t *frame, uintptr_t user_sp, uintptr_t user_pc)#

Initializes trap frame for entering userspace via sret.

The frame is cleared and configured to enter user mode at user_pc with stack pointer user_sp.

Parameters:
  • frame – Trap frame to initialize.

  • user_sp – User-mode stack pointer.

  • user_pc – User-mode program counter.

error_t hal_trap_init(void)#

Initialize trap handling subsystem.

Sets up trap entry point and registers trap vector. Specific handlers for timers and syscalls can be registered separately using dedicated registration functions.

Return values:

ERR_NONE – success

error_t hal_trap_register_timer_handler(hal_timer_handler_t handler)#

Register a timer interrupt handler.

Installs a dedicated handler for timer interrupts to be called in addition to (or instead of) the generic trap handler.

Parameters:

handler – Non-null timer handler, or NULL to disable.

Return values:

ERR_NONE – success

error_t hal_trap_register_syscall_handler(hal_syscall_handler_t handler)#

Register a system call handler.

Installs a dedicated handler for system calls (ecall/svc instructions). The handler receives the syscall ID and arguments as architecture-dependent register types, and returns both an error code and value.

Parameters:

handler – Non-null syscall handler, or NULL to disable.

Return values:

ERR_NONE – success

error_t hal_trap_request_deferred_frame_swap(hal_trap_frame_t *frame)#

Request a deferred frame swap to occur right before returning from the handler.

This function is only valid while running inside trap handling code. The provided frame will be swapped with the current frame when exiting the trap handler, allowing the restored task’s register state (including results in a0/a1) to be preserved without needing to explicitly skip syscall result writeback.

This is useful for context-switching syscalls where you want to return control with the restored task’s registers intact, rather than writing the current syscall results.

Parameters:

frame – Frame to swap with the current frame on handler exit

Return values:
  • ERR_NONE – on success

  • ERR_BAD_ARG – if frame is NULL

  • ERR_NOT_VALID – if called outside trap context

void hal_trap_start_task(const hal_trap_frame_t *frame)#

Start execution of a prepared userspace task frame.

Restores the provided trap frame and transfers control to userspace via sret. This is a one-way operation that does not return.

The frame should be initialized with hal_trap_frame_init_userspace.

Parameters:

frame – Prepared userspace trap frame to run.

void hal_wait_for_interrupt(void)#

Wait for the next interrupt.

Executes a wait-for-interrupt instruction. Control returns when an enabled interrupt occurs and is processed.

struct riscv_trap_frame_t#
struct hal_syscall_result_t#
#include <trap.h>

Syscall return value structure.

Holds both the error code and the return value from a syscall. This allows architecture-independent representation of syscall results.